Compare commits
1367 Commits
sourcemod-
...
1.10-fork
Author | SHA1 | Date | |
---|---|---|---|
|
178202a5b3 | ||
|
60f3268236 | ||
|
64b3c8fbd8 | ||
|
4c4629fca7 | ||
|
8749877c62 | ||
|
102b01c626 | ||
|
8e07790997 | ||
|
a701408c71 | ||
|
2d0fff79a8 | ||
|
9da44d67f1 | ||
|
1847f5e2dc | ||
|
0dd3361050 | ||
|
11d12aad11 | ||
|
8ac0c18674 | ||
|
a0b8153f4b | ||
|
a363587be9 | ||
|
fdcce81a41 | ||
|
c3102c7e9f | ||
|
77f4ddf2c2 | ||
|
024ae2b9ed | ||
|
8a4295d699 | ||
|
f05e39afe1 | ||
|
3b1fb85bb8 | ||
|
a405f85eee | ||
|
78511afa4c | ||
|
c37c4f830f | ||
|
4fe2ae780b | ||
|
e02e6bcb4f | ||
|
c7392aeded | ||
|
14247af323 | ||
|
32cb00a4c6 | ||
|
d93f6984cc | ||
|
207584818f | ||
|
7a42d6b564 | ||
|
94b3ca08a2 | ||
|
ab5f00b65b | ||
|
b8fd7db58d | ||
|
22635d8d35 | ||
|
fb9b284bcf | ||
|
5868ffd04e | ||
|
8ce99e0540 | ||
|
efb02755bc | ||
|
fcafd0784c | ||
|
199802150b | ||
|
e47c1a840a | ||
|
14227c04b8 | ||
|
cf0a49881e | ||
|
527a998740 | ||
|
352f078b07 | ||
|
4f3c3175e6 | ||
|
81dc80fbd1 | ||
|
28036966a6 | ||
|
2164f5191e | ||
|
216ba8b4e9 | ||
|
9c55eed549 | ||
|
f9ce25a7fe | ||
|
7e418933e7 | ||
|
05b3fc0fb9 | ||
|
d7990596f9 | ||
|
86f974f242 | ||
|
6addc5c8dd | ||
|
15a7faeafd | ||
|
626963fc49 | ||
|
2e72fc115d | ||
|
26462f2848 | ||
|
9cd2a74271 | ||
|
e1648ba8f9 | ||
|
dae6d13f06 | ||
|
ccf1d7abbd | ||
|
b92381505a | ||
|
5ba6b1426b | ||
|
fc7453a6c7 | ||
|
ae00144e84 | ||
|
59baaf1123 | ||
|
e2eac382c0 | ||
|
dd81d7c78f | ||
|
e3f4d239f1 | ||
|
8f0527487f | ||
|
318b36cdcf | ||
|
f4b9dfb2e7 | ||
|
2e11d3400e | ||
|
364cd094d9 | ||
|
2af7600057 | ||
|
8031e42bda | ||
|
7f9ceaac06 | ||
|
ae0a03d438 | ||
|
d105ce778d | ||
|
653e9325fc | ||
|
5d7d7c122e | ||
|
45fb26d282 | ||
|
c501c837d0 | ||
|
590f71436f | ||
|
b7e252dfd6 | ||
|
a2246af121 | ||
|
3e454db2d8 | ||
|
b88e0d7875 | ||
|
821251b176 | ||
|
1b3599c189 | ||
|
5e7596dea6 | ||
|
ab7519530e | ||
|
faa10f52a8 | ||
|
53df09fbb7 | ||
|
c8f3035cb0 | ||
|
f465985370 | ||
|
470486ba7e | ||
|
9a4fe1c475 | ||
|
dd61223c0b | ||
|
c196082988 | ||
|
9e58476631 | ||
|
4bebdc18a2 | ||
|
a01529b210 | ||
|
0b35c84bf0 | ||
|
846a99e57f | ||
|
c28f957fb3 | ||
|
f0aec6b0b6 | ||
|
d79c5e0dfa | ||
|
cb8d92edeb | ||
|
db9925493a | ||
|
1b795a70b0 | ||
|
ccfd2ffe38 | ||
|
c1d235a59c | ||
|
b5320a4f8a | ||
|
a1271ec3a8 | ||
|
a659896f8a | ||
|
a4e169aa8f | ||
|
7dd733cf46 | ||
|
6eb319f46e | ||
|
3add38f665 | ||
|
34e91fbd81 | ||
|
a9ca1a2fd6 | ||
|
a21c7564c1 | ||
|
1ca4517f46 | ||
|
22b43e3869 | ||
|
fc14e37d0f | ||
|
7ed329c11f | ||
|
6ad6abd319 | ||
|
bece74491d | ||
|
990a02dbe0 | ||
|
75193e9ee9 | ||
|
a5b22498ce | ||
|
398522712e | ||
|
caf0914289 | ||
|
17700e45b0 | ||
|
ba8b42ef1b | ||
|
144fb907f1 | ||
|
e7c6b23439 | ||
|
a65c215217 | ||
|
7e3b1c395b | ||
|
3511d2a44d | ||
|
beaf812909 | ||
|
7068c3e865 | ||
|
255b9323cc | ||
|
d14c94c353 | ||
|
11abe77eed | ||
|
7d8dfb09d8 | ||
|
3baa703256 | ||
|
2b3159f418 | ||
|
72acca4b9e | ||
|
32d12ea4a6 | ||
|
e4862dade8 | ||
|
ed908b6545 | ||
|
a81b52a787 | ||
|
52cdbb4fc1 | ||
|
d0bf26135c | ||
|
4f2bb62ff9 | ||
|
28f1ea82b6 | ||
|
aaac0b9eb2 | ||
|
daee19d502 | ||
|
70145dfd74 | ||
|
c09b32010f | ||
|
85a1d3e78a | ||
|
a9c9da1066 | ||
|
2860f31cb0 | ||
|
54cf1337c1 | ||
|
dcde5927b1 | ||
|
c458d1e600 | ||
|
aae7161273 | ||
|
6287774d69 | ||
|
dc4d597fb9 | ||
|
9ceb1af4fe | ||
|
b9b6832a11 | ||
|
53c63def07 | ||
|
4f70185aef | ||
|
6fcb411fe4 | ||
|
9cc518e408 | ||
|
ddebc2a075 | ||
|
fe6abb0c48 | ||
|
90e66cbeef | ||
|
487e01e4ed | ||
|
25b3d8f354 | ||
|
d430bd2f5c | ||
|
e2767a3c80 | ||
|
7f552e4d75 | ||
|
cbcda61135 | ||
|
2904c87b62 | ||
|
cfdedce362 | ||
|
467d57059a | ||
|
c993712438 | ||
|
a69d18ae1c | ||
|
95dae67d5b | ||
|
f6a64da672 | ||
|
11b23a6d07 | ||
|
82f1c5a20b | ||
|
7e080d259e | ||
|
1ab6ab1e5c | ||
|
b0e7bab980 | ||
|
9b8d28de56 | ||
|
5611ec54a2 | ||
|
6c7e29cbdb | ||
|
118d6dc9b1 | ||
|
08fe840bfd | ||
|
4637cf9221 | ||
|
4fd68939d3 | ||
|
be6a930e82 | ||
|
956f264b85 | ||
|
0a91b1f5b1 | ||
|
a17b47a2dc | ||
|
2a8c390498 | ||
|
41ffe975fd | ||
|
5ac3390656 | ||
|
f9faf9e48c | ||
|
e57dce76e1 | ||
|
64a6972757 | ||
|
1293d15f72 | ||
|
12fca79006 | ||
|
55b8371fa8 | ||
|
a8080c0bbb | ||
|
8c61fdc99d | ||
|
9374620b8b | ||
|
5a35760215 | ||
|
6b257de75a | ||
|
40356fc9db | ||
|
de108cca44 | ||
|
5f5a6b3a16 | ||
|
29b1926432 | ||
|
e0a154faa0 | ||
|
1706fdfed9 | ||
|
945df342d8 | ||
|
bfb11c7712 | ||
|
fa7d8757dc | ||
|
3c7978153b | ||
|
7cb3d4d8ff | ||
|
870e118150 | ||
|
e27f8fba1a | ||
|
ce1a4dcac0 | ||
|
057a5790e2 | ||
|
87858ef264 | ||
|
98fea02eaa | ||
|
1de6dbacad | ||
|
64ab3a08b5 | ||
|
4007ec8cf8 | ||
|
c33bf330a0 | ||
|
830c3f36d3 | ||
|
a5583882f4 | ||
|
6896ef739d | ||
|
c87afde1bd | ||
|
51cea0e04e | ||
|
89732f7935 | ||
|
8589a091dd | ||
|
d9bf0a816e | ||
|
38ba9b4561 | ||
|
8e6ca1ce09 | ||
|
d685f30847 | ||
|
43cdf20fd3 | ||
|
7507672895 | ||
|
95afe72307 | ||
|
539adcb8a2 | ||
|
3a1bb177fc | ||
|
f156d48f45 | ||
|
404e96ad45 | ||
|
90ddc16a4b | ||
|
c3b25e54f8 | ||
|
b6a2f72e95 | ||
|
6085afbaae | ||
|
2658636377 | ||
|
4bab834716 | ||
|
8f6f881937 | ||
|
8807939a14 | ||
|
27b69559a3 | ||
|
373fb4f776 | ||
|
8c88614c2e | ||
|
858a0ba17d | ||
|
5cf6a0c875 | ||
|
a5c213ae7d | ||
|
23a1c5f952 | ||
|
5aaea4c2c5 | ||
|
ab303e7394 | ||
|
4f54df65e9 | ||
|
36f9a8ed7a | ||
|
2ccaa376ba | ||
|
65bf85fcbe | ||
|
30f061e818 | ||
|
22e3d2d198 | ||
|
687db96b38 | ||
|
588e88c7ee | ||
|
65a8f3cbf8 | ||
|
82e6d00cea | ||
|
bbdecceb4b | ||
|
f67e4ce610 | ||
|
f289799c57 | ||
|
aac279322b | ||
|
5d234bb9d6 | ||
|
7e898ee530 | ||
|
54565c92f7 | ||
|
4e996a116d | ||
|
8c8af88cee | ||
|
8a36d0486b | ||
|
1f3b14367d | ||
|
79ba2835f6 | ||
|
3d461ecea1 | ||
|
b4d34ef062 | ||
|
a341a0e85c | ||
|
d8f0484327 | ||
|
b68405b651 | ||
|
453e9da7c5 | ||
|
0e7a3b0173 | ||
|
7eef3948b1 | ||
|
e609a33e6d | ||
|
41a9889cdd | ||
|
3de269946c | ||
|
9fa4ed8bac | ||
|
22033c21f2 | ||
|
d705f6a2e1 | ||
|
3d19bfd57e | ||
|
ea6cf26929 | ||
|
68c00b8ae7 | ||
|
9af507a322 | ||
|
5f9d571e12 | ||
|
f7d3e44b19 | ||
|
a01e9e510c | ||
|
3eb297bee1 | ||
|
8627c0cbfc | ||
|
cbb5c6d740 | ||
|
955a29a4aa | ||
|
1d9ea142c4 | ||
|
cb83a307ec | ||
|
902cae595b | ||
|
b7b422f046 | ||
|
01c6bb8c6f | ||
|
aeb52d4f45 | ||
|
41bf281f1d | ||
|
11aab699a5 | ||
|
1924da3527 | ||
|
2e6d02ad52 | ||
|
e4047c3f87 | ||
|
fa1d4ec5d6 | ||
|
bcfdef0171 | ||
|
60320cd845 | ||
|
8840ce905d | ||
|
fd87cb6b23 | ||
|
29d1187434 | ||
|
fdac8a1677 | ||
|
44c744b8fd | ||
|
7f71f43c2e | ||
|
16d7e39b57 | ||
|
9a6900a0ba | ||
|
e762c2ee56 | ||
|
c31eaa01a3 | ||
|
338fdb37f6 | ||
|
79970ca5fa | ||
|
bcae547365 | ||
|
f7434cdae1 | ||
|
b9fd586f2f | ||
|
e6e54813bb | ||
|
328fa3b430 | ||
|
78a2dec19e | ||
|
f413ea7f4b | ||
|
2f0272f864 | ||
|
a984e23bf6 | ||
|
2acf5f85cd | ||
|
fc1da58040 | ||
|
b3a89b70b5 | ||
|
8753e58d7f | ||
|
ae0ece411e | ||
|
b7be7eb44e | ||
|
946150c8a2 | ||
|
9ebea1cdac | ||
|
27b4f9538a | ||
|
4ce13e9cbd | ||
|
7006533409 | ||
|
001503c85f | ||
|
1831449e81 | ||
|
cd530679bd | ||
|
1351df4260 | ||
|
de42dfc783 | ||
|
ed42d2feea | ||
|
0a81a28b07 | ||
|
c0ec537f29 | ||
|
ba81b5b2a5 | ||
|
3671a69b9d | ||
|
6a77e04a8e | ||
|
8401ca3269 | ||
|
a36dafb906 | ||
|
e880471296 | ||
|
e987cf6bfc | ||
|
7bb78e53c6 | ||
|
99f7ee0588 | ||
|
705ad3bcfc | ||
|
2febfae906 | ||
|
2db2af9343 | ||
|
8e813109a2 | ||
|
8a6889663d | ||
|
aee82c9be4 | ||
|
a5d364be49 | ||
|
3f21fa4b39 | ||
|
0961e5dde3 | ||
|
89c4be525b | ||
|
1135f9024a | ||
|
9924a28acf | ||
|
8ad5862461 | ||
|
b67da15b5b | ||
|
c1888c2d05 | ||
|
9d932b47fd | ||
|
25af750af0 | ||
|
08238a8036 | ||
|
61f46845bd | ||
|
9aec0b23dd | ||
|
86363dd3ec | ||
|
23feb54f6a | ||
|
55e463426d | ||
|
0743b757f6 | ||
|
af9852a68f | ||
|
113a4a55c6 | ||
|
5e4a69def6 | ||
|
6e79114dee | ||
|
04055c411e | ||
|
90b3df1181 | ||
|
9e27a867dd | ||
|
7239f1d00a | ||
|
613838626e | ||
|
5118ea621d | ||
|
ea8fdd8fbb | ||
|
f9ec1484f8 | ||
|
c7f413f1b0 | ||
|
3fd7b29d64 | ||
|
a0f060f000 | ||
|
fd399b9b4b | ||
|
ad3588d0aa | ||
|
d9312799c3 | ||
|
cb39030cce | ||
|
0aa11374d8 | ||
|
0b7d99f03d | ||
|
47d22a3051 | ||
|
600f7e2342 | ||
|
fbe377a53d | ||
|
8a7262afd5 | ||
|
02fcf37088 | ||
|
ec455394b4 | ||
|
ee501058fb | ||
|
b74573fa12 | ||
|
d3d16a93cf | ||
|
71788e2325 | ||
|
70d81430f8 | ||
|
19db7aef46 | ||
|
151834a948 | ||
|
ec9af8feb6 | ||
|
3e201dd521 | ||
|
152a86f6f4 | ||
|
93da058dbd | ||
|
7885d62f03 | ||
|
c4487b74ee | ||
|
90cefa9daf | ||
|
f3994ce6dc | ||
|
2f82ef5ec6 | ||
|
e2ac0a085e | ||
|
6290834e2b | ||
|
efa98f6b7f | ||
|
87b0a8533f | ||
|
7a4a0271ef | ||
|
990b45a273 | ||
|
1ff7b72bb0 | ||
|
7907a07686 | ||
|
4a8068d1c4 | ||
|
6a4500733d | ||
|
482a2f2eb5 | ||
|
e74b5807a9 | ||
|
371e9f2f93 | ||
|
20b7592fcd | ||
|
9158d3734e | ||
|
6f9776e3f4 | ||
|
d5ff829952 | ||
|
7fda6e412a | ||
|
273cab1bbf | ||
|
c097bdc9ce | ||
|
da69ae0371 | ||
|
72ddd865d1 | ||
|
1dd84e3ed3 | ||
|
fdb80bd9cf | ||
|
549fea4b0a | ||
|
0c08b72b5e | ||
|
227e324aa9 | ||
|
aae39da235 | ||
|
cff585f2a1 | ||
|
ec7f1727e5 | ||
|
098a693c1a | ||
|
215599b90f | ||
|
47eb7d60e5 | ||
|
2deaa666f3 | ||
|
47dd2870d9 | ||
|
999f37800c | ||
|
a54ee12ade | ||
|
07ba8df977 | ||
|
27e812461f | ||
|
29d4ea3245 | ||
|
f70a3ea297 | ||
|
237db0504c | ||
|
015b9e92b6 | ||
|
ab53e580db | ||
|
ecbedb7b11 | ||
|
5b9ae5917b | ||
|
f3c454084a | ||
|
94383d995d | ||
|
51a6b9ce30 | ||
|
a25e3755db | ||
|
0707f14c7a | ||
|
4b52a7e531 | ||
|
f2751815be | ||
|
988d023e89 | ||
|
f06bdc9121 | ||
|
a7f5fb7a08 | ||
|
61e958e679 | ||
|
919a1e7bb9 | ||
|
56585fc32a | ||
|
57229aac91 | ||
|
3cccfc15da | ||
|
7008a566a8 | ||
|
100ddd6724 | ||
|
2c8614c639 | ||
|
a34555c45d | ||
|
adba0560d7 | ||
|
1b30e78db3 | ||
|
cb7eeef014 | ||
|
fc9aa50f3c | ||
|
f268fddc3c | ||
|
3152e7f43f | ||
|
a2ceb8f7d5 | ||
|
9db8c4af3e | ||
|
34dedcaab1 | ||
|
58c00f4487 | ||
|
f425236bac | ||
|
023a3ca056 | ||
|
34a0cb170e | ||
|
5e4ee1b849 | ||
|
f668b3fe6c | ||
|
f12924458f | ||
|
857f5fcced | ||
|
4eb1e8a4b0 | ||
|
0f96a28cca | ||
|
4d8e76202d | ||
|
e356758743 | ||
|
4e654704dc | ||
|
1790033458 | ||
|
e3d7a047bd | ||
|
a67c54a67c | ||
|
b9f7f20046 | ||
|
c42f73b66c | ||
|
5a2bc4479d | ||
|
31928e6282 | ||
|
9b3b2eb23e | ||
|
e127a55b0a | ||
|
b7223932d2 | ||
|
542bb59978 | ||
|
f91d659c6f | ||
|
7451257578 | ||
|
d8835a426f | ||
|
5edc46c994 | ||
|
57c6e09fcf | ||
|
626ee9ac65 | ||
|
59191486b6 | ||
|
f645ca0daf | ||
|
20c9815619 | ||
|
98e8f70424 | ||
|
6d9f46e983 | ||
|
d9fb0ba64e | ||
|
e8734ccf28 | ||
|
11b4320204 | ||
|
fb2117137e | ||
|
730a9a4a40 | ||
|
40f2512317 | ||
|
6dc602ad7c | ||
|
b5876bdd33 | ||
|
29a5daab98 | ||
|
ed46ca3328 | ||
|
e6ec89d145 | ||
|
b196d3e3c0 | ||
|
ebb5607bd4 | ||
|
416abd81a1 | ||
|
c536a43914 | ||
|
283bdad552 | ||
|
0c8e6e2918 | ||
|
8924a9744e | ||
|
5815e49d93 | ||
|
70bc24218f | ||
|
4f4903a05e | ||
|
f7bb423f06 | ||
|
19bcc8417d | ||
|
b65de29c92 | ||
|
7bd1ed2339 | ||
|
a7c7e72004 | ||
|
df59fd5b0e | ||
|
0d80d3c57c | ||
|
060f63e9db | ||
|
e243de0538 | ||
|
11253eae1c | ||
|
c81e1865e0 | ||
|
39d9f4da3f | ||
|
6d5dd40875 | ||
|
051e7cf320 | ||
|
37210c9ef1 | ||
|
3215e25318 | ||
|
9d72f0b335 | ||
|
803c6b0a82 | ||
|
4b04b8d51e | ||
|
b239430247 | ||
|
700ec92a9a | ||
|
272655f340 | ||
|
7c3bcc9c25 | ||
|
1ff13c59cf | ||
|
936bdc47f0 | ||
|
9008705b9d | ||
|
886c358e91 | ||
|
76f33d2742 | ||
|
5703c323d6 | ||
|
40434f54aa | ||
|
b9e9e15647 | ||
|
7fbc9869bd | ||
|
148943dad6 | ||
|
90ca9d7a47 | ||
|
a0e6f33828 | ||
|
52e3b580f3 | ||
|
1c0a5b0420 | ||
|
f9448e30c9 | ||
|
2f5257fcb5 | ||
|
5a50c28afd | ||
|
3c24ce4d7b | ||
|
441bb0483a | ||
|
05c7bd4be9 | ||
|
3dc9c23b65 | ||
|
e0e9e87326 | ||
|
52c7ef0f6f | ||
|
7ada5f957e | ||
|
d3cc797f0f | ||
|
8f4f0f61ea | ||
|
edb820eae8 | ||
|
497b51814d | ||
|
311203b5cf | ||
|
7dc4d49b86 | ||
|
4cba1925fd | ||
|
23fafbd47d | ||
|
7fbcb81916 | ||
|
2812f227b7 | ||
|
ce07a44fb0 | ||
|
23f9a1a524 | ||
|
c81466bb33 | ||
|
26b056d2c4 | ||
|
bd9fd43b76 | ||
|
184ad9083c | ||
|
8e7093ba2b | ||
|
eb3e7fcc32 | ||
|
c5a81d7c6f | ||
|
f42e9ff812 | ||
|
dc791f1fbe | ||
|
bbd3d3f4b6 | ||
|
8370112aa4 | ||
|
5e51ca0f80 | ||
|
7821c34a7b | ||
|
272d3c4b9e | ||
|
dd9d60e1d7 | ||
|
3219abcd1f | ||
|
5733bb5b08 | ||
|
75484c02a0 | ||
|
3e1ba143bf | ||
|
d3ea10a600 | ||
|
818e1e4e18 | ||
|
126ce99cd9 | ||
|
0d787e24ce | ||
|
c11ac4c25e | ||
|
ef147860c2 | ||
|
0e80ffef55 | ||
|
eb8996699e | ||
|
cf4f500eda | ||
|
fec2fa3bf0 | ||
|
a4d06e1077 | ||
|
5f9aaadacb | ||
|
a802fe3a8b | ||
|
6ab0c35837 | ||
|
b81b6cd1c6 | ||
|
c3e5d62bf6 | ||
|
e2b399b8d3 | ||
|
ce25a44e00 | ||
|
72edc74e8b | ||
|
cf07ecef46 | ||
|
c8caf7c860 | ||
|
3b3b1d6342 | ||
|
04161da5a0 | ||
|
cce6fde4ea | ||
|
b8e9aabd67 | ||
|
625f225448 | ||
|
e8eb9970a6 | ||
|
ed5771a861 | ||
|
2c03498986 | ||
|
de675be862 | ||
|
c109ea2cb6 | ||
|
c1f8ebf65c | ||
|
c6323512ef | ||
|
0387c45995 | ||
|
2ea3d9023b | ||
|
248d776a23 | ||
|
637941a978 | ||
|
1f4be9798e | ||
|
c849616003 | ||
|
d674414cf0 | ||
|
cb3f6df111 | ||
|
59623695af | ||
|
87e9dee78b | ||
|
62edc5f4c0 | ||
|
903315747d | ||
|
485ade2610 | ||
|
9e4fff3362 | ||
|
7cc911ae58 | ||
|
82ff7d5af7 | ||
|
c4c6efb140 | ||
|
f078ea1f8a | ||
|
ab1b915a3c | ||
|
709149fbed | ||
|
e57a076dc8 | ||
|
c21b3a36fc | ||
|
f765c8d436 | ||
|
ae44a6540a | ||
|
f27dbaf716 | ||
|
717ad38d06 | ||
|
60f06d1414 | ||
|
a579136a3d | ||
|
2f3d523ac0 | ||
|
df5c53fa4a | ||
|
46c069dbbe | ||
|
bda9defc0f | ||
|
8817b4277d | ||
|
4346e963e5 | ||
|
9bbcae1648 | ||
|
fc504737c5 | ||
|
1a09f2b6df | ||
|
44d34d0e5d | ||
|
56339ed43a | ||
|
393ab89c34 | ||
|
38fd55a05d | ||
|
e0e946afac | ||
|
4d3c89c065 | ||
|
a7b1a9a5fa | ||
|
529d7e2659 | ||
|
4be998c4dc | ||
|
261a4bb81b | ||
|
beba03292a | ||
|
6042518691 | ||
|
02a9db8e50 | ||
|
d0dda098a2 | ||
|
195a836999 | ||
|
366c3c0e16 | ||
|
a4b45aea9b | ||
|
fa65b62a04 | ||
|
71439b30ab | ||
|
e585e34670 | ||
|
2f2f057b47 | ||
|
7e4bfce892 | ||
|
6c5ab80418 | ||
|
121124e362 | ||
|
f4adf33b4e | ||
|
6fe4175fd2 | ||
|
8627fe1fa8 | ||
|
9310cfd164 | ||
|
722c0eb32b | ||
|
66a3811049 | ||
|
c3fcc44718 | ||
|
8b6e040581 | ||
|
88a47ff681 | ||
|
d0843ab997 | ||
|
c1396de2fc | ||
|
0810c4b217 | ||
|
632c7d05dd | ||
|
dcc192ee0d | ||
|
9b1678bd18 | ||
|
5f19fc036d | ||
|
5eec2e7d6d | ||
|
3195dec436 | ||
|
15f4a05122 | ||
|
e559e6ffa8 | ||
|
23290b35a7 | ||
|
2b3da56fb5 | ||
|
370710c0ff | ||
|
4fc7eb8a6b | ||
|
38c01714d7 | ||
|
0e1a34a4d7 | ||
|
d5d7e8c9cf | ||
|
76d681761d | ||
|
3807edbeb8 | ||
|
d9216cc599 | ||
|
d551338510 | ||
|
8a7dfdbc11 | ||
|
1a7b708df8 | ||
|
168b779786 | ||
|
c853050265 | ||
|
c614d19af0 | ||
|
8b4f27a038 | ||
|
48eee4db9b | ||
|
c66d14605a | ||
|
ac8a7ecad7 | ||
|
292df5010f | ||
|
5f3f9e869e | ||
|
e748d49343 | ||
|
c085444a03 | ||
|
c982cc9991 | ||
|
249be7ad56 | ||
|
6268abe2c3 | ||
|
6aa776eab7 | ||
|
c86a6abdc5 | ||
|
0e4edd4419 | ||
|
2a6b37dc81 | ||
|
485975fd99 | ||
|
c36f80b93d | ||
|
08cadcdda6 | ||
|
d473b0441d | ||
|
189369fcf3 | ||
|
a01a63cb71 | ||
|
10a95cfdce | ||
|
653dd36020 | ||
|
28bf744a18 | ||
|
e7d9795fc1 | ||
|
2adae27557 | ||
|
3430962cbe | ||
|
0aaa659e29 | ||
|
9ef8cc7064 | ||
|
44bacdc067 | ||
|
7d2c0bd962 | ||
|
bb39c54f17 | ||
|
8f8c00c66d | ||
|
5b3b17799f | ||
|
3a59baab2c | ||
|
fc947c68f7 | ||
|
cfd116b93b | ||
|
afc88694fd | ||
|
274e7bd329 | ||
|
8777d0d0da | ||
|
8ce41407dd | ||
|
bcd80d3e84 | ||
|
cfa09f22c1 | ||
|
cec5bfe7b2 | ||
|
f1a907c298 | ||
|
f6d7fd4949 | ||
|
2bd91dd93b | ||
|
2b13f28cfc | ||
|
3c264d78bb | ||
|
82b7485001 | ||
|
c6c034f90a | ||
|
cb9f2b9144 | ||
|
6909f7f23c | ||
|
f59df243ea | ||
|
d9839bab68 | ||
|
fe16e8e47c | ||
|
fd961f4712 | ||
|
b548ba7b58 | ||
|
df672dd8ce | ||
|
c54b54ded0 | ||
|
5757b729ac | ||
|
b048dc7b10 | ||
|
b63bfdc72a | ||
|
fa93426f6a | ||
|
86f0a77e73 | ||
|
13a783d441 | ||
|
e08697ad54 | ||
|
67ba703b84 | ||
|
d85568b54b | ||
|
67c8ee4ce3 | ||
|
69984f472f | ||
|
2ab7c08da9 | ||
|
4e275eea97 | ||
|
4f1705e001 | ||
|
5d55ff23bd | ||
|
2ed044804d | ||
|
32ba03538b | ||
|
23feee0e00 | ||
|
401aa038f8 | ||
|
38e1c2f1f3 | ||
|
9e4d396d5e | ||
|
5c5d43137d | ||
|
bdfdab1d3a | ||
|
9366882ac4 | ||
|
0f9e5234fe | ||
|
3d5c9f0e21 | ||
|
a2dac43833 | ||
|
28346c99f2 | ||
|
23d55dd9d5 | ||
|
2c886943a0 | ||
|
9d805ea9fb | ||
|
e992c33f35 | ||
|
ecbcc7ba16 | ||
|
6503e92d66 | ||
|
207f643d3a | ||
|
ec01ca72a0 | ||
|
5ecd906905 | ||
|
e78fe93e92 | ||
|
9d2bee261c | ||
|
c261bb0b2e | ||
|
204ca3aca5 | ||
|
a158205f30 | ||
|
3786a2756b | ||
|
457266d249 | ||
|
9ba1363d86 | ||
|
2d40af31a2 | ||
|
c87b3c0859 | ||
|
e30b57cb4a | ||
|
569a53182c | ||
|
ee2a408d44 | ||
|
e030bb4451 | ||
|
9e3ed67185 | ||
|
d1768b7089 | ||
|
55647cc18e | ||
|
9ebd4ad627 | ||
|
d6476728f9 | ||
|
1e1b23dc31 | ||
|
5cdf35d687 | ||
|
229769ed22 | ||
|
4dd641287d | ||
|
199d1b8eeb | ||
|
31cd5c7863 | ||
|
a95527a72c | ||
|
4f0c06d068 | ||
|
af4573e7af | ||
|
620cb405b1 | ||
|
a08a693bf3 | ||
|
8a726a8fbb | ||
|
ff692f6040 | ||
|
246c32a202 | ||
|
f81786cea0 | ||
|
bcfef75c5d | ||
|
0a14d3f50c | ||
|
17c4649651 | ||
|
4c895a78c6 | ||
|
152807b977 | ||
|
45f5ac64e1 | ||
|
b438a5b39e | ||
|
b705de0143 | ||
|
f589298879 | ||
|
7d153cf9f9 | ||
|
86b04e36b5 | ||
|
33d13ff81c | ||
|
dcbc85b2cf | ||
|
5123527c66 | ||
|
c4e7b8a795 | ||
|
41297b96d0 | ||
|
d30cab04c3 | ||
|
3ab31eba7b | ||
|
e7aa159896 | ||
|
4db1280c59 | ||
|
5893737321 | ||
|
c85cc5cbf7 | ||
|
705b5d3f5f | ||
|
8a978dc71f | ||
|
c32683225f | ||
|
01941d5504 | ||
|
8fb97a6152 | ||
|
801da2db37 | ||
|
52147ca75f | ||
|
2f3a3942b5 | ||
|
ed57a2f3d8 | ||
|
3ab4e4f24e | ||
|
1336d9cf5e | ||
|
1b706bcbcf | ||
|
1a5714c3ca | ||
|
e0a83ff7b2 | ||
|
93bec920cf | ||
|
8d8c9aa55b | ||
|
668839d1cb | ||
|
a410aefd6d | ||
|
c6a7e86762 | ||
|
f960c64dc6 | ||
|
80838af4a2 | ||
|
7564c09aff | ||
|
60ac7e23d0 | ||
|
c383f1dc43 | ||
|
f107ff9cd2 | ||
|
25a8209ffc | ||
|
3c0b89b80f | ||
|
11c40e385e | ||
|
d0574dbe28 | ||
|
b4011f3e8b | ||
|
0f9b9d0a24 | ||
|
c0d4dfa6ed | ||
|
a4821f9389 | ||
|
14e0a9a487 | ||
|
b17c7adcd5 | ||
|
a70722eb25 | ||
|
13ecd11543 | ||
|
ba0bf5668d | ||
|
338b4ed5d9 | ||
|
a4f5c802a9 | ||
|
8bc3d5d93c | ||
|
850a73d718 | ||
|
74802ce96e | ||
|
952ee53383 | ||
|
1804dce9d9 | ||
|
4231adaedf | ||
|
9e0dbfcf68 | ||
|
5139eef183 | ||
|
974e18292a | ||
|
3291e3a38f | ||
|
4db57b84b5 | ||
|
c2ba31e341 | ||
|
cb6024e334 | ||
|
12239fe852 | ||
|
a88070d063 | ||
|
9f8a40f482 | ||
|
d4babee202 | ||
|
7cfadb4584 | ||
|
fc2fe79fe7 | ||
|
2abb8e6335 | ||
|
cb4b710885 | ||
|
869777e9c4 | ||
|
eab5e78150 | ||
|
0344c3d56f | ||
|
43f4a2f7b7 | ||
|
0022b750b5 | ||
|
d49714bb10 | ||
|
fd48f4adfd | ||
|
7f97e67931 | ||
|
11bf32f6f1 | ||
|
55dee2d847 | ||
|
ae78acf97a | ||
|
fda0978225 | ||
|
227323c96d | ||
|
51344262c6 | ||
|
4152e05dcd | ||
|
5574acda3d | ||
|
75a93314a2 | ||
|
91b2ab8be1 | ||
|
8fc689c89a | ||
|
b3efc36487 | ||
|
71cb002bc1 | ||
|
78dcb8a0f3 | ||
|
9d6cbfe0cc | ||
|
7ab3d76c9f | ||
|
6686badc93 | ||
|
1b47b68cc7 | ||
|
b70873e046 | ||
|
f7c6fc9d1f | ||
|
f57dbeb60f | ||
|
397c45457a | ||
|
909598920b | ||
|
dac3d1c988 | ||
|
9164730b07 | ||
|
64f9aedebc | ||
|
5694a759ce | ||
|
ffedae66f4 | ||
|
a480bf0014 | ||
|
2432540d6e | ||
|
16eeaf625f | ||
|
f421278166 | ||
|
03e0c7317d | ||
|
fee99f3629 | ||
|
35c81365be | ||
|
8ff1a9daf3 | ||
|
6c6ed241d3 | ||
|
b84114bc8e | ||
|
1748a411e1 | ||
|
aa99eb803b | ||
|
47eabfb7fb | ||
|
a6ab14f28e | ||
|
a42cfed39c | ||
|
88c4618230 | ||
|
de58944140 | ||
|
7341bd184e | ||
|
7a8bf78f39 | ||
|
7268987461 | ||
|
ce56680fff | ||
|
ea7d5ad8f1 | ||
|
91302da050 | ||
|
d49c72cf8b | ||
|
c11036a7b9 | ||
|
5dd4037c02 | ||
|
176a8182e8 | ||
|
debbaea384 | ||
|
756255999f | ||
|
35e4374e2e | ||
|
7b56dd5c8a | ||
|
53f9bb0402 | ||
|
885117fb66 | ||
|
d12d7625aa | ||
|
7399991181 | ||
|
e62654acba | ||
|
7d795b523e | ||
|
38817bdd2c | ||
|
4b8a581c9a | ||
|
8b0a10ad1d | ||
|
7fc993e079 | ||
|
d846d91b0b | ||
|
660d6201ab | ||
|
2ab3498ab0 | ||
|
f7f4ea4243 | ||
|
637471ef29 | ||
|
f06a3605d2 | ||
|
f523d6a74d | ||
|
ff8cbf97c4 | ||
|
a947dfa9d5 | ||
|
28870d2ae5 | ||
|
cc3b86ea80 | ||
|
ae8efdddcb | ||
|
7f24f137d6 | ||
|
eaea3c927d | ||
|
72475d6770 | ||
|
8bb6f0e5c6 | ||
|
0b990e46ab | ||
|
1d313e3120 | ||
|
561004c4bf | ||
|
6f1eefbdbe | ||
|
23ac0b4637 | ||
|
a008a3f804 | ||
|
c81e7e3410 | ||
|
d459ebee41 | ||
|
ea684d5933 | ||
|
a730cfe9b5 | ||
|
c9b6b7b212 | ||
|
d72a9150a1 | ||
|
bfaedba9ed | ||
|
0c5cbe536f | ||
|
175f9afa68 | ||
|
8216097b2c | ||
|
adbdcd6b1d | ||
|
ac4f594063 | ||
|
2d53547e03 | ||
|
7c775aee2e | ||
|
b1ae2a178f | ||
|
fa2dc5b20a | ||
|
dd8fa985c1 | ||
|
81926ceae2 | ||
|
d3da389f9f | ||
|
782eee3c58 | ||
|
d0d0ea5051 | ||
|
3509f963ee | ||
|
98cbef547a | ||
|
90d3841ab2 | ||
|
3f2ad5ccb0 | ||
|
6f8ffd55a7 | ||
|
96703c247c | ||
|
c39565ddb1 | ||
|
70390ff1f7 | ||
|
924b7621ac | ||
|
715a51d01f | ||
|
a1afa23bc4 | ||
|
b53947ccc3 | ||
|
b43da7b7f0 | ||
|
fdc3c0791e | ||
|
04827466b0 | ||
|
afbcdc8a20 | ||
|
b5ae5defcf | ||
|
1f351c50d5 | ||
|
9a37b94f4d | ||
|
acf6dcac86 | ||
|
fcec0ee7c7 | ||
|
b9b0ec865c | ||
|
fcaa5361c8 | ||
|
33588b65ce | ||
|
c09c65e4c7 | ||
|
11ea385169 | ||
|
3a0310e832 | ||
|
31ab1ced06 | ||
|
b2c61a341a | ||
|
4c9321f02a | ||
|
d2005bd42a | ||
|
8817de8a55 | ||
|
97dbc7ff07 | ||
|
9c104ef310 | ||
|
7f0ff04ccf | ||
|
5502fbbdc1 | ||
|
deedc1aaa6 | ||
|
37af05c456 | ||
|
8c35d79576 | ||
|
6572989993 | ||
|
8eed58a467 | ||
|
2e77155b4e | ||
|
8b8edf6e70 | ||
|
f0aa177bf8 | ||
|
e163204643 | ||
|
50d7d7eedb | ||
|
ec05036a2d | ||
|
b8223d1b98 | ||
|
781c5129a9 | ||
|
111dd7eb68 | ||
|
21f5400d9c | ||
|
8cf3e227ea | ||
|
8c95919b32 | ||
|
b406c3d03d | ||
|
c70e87d582 | ||
|
57ba8fd09b | ||
|
3cf3f6c3f8 | ||
|
499f7b3929 | ||
|
e58415f94a | ||
|
38d2c3690a | ||
|
4212fb88c8 | ||
|
f769e1a00c | ||
|
1f9b898702 | ||
|
2f71cb4cd7 | ||
|
b8d2be9a0d | ||
|
b2d8dde3a5 | ||
|
0ee4885056 | ||
|
45bac7feb0 | ||
|
892b8c05b1 | ||
|
7d64ade621 | ||
|
45c43f4aee | ||
|
1b47aa10ca | ||
|
bcd88b4437 | ||
|
10d778e344 | ||
|
0100ebadb9 | ||
|
20b5f76572 | ||
|
62ed3973b5 | ||
|
5f7e800444 | ||
|
b52b5f46f0 | ||
|
3386a3af80 | ||
|
9099516906 | ||
|
f235f97d95 | ||
|
4bd4d8d4a5 | ||
|
284fab7254 | ||
|
f772c88eed | ||
|
58d94c2827 | ||
|
7e8d4b89ca | ||
|
70be2941fe | ||
|
9ffbac4f4e | ||
|
684b59a921 | ||
|
e8765c5d3d | ||
|
d179240c45 | ||
|
ac530a4ce0 | ||
|
589482736f | ||
|
3d2bd070ad | ||
|
c4a58b1c95 | ||
|
b9579a53ce | ||
|
94c439e533 | ||
|
a327a788c1 | ||
|
a541acb2bc | ||
|
63d1fa2d8e | ||
|
e4ee52e1ac | ||
|
c0729ff5e2 | ||
|
c2d37cdff5 | ||
|
0f00a2db08 | ||
|
67e74581cc | ||
|
eb9f496cd8 | ||
|
0203d2c811 | ||
|
6bc2d20177 | ||
|
350eb462ca | ||
|
591aea54b6 | ||
|
00ad38f5b7 | ||
|
261e135845 | ||
|
f50d8317f6 | ||
|
3558418ed7 | ||
|
fca927884b | ||
|
10c62dc0c0 | ||
|
7e9b22cb6e | ||
|
c427dfbea7 | ||
|
e88039d4e0 | ||
|
84a59c6fb7 | ||
|
19be28cc2e | ||
|
c116a731f1 | ||
|
cf9dd08c45 | ||
|
a88b447327 | ||
|
52514a96bd | ||
|
5ffb4d9845 | ||
|
0bb2dc32af | ||
|
213e7ced8c | ||
|
380479cadd | ||
|
04c23383b1 | ||
|
90ff154598 | ||
|
840b432ce0 | ||
|
e1b6e09cd3 | ||
|
ad8373925a | ||
|
2292515315 | ||
|
d9ce8249cb | ||
|
b3bb37323d | ||
|
c6b5675262 | ||
|
43bca4dcc2 | ||
|
dbbc30368d | ||
|
5f651f7fde | ||
|
eadfec75a4 | ||
|
e2aab2ab10 | ||
|
8705aea634 | ||
|
3040708d4e | ||
|
2382902fe4 | ||
|
ee0575bbb0 | ||
|
aff2551942 | ||
|
18b54b9064 | ||
|
d1af9b5fd1 | ||
|
e3349116cb | ||
|
c70f16c65a | ||
|
37d9867c06 | ||
|
cddae6f456 | ||
|
ff27484527 | ||
|
324d52bf2b | ||
|
9f648879e5 | ||
|
a7c41f6ac2 | ||
|
fbb6e88d0d | ||
|
49383e7391 | ||
|
f715952128 | ||
|
2516654d2e | ||
|
8dbcfde314 | ||
|
4218674e7c | ||
|
89119880b5 | ||
|
42956c0a10 | ||
|
e0e2c00d12 | ||
|
691d891794 | ||
|
df6dfec728 | ||
|
dfa36b7735 | ||
|
c28426a09f | ||
|
8567246772 | ||
|
a9961d3bb4 | ||
|
bded4f9142 | ||
|
491036a1e6 | ||
|
3e012e7f79 | ||
|
3929ff1f27 | ||
|
56d768f546 | ||
|
4ec992474e | ||
|
822501b8a1 | ||
|
bf3ff460b3 | ||
|
ff9ae0782e | ||
|
66defdfc27 | ||
|
3e65d308a8 | ||
|
a88d0da1af | ||
|
aa38226337 | ||
|
5961ed2e4a | ||
|
4dd9131847 | ||
|
6d1a2b0d86 | ||
|
cdaf54dfe0 | ||
|
7f0edd441e | ||
|
4a9dffd3e1 | ||
|
f69f4eb85f | ||
|
84782a40df | ||
|
047c143879 | ||
|
a7c9aff568 | ||
|
fe6d44bbd5 | ||
|
489b7f1d33 | ||
|
ad9de71ac9 | ||
|
3edaac9bd7 | ||
|
9247a8ab00 | ||
|
7b71ff2643 | ||
|
97e88640ca | ||
|
e1b89a3008 | ||
|
6dff44da54 | ||
|
7fddf5abf4 | ||
|
6c17f247df | ||
|
9b2e77711a | ||
|
0b131d6864 | ||
|
abb8d8447f | ||
|
7edc1f8a6d | ||
|
a0dd8cbc97 | ||
|
4f15715993 | ||
|
679b2863fa | ||
|
13f6e2d4d0 | ||
|
4311dc3270 | ||
|
01f4b204c9 | ||
|
f40bfbf762 | ||
|
ccf5aa6b54 | ||
|
032dde7be9 | ||
|
2d5b71c832 | ||
|
8272151d78 | ||
|
1b79252947 | ||
|
bc4d6b7104 | ||
|
46839b9752 | ||
|
f27c33cd18 | ||
|
d2e01da287 | ||
|
3ef2bdcb8d | ||
|
cd304dc800 | ||
|
901890e36d |
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# GitHub views all .h files as C, let's assume it's C++
|
||||||
|
*.h linguist-language=c++
|
||||||
|
|
||||||
|
# Internal tools overriding
|
||||||
|
tools/* linguist-vendored
|
||||||
|
editor/* linguist-vendored
|
||||||
|
|
||||||
|
# Third-party overriding
|
||||||
|
extensions/curl/curl-src/* linguist-vendored
|
||||||
|
extensions/geoip/GeoIP.c linguist-vendored
|
||||||
|
extensions/geoip/GeoIP.h linguist-vendored
|
||||||
|
extensions/sqlite/sqlite-source/* linguist-vendored
|
74
.github/CONTRIBUTING.md
vendored
Normal file
74
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Contributing to SourceMod
|
||||||
|
|
||||||
|
## Issue reports
|
||||||
|
|
||||||
|
Please consider the following guidelines when reporting an issue.
|
||||||
|
|
||||||
|
#### Not for general support
|
||||||
|
This is not the right place to get help with using or installing SourceMod, or for issues with specific, third-party SourceMod plugins or extensions.
|
||||||
|
|
||||||
|
For help with SourceMod, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). Similarly, for assistance with, or to report issues with, third-party SourceMod plugins or extensions, you should post in the existing thread for that plugin or extension on the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52).
|
||||||
|
|
||||||
|
#### Details, details, details
|
||||||
|
Provide as much detail as possible when reporting an issue.
|
||||||
|
|
||||||
|
For bugs or other undesired behavior, answers to the following questions are a great start:
|
||||||
|
* What is the issue?
|
||||||
|
* What behavior are you expecting instead?
|
||||||
|
* On what operating system is the game server running?
|
||||||
|
* What game is the game server running?
|
||||||
|
* What exact version (full x.y.z.a version number) of Metamod:Source and SourceMod are installed on the game server?
|
||||||
|
* What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem.
|
||||||
|
|
||||||
|
If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation.
|
||||||
|
* What is your end goal, or what are you trying to accomplish?
|
||||||
|
* Why is this necessary, or what benefit do you see with it?
|
||||||
|
* Will this be useful to others?
|
||||||
|
|
||||||
|
#### Issues with security implications
|
||||||
|
Please report any security bugs to [security@alliedmods.net](mailto:security@alliedmods.net) rather than to this public issue tracker.
|
||||||
|
|
||||||
|
#### We're only human
|
||||||
|
Please keep in mind that we maintain this project in our spare time, at no cost. There is no SLA, and you are not owed a response or a fix.
|
||||||
|
|
||||||
|
#### Conduct
|
||||||
|
Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules)
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
|
||||||
|
Firstly, thank you for considering contributing changes to the project!
|
||||||
|
|
||||||
|
However, if this is anything more than a small fix such as a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
|
||||||
|
|
||||||
|
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel like you wasted your time writing something only for us to shoot it down.
|
||||||
|
|
||||||
|
#### Rejection
|
||||||
|
*Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.*
|
||||||
|
|
||||||
|
> If you send us a patch without coordinating it with us first, it will probably be immediately rejected, or sit in limbo for a long time and eventually be rejected. The reasons we do this vary from patch to patch, but some of the most common reasons are:
|
||||||
|
>
|
||||||
|
> **Unjustifiable Costs**: We support code in the upstream forever. Support is enormously expensive and takes up a huge amount of our time. The cost to support a change over its lifetime is often 10x or 100x or 1000x greater than the cost to write the first version of it. Many uncoordinated patches we receive are "white elephants", which would cost much more to maintain than the value they provide.
|
||||||
|
>
|
||||||
|
> As an author, it may look like you're giving us free work and we're rejecting it as too expensive, but this viewpoint doesn't align with the reality of a large project which is actively supported by a small, experienced team. Writing code is cheap; maintaining it is expensive.
|
||||||
|
>
|
||||||
|
> By coordinating with us first, you can make sure the patch is something we consider valuable enough to put long-term support resources behind, and that you're building it in a way that we're comfortable taking over.
|
||||||
|
>
|
||||||
|
> **Not a Good Fit**: Many patches aren't good fits for the upstream: they implement features we simply don't want. You can find more information in Contributing Feature Requests. Coordinating with us first helps make sure we're on the same page and interested in a feature.
|
||||||
|
>
|
||||||
|
> The most common type of patch along these lines is a patch which adds new configuration options. We consider additional configuration options to have an exceptionally high lifetime support cost and are very unlikely to accept them. Coordinate with us first.
|
||||||
|
>
|
||||||
|
> **Not a Priority**: If you send us a patch against something which isn't a priority, we probably won't have time to look at it. We don't give special treatment to low-priority issues just because there's code written: we'd still be spending time on something lower-priority when we could be spending it on something higher-priority instead.
|
||||||
|
>
|
||||||
|
> If you coordinate with us first, you can make sure your patch is in an area of the codebase that we can prioritize.
|
||||||
|
>
|
||||||
|
> **Overly Ambitious Patches**: Sometimes we'll get huge patches from new contributors. These can have a lot of fundamental problems and require a huge amount of our time to review and correct. If you're interested in contributing, you'll have more success if you start small and learn as you go.
|
||||||
|
>
|
||||||
|
> We can help you break a large change into smaller pieces and learn how the codebase works as you proceed through the implementation, but only if you coordinate with us first.
|
||||||
|
>
|
||||||
|
> **Generality**: We often receive several feature requests which ask for similar features, and can come up with a general approach which covers all of the use cases. If you send us a patch for your use case only, the approach may be too specific. When a cleaner and more general approach is available, we usually prefer to pursue it.
|
||||||
|
>
|
||||||
|
> By coordinating with us first, we can make you aware of similar use cases and opportunities to generalize an approach. These changes are often small, but can have a big impact on how useful a piece of code is.
|
||||||
|
>
|
||||||
|
> **Infrastructure and Sequencing**: Sometimes patches are written against a piece of infrastructure with major planned changes. We don't want to accept these because they'll make the infrastructure changes more difficult to implement.
|
||||||
|
>
|
||||||
|
> Coordinate with us first to make sure a change doesn't need to wait on other pieces of infrastructure. We can help you identify technical blockers and possibly guide you through resolving them if you're interested.
|
8
.github/FUNDING.yml
vendored
Normal file
8
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
custom: https://www.sourcemod.net/donate.php
|
26
.github/ISSUE_TEMPLATE.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Help us help you
|
||||||
|
- [ ] I have checked that my issue [doesn't exist yet](https://github.com/alliedmodders/sourcemod/issues).
|
||||||
|
- [ ] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
|
||||||
|
- [ ] I can always reproduce the issue with the provided description below.
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
* Operating System version:
|
||||||
|
* Game/AppID (with version if applicable):
|
||||||
|
* Current SourceMod version:
|
||||||
|
* Current SourceMod snapshot:
|
||||||
|
* Current Metamod: Source snapshot:
|
||||||
|
- [ ] I have updated SourceMod to the [latest version](https://www.sourcemod.net/downloads.php) and it still happens.
|
||||||
|
- [ ] I have updated SourceMod to the [latest snapshot](https://www.sourcemod.net/downloads.php?branch=dev) and it still happens.
|
||||||
|
- [ ] I have updated SourceMM to the [latest snapshot](https://sourcemm.net/downloads.php?branch=dev) and it still happens.
|
||||||
|
|
||||||
|
# Description
|
||||||
|
|
||||||
|
|
||||||
|
# Problematic Code (or Steps to Reproduce)
|
||||||
|
```
|
||||||
|
// TODO(you): code here to reproduce the problem
|
||||||
|
```
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
* Please attach in separate files: game output, library logs, kernel logs, and any other supporting information.
|
||||||
|
* In case of a crash, please attach minidump or dump analyze output.
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -35,3 +35,4 @@ obj-*/
|
|||||||
*.orig
|
*.orig
|
||||||
*.smx
|
*.smx
|
||||||
*.swp
|
*.swp
|
||||||
|
*.gdb_history
|
||||||
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "public/amtl"]
|
||||||
|
path = public/amtl
|
||||||
|
url = https://github.com/alliedmodders/amtl
|
||||||
|
[submodule "sourcepawn"]
|
||||||
|
path = sourcepawn
|
||||||
|
url = https://github.com/BotoX/sourcepawn.git
|
117
.travis.yml
117
.travis.yml
@ -1,11 +1,118 @@
|
|||||||
|
git:
|
||||||
|
depth: 3
|
||||||
|
|
||||||
|
sudo: false
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler:
|
os: linux
|
||||||
- clang
|
dist: trusty
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-3.9
|
||||||
|
- llvm-toolchain-trusty-4.0
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
|
packages:
|
||||||
|
- lib32stdc++6
|
||||||
|
- lib32z1-dev
|
||||||
|
- libc6-dev-i386
|
||||||
|
- linux-libc-dev
|
||||||
|
- g++-multilib
|
||||||
|
# - clang-3.6
|
||||||
|
# - clang-3.8
|
||||||
|
# - clang-4.0
|
||||||
|
# - clang-5.0
|
||||||
|
# - g++-6
|
||||||
|
# - g++-6-multilib
|
||||||
|
- clang-3.9
|
||||||
|
- g++-4.8-multilib
|
||||||
|
- g++-4.8
|
||||||
|
- g++-4.9-multilib
|
||||||
|
- g++-4.9
|
||||||
|
- g++-5-multilib
|
||||||
|
- g++-5
|
||||||
|
- g++-7-multilib
|
||||||
|
- g++-7
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- ../mysql-5.0
|
||||||
|
env:
|
||||||
|
- MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
|
||||||
|
- MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
|
||||||
|
- MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
|
||||||
|
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||||
|
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages: ['clang-3.6', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||||
|
cache:
|
||||||
|
directories: ['../mysql-5.0']
|
||||||
|
env: ['MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"']
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||||
|
cache:
|
||||||
|
directories: ['../mysql-5.0']
|
||||||
|
env: ['MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"']
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-trusty-4.0']
|
||||||
|
packages: ['clang-4.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||||
|
cache:
|
||||||
|
directories: ['../mysql-5.0']
|
||||||
|
env: ['MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"']
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-trusty-5.0']
|
||||||
|
packages: ['clang-5.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||||
|
cache:
|
||||||
|
directories: ['../mysql-5.0']
|
||||||
|
env: ['MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"']
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-6', 'g++-6-multilib', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||||
|
cache:
|
||||||
|
directories: ['../mysql-5.0']
|
||||||
|
env: ['MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"']
|
||||||
|
|
||||||
|
allow_failures:
|
||||||
|
- env: MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
|
||||||
|
- env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
|
||||||
|
- env: MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
|
||||||
|
- env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
|
||||||
|
- env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||||
|
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||||
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- sudo apt-get update -qq
|
|
||||||
- sudo apt-get install -y g++-multilib libc6-dev-i386 lib32stdc++6 lib32z1-dev
|
|
||||||
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
|
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
|
||||||
script:
|
script:
|
||||||
- mkdir build && cd build
|
- mkdir build && cd build
|
||||||
- python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota
|
- PATH="~/.local/bin:$PATH"
|
||||||
|
- eval "${MATRIX_EVAL}"
|
||||||
|
- python ../configure.py --enable-optimize --sdks=episode1,css,tf2,l4d2,csgo,dota
|
||||||
- ambuild
|
- ambuild
|
403
AMBuildScript
403
AMBuildScript
@ -11,32 +11,52 @@ class SDK(object):
|
|||||||
self.platform = platform
|
self.platform = platform
|
||||||
self.name = dir
|
self.name = dir
|
||||||
self.path = None # Actual path
|
self.path = None # Actual path
|
||||||
|
self.platformSpec = platform
|
||||||
|
|
||||||
|
# By default, nothing supports x64.
|
||||||
|
if type(platform) is list:
|
||||||
|
self.platformSpec = {p: ['x86'] for p in platform}
|
||||||
|
else:
|
||||||
|
self.platformSpec = platform
|
||||||
|
|
||||||
|
def shouldBuild(self, target, archs):
|
||||||
|
if target.platform not in self.platformSpec:
|
||||||
|
return False
|
||||||
|
if not len([i for i in self.platformSpec[target.platform] if i in archs]):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
WinOnly = ['windows']
|
WinOnly = ['windows']
|
||||||
WinLinux = ['windows', 'linux']
|
WinLinux = ['windows', 'linux']
|
||||||
WinLinuxMac = ['windows', 'linux', 'mac']
|
WinLinuxMac = ['windows', 'linux', 'mac']
|
||||||
|
CSGO = {
|
||||||
|
'windows': ['x86'],
|
||||||
|
'linux': ['x86', 'x64'],
|
||||||
|
'mac': ['x64']
|
||||||
|
}
|
||||||
|
|
||||||
PossibleSDKs = {
|
PossibleSDKs = {
|
||||||
'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
|
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
|
||||||
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
|
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
|
||||||
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
|
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
|
||||||
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
|
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
|
||||||
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
|
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
|
||||||
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
|
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
|
||||||
'tf2': SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
|
'tf2': SDK('HL2SDKTF2', '2.tf2', '11', 'TF2', WinLinuxMac, 'tf2'),
|
||||||
'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
|
'l4d': SDK('HL2SDKL4D', '2.l4d', '12', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
|
||||||
'nucleardawn': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
|
'nucleardawn': SDK('HL2SDKND', '2.nd', '13', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
|
||||||
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '14', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
|
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '15', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
|
||||||
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
|
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
|
||||||
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '15', 'ALIENSWARM', WinOnly, 'swarm'),
|
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'),
|
||||||
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
|
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
|
||||||
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
|
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
|
||||||
'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'),
|
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'),
|
||||||
'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'),
|
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
|
||||||
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
|
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
|
||||||
'blade': SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'),
|
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
|
||||||
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'),
|
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '14', 'CONTAGION', WinOnly, 'contagion'),
|
||||||
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'),
|
'bms': SDK('HL2SDKBMS', '2.bms', '10', 'BMS', WinLinux, 'bms'),
|
||||||
|
'doi': SDK('HL2SDKDOI', '2.doi', '20', 'DOI', WinLinuxMac, 'doi'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def ResolveEnvPath(env, folder):
|
def ResolveEnvPath(env, folder):
|
||||||
@ -60,6 +80,28 @@ def ResolveEnvPath(env, folder):
|
|||||||
def Normalize(path):
|
def Normalize(path):
|
||||||
return os.path.abspath(os.path.normpath(path))
|
return os.path.abspath(os.path.normpath(path))
|
||||||
|
|
||||||
|
def SetArchFlags(compiler, arch, platform):
|
||||||
|
if compiler.behavior == 'gcc':
|
||||||
|
if arch == 'x86':
|
||||||
|
compiler.cflags += ['-m32']
|
||||||
|
compiler.linkflags += ['-m32']
|
||||||
|
if platform == 'mac':
|
||||||
|
compiler.linkflags += ['-arch', 'i386']
|
||||||
|
elif arch == 'x64':
|
||||||
|
compiler.cflags += ['-m64', '-fPIC']
|
||||||
|
compiler.linkflags += ['-m64']
|
||||||
|
if platform == 'mac':
|
||||||
|
compiler.linkflags += ['-arch', 'x86_64']
|
||||||
|
elif compiler.like('msvc'):
|
||||||
|
if builder.target.arch == 'x86':
|
||||||
|
compiler.linkflags += ['/MACHINE:X86']
|
||||||
|
elif builder.target.arch == 'x64':
|
||||||
|
compiler.linkflags += ['/MACHINE:X64']
|
||||||
|
|
||||||
|
def AppendArchSuffix(binary, name, arch):
|
||||||
|
if arch == 'x64':
|
||||||
|
binary.localFolder = name + '.x64'
|
||||||
|
|
||||||
class SMConfig(object):
|
class SMConfig(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sdks = {}
|
self.sdks = {}
|
||||||
@ -67,10 +109,12 @@ class SMConfig(object):
|
|||||||
self.extensions = []
|
self.extensions = []
|
||||||
self.generated_headers = None
|
self.generated_headers = None
|
||||||
self.mms_root = None
|
self.mms_root = None
|
||||||
self.mysql_root = None
|
self.mysql_root = {}
|
||||||
self.spcomp = None
|
self.spcomp = None
|
||||||
|
self.spcomp_bins = None
|
||||||
self.smx_files = {}
|
self.smx_files = {}
|
||||||
self.versionlib = None
|
self.versionlib = None
|
||||||
|
self.archs = builder.target.arch.replace('x86_64', 'x64').split(',')
|
||||||
|
|
||||||
def use_auto_versioning(self):
|
def use_auto_versioning(self):
|
||||||
if builder.backend != 'amb2':
|
if builder.backend != 'amb2':
|
||||||
@ -104,7 +148,7 @@ class SMConfig(object):
|
|||||||
|
|
||||||
for sdk_name in PossibleSDKs:
|
for sdk_name in PossibleSDKs:
|
||||||
sdk = PossibleSDKs[sdk_name]
|
sdk = PossibleSDKs[sdk_name]
|
||||||
if builder.target_platform in sdk.platform:
|
if sdk.shouldBuild(builder.target, self.archs):
|
||||||
if builder.options.hl2sdk_root:
|
if builder.options.hl2sdk_root:
|
||||||
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
|
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
|
||||||
else:
|
else:
|
||||||
@ -117,9 +161,9 @@ class SMConfig(object):
|
|||||||
sdk.path = Normalize(sdk_path)
|
sdk.path = Normalize(sdk_path)
|
||||||
self.sdks[sdk_name] = sdk
|
self.sdks[sdk_name] = sdk
|
||||||
|
|
||||||
if len(self.sdks) < 1:
|
if len(self.sdks) < 1 and len(sdk_list):
|
||||||
raise Exception('At least one SDK must be available.')
|
raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format(
|
||||||
|
builder.target.platform, builder.target.arch))
|
||||||
|
|
||||||
if builder.options.mms_path:
|
if builder.options.mms_path:
|
||||||
self.mms_root = builder.options.mms_path
|
self.mms_root = builder.options.mms_path
|
||||||
@ -136,22 +180,77 @@ class SMConfig(object):
|
|||||||
|
|
||||||
if builder.options.hasMySql:
|
if builder.options.hasMySql:
|
||||||
if builder.options.mysql_path:
|
if builder.options.mysql_path:
|
||||||
self.mysql_root = builder.options.mysql_path
|
self.mysql_root['x86'] = builder.options.mysql_path
|
||||||
else:
|
else:
|
||||||
for i in range(7):
|
for i in range(10):
|
||||||
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
|
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
|
||||||
if self.mysql_root:
|
if self.mysql_root['x86']:
|
||||||
break
|
break
|
||||||
if not self.mysql_root or not os.path.isdir(self.mysql_root):
|
if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
|
||||||
raise Exception('Could not find a path to MySQL!')
|
raise Exception('Could not find a path to MySQL!')
|
||||||
self.mysql_root = Normalize(self.mysql_root)
|
self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
|
||||||
|
|
||||||
|
# For now, ignore 64-bit MySQL on Windows
|
||||||
|
if 'x64' in self.archs and builder.target.platform != 'windows':
|
||||||
|
if builder.options.mysql64_path:
|
||||||
|
self.mysql_root['x64'] = builder.options.mysql64_path
|
||||||
|
else:
|
||||||
|
for i in range(10):
|
||||||
|
self.mysql_root['x64'] = ResolveEnvPath('MYSQL55_64', 'mysql-5.' + str(i) + '-x86_64')
|
||||||
|
if self.mysql_root['x64']:
|
||||||
|
break
|
||||||
|
if not self.mysql_root['x64'] or not os.path.isdir(self.mysql_root['x64']):
|
||||||
|
raise Exception('Could not find a path to 64-bit MySQL!')
|
||||||
|
self.mysql_root['x64'] = Normalize(self.mysql_root['x64'])
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
builder.AddConfigureFile('pushbuild.txt')
|
builder.AddConfigureFile('pushbuild.txt')
|
||||||
|
|
||||||
cxx = builder.DetectCompilers()
|
if not set(self.archs).issubset(['x86', 'x64']):
|
||||||
|
raise Exception('Unknown target architecture: {0}'.format(builder.target.arch))
|
||||||
|
|
||||||
|
cxx = builder.DetectCxx()
|
||||||
|
|
||||||
|
if cxx.like('msvc') and len(self.archs) > 1:
|
||||||
|
raise Exception('Building multiple archs with MSVC is not currently supported')
|
||||||
|
|
||||||
if cxx.like('gcc'):
|
if cxx.like('gcc'):
|
||||||
|
self.configure_gcc(cxx)
|
||||||
|
elif cxx.family == 'msvc':
|
||||||
|
self.configure_msvc(cxx)
|
||||||
|
|
||||||
|
# Optimizaiton
|
||||||
|
if builder.options.opt == '1':
|
||||||
|
cxx.defines += ['NDEBUG']
|
||||||
|
|
||||||
|
# Debugging
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
cxx.defines += ['DEBUG', '_DEBUG']
|
||||||
|
|
||||||
|
# Platform-specifics
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
self.configure_linux(cxx)
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
self.configure_mac(cxx)
|
||||||
|
elif builder.target.platform == 'windows':
|
||||||
|
self.configure_windows(cxx)
|
||||||
|
|
||||||
|
# Finish up.
|
||||||
|
cxx.defines += [
|
||||||
|
'SOURCEMOD_BUILD',
|
||||||
|
'SM_USE_VERSIONLIB',
|
||||||
|
]
|
||||||
|
cxx.includes += [
|
||||||
|
os.path.join(builder.sourcePath, 'public'),
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
cxx.defines += ['SM_GENERATED_BUILD']
|
||||||
|
cxx.includes += [
|
||||||
|
os.path.join(builder.buildPath, 'includes'),
|
||||||
|
os.path.join(builder.sourcePath, 'versionlib'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def configure_gcc(self, cxx):
|
||||||
cxx.defines += [
|
cxx.defines += [
|
||||||
'stricmp=strcasecmp',
|
'stricmp=strcasecmp',
|
||||||
'_stricmp=strcasecmp',
|
'_stricmp=strcasecmp',
|
||||||
@ -169,23 +268,35 @@ class SMConfig(object):
|
|||||||
'-Wno-switch',
|
'-Wno-switch',
|
||||||
'-Wno-array-bounds',
|
'-Wno-array-bounds',
|
||||||
'-msse',
|
'-msse',
|
||||||
'-m32',
|
'-fvisibility=hidden',
|
||||||
]
|
]
|
||||||
cxx.cxxflags += [
|
cxx.cxxflags += [
|
||||||
'-std=c++11',
|
'-std=c++11',
|
||||||
|
'-fno-exceptions',
|
||||||
|
'-fno-threadsafe-statics',
|
||||||
|
'-Wno-non-virtual-dtor',
|
||||||
|
'-Wno-overloaded-virtual',
|
||||||
|
'-fvisibility-inlines-hidden',
|
||||||
]
|
]
|
||||||
|
|
||||||
have_gcc = cxx.vendor == 'gcc'
|
have_gcc = cxx.family == 'gcc'
|
||||||
have_clang = cxx.vendor == 'clang'
|
have_clang = cxx.family == 'clang'
|
||||||
if have_clang or (have_gcc and cxx.version >= '4'):
|
if cxx.version >= 'clang-3.9':
|
||||||
cxx.cflags += ['-fvisibility=hidden']
|
cxx.cxxflags += ['-Wno-expansion-to-defined']
|
||||||
cxx.cxxflags += ['-fvisibility-inlines-hidden']
|
if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
|
||||||
if have_clang or (have_gcc and cxx.version >= '4.6'):
|
cxx.cflags += ['-Wno-varargs']
|
||||||
|
if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0':
|
||||||
|
cxx.cxxflags += ['-Wno-inconsistent-missing-override']
|
||||||
|
if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
|
||||||
|
cxx.cxxflags += ['-Wno-null-dereference']
|
||||||
|
if have_clang or (cxx.version >= 'gcc-4.6'):
|
||||||
cxx.cflags += ['-Wno-narrowing']
|
cxx.cflags += ['-Wno-narrowing']
|
||||||
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
|
if have_clang or (cxx.version >= 'gcc-4.7'):
|
||||||
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||||
if have_gcc and cxx.version >= '4.8':
|
if cxx.version >= 'gcc-4.8':
|
||||||
cxx.cflags += ['-Wno-unused-result']
|
cxx.cflags += ['-Wno-unused-result']
|
||||||
|
if cxx.version >= 'gcc-9.0':
|
||||||
|
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
|
||||||
if have_clang:
|
if have_clang:
|
||||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||||
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
||||||
@ -194,17 +305,14 @@ class SMConfig(object):
|
|||||||
cxx.cxxflags += ['-Wno-deprecated']
|
cxx.cxxflags += ['-Wno-deprecated']
|
||||||
cxx.cflags += ['-Wno-sometimes-uninitialized']
|
cxx.cflags += ['-Wno-sometimes-uninitialized']
|
||||||
|
|
||||||
cxx.linkflags += ['-m32']
|
|
||||||
cxx.cxxflags += [
|
|
||||||
'-fno-exceptions',
|
|
||||||
'-fno-threadsafe-statics',
|
|
||||||
'-Wno-non-virtual-dtor',
|
|
||||||
'-Wno-overloaded-virtual',
|
|
||||||
]
|
|
||||||
|
|
||||||
if have_gcc:
|
if have_gcc:
|
||||||
cxx.cflags += ['-mfpmath=sse']
|
cxx.cflags += ['-mfpmath=sse']
|
||||||
elif cxx.vendor == 'msvc':
|
cxx.cflags += ['-Wno-maybe-uninitialized']
|
||||||
|
|
||||||
|
if builder.options.opt == '1':
|
||||||
|
cxx.cflags += ['-O3']
|
||||||
|
|
||||||
|
def configure_msvc(self, cxx):
|
||||||
if builder.options.debug == '1':
|
if builder.options.debug == '1':
|
||||||
cxx.cflags += ['/MTd']
|
cxx.cflags += ['/MTd']
|
||||||
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
||||||
@ -216,8 +324,6 @@ class SMConfig(object):
|
|||||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||||
'_ITERATOR_DEBUG_LEVEL=0',
|
'_ITERATOR_DEBUG_LEVEL=0',
|
||||||
]
|
]
|
||||||
if cxx.version < 1800:
|
|
||||||
cxx.defines += 'strtoull=_strtoui64'
|
|
||||||
cxx.cflags += [
|
cxx.cflags += [
|
||||||
'/W3',
|
'/W3',
|
||||||
]
|
]
|
||||||
@ -227,8 +333,6 @@ class SMConfig(object):
|
|||||||
'/TP',
|
'/TP',
|
||||||
]
|
]
|
||||||
cxx.linkflags += [
|
cxx.linkflags += [
|
||||||
'/MACHINE:X86',
|
|
||||||
'/SUBSYSTEM:WINDOWS',
|
|
||||||
'kernel32.lib',
|
'kernel32.lib',
|
||||||
'user32.lib',
|
'user32.lib',
|
||||||
'gdi32.lib',
|
'gdi32.lib',
|
||||||
@ -243,58 +347,40 @@ class SMConfig(object):
|
|||||||
'odbccp32.lib',
|
'odbccp32.lib',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Optimization
|
|
||||||
if builder.options.opt == '1':
|
if builder.options.opt == '1':
|
||||||
cxx.defines += ['NDEBUG']
|
|
||||||
if cxx.like('gcc'):
|
|
||||||
cxx.cflags += ['-O3']
|
|
||||||
elif cxx.like('msvc'):
|
|
||||||
cxx.cflags += ['/Ox', '/Zo']
|
cxx.cflags += ['/Ox', '/Zo']
|
||||||
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
||||||
|
|
||||||
# Debugging
|
|
||||||
if builder.options.debug == '1':
|
if builder.options.debug == '1':
|
||||||
cxx.defines += ['DEBUG', '_DEBUG']
|
|
||||||
if cxx.like('msvc'):
|
|
||||||
cxx.cflags += ['/Od', '/RTC1']
|
cxx.cflags += ['/Od', '/RTC1']
|
||||||
|
|
||||||
# This needs to be after our optimization flags which could otherwise disable it.
|
# This needs to be after our optimization flags which could otherwise disable it.
|
||||||
if cxx.vendor == 'msvc':
|
|
||||||
# Don't omit the frame pointer.
|
# Don't omit the frame pointer.
|
||||||
cxx.cflags += ['/Oy-']
|
cxx.cflags += ['/Oy-']
|
||||||
|
|
||||||
# Platform-specifics
|
def configure_linux(self, cxx):
|
||||||
if builder.target_platform == 'linux':
|
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
|
||||||
cxx.defines += ['_LINUX', 'POSIX']
|
cxx.linkflags += ['-lm']
|
||||||
if cxx.vendor == 'gcc':
|
if cxx.family == 'gcc':
|
||||||
cxx.linkflags += ['-static-libgcc']
|
cxx.linkflags += ['-static-libgcc']
|
||||||
elif cxx.vendor == 'clang':
|
elif cxx.family == 'clang':
|
||||||
cxx.linkflags += ['-lgcc_eh']
|
cxx.linkflags += ['-lgcc_eh']
|
||||||
elif builder.target_platform == 'mac':
|
|
||||||
cxx.defines += ['OSX', '_OSX', 'POSIX']
|
def configure_mac(self, cxx):
|
||||||
|
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
|
||||||
cxx.cflags += ['-mmacosx-version-min=10.5']
|
cxx.cflags += ['-mmacosx-version-min=10.5']
|
||||||
cxx.linkflags += [
|
cxx.linkflags += [
|
||||||
'-mmacosx-version-min=10.5',
|
'-mmacosx-version-min=10.5',
|
||||||
'-arch', 'i386',
|
|
||||||
'-lstdc++',
|
'-lstdc++',
|
||||||
'-stdlib=libstdc++',
|
'-stdlib=libstdc++',
|
||||||
]
|
]
|
||||||
cxx.cxxflags += ['-stdlib=libstdc++']
|
cxx.cxxflags += ['-stdlib=libstdc++']
|
||||||
elif builder.target_platform == 'windows':
|
|
||||||
|
def configure_windows(self, cxx):
|
||||||
cxx.defines += ['WIN32', '_WINDOWS']
|
cxx.defines += ['WIN32', '_WINDOWS']
|
||||||
|
|
||||||
# Finish up.
|
def AddVersioning(self, binary, arch):
|
||||||
cxx.defines += [
|
if builder.target.platform == 'windows':
|
||||||
'SOURCEMOD_BUILD',
|
|
||||||
'SM_USE_VERSIONLIB',
|
|
||||||
]
|
|
||||||
if self.use_auto_versioning():
|
|
||||||
cxx.defines += ['SM_GENERATED_BUILD']
|
|
||||||
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
|
|
||||||
cxx.includes += [os.path.join(builder.sourcePath, 'versionlib')]
|
|
||||||
|
|
||||||
def AddVersioning(self, binary):
|
|
||||||
if builder.target_platform == 'windows':
|
|
||||||
binary.sources += ['version.rc']
|
binary.sources += ['version.rc']
|
||||||
binary.compiler.rcdefines += [
|
binary.compiler.rcdefines += [
|
||||||
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
||||||
@ -302,52 +388,83 @@ class SMConfig(object):
|
|||||||
]
|
]
|
||||||
if self.use_auto_versioning():
|
if self.use_auto_versioning():
|
||||||
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
|
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
|
||||||
elif builder.target_platform == 'mac':
|
elif builder.target.platform == 'mac':
|
||||||
if binary.type == 'library':
|
if binary.type == 'library':
|
||||||
binary.compiler.postlink += [
|
binary.compiler.postlink += [
|
||||||
'-compatibility_version', '1.0.0',
|
'-compatibility_version', '1.0.0',
|
||||||
'-current_version', self.productVersion
|
'-current_version', self.productVersion
|
||||||
]
|
]
|
||||||
if self.use_auto_versioning():
|
if self.use_auto_versioning():
|
||||||
binary.compiler.linkflags += [self.versionlib]
|
binary.compiler.linkflags += [self.versionlib[arch]]
|
||||||
binary.compiler.sourcedeps += SM.generated_headers
|
binary.compiler.sourcedeps += SM.generated_headers
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
def Library(self, context, name):
|
def LibraryBuilder(self, compiler, name, arch):
|
||||||
binary = context.compiler.Library(name)
|
binary = compiler.Library(name)
|
||||||
return self.AddVersioning(binary)
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
self.AddVersioning(binary, arch)
|
||||||
|
if binary.compiler.like('msvc'):
|
||||||
|
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
|
||||||
|
return binary
|
||||||
|
|
||||||
def Program(self, context, name):
|
def ProgramBuilder(self, compiler, name, arch):
|
||||||
binary = context.compiler.Program(name)
|
binary = compiler.Program(name)
|
||||||
return self.AddVersioning(binary)
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
self.AddVersioning(binary, arch)
|
||||||
|
if '-static-libgcc' in binary.compiler.linkflags:
|
||||||
|
binary.compiler.linkflags.remove('-static-libgcc')
|
||||||
|
if '-lgcc_eh' in binary.compiler.linkflags:
|
||||||
|
binary.compiler.linkflags.remove('-lgcc_eh')
|
||||||
|
if binary.compiler.like('gcc'):
|
||||||
|
binary.compiler.linkflags += ['-lstdc++', '-lpthread']
|
||||||
|
if binary.compiler.like('msvc'):
|
||||||
|
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def StaticLibraryBuilder(self, compiler, name, arch):
|
||||||
|
binary = compiler.StaticLibrary(name)
|
||||||
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
return binary;
|
||||||
|
|
||||||
|
def Library(self, context, name, arch):
|
||||||
|
compiler = context.cxx.clone()
|
||||||
|
SetArchFlags(compiler, arch, builder.target.platform)
|
||||||
|
return self.LibraryBuilder(compiler, name, arch)
|
||||||
|
|
||||||
|
def Program(self, context, name, arch):
|
||||||
|
compiler = context.cxx.clone()
|
||||||
|
SetArchFlags(compiler, arch, builder.target.platform)
|
||||||
|
return self.ProgramBuilder(compiler, name, arch)
|
||||||
|
|
||||||
|
def StaticLibrary(self, context, name, arch):
|
||||||
|
compiler = context.cxx.clone()
|
||||||
|
SetArchFlags(compiler, arch, builder.target.platform)
|
||||||
|
return self.StaticLibraryBuilder(compiler, name, arch)
|
||||||
|
|
||||||
def ConfigureForExtension(self, context, compiler):
|
def ConfigureForExtension(self, context, compiler):
|
||||||
compiler.cxxincludes += [
|
compiler.cxxincludes += [
|
||||||
os.path.join(context.currentSourcePath),
|
os.path.join(context.currentSourcePath),
|
||||||
os.path.join(context.currentSourcePath, 'sdk'),
|
os.path.join(context.currentSourcePath, 'sdk'),
|
||||||
os.path.join(builder.sourcePath, 'public'),
|
|
||||||
os.path.join(builder.sourcePath, 'public', 'extensions'),
|
os.path.join(builder.sourcePath, 'public', 'extensions'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
]
|
]
|
||||||
return compiler
|
return compiler
|
||||||
|
|
||||||
def ExtLibrary(self, context, name):
|
def ExtLibrary(self, context, name, arch):
|
||||||
binary = context.compiler.Library(name)
|
binary = self.Library(context, name, arch)
|
||||||
self.ConfigureForExtension(context, binary.compiler)
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
return self.AddVersioning(binary)
|
return binary
|
||||||
|
|
||||||
def ConfigureForHL2(self, binary, sdk):
|
def ConfigureForHL2(self, binary, sdk, arch):
|
||||||
compiler = binary.compiler
|
compiler = binary.compiler
|
||||||
|
|
||||||
if sdk.name == 'episode1':
|
SetArchFlags(compiler, arch, builder.target.platform)
|
||||||
mms_path = os.path.join(self.mms_root, 'core-legacy')
|
|
||||||
else:
|
|
||||||
mms_path = os.path.join(self.mms_root, 'core')
|
|
||||||
|
|
||||||
compiler.cxxincludes += [
|
compiler.cxxincludes += [
|
||||||
os.path.join(mms_path),
|
os.path.join(self.mms_root, 'core'),
|
||||||
os.path.join(mms_path, 'sourcehook'),
|
os.path.join(self.mms_root, 'core', 'sourcehook'),
|
||||||
]
|
]
|
||||||
|
|
||||||
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
|
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
|
||||||
@ -372,7 +489,7 @@ class SMConfig(object):
|
|||||||
|
|
||||||
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
|
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
|
||||||
|
|
||||||
if sdk.name == 'sdk2013' and compiler.like('gcc'):
|
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
|
||||||
# The 2013 SDK already has these in public/tier0/basetypes.h
|
# The 2013 SDK already has these in public/tier0/basetypes.h
|
||||||
compiler.defines.remove('stricmp=strcasecmp')
|
compiler.defines.remove('stricmp=strcasecmp')
|
||||||
compiler.defines.remove('_stricmp=strcasecmp')
|
compiler.defines.remove('_stricmp=strcasecmp')
|
||||||
@ -381,39 +498,49 @@ class SMConfig(object):
|
|||||||
|
|
||||||
if compiler.like('msvc'):
|
if compiler.like('msvc'):
|
||||||
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
|
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
|
||||||
|
if compiler.version >= 1900:
|
||||||
|
compiler.linkflags += ['legacy_stdio_definitions.lib']
|
||||||
else:
|
else:
|
||||||
compiler.defines += ['COMPILER_GCC']
|
compiler.defines += ['COMPILER_GCC']
|
||||||
|
|
||||||
|
if arch == 'x64':
|
||||||
|
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
|
||||||
|
|
||||||
# For everything after Swarm, this needs to be defined for entity networking
|
# For everything after Swarm, this needs to be defined for entity networking
|
||||||
# to work properly with sendprop value changes.
|
# to work properly with sendprop value changes.
|
||||||
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
|
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
|
||||||
compiler.defines += ['NETWORK_VARS_ENABLED']
|
compiler.defines += ['NETWORK_VARS_ENABLED']
|
||||||
|
|
||||||
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
|
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2']:
|
||||||
if builder.target_platform in ['linux', 'mac']:
|
if builder.target.platform in ['linux', 'mac']:
|
||||||
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
||||||
|
|
||||||
if sdk.name == 'csgo' and builder.target_platform == 'linux':
|
if sdk.name == 'csgo' and builder.target.platform == 'linux':
|
||||||
compiler.linkflags += ['-lstdc++']
|
compiler.linkflags += ['-lstdc++']
|
||||||
|
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
|
||||||
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
||||||
|
|
||||||
if builder.target_platform == 'linux':
|
if builder.target.platform == 'linux':
|
||||||
if sdk.name == 'episode1':
|
if sdk.name == 'episode1':
|
||||||
lib_folder = os.path.join(sdk.path, 'linux_sdk')
|
lib_folder = os.path.join(sdk.path, 'linux_sdk')
|
||||||
elif sdk.name == 'sdk2013':
|
elif sdk.name in ['sdk2013', 'bms']:
|
||||||
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
|
||||||
|
elif arch == 'x64':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
|
||||||
else:
|
else:
|
||||||
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
|
||||||
elif builder.target_platform == 'mac':
|
elif builder.target.platform == 'mac':
|
||||||
if sdk.name == 'sdk2013':
|
if sdk.name in ['sdk2013', 'bms']:
|
||||||
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
|
||||||
|
elif arch == 'x64':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'osx64')
|
||||||
else:
|
else:
|
||||||
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
|
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
|
||||||
|
|
||||||
if builder.target_platform in ['linux', 'mac']:
|
if builder.target.platform in ['linux', 'mac']:
|
||||||
if sdk.name == 'sdk2013':
|
if sdk.name in ['sdk2013', 'bms'] or arch == 'x64':
|
||||||
compiler.postlink += [
|
compiler.postlink += [
|
||||||
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
|
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
|
||||||
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
|
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
|
||||||
@ -424,26 +551,28 @@ class SMConfig(object):
|
|||||||
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
|
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
|
||||||
]
|
]
|
||||||
|
|
||||||
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
|
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
|
||||||
|
if arch == 'x64':
|
||||||
|
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces.a'))]
|
||||||
|
else:
|
||||||
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
|
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
|
||||||
|
|
||||||
self.AddVersioning(binary)
|
|
||||||
|
|
||||||
dynamic_libs = []
|
dynamic_libs = []
|
||||||
if builder.target_platform == 'linux':
|
if builder.target.platform == 'linux':
|
||||||
compiler.linkflags[0:0] = ['-lm']
|
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']:
|
||||||
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'nucleardawn', 'l4d2']:
|
|
||||||
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
|
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
|
||||||
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
|
elif arch == 'x64' and sdk.name == 'csgo':
|
||||||
|
dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so']
|
||||||
|
elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']:
|
||||||
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
|
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
|
||||||
else:
|
else:
|
||||||
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
|
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
|
||||||
elif builder.target_platform == 'mac':
|
elif builder.target.platform == 'mac':
|
||||||
compiler.linkflags.append('-liconv')
|
compiler.linkflags.append('-liconv')
|
||||||
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
|
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
|
||||||
elif builder.target_platform == 'windows':
|
elif builder.target.platform == 'windows':
|
||||||
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||||
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
|
if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']:
|
||||||
libs.append('interfaces')
|
libs.append('interfaces')
|
||||||
for lib in libs:
|
for lib in libs:
|
||||||
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
||||||
@ -464,19 +593,21 @@ class SMConfig(object):
|
|||||||
|
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
def HL2Library(self, context, name, sdk):
|
def HL2Library(self, context, name, sdk, arch):
|
||||||
binary = context.compiler.Library(name)
|
binary = self.Library(context, name, arch)
|
||||||
self.ConfigureForExtension(context, binary.compiler)
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
return self.ConfigureForHL2(binary, sdk)
|
return self.ConfigureForHL2(binary, sdk, arch)
|
||||||
|
|
||||||
def HL2Project(self, context, name):
|
def HL2Project(self, context, name):
|
||||||
project = context.compiler.LibraryProject(name)
|
project = context.cxx.LibraryProject(name)
|
||||||
self.ConfigureForExtension(context, project.compiler)
|
self.ConfigureForExtension(context, project.compiler)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
def HL2Config(self, project, name, sdk):
|
def HL2Config(self, project, name, sdk, arch):
|
||||||
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
|
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
|
||||||
return self.ConfigureForHL2(binary, sdk)
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
self.AddVersioning(binary, arch)
|
||||||
|
return self.ConfigureForHL2(binary, sdk, arch)
|
||||||
|
|
||||||
SM = SMConfig()
|
SM = SMConfig()
|
||||||
SM.detectProductVersion()
|
SM.detectProductVersion()
|
||||||
@ -484,15 +615,31 @@ SM.detectSDKs()
|
|||||||
SM.configure()
|
SM.configure()
|
||||||
|
|
||||||
if SM.use_auto_versioning():
|
if SM.use_auto_versioning():
|
||||||
SM.generated_headers = builder.RunScript(
|
SM.generated_headers = builder.Build(
|
||||||
'tools/buildbot/Versioning',
|
'tools/buildbot/Versioning',
|
||||||
{ 'SM': SM }
|
{ 'SM': SM }
|
||||||
)
|
)
|
||||||
SM.versionlib = builder.RunScript(
|
SM.versionlib = builder.Build(
|
||||||
'versionlib/AMBuilder',
|
'versionlib/AMBuilder',
|
||||||
{ 'SM': SM }
|
{ 'SM': SM }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Build SourcePawn externally.
|
||||||
|
SP = builder.Build('sourcepawn/AMBuildScript', {
|
||||||
|
'external_root': SM,
|
||||||
|
'external_amtl': os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
|
'external_build': ['core'],
|
||||||
|
})
|
||||||
|
if len(SP.spcomp) > 1:
|
||||||
|
SM.spcomp = SP.spcomp['x86']
|
||||||
|
else:
|
||||||
|
SM.spcomp = SP.spcomp[list(SP.spcomp.keys())[0]]
|
||||||
|
SM.spcomp_bins = list(SP.spcomp.values())
|
||||||
|
for arch in SM.archs:
|
||||||
|
SM.binaries += [
|
||||||
|
SP.libsourcepawn[arch]
|
||||||
|
]
|
||||||
|
|
||||||
BuildScripts = [
|
BuildScripts = [
|
||||||
'loader/AMBuilder',
|
'loader/AMBuilder',
|
||||||
'core/AMBuilder',
|
'core/AMBuilder',
|
||||||
@ -510,8 +657,6 @@ BuildScripts = [
|
|||||||
'extensions/tf2/AMBuilder',
|
'extensions/tf2/AMBuilder',
|
||||||
'extensions/topmenus/AMBuilder',
|
'extensions/topmenus/AMBuilder',
|
||||||
'extensions/updater/AMBuilder',
|
'extensions/updater/AMBuilder',
|
||||||
'sourcepawn/compiler/AMBuilder',
|
|
||||||
'sourcepawn/jit/AMBuilder',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if builder.backend == 'amb2':
|
if builder.backend == 'amb2':
|
||||||
@ -520,7 +665,7 @@ if builder.backend == 'amb2':
|
|||||||
'tools/buildbot/PackageScript',
|
'tools/buildbot/PackageScript',
|
||||||
]
|
]
|
||||||
|
|
||||||
builder.RunBuildScripts(BuildScripts, { 'SM': SM })
|
builder.Build(BuildScripts, { 'SM': SM })
|
||||||
|
|
||||||
if builder.options.breakpad_dump:
|
if builder.options.breakpad_dump:
|
||||||
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
|
builder.Build('tools/buildbot/BreakpadSymbols', { 'SM': SM })
|
||||||
|
16
README.md
16
README.md
@ -6,12 +6,22 @@ General
|
|||||||
- [SourceMod website](http://www.sourcemod.net): Source Engine scripting and server administration
|
- [SourceMod website](http://www.sourcemod.net): Source Engine scripting and server administration
|
||||||
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=52): Discussion forum including plugin/extension development
|
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=52): Discussion forum including plugin/extension development
|
||||||
- [General documentation](https://wiki.alliedmods.net/Category:SourceMod_Documentation): Miscellaneous information about SourceMod
|
- [General documentation](https://wiki.alliedmods.net/Category:SourceMod_Documentation): Miscellaneous information about SourceMod
|
||||||
- [Latest release](http://www.sourcemod.net/downloads.php): The latest stable SourceMod release
|
- [Stable builds](http://www.sourcemod.net/downloads.php?branch=stable): The latest stable SourceMod releases
|
||||||
- [Build snapshots](http://www.sourcemod.net/snapshots.php): Builds of recent development versions
|
- [Dev builds](http://www.sourcemod.net/downloads.php?branch=dev): Builds of recent development versions
|
||||||
|
|
||||||
Development
|
Development
|
||||||
-----------
|
-----------
|
||||||
- [Issue tracker](https://bugs.alliedmods.net): Issues that require back and forth communication
|
- [Issue tracker](https://github.com/alliedmodders/sourcemod/issues): Issues that require back and forth communication
|
||||||
- [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild)
|
- [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild)
|
||||||
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
|
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
|
||||||
|
- [SourceMod plugin API](https://sm.alliedmods.net/new-api): Online SourceMod plugin API reference generated from the include files
|
||||||
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
|
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
- Connect with us on [GameSurge](https://gamesurge.net) IRC in #sourcemod
|
||||||
|
- Alternatively feel free to join our [Discord](https://discord.gg/HgZctSS) server
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
SourceMod is licensed under the GNU General Public License version 3. Special exceptions are outlined in the LICENSE.txt file inside of the licenses folder.
|
||||||
|
46
bridge/include/BridgeAPI.h
Normal file
46
bridge/include/BridgeAPI.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_API_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_API_H_
|
||||||
|
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
#include <bridge/include/LogicProvider.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
// Add 1 to the RHS of this expression to bump the intercom file
|
||||||
|
// This is to prevent mismatching core/logic binaries
|
||||||
|
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 57;
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
typedef void (*LogicInitFunction)(SourceMod::CoreProvider *core, SourceMod::sm_logic_t *logic);
|
||||||
|
typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
|
||||||
|
typedef SourceMod::ITextParsers *(*GetITextParsers)();
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_API_H_
|
140
bridge/include/CoreProvider.h
Normal file
140
bridge/include/CoreProvider.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CORE_PROVIDER_API_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CORE_PROVIDER_API_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <IAdminSystem.h>
|
||||||
|
#include <amtl/am-function.h>
|
||||||
|
|
||||||
|
namespace SourcePawn {
|
||||||
|
class ISourcePawnEngine;
|
||||||
|
class ISourcePawnEngine2;
|
||||||
|
} // namespace SourcePawn
|
||||||
|
|
||||||
|
// SDK types.
|
||||||
|
#if defined(SM_LOGIC)
|
||||||
|
class ConCommandBase {};
|
||||||
|
class ConVar : public ConCommandBase {};
|
||||||
|
#else
|
||||||
|
class ConCommandBase;
|
||||||
|
class ConVar;
|
||||||
|
#endif
|
||||||
|
class KeyValues;
|
||||||
|
|
||||||
|
struct ServerGlobals
|
||||||
|
{
|
||||||
|
const double *universalTime;
|
||||||
|
float *interval_per_tick;
|
||||||
|
float *frametime;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
class ISourceMod;
|
||||||
|
class IVEngineServerBridge;
|
||||||
|
class IFileSystemBridge;
|
||||||
|
class ITimerSystem;
|
||||||
|
class IPlayerManager;
|
||||||
|
class IGameHelpers;
|
||||||
|
class IMenuManager;
|
||||||
|
struct DatabaseInfo;
|
||||||
|
class IPlayerInfoBridge;
|
||||||
|
class ICommandArgs;
|
||||||
|
|
||||||
|
typedef ke::Lambda<bool(int client, const ICommandArgs*)> CommandFunc;
|
||||||
|
|
||||||
|
class CoreProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* Objects */
|
||||||
|
ISourceMod *sm;
|
||||||
|
IVEngineServerBridge *engine;
|
||||||
|
IFileSystemBridge *filesystem;
|
||||||
|
IPlayerInfoBridge *playerInfo;
|
||||||
|
ITimerSystem *timersys;
|
||||||
|
IPlayerManager *playerhelpers;
|
||||||
|
IGameHelpers *gamehelpers;
|
||||||
|
IMenuManager *menus;
|
||||||
|
SourcePawn::ISourcePawnEngine **spe1;
|
||||||
|
SourcePawn::ISourcePawnEngine2 **spe2;
|
||||||
|
const char *gamesuffix;
|
||||||
|
/* Data */
|
||||||
|
ServerGlobals *serverGlobals;
|
||||||
|
void * serverFactory;
|
||||||
|
void * engineFactory;
|
||||||
|
void * matchmakingDSFactory;
|
||||||
|
SMGlobalClass * listeners;
|
||||||
|
|
||||||
|
// ConVar functions.
|
||||||
|
virtual ConVar *FindConVar(const char *name) = 0;
|
||||||
|
virtual const char *GetCvarString(ConVar *cvar) = 0;
|
||||||
|
virtual bool GetCvarBool(ConVar* cvar) = 0;
|
||||||
|
|
||||||
|
// Command functions.
|
||||||
|
virtual void DefineCommand(const char *cmd, const char *help, const CommandFunc &callback) = 0;
|
||||||
|
|
||||||
|
// Game description functions.
|
||||||
|
virtual bool GetGameName(char *buffer, size_t maxlength) = 0;
|
||||||
|
virtual const char *GetGameDescription() = 0;
|
||||||
|
virtual const char *GetSourceEngineName() = 0;
|
||||||
|
virtual bool SymbolsAreHidden() = 0;
|
||||||
|
|
||||||
|
// Game state and helper functions.
|
||||||
|
virtual bool IsMapLoading() = 0;
|
||||||
|
virtual bool IsMapRunning() = 0;
|
||||||
|
virtual int MaxClients() = 0;
|
||||||
|
virtual bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) = 0;
|
||||||
|
virtual void LogToGame(const char *message) = 0;
|
||||||
|
virtual void ConPrint(const char *message) = 0;
|
||||||
|
virtual void ConsolePrint(const char *fmt, ...) = 0;
|
||||||
|
virtual void ConsolePrintVa(const char *fmt, va_list ap) = 0;
|
||||||
|
|
||||||
|
// Game engine helper functions.
|
||||||
|
virtual bool IsClientConVarQueryingSupported() = 0;
|
||||||
|
virtual int QueryClientConVar(int client, const char *cvar) = 0;
|
||||||
|
|
||||||
|
// Metamod:Source functions.
|
||||||
|
virtual int LoadMMSPlugin(const char *file, bool *ok, char *error, size_t maxlength) = 0;
|
||||||
|
virtual void UnloadMMSPlugin(int id) = 0;
|
||||||
|
|
||||||
|
const char * (*GetCoreConfigValue)(const char*);
|
||||||
|
void (*DoGlobalPluginLoads)();
|
||||||
|
bool (*AreConfigsExecuted)();
|
||||||
|
void (*ExecuteConfigs)(IPluginContext *ctx);
|
||||||
|
void (*GetDBInfoFromKeyValues)(KeyValues *, DatabaseInfo *);
|
||||||
|
int (*GetActivityFlags)();
|
||||||
|
int (*GetImmunityMode)();
|
||||||
|
void (*UpdateAdminCmdFlags)(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||||
|
bool (*LookForCommandAdminFlags)(const char *cmd, FlagBits *pFlags);
|
||||||
|
int (*GetGlobalTarget)();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_CORE_PROVIDER_API_H_
|
81
bridge/include/IExtensionBridge.h
Normal file
81
bridge/include/IExtensionBridge.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IEXTBRIDGE_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IEXTBRIDGE_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
#include <IExtensionSys.h>
|
||||||
|
#include <sh_vector.h>
|
||||||
|
|
||||||
|
struct edict_t;
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
using namespace SourceHook;
|
||||||
|
using namespace SourcePawn;
|
||||||
|
class SMPlugin;
|
||||||
|
|
||||||
|
class IExtensionSys : public IExtensionManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IExtension *LoadAutoExtension(const char *name, bool bErrorOnMissing=true) = 0;
|
||||||
|
virtual void TryAutoload() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
virtual IExtension *FindExtensionByFile(const char *name) = 0;
|
||||||
|
virtual bool LibraryExists(const char *name) = 0;
|
||||||
|
virtual void CallOnCoreMapStart(edict_t *edictList, int edictCount, int maxClients) = 0;
|
||||||
|
virtual IExtension *GetExtensionFromIdent(IdentityToken_t *token) = 0;
|
||||||
|
virtual void BindChildPlugin(IExtension *ext, SMPlugin *plugin) = 0;
|
||||||
|
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
|
||||||
|
virtual const CVector<IExtension *> *ListExtensions() = 0;
|
||||||
|
virtual void FreeExtensionList(const CVector<IExtension *> *list) = 0;
|
||||||
|
virtual void CallOnCoreMapEnd() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoExtensionList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutoExtensionList(IExtensionSys *extensions)
|
||||||
|
: extensions_(extensions), list_(extensions_->ListExtensions())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~AutoExtensionList()
|
||||||
|
{
|
||||||
|
extensions_->FreeExtensionList(list_);
|
||||||
|
}
|
||||||
|
const CVector<IExtension *> *operator ->()
|
||||||
|
{
|
||||||
|
return list_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
IExtensionSys *extensions_;
|
||||||
|
const CVector<IExtension *> *list_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IEXTBRIDGE_H_
|
63
bridge/include/IFileSystemBridge.h
Normal file
63
bridge/include/IFileSystemBridge.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_IFILESYSTEM_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_IFILESYSTEM_H_
|
||||||
|
|
||||||
|
typedef void * FileHandle_t;
|
||||||
|
typedef int FileFindHandle_t;
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
class IFileSystemBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
|
||||||
|
virtual const char *FindNext(FileFindHandle_t handle) = 0;
|
||||||
|
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
|
||||||
|
virtual void FindClose(FileFindHandle_t handle) = 0;
|
||||||
|
virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0;
|
||||||
|
virtual void Close(FileHandle_t file) = 0;
|
||||||
|
virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) = 0;
|
||||||
|
virtual bool EndOfFile(FileHandle_t file) = 0;
|
||||||
|
virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0;
|
||||||
|
virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0;
|
||||||
|
virtual int Read(void* pOutput, int size, FileHandle_t file) = 0;
|
||||||
|
virtual int Write(void const* pInput, int size, FileHandle_t file) = 0;
|
||||||
|
virtual void Seek(FileHandle_t file, int post, int seekType) = 0;
|
||||||
|
virtual unsigned int Tell(FileHandle_t file) = 0;
|
||||||
|
virtual int FPrint(FileHandle_t file, const char *pData) = 0;
|
||||||
|
virtual void Flush(FileHandle_t file) = 0;
|
||||||
|
virtual bool IsOk(FileHandle_t file) = 0;
|
||||||
|
virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0;
|
||||||
|
virtual void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID = 0) = 0;
|
||||||
|
virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0;
|
||||||
|
virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_IFILESYSTEM_H_
|
43
bridge/include/ILogger.h
Normal file
43
bridge/include/ILogger.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_LOGGER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_LOGGER_H_
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
class ILogger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void LogMessage(const char *msg, ...) = 0;
|
||||||
|
virtual void LogError(const char *msg, ...) = 0;
|
||||||
|
virtual void LogFatal(const char *msg, ...) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_LOGGER_H_
|
||||||
|
|
55
bridge/include/IPlayerInfoBridge.h
Normal file
55
bridge/include/IPlayerInfoBridge.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPLAYERINFO_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPLAYERINFO_H_
|
||||||
|
|
||||||
|
class IPlayerInfo;
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
class IPlayerInfoBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool IsObserver(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual int GetTeamIndex(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual int GetFragCount(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual int GetDeathCount(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual int GetArmorValue(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual void GetAbsOrigin(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
|
||||||
|
virtual void GetAbsAngles(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
|
||||||
|
virtual void GetPlayerMins(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
|
||||||
|
virtual void GetPlayerMaxs(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
|
||||||
|
virtual const char *GetWeaponName(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual const char *GetModelName(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual int GetHealth(IPlayerInfo *pInfo) = 0;
|
||||||
|
virtual void ChangeTeam(IPlayerInfo *pInfo, int iTeamNum) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPLAYERINFO_H_
|
||||||
|
|
45
bridge/include/IProviderCallbacks.h
Normal file
45
bridge/include/IProviderCallbacks.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
// Global callbacks provided to Core.
|
||||||
|
class IProviderCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Called when a log message is printed. Return true to supercede.
|
||||||
|
virtual bool OnLogPrint(const char *msg) = 0;
|
||||||
|
|
||||||
|
// Called each frame tick.
|
||||||
|
virtual void OnThink(bool simulating) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_
|
112
bridge/include/IScriptManager.h
Normal file
112
bridge/include/IScriptManager.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
#include <IPluginSys.h>
|
||||||
|
#include <sh_vector.h>
|
||||||
|
#include <sh_string.h>
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
using namespace SourceHook;
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
class IChangeableForward;
|
||||||
|
|
||||||
|
enum LibraryAction
|
||||||
|
{
|
||||||
|
LibraryAction_Removed,
|
||||||
|
LibraryAction_Added
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AutoConfig
|
||||||
|
{
|
||||||
|
SourceHook::String autocfg;
|
||||||
|
SourceHook::String folder;
|
||||||
|
bool create;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SMPlugin : public IPlugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual size_t GetConfigCount() = 0;
|
||||||
|
virtual AutoConfig *GetConfig(size_t i) = 0;
|
||||||
|
virtual void AddLibrary(const char *name) = 0;
|
||||||
|
virtual void AddConfig(bool create, const char *cfg, const char *folder) = 0;
|
||||||
|
virtual void EvictWithError(PluginStatus status, const char *fmt, ...) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IScriptManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void LoadAll(const char *config_path, const char *plugins_path) = 0;
|
||||||
|
virtual void RefreshAll() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
virtual IdentityToken_t *GetIdentity() = 0;
|
||||||
|
virtual void SyncMaxClients(int maxClients) = 0;
|
||||||
|
virtual void AddPluginsListener(IPluginsListener *listener) = 0;
|
||||||
|
virtual void RemovePluginsListener(IPluginsListener *listener) = 0;
|
||||||
|
virtual IPluginIterator *GetPluginIterator() = 0;
|
||||||
|
virtual void OnLibraryAction(const char *name, LibraryAction action) = 0;
|
||||||
|
virtual bool LibraryExists(const char *name) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByOrder(unsigned num) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByIdentity(IdentityToken_t *ident) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByContext(IPluginContext *ctx) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByContext(sp_context_t *ctx) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByConsoleArg(const char *text) = 0;
|
||||||
|
virtual SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) = 0;
|
||||||
|
virtual bool UnloadPlugin(IPlugin *plugin) = 0;
|
||||||
|
virtual const CVector<SMPlugin *> *ListPlugins() = 0;
|
||||||
|
virtual void FreePluginList(const CVector<SMPlugin *> *list) = 0;
|
||||||
|
virtual void AddFunctionsToForward(const char *name, IChangeableForward *fwd) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoPluginList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutoPluginList(IScriptManager *scripts)
|
||||||
|
: scripts_(scripts), list_(scripts->ListPlugins())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~AutoPluginList()
|
||||||
|
{
|
||||||
|
scripts_->FreePluginList(list_);
|
||||||
|
}
|
||||||
|
const CVector<SMPlugin *> *operator ->()
|
||||||
|
{
|
||||||
|
return list_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
IScriptManager *scripts_;
|
||||||
|
const CVector<SMPlugin *> *list_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_
|
48
bridge/include/IVEngineServerBridge.h
Normal file
48
bridge/include/IVEngineServerBridge.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_BRIDGE_IVENGINESERVER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_BRIDGE_IVENGINESERVER_H_
|
||||||
|
|
||||||
|
struct edict_t;
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
class IVEngineServerBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool IsDedicatedServer() = 0;
|
||||||
|
virtual void InsertServerCommand(const char *cmd) = 0;
|
||||||
|
virtual void ServerCommand(const char *cmd) = 0;
|
||||||
|
virtual void ServerExecute() = 0;
|
||||||
|
virtual const char *GetClientConVarValue(int clientIndex, const char *name) = 0;
|
||||||
|
virtual void ClientCommand(edict_t *pEdict, const char *szCommand) = 0;
|
||||||
|
virtual void FakeClientCommand(edict_t *pEdict, const char *szCommand) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_BRIDGE_IVENGINESERVER_H_
|
92
bridge/include/LogicProvider.h
Normal file
92
bridge/include/LogicProvider.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_LOGIC_PROVIDER_API_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_LOGIC_PROVIDER_API_H_
|
||||||
|
|
||||||
|
#include <sp_vm_api.h>
|
||||||
|
|
||||||
|
class SMGlobalClass;
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
class CoreProvider;
|
||||||
|
class IThreader;
|
||||||
|
class ITranslator;
|
||||||
|
class IGameConfig;
|
||||||
|
class IScriptManager;
|
||||||
|
class IShareSys;
|
||||||
|
class IHandleSys;
|
||||||
|
class ICommandArgs;
|
||||||
|
class IForwardManager;
|
||||||
|
class IAdminSystem;
|
||||||
|
class IRootConsole;
|
||||||
|
class IProviderCallbacks;
|
||||||
|
class IExtensionSys;
|
||||||
|
class ITextParsers;
|
||||||
|
class ILogger;
|
||||||
|
class ICellArray;
|
||||||
|
|
||||||
|
struct sm_logic_t
|
||||||
|
{
|
||||||
|
SMGlobalClass *head;
|
||||||
|
IThreader *threader;
|
||||||
|
ITranslator *translator;
|
||||||
|
const char *(*stristr)(const char *, const char *);
|
||||||
|
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
|
||||||
|
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
|
||||||
|
void (*AddCorePhraseFile)(const char *filename);
|
||||||
|
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
|
||||||
|
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
|
||||||
|
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
|
||||||
|
IGameConfig * (*GetCoreGameConfig)();
|
||||||
|
IDebugListener *debugger;
|
||||||
|
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||||
|
void (*AddNatives)(sp_nativeinfo_t *natives);
|
||||||
|
void (*RegisterProfiler)(IProfilingTool *tool);
|
||||||
|
ICellArray * (*CreateCellArray)(size_t blocksize);
|
||||||
|
void (*FreeCellArray)(ICellArray *arr);
|
||||||
|
void * (*FromPseudoAddress)(uint32_t pseudoAddr);
|
||||||
|
uint32_t (*ToPseudoAddress)(void *addr);
|
||||||
|
IScriptManager *scripts;
|
||||||
|
IShareSys *sharesys;
|
||||||
|
IExtensionSys *extsys;
|
||||||
|
IHandleSys *handlesys;
|
||||||
|
IForwardManager *forwardsys;
|
||||||
|
IAdminSystem *adminsys;
|
||||||
|
IdentityToken_t *core_ident;
|
||||||
|
ILogger *logger;
|
||||||
|
IRootConsole *rootmenu;
|
||||||
|
IProviderCallbacks *callbacks;
|
||||||
|
float sentinel;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_LOGIC_PROVIDER_API_H_
|
||||||
|
|
@ -65,6 +65,10 @@ sm_flood_time 0.75
|
|||||||
// no reserved slot access (spectator players are selected first) is kicked to make room. Thus, the reserved
|
// no reserved slot access (spectator players are selected first) is kicked to make room. Thus, the reserved
|
||||||
// slots always remains free. The only situation where the reserved slot(s) can become properly occupied is
|
// slots always remains free. The only situation where the reserved slot(s) can become properly occupied is
|
||||||
// if the server is full with reserve slot access clients.
|
// if the server is full with reserve slot access clients.
|
||||||
|
// 2 : The same as sm_reserve_type 1 except once a certain number of admins have been reached, the reserve slot
|
||||||
|
// stops kicking people and anyone can join to fill the server. You can use this to simulate having a large
|
||||||
|
// number of reserved slots with sm_reserve_type 0 but with only need to have 1 slot unavailable when there are
|
||||||
|
// less admins connected.
|
||||||
// --
|
// --
|
||||||
// Requires: reservedslots.smx
|
// Requires: reservedslots.smx
|
||||||
// Default: 0
|
// Default: 0
|
||||||
@ -93,7 +97,7 @@ sm_hide_slots 0
|
|||||||
// Default: 1
|
// Default: 1
|
||||||
sm_chat_mode 1
|
sm_chat_mode 1
|
||||||
|
|
||||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
// Specifies whether or not "timeleft" will automatically be triggered every
|
||||||
// x seconds. Valid values are 0 (Disabled) to 1800 seconds.
|
// x seconds. Valid values are 0 (Disabled) to 1800 seconds.
|
||||||
// --
|
// --
|
||||||
// Requires: basetriggers.smx
|
// Requires: basetriggers.smx
|
||||||
@ -105,8 +109,8 @@ sm_timeleft_interval 0
|
|||||||
// 1 (Enabled)
|
// 1 (Enabled)
|
||||||
// --
|
// --
|
||||||
// Requires: basetriggers.smx
|
// Requires: basetriggers.smx
|
||||||
// Default: 1
|
// Default: 0
|
||||||
sm_trigger_show 1
|
sm_trigger_show 0
|
||||||
|
|
||||||
// Specifies whether or not to display vote progress to clients in the
|
// Specifies whether or not to display vote progress to clients in the
|
||||||
// "hint" box (near the bottom of the screen in most games).
|
// "hint" box (near the bottom of the screen in most games).
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
"ServerLang" "en"
|
"ServerLang" "en"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String to use as the public chat trigger. Set an empty string to disable.
|
* List of characters to use for public chat triggers. Set an empty list to disable.
|
||||||
*/
|
*/
|
||||||
"PublicChatTrigger" "!"
|
"PublicChatTrigger" "!"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String to use as the silent chat trigger. Set an empty string to disable.
|
* List of characters to use for silent chat triggers. Set an empty list to disable.
|
||||||
*/
|
*/
|
||||||
"SilentChatTrigger" "/"
|
"SilentChatTrigger" "/"
|
||||||
|
|
||||||
@ -44,7 +44,7 @@
|
|||||||
* but it does not evaluate to an actual command, it will be displayed
|
* but it does not evaluate to an actual command, it will be displayed
|
||||||
* publicly. This setting allows you to suppress accidental typings.
|
* publicly. This setting allows you to suppress accidental typings.
|
||||||
*
|
*
|
||||||
* The default value is "no". A value of "yes" will supress.
|
* The default value is "no". A value of "yes" will suppress.
|
||||||
*/
|
*/
|
||||||
"SilentFailSuppress" "no"
|
"SilentFailSuppress" "no"
|
||||||
|
|
||||||
@ -132,5 +132,18 @@
|
|||||||
* passed. You can disable this feature by setting the value to "0".
|
* passed. You can disable this feature by setting the value to "0".
|
||||||
*/
|
*/
|
||||||
"SlowScriptTimeout" "8"
|
"SlowScriptTimeout" "8"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per "http://blog.counter-strike.net/index.php/server_guidelines/", certain plugin
|
||||||
|
* functionality will trigger all of the game server owner's Game Server Login Tokens
|
||||||
|
* (GSLTs) to get banned when executed on a Counter-Strike: Global Offensive game server.
|
||||||
|
*
|
||||||
|
* Enabling this option will block plugins from using functionality that is known to cause this.
|
||||||
|
* This option only has any effect on CS:GO. Note that this does NOT guarantee that you cannot
|
||||||
|
* receive a ban.
|
||||||
|
*
|
||||||
|
* Disable this option at your own risk.
|
||||||
|
*/
|
||||||
|
"FollowCSGOServerGuidelines" "yes"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
configure.py
32
configure.py
@ -1,7 +1,7 @@
|
|||||||
# vim: set ts=2 sw=2 tw=99 noet:
|
# vim: set ts=2 sw=2 tw=99 noet:
|
||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
from ambuild2 import run
|
from ambuild2 import run, util
|
||||||
except:
|
except:
|
||||||
try:
|
try:
|
||||||
import ambuild
|
import ambuild
|
||||||
@ -12,25 +12,31 @@ except:
|
|||||||
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
run = run.PrepareBuild(sourcePath=sys.path[0])
|
def make_objdir_name(p):
|
||||||
run.default_build_folder = 'obj-' + run.target_platform
|
return 'obj-' + util.Platform() + '-' + p.target_arch
|
||||||
run.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
|
||||||
|
parser = run.BuildParser(sourcePath=sys.path[0], api='2.1')
|
||||||
|
parser.default_arch = 'x86'
|
||||||
|
parser.default_build_folder = make_objdir_name
|
||||||
|
parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
||||||
help='Root search folder for HL2SDKs')
|
help='Root search folder for HL2SDKs')
|
||||||
run.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
|
parser.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
|
||||||
help='Path to MySQL 5')
|
help='Path to MySQL 5')
|
||||||
run.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
|
parser.options.add_option('--mysql64-path', type=str, dest='mysql64_path', default=None,
|
||||||
|
help='Path to 64-bit MySQL 5')
|
||||||
|
parser.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
|
||||||
help='Path to Metamod:Source')
|
help='Path to Metamod:Source')
|
||||||
run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
||||||
help='Enable debugging symbols')
|
help='Enable debugging symbols')
|
||||||
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||||
help='Enable optimization')
|
help='Enable optimization')
|
||||||
run.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
parser.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
||||||
help='Disable building MySQL extension')
|
help='Disable building MySQL extension')
|
||||||
run.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
parser.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
||||||
help='Build against specified SDKs; valid args are "all", "present", or '
|
help='Build against specified SDKs; valid args are "all", "present", or '
|
||||||
'comma-delimited list of engine names (default: %default)')
|
'comma-delimited list of engine names (default: %default)')
|
||||||
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||||
default=False, help='Dump and upload breakpad symbols')
|
default=False, help='Dump and upload breakpad symbols')
|
||||||
run.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
parser.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
||||||
default=False, help='Disable the auto versioning script')
|
default=False, help='Disable the auto versioning script')
|
||||||
run.Configure()
|
parser.Configure()
|
||||||
|
@ -9,7 +9,6 @@ project.sources += [
|
|||||||
'sm_stringutil.cpp',
|
'sm_stringutil.cpp',
|
||||||
'MenuVoting.cpp',
|
'MenuVoting.cpp',
|
||||||
'smn_events.cpp',
|
'smn_events.cpp',
|
||||||
'CDataPack.cpp',
|
|
||||||
'frame_hooks.cpp',
|
'frame_hooks.cpp',
|
||||||
'smn_nextmap.cpp',
|
'smn_nextmap.cpp',
|
||||||
'sourcemm_api.cpp',
|
'sourcemm_api.cpp',
|
||||||
@ -21,7 +20,6 @@ project.sources += [
|
|||||||
'NextMap.cpp',
|
'NextMap.cpp',
|
||||||
'ConCmdManager.cpp',
|
'ConCmdManager.cpp',
|
||||||
'ConVarManager.cpp',
|
'ConVarManager.cpp',
|
||||||
'LibrarySys.cpp',
|
|
||||||
'PlayerManager.cpp',
|
'PlayerManager.cpp',
|
||||||
'TimerSys.cpp',
|
'TimerSys.cpp',
|
||||||
'CoreConfig.cpp',
|
'CoreConfig.cpp',
|
||||||
@ -38,52 +36,60 @@ project.sources += [
|
|||||||
'EventManager.cpp',
|
'EventManager.cpp',
|
||||||
'MenuStyle_Radio.cpp',
|
'MenuStyle_Radio.cpp',
|
||||||
'sm_autonatives.cpp',
|
'sm_autonatives.cpp',
|
||||||
'sm_srvcmds.cpp',
|
|
||||||
'ConsoleDetours.cpp',
|
'ConsoleDetours.cpp',
|
||||||
'vprof_tool.cpp',
|
'vprof_tool.cpp',
|
||||||
'smn_commandline.cpp',
|
'smn_commandline.cpp',
|
||||||
|
'GameHooks.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
for sdk_name in SM.sdks:
|
for sdk_name in SM.sdks:
|
||||||
sdk = SM.sdks[sdk_name]
|
sdk = SM.sdks[sdk_name]
|
||||||
|
for arch in SM.archs:
|
||||||
|
if not arch in sdk.platformSpec[builder.target.platform]:
|
||||||
|
continue
|
||||||
|
|
||||||
binary_name = 'sourcemod.' + sdk.ext
|
binary_name = 'sourcemod.' + sdk.ext
|
||||||
|
|
||||||
binary = SM.HL2Config(project, binary_name, sdk)
|
binary = SM.HL2Config(project, binary_name, sdk, arch)
|
||||||
compiler = binary.compiler
|
compiler = binary.compiler
|
||||||
|
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
builder.sourcePath
|
||||||
|
]
|
||||||
|
|
||||||
if sdk.name == 'csgo':
|
if sdk.name == 'csgo':
|
||||||
compiler.cxxincludes += [
|
compiler.cxxincludes += [
|
||||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||||
]
|
]
|
||||||
elif sdk.name == 'dota':
|
|
||||||
compiler.cxxincludes += [
|
|
||||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
|
||||||
]
|
|
||||||
|
|
||||||
if builder.target_platform == 'linux':
|
if compiler.like('msvc'):
|
||||||
|
compiler.defines += ['_ALLOW_KEYWORD_MACROS']
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
compiler.postlink += ['-lpthread', '-lrt']
|
compiler.postlink += ['-lpthread', '-lrt']
|
||||||
|
|
||||||
if sdk.name == 'csgo' or sdk.name == 'dota':
|
if sdk.name == 'csgo':
|
||||||
if builder.target_platform == 'linux':
|
if builder.target.platform == 'linux':
|
||||||
|
if arch == 'x86':
|
||||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||||
elif builder.target_platform == 'mac':
|
elif arch == 'x64':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'linux64', 'release', 'libprotobuf.a')
|
||||||
|
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
if arch == 'x86':
|
||||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||||
elif builder.target_platform == 'windows':
|
elif arch == 'x64':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
|
||||||
|
elif builder.target.platform == 'windows':
|
||||||
msvc_ver = compiler.version
|
msvc_ver = compiler.version
|
||||||
vs_year = ''
|
vs_year = ''
|
||||||
if msvc_ver == 1800:
|
if msvc_ver == 1800:
|
||||||
vs_year = '2013'
|
vs_year = '2013'
|
||||||
elif msvc_ver == 1700:
|
elif 1900 <= msvc_ver < 2000:
|
||||||
vs_year = '2012'
|
vs_year = '2015'
|
||||||
elif msvc_ver == 1600:
|
|
||||||
vs_year = '2010'
|
|
||||||
else:
|
else:
|
||||||
raise Exception('Cannot find libprotobuf for MSVC version "' + compiler.version + '"')
|
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||||
|
|
||||||
if 'DEBUG' in compiler.defines:
|
if 'DEBUG' in compiler.defines:
|
||||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
@ -91,7 +97,7 @@ for sdk_name in SM.sdks:
|
|||||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||||
|
|
||||||
if sdk.name in ['csgo', 'dota']:
|
if sdk.name == 'csgo':
|
||||||
binary.sources += ['smn_protobuf.cpp']
|
binary.sources += ['smn_protobuf.cpp']
|
||||||
else:
|
else:
|
||||||
binary.sources += ['smn_bitbuffer.cpp']
|
binary.sources += ['smn_bitbuffer.cpp']
|
||||||
@ -102,17 +108,6 @@ for sdk_name in SM.sdks:
|
|||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||||
]
|
]
|
||||||
elif sdk.name == 'dota':
|
|
||||||
binary.sources += [
|
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'network_connection.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessages.pb.cc'),
|
|
||||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessage_helpers.cpp'),
|
|
||||||
]
|
|
||||||
|
|
||||||
SM.binaries += builder.Add(project)
|
SM.binaries += builder.Add(project)
|
||||||
|
|
||||||
|
@ -1,333 +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 <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "CDataPack.h"
|
|
||||||
|
|
||||||
#define DATAPACK_INITIAL_SIZE 512
|
|
||||||
|
|
||||||
CDataPack::CDataPack()
|
|
||||||
{
|
|
||||||
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
|
|
||||||
m_capacity = DATAPACK_INITIAL_SIZE;
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
CDataPack::~CDataPack()
|
|
||||||
{
|
|
||||||
free(m_pBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::Initialize()
|
|
||||||
{
|
|
||||||
m_curptr = m_pBase;
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::CheckSize(size_t typesize)
|
|
||||||
{
|
|
||||||
if (m_curptr - m_pBase + typesize <= m_capacity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t pos = m_curptr - m_pBase;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
m_capacity *= 2;
|
|
||||||
m_pBase = (char *)realloc(m_pBase, m_capacity);
|
|
||||||
m_curptr = m_pBase + pos;
|
|
||||||
} while (m_curptr - m_pBase + typesize > m_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::ResetSize()
|
|
||||||
{
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(char) + sizeof(size_t) + size);
|
|
||||||
size_t pos = m_curptr - m_pBase;
|
|
||||||
|
|
||||||
*(char *)m_curptr = Raw;
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = size;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
*addr = m_curptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += size;
|
|
||||||
m_size += sizeof(char) + sizeof(size_t) + size;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackCell(cell_t cell)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
|
||||||
|
|
||||||
*(char *)m_curptr = Cell;
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(cell_t);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(cell_t *)m_curptr = cell;
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
|
|
||||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackFloat(float val)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
|
|
||||||
|
|
||||||
*(char *)m_curptr = Float;
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(float);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(float *)m_curptr = val;
|
|
||||||
m_curptr += sizeof(float);
|
|
||||||
|
|
||||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackString(const char *string)
|
|
||||||
{
|
|
||||||
size_t len = strlen(string);
|
|
||||||
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
|
|
||||||
CheckSize(maxsize);
|
|
||||||
|
|
||||||
*(char *)m_curptr = String;
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
// Pack the string length first for buffer overrun checking.
|
|
||||||
*(size_t *)m_curptr = len;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
// Now pack the string.
|
|
||||||
memcpy(m_curptr, string, len);
|
|
||||||
m_curptr[len] = '\0';
|
|
||||||
m_curptr += len + 1;
|
|
||||||
|
|
||||||
m_size += maxsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::Reset() const
|
|
||||||
{
|
|
||||||
m_curptr = m_pBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CDataPack::GetPosition() const
|
|
||||||
{
|
|
||||||
return static_cast<size_t>(m_curptr - m_pBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDataPack::SetPosition(size_t pos) const
|
|
||||||
{
|
|
||||||
if (pos > m_size-1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_curptr = m_pBase + pos;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t CDataPack::ReadCell() const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<char *>(m_curptr) != Cell)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
float CDataPack::ReadFloat() const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<char *>(m_curptr) != Float)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
float val = *reinterpret_cast<float *>(m_curptr);
|
|
||||||
m_curptr += sizeof(float);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDataPack::IsReadable(size_t bytes) const
|
|
||||||
{
|
|
||||||
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *CDataPack::ReadString(size_t *len) const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<char *>(m_curptr) != String)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
size_t real_len = *(size_t *)m_curptr;
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
char *str = (char *)m_curptr;
|
|
||||||
|
|
||||||
if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len)
|
|
||||||
{
|
|
||||||
*len = real_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += real_len + 1;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *CDataPack::GetMemory() const
|
|
||||||
{
|
|
||||||
return m_curptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *CDataPack::ReadMemory(size_t *size) const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(size_t)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<char *>(m_curptr) != Raw)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
size_t bytecount = *(size_t *)m_curptr;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
if (!IsReadable(bytecount))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ptr = m_curptr;
|
|
||||||
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
*size = bytecount;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += bytecount;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackFunction(cell_t function)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
|
||||||
|
|
||||||
*(char *)m_curptr = Function;
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(cell_t);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(cell_t *)m_curptr = function;
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
|
|
||||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t CDataPack::ReadFunction() const
|
|
||||||
{
|
|
||||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*reinterpret_cast<char *>(m_curptr) != Function)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_curptr += sizeof(char);
|
|
||||||
|
|
||||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
|
||||||
m_curptr += sizeof(cell_t);
|
|
||||||
return val;
|
|
||||||
}
|
|
@ -44,11 +44,7 @@ public: //IRecipientFilter
|
|||||||
bool IsReliable() const;
|
bool IsReliable() const;
|
||||||
bool IsInitMessage() const;
|
bool IsInitMessage() const;
|
||||||
int GetRecipientCount() const;
|
int GetRecipientCount() const;
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
CEntityIndex GetRecipientIndex(int slot) const;
|
|
||||||
#else
|
|
||||||
int GetRecipientIndex(int slot) const;
|
int GetRecipientIndex(int slot) const;
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
void Initialize(const cell_t *ptr, size_t count);
|
void Initialize(const cell_t *ptr, size_t count);
|
||||||
void SetToReliable(bool isreliable);
|
void SetToReliable(bool isreliable);
|
||||||
@ -83,11 +79,7 @@ inline int CellRecipientFilter::GetRecipientCount() const
|
|||||||
return m_Size;
|
return m_Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
|
|
||||||
#else
|
|
||||||
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if ((slot < 0) || (slot >= GetRecipientCount()))
|
if ((slot < 0) || (slot >= GetRecipientCount()))
|
||||||
@ -99,11 +91,7 @@ inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
|||||||
ret = static_cast<int>(m_Players[slot]);
|
ret = static_cast<int>(m_Players[slot]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
return CEntityIndex(ret);
|
|
||||||
#else
|
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -37,32 +37,18 @@
|
|||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
|
#include "provider.h"
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#include <bridge/include/ILogger.h>
|
||||||
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
#include <amtl/am-string.h>
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
|
||||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
|
||||||
#else
|
|
||||||
# if SH_IMPL_VERSION >= 4
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
# else
|
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
# endif
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ChatTriggers g_ChatTriggers;
|
ChatTriggers g_ChatTriggers;
|
||||||
bool g_bSupressSilentFails = false;
|
bool g_bSupressSilentFails = false;
|
||||||
|
|
||||||
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
ChatTriggers::ChatTriggers() : m_bWillProcessInPost(false),
|
||||||
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
|
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
|
||||||
{
|
{
|
||||||
m_PubTrigger = sm_strdup("!");
|
m_PubTrigger = "!";
|
||||||
m_PrivTrigger = sm_strdup("/");
|
m_PrivTrigger = "/";
|
||||||
m_PubTriggerSize = 1;
|
|
||||||
m_PrivTriggerSize = 1;
|
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
m_bPluginIgnored = true;
|
m_bPluginIgnored = true;
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
@ -72,14 +58,33 @@ ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
|||||||
|
|
||||||
ChatTriggers::~ChatTriggers()
|
ChatTriggers::~ChatTriggers()
|
||||||
{
|
{
|
||||||
delete [] m_PubTrigger;
|
|
||||||
m_PubTrigger = NULL;
|
|
||||||
delete [] m_PrivTrigger;
|
|
||||||
m_PrivTrigger = NULL;
|
|
||||||
delete [] m_ArgSBackup;
|
delete [] m_ArgSBackup;
|
||||||
m_ArgSBackup = NULL;
|
m_ArgSBackup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatTriggers::SetChatTrigger(ChatTriggerType type, const char *value)
|
||||||
|
{
|
||||||
|
ke::AutoPtr<char[]> filtered(new char[strlen(value) + 1]);
|
||||||
|
|
||||||
|
const char *src = value;
|
||||||
|
char *dest = filtered.get();
|
||||||
|
char c;
|
||||||
|
while ((c = *src++) != '\0') {
|
||||||
|
if (c <= ' ' || c == '"' || c == '\'' || (c >= '0' && c <= '9') || c == ';' || (c >= 'A' && c <= 'Z') || c == '\\' || (c >= 'a' && c <= 'z') || c >= 0x7F) {
|
||||||
|
logger->LogError("Ignoring %s chat trigger character '%c', not in valid set: %s", (type == ChatTrigger_Private ? "silent" : "public"), c, "!#$%&()*+,-./:<=>?@[]^_`{|}~");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*dest++ = c;
|
||||||
|
}
|
||||||
|
*dest = '\0';
|
||||||
|
|
||||||
|
if (type == ChatTrigger_Private) {
|
||||||
|
m_PrivTrigger = filtered.get();
|
||||||
|
} else {
|
||||||
|
m_PubTrigger = filtered.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
||||||
const char *value,
|
const char *value,
|
||||||
ConfigSource source,
|
ConfigSource source,
|
||||||
@ -88,16 +93,12 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
|||||||
{
|
{
|
||||||
if (strcmp(key, "PublicChatTrigger") == 0)
|
if (strcmp(key, "PublicChatTrigger") == 0)
|
||||||
{
|
{
|
||||||
delete [] m_PubTrigger;
|
SetChatTrigger(ChatTrigger_Public, value);
|
||||||
m_PubTrigger = sm_strdup(value);
|
|
||||||
m_PubTriggerSize = strlen(m_PubTrigger);
|
|
||||||
return ConfigResult_Accept;
|
return ConfigResult_Accept;
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "SilentChatTrigger") == 0)
|
else if (strcmp(key, "SilentChatTrigger") == 0)
|
||||||
{
|
{
|
||||||
delete [] m_PrivTrigger;
|
SetChatTrigger(ChatTrigger_Private, value);
|
||||||
m_PrivTrigger = sm_strdup(value);
|
|
||||||
m_PrivTriggerSize = strlen(m_PrivTrigger);
|
|
||||||
return ConfigResult_Accept;
|
return ConfigResult_Accept;
|
||||||
}
|
}
|
||||||
else if (strcmp(key, "SilentFailSuppress") == 0)
|
else if (strcmp(key, "SilentFailSuppress") == 0)
|
||||||
@ -124,70 +125,43 @@ void ChatTriggers::OnSourceModAllInitialized_Post()
|
|||||||
|
|
||||||
void ChatTriggers::OnSourceModGameInitialized()
|
void ChatTriggers::OnSourceModGameInitialized()
|
||||||
{
|
{
|
||||||
m_pSayCmd = FindCommand("say");
|
ConCommand *say_team = FindCommand("say_team");
|
||||||
m_pSayTeamCmd = FindCommand("say_team");
|
|
||||||
|
|
||||||
if (m_pSayCmd)
|
CommandHook::Callback pre_hook = [this] (int client, const ICommandArgs *args) -> bool {
|
||||||
{
|
return this->OnSayCommand_Pre(client, args);
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
};
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
CommandHook::Callback post_hook = [this] (int client, const ICommandArgs *args) -> bool {
|
||||||
|
return this->OnSayCommand_Post(client, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ConCommand *say = FindCommand("say")) {
|
||||||
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say, pre_hook));
|
||||||
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say, post_hook));
|
||||||
}
|
}
|
||||||
if (m_pSayTeamCmd)
|
if (ConCommand *say_team = FindCommand("say_team")) {
|
||||||
{
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say_team, pre_hook));
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
|
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
|
||||||
|
if (m_bIsINS) {
|
||||||
if (m_bIsINS)
|
if (ConCommand *say2 = FindCommand("say2")) {
|
||||||
{
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
|
||||||
m_pSay2Cmd = FindCommand("say2");
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
|
||||||
if (m_pSay2Cmd)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||||
m_pSaySquadCmd = FindCommand("say_squad");
|
if (ConCommand *say_squad = FindCommand("say_squad")) {
|
||||||
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
|
||||||
if (m_pSaySquadCmd)
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
|
||||||
{
|
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModShutdown()
|
void ChatTriggers::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
if (m_pSayCmd)
|
hooks_.clear();
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pSayTeamCmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
|
||||||
if (m_bIsINS && m_pSay2Cmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
}
|
|
||||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
|
||||||
if (m_pSaySquadCmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
forwardsys->ReleaseForward(m_pShouldFloodBlock);
|
forwardsys->ReleaseForward(m_pShouldFloodBlock);
|
||||||
forwardsys->ReleaseForward(m_pDidFloodBlock);
|
forwardsys->ReleaseForward(m_pDidFloodBlock);
|
||||||
@ -195,32 +169,20 @@ void ChatTriggers::OnSourceModShutdown()
|
|||||||
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
|
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
bool ChatTriggers::OnSayCommand_Pre(int client, const ICommandArgs *command)
|
||||||
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
|
|
||||||
{
|
{
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
|
||||||
{
|
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Pre()
|
|
||||||
{
|
|
||||||
CCommand command;
|
|
||||||
#endif
|
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
m_bWasFloodedMessage = false;
|
m_bWasFloodedMessage = false;
|
||||||
m_bPluginIgnored = true;
|
m_bPluginIgnored = true;
|
||||||
|
|
||||||
const char *args = command.ArgS();
|
const char *args = command->ArgS();
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
return false;
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save these off for post hook as the command data returned from the engine in older engine versions
|
/* Save these off for post hook as the command data returned from the engine in older engine versions
|
||||||
* can be NULL, despite the data still being there and valid. */
|
* can be NULL, despite the data still being there and valid. */
|
||||||
m_Arg0Backup = command.Arg(0);
|
m_Arg0Backup = command->Arg(0);
|
||||||
size_t len = strlen(args);
|
size_t len = strlen(args);
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
@ -233,9 +195,7 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -253,9 +213,7 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
/* The server normally won't display empty say commands, but in this case it does.
|
/* The server normally won't display empty say commands, but in this case it does.
|
||||||
* I don't think it's desired so let's block it. */
|
* I don't think it's desired so let's block it. */
|
||||||
if (len <= 2)
|
if (len <= 2)
|
||||||
{
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
args++;
|
args++;
|
||||||
len--;
|
len--;
|
||||||
@ -284,20 +242,16 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
if (client == 0)
|
if (client == 0)
|
||||||
{
|
{
|
||||||
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
{
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_META(MRES_IGNORED);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
|
||||||
/* We guarantee the client is connected */
|
/* We guarantee the client is connected */
|
||||||
if (!pPlayer || !pPlayer->IsConnected())
|
if (!pPlayer || !pPlayer->IsConnected())
|
||||||
{
|
return false;
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we need to block this message from being sent */
|
/* Check if we need to block this message from being sent */
|
||||||
if (ClientIsFlooding(client))
|
if (ClientIsFlooding(client))
|
||||||
@ -305,33 +259,32 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
|
|
||||||
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
|
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
|
||||||
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
|
ke::SafeSprintf(buffer, sizeof(buffer), "You are flooding the server!");
|
||||||
|
|
||||||
/* :TODO: we should probably kick people who spam too much. */
|
/* :TODO: we should probably kick people who spam too much. */
|
||||||
|
|
||||||
char fullbuffer[192];
|
char fullbuffer[192];
|
||||||
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
|
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
|
||||||
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
|
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
|
||||||
|
|
||||||
m_bWasFloodedMessage = true;
|
m_bWasFloodedMessage = true;
|
||||||
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_trigger = false;
|
bool is_trigger = false;
|
||||||
bool is_silent = false;
|
bool is_silent = false;
|
||||||
|
|
||||||
/* Check for either trigger */
|
// Prefer the silent trigger in case of clashes.
|
||||||
if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0)
|
if (strchr(m_PrivTrigger.chars(), m_ArgSBackup[0])) {
|
||||||
{
|
|
||||||
is_trigger = true;
|
|
||||||
args = &m_ArgSBackup[m_PubTriggerSize];
|
|
||||||
}
|
|
||||||
else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0)
|
|
||||||
{
|
|
||||||
is_trigger = true;
|
is_trigger = true;
|
||||||
is_silent = true;
|
is_silent = true;
|
||||||
args = &m_ArgSBackup[m_PrivTriggerSize];
|
} else if (strchr(m_PubTrigger.chars(), m_ArgSBackup[0])) {
|
||||||
|
is_trigger = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_trigger) {
|
||||||
|
// Bump the args past the chat trigger - we only support single-character triggers now.
|
||||||
|
args = &m_ArgSBackup[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -348,29 +301,17 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
|
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
|
||||||
{
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
{
|
return true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, let the command continue */
|
/* Otherwise, let the command continue */
|
||||||
RETURN_META(MRES_IGNORED);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
bool ChatTriggers::OnSayCommand_Post(int client, const ICommandArgs *command)
|
||||||
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Post()
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
|
|
||||||
if (m_bWillProcessInPost)
|
if (m_bWillProcessInPost)
|
||||||
{
|
{
|
||||||
/* Reset this for re-entrancy */
|
/* Reset this for re-entrancy */
|
||||||
@ -378,11 +319,7 @@ void ChatTriggers::OnSayCommand_Post()
|
|||||||
|
|
||||||
/* Execute the cached command */
|
/* Execute the cached command */
|
||||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
engine->ClientCommand(client, "%s", m_ToExecute);
|
|
||||||
#else
|
|
||||||
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
||||||
#endif
|
|
||||||
SetReplyTo(old);
|
SetReplyTo(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +333,7 @@ void ChatTriggers::OnSayCommand_Post()
|
|||||||
|
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
m_bWasFloodedMessage = false;
|
m_bWasFloodedMessage = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
||||||
@ -433,7 +371,7 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
|||||||
*/
|
*/
|
||||||
char new_buf[80];
|
char new_buf[80];
|
||||||
strcpy(new_buf, "sm_");
|
strcpy(new_buf, "sm_");
|
||||||
strncopy(&new_buf[3], cmd_buf, sizeof(new_buf)-3);
|
ke::SafeStrcpy(&new_buf[3], sizeof(new_buf)-3, cmd_buf);
|
||||||
|
|
||||||
/* Recheck */
|
/* Recheck */
|
||||||
if (!g_ConCmds.LookForSourceModCommand(new_buf))
|
if (!g_ConCmds.LookForSourceModCommand(new_buf))
|
||||||
@ -452,12 +390,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
|||||||
/* Check if we need to prepend sm_ */
|
/* Check if we need to prepend sm_ */
|
||||||
if (prepended)
|
if (prepended)
|
||||||
{
|
{
|
||||||
len = UTIL_Format(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
|
len = ke::SafeSprintf(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
|
||||||
} else {
|
} else {
|
||||||
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
len = ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -34,9 +34,11 @@
|
|||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include "GameHooks.h"
|
||||||
#include <IGameHelpers.h>
|
#include <IGameHelpers.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
class ChatTriggers : public SMGlobalClass
|
class ChatTriggers : public SMGlobalClass
|
||||||
{
|
{
|
||||||
@ -54,37 +56,26 @@ public: //SMGlobalClass
|
|||||||
char *error,
|
char *error,
|
||||||
size_t maxlength);
|
size_t maxlength);
|
||||||
private: //ConCommand
|
private: //ConCommand
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
bool OnSayCommand_Pre(int client, const ICommandArgs *args);
|
||||||
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
|
bool OnSayCommand_Post(int client, const ICommandArgs *args);
|
||||||
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void OnSayCommand_Pre(const CCommand &command);
|
|
||||||
void OnSayCommand_Post(const CCommand &command);
|
|
||||||
#else
|
|
||||||
void OnSayCommand_Pre();
|
|
||||||
void OnSayCommand_Post();
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
unsigned int GetReplyTo();
|
unsigned int GetReplyTo();
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
unsigned int SetReplyTo(unsigned int reply);
|
||||||
bool IsChatTrigger();
|
bool IsChatTrigger();
|
||||||
bool WasFloodedMessage();
|
bool WasFloodedMessage();
|
||||||
private:
|
private:
|
||||||
|
enum ChatTriggerType {
|
||||||
|
ChatTrigger_Public,
|
||||||
|
ChatTrigger_Private,
|
||||||
|
};
|
||||||
|
void SetChatTrigger(ChatTriggerType type, const char *value);
|
||||||
bool PreProcessTrigger(edict_t *pEdict, const char *args);
|
bool PreProcessTrigger(edict_t *pEdict, const char *args);
|
||||||
bool ClientIsFlooding(int client);
|
bool ClientIsFlooding(int client);
|
||||||
cell_t CallOnClientSayCommand(int client);
|
cell_t CallOnClientSayCommand(int client);
|
||||||
private:
|
private:
|
||||||
ConCommand *m_pSayCmd;
|
ke::Vector<ke::RefPtr<CommandHook>> hooks_;
|
||||||
ConCommand *m_pSayTeamCmd;
|
ke::AString m_PubTrigger;
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
ke::AString m_PrivTrigger;
|
||||||
ConCommand *m_pSay2Cmd;
|
|
||||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
|
||||||
ConCommand *m_pSaySquadCmd;
|
|
||||||
#endif
|
|
||||||
char *m_PubTrigger;
|
|
||||||
size_t m_PubTriggerSize;
|
|
||||||
char *m_PrivTrigger;
|
|
||||||
size_t m_PrivTriggerSize;
|
|
||||||
bool m_bWillProcessInPost;
|
bool m_bWillProcessInPost;
|
||||||
bool m_bIsChatTrigger;
|
bool m_bIsChatTrigger;
|
||||||
bool m_bWasFloodedMessage;
|
bool m_bWasFloodedMessage;
|
||||||
|
@ -30,33 +30,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "ChatTriggers.h"
|
#include "ChatTriggers.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include "sourcemod.h"
|
||||||
|
#include "provider.h"
|
||||||
|
#include "command_args.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
using namespace ke;
|
using namespace ke;
|
||||||
|
|
||||||
ConCmdManager g_ConCmds;
|
ConCmdManager g_ConCmds;
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
|
||||||
#elif 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);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
|
|
||||||
|
|
||||||
typedef ke::LinkedList<CmdHook *> PluginHookList;
|
typedef ke::LinkedList<CmdHook *> PluginHookList;
|
||||||
void RegisterInPlugin(CmdHook *hook);
|
void RegisterInPlugin(CmdHook *hook);
|
||||||
|
|
||||||
ConCmdManager::ConCmdManager()
|
ConCmdManager::ConCmdManager()
|
||||||
{
|
{
|
||||||
m_CmdClient = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConCmdManager::~ConCmdManager()
|
ConCmdManager::~ConCmdManager()
|
||||||
@ -66,19 +58,16 @@ ConCmdManager::~ConCmdManager()
|
|||||||
void ConCmdManager::OnSourceModAllInitialized()
|
void ConCmdManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
scripts->AddPluginsListener(this);
|
scripts->AddPluginsListener(this);
|
||||||
g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", this);
|
rootmenu->AddRootConsoleCommand3("cmds", "List console commands", this);
|
||||||
SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::OnSourceModShutdown()
|
void ConCmdManager::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
scripts->RemovePluginsListener(this);
|
scripts->RemovePluginsListener(this);
|
||||||
/* All commands should already be removed by the time we're done */
|
rootmenu->RemoveRootConsoleCommand("cmds", this);
|
||||||
SH_REMOVE_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
|
|
||||||
g_RootMenu.RemoveRootConsoleCommand("cmds", this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name)
|
||||||
{
|
{
|
||||||
/* Whoa, first get its information struct */
|
/* Whoa, first get its information struct */
|
||||||
ConCmdInfo *pInfo;
|
ConCmdInfo *pInfo;
|
||||||
@ -113,7 +102,7 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
|||||||
delete hook;
|
delete hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveConCmd(pInfo, name, is_read_safe, false);
|
RemoveConCmd(pInfo, name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
||||||
@ -132,7 +121,7 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
|||||||
hook->admin->group->hooks.remove(hook);
|
hook->admin->group->hooks.remove(hook);
|
||||||
|
|
||||||
if (hook->info->hooks.empty())
|
if (hook->info->hooks.empty())
|
||||||
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true);
|
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true);
|
||||||
|
|
||||||
iter = pList->erase(iter);
|
iter = pList->erase(iter);
|
||||||
delete hook;
|
delete hook;
|
||||||
@ -141,28 +130,13 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
|||||||
delete pList;
|
delete pList;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
void CommandCallback(DISPATCH_ARGS)
|
||||||
void CommandCallback(const CCommandContext &context, const CCommand &command)
|
|
||||||
{
|
{
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
DISPATCH_PROLOGUE;
|
||||||
void CommandCallback(const CCommand &command)
|
EngineArgs args(command);
|
||||||
{
|
|
||||||
#else
|
|
||||||
void CommandCallback()
|
|
||||||
{
|
|
||||||
CCommand command;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_HL2.PushCommandStack(&command);
|
AutoEnterCommand autoEnterCommand(&args);
|
||||||
|
g_ConCmds.InternalDispatch(sCoreProviderImpl.CommandClient(), &args);
|
||||||
g_ConCmds.InternalDispatch(command);
|
|
||||||
|
|
||||||
g_HL2.PopCommandStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConCmdManager::SetCommandClient(int client)
|
|
||||||
{
|
|
||||||
m_CmdClient = client + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
|
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
|
||||||
@ -218,6 +192,7 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
|
|||||||
hook->pf->PushCell(args);
|
hook->pf->PushCell(args);
|
||||||
|
|
||||||
cell_t tempres = result;
|
cell_t tempres = result;
|
||||||
|
|
||||||
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (tempres > result)
|
if (tempres > result)
|
||||||
@ -230,15 +205,13 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
|
|||||||
return (ResultType)result;
|
return (ResultType)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::InternalDispatch(const CCommand &command)
|
bool ConCmdManager::InternalDispatch(int client, const ICommandArgs *args)
|
||||||
{
|
{
|
||||||
int client = m_CmdClient;
|
|
||||||
|
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
if (!pPlayer || !pPlayer->IsConnected())
|
if (!pPlayer || !pPlayer->IsConnected())
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,11 +229,11 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
|||||||
* case-insensitive. We can't even use our sortedness.
|
* case-insensitive. We can't even use our sortedness.
|
||||||
*/
|
*/
|
||||||
if (client == 0 && !engine->IsDedicatedServer())
|
if (client == 0 && !engine->IsDedicatedServer())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
ConCmdList::iterator item = FindInList(cmd);
|
ConCmdList::iterator item = FindInList(cmd);
|
||||||
if (item == m_CmdList.end())
|
if (item == m_CmdList.end())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
pInfo = *item;
|
pInfo = *item;
|
||||||
}
|
}
|
||||||
@ -270,10 +243,10 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
|||||||
* "nicer" when we expose explicit say hooks.
|
* "nicer" when we expose explicit say hooks.
|
||||||
*/
|
*/
|
||||||
if (g_ChatTriggers.WasFloodedMessage())
|
if (g_ChatTriggers.WasFloodedMessage())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
cell_t result = Pl_Continue;
|
cell_t result = Pl_Continue;
|
||||||
int args = command.ArgC() - 1;
|
int argc = args->ArgC() - 1;
|
||||||
|
|
||||||
// On a listen server, sometimes the server host's client index can be set
|
// On a listen server, sometimes the server host's client index can be set
|
||||||
// as 0. So index 1 is passed to the command callback to correct this
|
// as 0. So index 1 is passed to the command callback to correct this
|
||||||
@ -309,7 +282,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
|||||||
hook->pf->PushCell(realClient);
|
hook->pf->PushCell(realClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
hook->pf->PushCell(args);
|
hook->pf->PushCell(argc);
|
||||||
|
|
||||||
cell_t tempres = result;
|
cell_t tempres = result;
|
||||||
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||||
@ -322,11 +295,9 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result >= Pl_Handled)
|
if (result >= Pl_Handled)
|
||||||
{
|
return !pInfo->sourceMod;
|
||||||
if (!pInfo->sourceMod)
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
return false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
|
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
|
||||||
@ -346,20 +317,20 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
|
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command");
|
ke::SafeStrcpy(buffer, sizeof(buffer), "You do not have access to this command");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int replyto = g_ChatTriggers.GetReplyTo();
|
unsigned int replyto = g_ChatTriggers.GetReplyTo();
|
||||||
if (replyto == SM_REPLY_CONSOLE)
|
if (replyto == SM_REPLY_CONSOLE)
|
||||||
{
|
{
|
||||||
char fullbuffer[192];
|
char fullbuffer[192];
|
||||||
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
|
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
|
||||||
pPlayer->PrintToConsole(fullbuffer);
|
pPlayer->PrintToConsole(fullbuffer);
|
||||||
}
|
}
|
||||||
else if (replyto == SM_REPLY_CHAT)
|
else if (replyto == SM_REPLY_CHAT)
|
||||||
{
|
{
|
||||||
char fullbuffer[192];
|
char fullbuffer[192];
|
||||||
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer);
|
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer);
|
||||||
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
|
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,9 +342,10 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
|||||||
const char *group,
|
const char *group,
|
||||||
int adminflags,
|
int adminflags,
|
||||||
const char *description,
|
const char *description,
|
||||||
int flags)
|
int flags,
|
||||||
|
IPlugin *pPlugin)
|
||||||
{
|
{
|
||||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||||
|
|
||||||
if (!pInfo)
|
if (!pInfo)
|
||||||
return false;
|
return false;
|
||||||
@ -385,7 +357,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
|||||||
return false;
|
return false;
|
||||||
i->value = new CommandGroup();
|
i->value = new CommandGroup();
|
||||||
}
|
}
|
||||||
Ref<CommandGroup> cmdgroup = i->value;
|
RefPtr<CommandGroup> cmdgroup = i->value;
|
||||||
|
|
||||||
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
|
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
|
||||||
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags);
|
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags);
|
||||||
@ -417,10 +389,11 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
|||||||
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *description,
|
const char *description,
|
||||||
int flags)
|
int flags,
|
||||||
|
IPlugin *pPlugin)
|
||||||
|
|
||||||
{
|
{
|
||||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||||
|
|
||||||
if (!pInfo)
|
if (!pInfo)
|
||||||
return false;
|
return false;
|
||||||
@ -517,7 +490,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
|
|||||||
if (!r.found())
|
if (!r.found())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Ref<CommandGroup> group(r->value);
|
RefPtr<CommandGroup> group(r->value);
|
||||||
|
|
||||||
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
|
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
|
||||||
{
|
{
|
||||||
@ -531,7 +504,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack)
|
void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool untrack)
|
||||||
{
|
{
|
||||||
/* Remove from the trie */
|
/* Remove from the trie */
|
||||||
m_Cmds.remove(name);
|
m_Cmds.remove(name);
|
||||||
@ -554,17 +527,10 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_read_safe)
|
|
||||||
{
|
|
||||||
/* Remove the external hook */
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, info->pCmd, SH_STATIC(CommandCallback), false);
|
|
||||||
}
|
|
||||||
if (untrack)
|
if (untrack)
|
||||||
{
|
|
||||||
UntrackConCommandBase(info->pCmd, this);
|
UntrackConCommandBase(info->pCmd, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove from list */
|
/* Remove from list */
|
||||||
m_CmdList.remove(info);
|
m_CmdList.remove(info);
|
||||||
@ -591,7 +557,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
|
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin)
|
||||||
{
|
{
|
||||||
ConCmdInfo *pInfo;
|
ConCmdInfo *pInfo;
|
||||||
if (!m_Cmds.retrieve(name, &pInfo))
|
if (!m_Cmds.retrieve(name, &pInfo))
|
||||||
@ -616,12 +582,17 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
|||||||
char *new_name = sm_strdup(name);
|
char *new_name = sm_strdup(name);
|
||||||
char *new_help = sm_strdup(description);
|
char *new_help = sm_strdup(description);
|
||||||
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
|
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
|
||||||
|
pInfo->pPlugin = pPlugin;
|
||||||
pInfo->sourceMod = true;
|
pInfo->sourceMod = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TrackConCommandBase(pCmd, this);
|
TrackConCommandBase(pCmd, this);
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CommandCallback), false);
|
CommandHook::Callback callback = [this] (int client, const ICommandArgs *args) -> bool {
|
||||||
|
AutoEnterCommand autoEnterCommand(args);
|
||||||
|
return this->InternalDispatch(client, args);
|
||||||
|
};
|
||||||
|
pInfo->sh_hook = sCoreProviderImpl.AddCommandHook(pCmd, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
pInfo->pCmd = pCmd;
|
pInfo->pCmd = pCmd;
|
||||||
@ -633,17 +604,17 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
|||||||
return pInfo;
|
return pInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
|
||||||
{
|
{
|
||||||
if (command.ArgC() >= 3)
|
if (command->ArgC() >= 3)
|
||||||
{
|
{
|
||||||
const char *text = command.Arg(2);
|
const char *text = command->Arg(2);
|
||||||
|
|
||||||
IPlugin *pPlugin = scripts->FindPluginByConsoleArg(text);
|
IPlugin *pPlugin = scripts->FindPluginByConsoleArg(text);
|
||||||
|
|
||||||
if (!pPlugin)
|
if (!pPlugin)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", text);
|
UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,20 +624,20 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
PluginHookList *pList;
|
PluginHookList *pList;
|
||||||
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
|
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
|
UTIL_ConsolePrint("[SM] No commands found for: %s", plname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pList->empty())
|
if (pList->empty())
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
|
UTIL_ConsolePrint("[SM] No commands found for: %s", plname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *type = NULL;
|
const char *type = NULL;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *help;
|
const char *help;
|
||||||
g_RootMenu.ConsolePrint("[SM] Listing commands for: %s", plname);
|
UTIL_ConsolePrint("[SM] Listing commands for: %s", plname);
|
||||||
g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
|
UTIL_ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
|
||||||
for (PluginHookList::iterator iter = pList->begin(); iter != pList->end(); iter++)
|
for (PluginHookList::iterator iter = pList->begin(); iter != pList->end(); iter++)
|
||||||
{
|
{
|
||||||
CmdHook *hook = *iter;
|
CmdHook *hook = *iter;
|
||||||
@ -680,11 +651,11 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
help = hook->helptext.chars();
|
help = hook->helptext.chars();
|
||||||
else
|
else
|
||||||
help = hook->info->pCmd->GetHelpText();
|
help = hook->info->pCmd->GetHelpText();
|
||||||
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
|
UTIL_ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm cmds <plugin #>");
|
UTIL_ConsolePrint("[SM] Usage: sm cmds <plugin #>");
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include <IAdminSystem.h>
|
#include <IAdminSystem.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
|
#include "GameHooks.h"
|
||||||
|
#include <am-autoptr.h>
|
||||||
#include <sm_stringhashmap.h>
|
#include <sm_stringhashmap.h>
|
||||||
#include <am-utility.h>
|
#include <am-utility.h>
|
||||||
#include <am-inlinelist.h>
|
#include <am-inlinelist.h>
|
||||||
@ -58,13 +60,13 @@ struct CommandGroup : public ke::Refcounted<CommandGroup>
|
|||||||
|
|
||||||
struct AdminCmdInfo
|
struct AdminCmdInfo
|
||||||
{
|
{
|
||||||
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags)
|
AdminCmdInfo(const ke::RefPtr<CommandGroup> &group, FlagBits flags)
|
||||||
: group(group),
|
: group(group),
|
||||||
flags(flags),
|
flags(flags),
|
||||||
eflags(0)
|
eflags(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ke::Ref<CommandGroup> group;
|
ke::RefPtr<CommandGroup> group;
|
||||||
FlagBits flags; /* default flags */
|
FlagBits flags; /* default flags */
|
||||||
FlagBits eflags; /* effective flags */
|
FlagBits eflags; /* effective flags */
|
||||||
};
|
};
|
||||||
@ -97,14 +99,17 @@ struct ConCmdInfo
|
|||||||
{
|
{
|
||||||
ConCmdInfo()
|
ConCmdInfo()
|
||||||
{
|
{
|
||||||
|
pPlugin = nullptr;
|
||||||
sourceMod = false;
|
sourceMod = false;
|
||||||
pCmd = NULL;
|
pCmd = nullptr;
|
||||||
eflags = 0;
|
eflags = 0;
|
||||||
}
|
}
|
||||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
||||||
ConCommand *pCmd; /**< Pointer to the command itself */
|
ConCommand *pCmd; /**< Pointer to the command itself */
|
||||||
CmdHookList hooks; /**< Hook list */
|
CmdHookList hooks; /**< Hook list */
|
||||||
FlagBits eflags; /**< Effective admin flags */
|
FlagBits eflags; /**< Effective admin flags */
|
||||||
|
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
|
||||||
|
IPlugin *pPlugin; /**< Owning plugin handle. */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef List<ConCmdInfo *> ConCmdList;
|
typedef List<ConCmdInfo *> ConCmdList;
|
||||||
@ -115,13 +120,7 @@ class ConCmdManager :
|
|||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IConCommandTracker
|
public IConCommandTracker
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
friend void CommandCallback(DISPATCH_ARGS);
|
||||||
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
friend void CommandCallback(const CCommand &command);
|
|
||||||
#else
|
|
||||||
friend void CommandCallback();
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
ConCmdManager();
|
ConCmdManager();
|
||||||
~ConCmdManager();
|
~ConCmdManager();
|
||||||
@ -131,28 +130,28 @@ public: //SMGlobalClass
|
|||||||
public: //IPluginsListener
|
public: //IPluginsListener
|
||||||
void OnPluginDestroyed(IPlugin *plugin);
|
void OnPluginDestroyed(IPlugin *plugin);
|
||||||
public: //IRootConsoleCommand
|
public: //IRootConsoleCommand
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
|
||||||
public: //IConCommandTracker
|
public: //IConCommandTracker
|
||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
|
||||||
public:
|
public:
|
||||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *group,
|
const char *group,
|
||||||
int adminflags,
|
int adminflags,
|
||||||
const char *description,
|
const char *description,
|
||||||
int flags);
|
int flags,
|
||||||
|
IPlugin *pPlugin);
|
||||||
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
|
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
|
||||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||||
bool LookForSourceModCommand(const char *cmd);
|
bool LookForSourceModCommand(const char *cmd);
|
||||||
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
||||||
private:
|
private:
|
||||||
void InternalDispatch(const CCommand &command);
|
bool InternalDispatch(int client, const ICommandArgs *args);
|
||||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
|
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||||
void SetCommandClient(int client);
|
|
||||||
void AddToCmdList(ConCmdInfo *info);
|
void AddToCmdList(ConCmdInfo *info);
|
||||||
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
|
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack);
|
||||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||||
|
|
||||||
// Case insensitive
|
// Case insensitive
|
||||||
@ -161,21 +160,16 @@ private:
|
|||||||
// Case sensitive
|
// Case sensitive
|
||||||
ConCmdInfo *FindInTrie(const char *name);
|
ConCmdInfo *FindInTrie(const char *name);
|
||||||
public:
|
public:
|
||||||
inline int GetCommandClient()
|
|
||||||
{
|
|
||||||
return m_CmdClient;
|
|
||||||
}
|
|
||||||
inline const List<ConCmdInfo *> & GetCommandList()
|
inline const List<ConCmdInfo *> & GetCommandList()
|
||||||
{
|
{
|
||||||
return m_CmdList;
|
return m_CmdList;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap;
|
typedef StringHashMap<ke::RefPtr<CommandGroup> > GroupMap;
|
||||||
|
|
||||||
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
|
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
|
||||||
GroupMap m_CmdGrps; /* command group map */
|
GroupMap m_CmdGrps; /* command group map */
|
||||||
ConCmdList m_CmdList; /* command list */
|
ConCmdList m_CmdList; /* command list */
|
||||||
int m_CmdClient; /* current client */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConCmdManager g_ConCmds;
|
extern ConCmdManager g_ConCmds;
|
||||||
|
@ -29,28 +29,16 @@
|
|||||||
|
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sm_namehashset.h>
|
#include <sm_namehashset.h>
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include "sourcemod.h"
|
||||||
|
#include "provider.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
ConVarManager g_ConVarManager;
|
ConVarManager g_ConVarManager;
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
|
||||||
#else
|
|
||||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
#elif SOURCE_ENGINE != SE_DARKMESSIAH
|
|
||||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
||||||
typedef List<const ConVar *> ConVarList;
|
typedef List<const ConVar *> ConVarList;
|
||||||
NameHashSet<ConVarInfo *> convar_cache;
|
NameHashSet<ConVarInfo *> convar_cache;
|
||||||
@ -89,7 +77,7 @@ public:
|
|||||||
|
|
||||||
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
|
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
|
||||||
|
|
||||||
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
ConVarManager::ConVarManager() : m_ConVarType(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,29 +100,12 @@ void ConVarManager::OnSourceModStartup(bool late)
|
|||||||
|
|
||||||
void ConVarManager::OnSourceModAllInitialized()
|
void ConVarManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Episode 2 has this function by default, but the older versions do not.
|
|
||||||
*/
|
|
||||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
|
||||||
if (g_SMAPI->GetGameDLLVersion() >= 6)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
|
||||||
m_bIsDLLQueryHooked = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_Players.AddClientListener(this);
|
g_Players.AddClientListener(this);
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
|
|
||||||
#else
|
|
||||||
SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
scripts->AddPluginsListener(this);
|
scripts->AddPluginsListener(this);
|
||||||
|
|
||||||
/* Add the 'convars' option to the 'sm' console command */
|
/* Add the 'convars' option to the 'sm' console command */
|
||||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
rootmenu->AddRootConsoleCommand3("cvars", "View convars created by a plugin", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnSourceModShutdown()
|
void ConVarManager::OnSourceModShutdown()
|
||||||
@ -180,32 +151,10 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
}
|
}
|
||||||
convar_cache.clear();
|
convar_cache.clear();
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
|
||||||
/* Unhook things */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
|
||||||
m_bIsDLLQueryHooked = false;
|
|
||||||
}
|
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
|
||||||
#endif
|
|
||||||
m_bIsVSPQueryHooked = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_Players.RemoveClientListener(this);
|
g_Players.RemoveClientListener(this);
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
|
|
||||||
#else
|
|
||||||
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Remove the 'convars' option from the 'sm' console command */
|
/* Remove the 'convars' option from the 'sm' console command */
|
||||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
rootmenu->RemoveRootConsoleCommand("cvars", this);
|
||||||
|
|
||||||
scripts->RemovePluginsListener(this);
|
scripts->RemovePluginsListener(this);
|
||||||
|
|
||||||
@ -213,45 +162,12 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
|
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Orange Box will never use this.
|
|
||||||
*/
|
|
||||||
void ConVarManager::OnSourceModVSPReceived()
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Don't bother if the DLL is already hooked.
|
|
||||||
*/
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For later MM:S versions, use the updated API, since it's cleaner. */
|
|
||||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
|
||||||
int engine = g_SMAPI->GetSourceEngineBuild();
|
|
||||||
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (g_HL2.IsOriginalEngine() || vsp_version < 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA
|
|
||||||
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
|
||||||
m_bIsVSPQueryHooked = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
||||||
{
|
{
|
||||||
return convar_cache.retrieve(name, pVar);
|
return convar_cache.retrieve(name, pVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name)
|
||||||
{
|
{
|
||||||
/* Only check convars that have not been created by SourceMod's core */
|
/* Only check convars that have not been created by SourceMod's core */
|
||||||
ConVarInfo *pInfo;
|
ConVarInfo *pInfo;
|
||||||
@ -340,19 +256,19 @@ bool ConVarManager::GetHandleApproxSize(HandleType_t type, void *object, unsigne
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
|
||||||
{
|
{
|
||||||
int argcount = command.ArgC();
|
int argcount = command->ArgC();
|
||||||
if (argcount >= 3)
|
if (argcount >= 3)
|
||||||
{
|
{
|
||||||
bool wantReset = false;
|
bool wantReset = false;
|
||||||
|
|
||||||
/* Get plugin index that was passed */
|
/* Get plugin index that was passed */
|
||||||
const char *arg = command.Arg(2);
|
const char *arg = command->Arg(2);
|
||||||
if (argcount >= 4 && strcmp(arg, "reset") == 0)
|
if (argcount >= 4 && strcmp(arg, "reset") == 0)
|
||||||
{
|
{
|
||||||
wantReset = true;
|
wantReset = true;
|
||||||
arg = command.Arg(3);
|
arg = command->Arg(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get plugin object */
|
/* Get plugin object */
|
||||||
@ -360,7 +276,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
|
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
|
UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,14 +290,14 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
/* If no convar list... */
|
/* If no convar list... */
|
||||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
|
UTIL_ConsolePrint("[SM] No convars found for: %s", plname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wantReset)
|
if (!wantReset)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
UTIL_ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
UTIL_ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate convar list and display/reset each one */
|
/* Iterate convar list and display/reset each one */
|
||||||
@ -390,7 +306,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
|
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
|
||||||
if (!wantReset)
|
if (!wantReset)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
UTIL_ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
||||||
} else {
|
} else {
|
||||||
pConVar->Revert();
|
pConVar->Revert();
|
||||||
}
|
}
|
||||||
@ -398,14 +314,14 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
|
|
||||||
if (wantReset)
|
if (wantReset)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
|
UTIL_ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display usage of subcommand */
|
/* Display usage of subcommand */
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>");
|
UTIL_ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>");
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
|
Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
|
||||||
@ -625,35 +541,13 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
|||||||
|
|
||||||
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
|
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
|
||||||
{
|
{
|
||||||
QueryCvarCookie_t cookie = 0;
|
QueryCvarCookie_t cookie = sCoreProviderImpl.QueryClientConVar(IndexOfEdict(pPlayer), name);
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
|
||||||
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
|
|
||||||
#else
|
|
||||||
cookie = engine->StartQueryCvarValue(pPlayer, name);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return InvalidQueryCvarCookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCallback != NULL)
|
if (pCallback != NULL)
|
||||||
{
|
{
|
||||||
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||||
m_ConVarQueries.push_back(query);
|
m_ConVarQueries.push_back(query);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
@ -696,11 +590,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||||
#else
|
|
||||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/* If the values are the same, exit early in order to not trigger callbacks */
|
/* If the values are the same, exit early in order to not trigger callbacks */
|
||||||
if (strcmp(pConVar->GetString(), oldValue) == 0)
|
if (strcmp(pConVar->GetString(), oldValue) == 0)
|
||||||
@ -720,16 +610,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|||||||
|
|
||||||
if (pInfo->changeListeners.size() != 0)
|
if (pInfo->changeListeners.size() != 0)
|
||||||
{
|
{
|
||||||
for (List<IConVarChangeListener *>::iterator i = pInfo->changeListeners.begin();
|
for (auto i = pInfo->changeListeners.begin(); i != pInfo->changeListeners.end(); i++)
|
||||||
i != pInfo->changeListeners.end();
|
|
||||||
i++)
|
|
||||||
{
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
||||||
#else
|
|
||||||
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pForward != NULL)
|
if (pForward != NULL)
|
||||||
@ -746,23 +628,16 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|||||||
|
|
||||||
bool ConVarManager::IsQueryingSupported()
|
bool ConVarManager::IsQueryingSupported()
|
||||||
{
|
{
|
||||||
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
|
return sCoreProviderImpl.IsClientConVarQueryingSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie,
|
||||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
int client,
|
||||||
#else
|
EQueryCvarValueStatus result,
|
||||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
const char *cvarName,
|
||||||
#endif // SE_DOTA
|
const char *cvarValue)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
|
||||||
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IPluginFunction *pCallback = NULL;
|
IPluginFunction *pCallback = NULL;
|
||||||
cell_t value = 0;
|
cell_t value = 0;
|
||||||
List<ConVarQuery>::iterator iter;
|
List<ConVarQuery>::iterator iter;
|
||||||
@ -783,11 +658,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
|||||||
cell_t ret;
|
cell_t ret;
|
||||||
|
|
||||||
pCallback->PushCell(cookie);
|
pCallback->PushCell(cookie);
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
pCallback->PushCell(client);
|
||||||
pCallback->PushCell(player.Get());
|
|
||||||
#else
|
|
||||||
pCallback->PushCell(IndexOfEdict(pPlayer));
|
|
||||||
#endif
|
|
||||||
pCallback->PushCell(result);
|
pCallback->PushCell(result);
|
||||||
pCallback->PushString(cvarName);
|
pCallback->PushString(cvarName);
|
||||||
|
|
||||||
|
@ -43,11 +43,7 @@
|
|||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
#if SOURCE_ENGINE == SE_DARKMESSIAH
|
|
||||||
class EQueryCvarValueStatus;
|
|
||||||
typedef int QueryCvarCookie_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
@ -72,6 +68,10 @@ struct ConVarInfo
|
|||||||
{
|
{
|
||||||
return strcmp(name, info->pVar->GetName()) == 0;
|
return strcmp(name, info->pVar->GetName()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,16 +100,15 @@ public: // SMGlobalClass
|
|||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
void OnSourceModVSPReceived();
|
|
||||||
public: // IHandleTypeDispatch
|
public: // IHandleTypeDispatch
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
void OnHandleDestroy(HandleType_t type, void *object);
|
||||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||||
public: // IPluginsListener
|
public: // IPluginsListener
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public: //IRootConsoleCommand
|
public: //IRootConsoleCommand
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
|
||||||
public: //IConCommandTracker
|
public: //IConCommandTracker
|
||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
|
||||||
public: //IClientListener
|
public: //IClientListener
|
||||||
void OnClientDisconnected(int client);
|
void OnClientDisconnected(int client);
|
||||||
public:
|
public:
|
||||||
@ -147,37 +146,26 @@ public:
|
|||||||
|
|
||||||
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
|
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
|
||||||
|
|
||||||
|
// Called via game hooks.
|
||||||
|
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
void OnClientQueryFinished(
|
||||||
|
QueryCvarCookie_t cookie,
|
||||||
|
int client,
|
||||||
|
EQueryCvarValueStatus result,
|
||||||
|
const char *cvarName,
|
||||||
|
const char *cvarValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Adds a convar to a plugin's list.
|
* Adds a convar to a plugin's list.
|
||||||
*/
|
*/
|
||||||
static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
|
static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
|
||||||
|
|
||||||
/**
|
|
||||||
* Static callback that Valve's ConVar object executes when the convar's value changes.
|
|
||||||
*/
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
|
||||||
#else
|
|
||||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for when StartQueryCvarValue() has finished.
|
|
||||||
*/
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result,
|
|
||||||
const char *cvarName, const char *cvarValue);
|
|
||||||
#elif SOURCE_ENGINE != SE_DARKMESSIAH
|
|
||||||
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
|
||||||
const char *cvarName, const char *cvarValue);
|
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
HandleType_t m_ConVarType;
|
HandleType_t m_ConVarType;
|
||||||
List<ConVarInfo *> m_ConVars;
|
List<ConVarInfo *> m_ConVars;
|
||||||
List<ConVarQuery> m_ConVarQueries;
|
List<ConVarQuery> m_ConVarQueries;
|
||||||
bool m_bIsDLLQueryHooked;
|
|
||||||
bool m_bIsVSPQueryHooked;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConVarManager g_ConVarManager;
|
extern ConVarManager g_ConVarManager;
|
||||||
|
@ -50,7 +50,10 @@
|
|||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "ConCommandBaseIterator.h"
|
#include "ConCommandBaseIterator.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include "command_args.h"
|
||||||
|
#include "provider.h"
|
||||||
#include <am-utility.h>
|
#include <am-utility.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
#if defined PLATFORM_POSIX
|
#if defined PLATFORM_POSIX
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
@ -59,25 +62,11 @@
|
|||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SH_IMPL_VERSION >= 5
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
# if SOURCE_ENGINE == SE_DOTA
|
|
||||||
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
|
||||||
# elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
#else
|
#else
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
#endif
|
#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
|
class GenericCommandHooker : public IConCommandLinkListener
|
||||||
{
|
{
|
||||||
@ -134,9 +123,7 @@ class GenericCommandHooker : public IConCommandLinkListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void Dispatch(const CCommandContext &context, const CCommand& args)
|
|
||||||
# elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void Dispatch(const CCommand& args)
|
void Dispatch(const CCommand& args)
|
||||||
#else
|
#else
|
||||||
void Dispatch()
|
void Dispatch()
|
||||||
@ -262,308 +249,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
* BEGIN THE ACTUALLY GENERIC CODE.
|
||||||
*/
|
*/
|
||||||
@ -622,13 +307,13 @@ bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
|
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||||
IChangeableForward *forward;
|
IChangeableForward *forward;
|
||||||
if (!m_Listeners.retrieve(str, &forward))
|
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||||
{
|
{
|
||||||
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
||||||
Param_String, Param_Cell);
|
Param_String, Param_Cell);
|
||||||
m_Listeners.insert(str, forward);
|
m_Listeners.insert(str.get(), forward);
|
||||||
}
|
}
|
||||||
forward->AddFunction(fun);
|
forward->AddFunction(fun);
|
||||||
}
|
}
|
||||||
@ -644,18 +329,18 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
|
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||||
IChangeableForward *forward;
|
IChangeableForward *forward;
|
||||||
if (!m_Listeners.retrieve(str, &forward))
|
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||||
return false;
|
return false;
|
||||||
return forward->RemoveFunction(fun);
|
return forward->RemoveFunction(fun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
|
cell_t ConsoleDetours::InternalDispatch(int client, const ICommandArgs *args)
|
||||||
{
|
{
|
||||||
char name[255];
|
char name[255];
|
||||||
const char *realname = args.Arg(0);
|
const char *realname = args->Arg(0);
|
||||||
size_t len = strlen(realname);
|
size_t len = strlen(realname);
|
||||||
|
|
||||||
// Disallow command strings that are too long, for now.
|
// Disallow command strings that are too long, for now.
|
||||||
@ -674,7 +359,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
|
|||||||
cell_t result = Pl_Continue;
|
cell_t result = Pl_Continue;
|
||||||
m_pForward->PushCell(client);
|
m_pForward->PushCell(client);
|
||||||
m_pForward->PushString(name);
|
m_pForward->PushString(name);
|
||||||
m_pForward->PushCell(args.ArgC() - 1);
|
m_pForward->PushCell(args->ArgC() - 1);
|
||||||
m_pForward->Execute(&result, NULL);
|
m_pForward->Execute(&result, NULL);
|
||||||
|
|
||||||
/* Don't let plugins block this. */
|
/* Don't let plugins block this. */
|
||||||
@ -693,7 +378,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
|
|||||||
cell_t result2 = Pl_Continue;
|
cell_t result2 = Pl_Continue;
|
||||||
forward->PushCell(client);
|
forward->PushCell(client);
|
||||||
forward->PushString(name);
|
forward->PushString(name);
|
||||||
forward->PushCell(args.ArgC() - 1);
|
forward->PushCell(args->ArgC() - 1);
|
||||||
forward->Execute(&result2, NULL);
|
forward->Execute(&result2, NULL);
|
||||||
|
|
||||||
if (result2 > result)
|
if (result2 > result)
|
||||||
@ -713,27 +398,12 @@ cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
|
|||||||
{
|
{
|
||||||
CCommand args;
|
CCommand args;
|
||||||
#endif
|
#endif
|
||||||
g_HL2.PushCommandStack(&args);
|
EngineArgs cargs(args);
|
||||||
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args);
|
cell_t res;
|
||||||
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
|
AutoEnterCommand autoEnterCommand(&cargs);
|
||||||
* is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY.
|
res = g_ConsoleDetours.InternalDispatch(sCoreProviderImpl.CommandClient(), &cargs);
|
||||||
*/
|
|
||||||
SH_ADD_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
|
|
||||||
dummy_hook_set = true;
|
|
||||||
pBase->Dispatch();
|
|
||||||
SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make sure the command gets invoked. See bug 4019 on making this better. */
|
|
||||||
pBase->Dispatch();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <sm_stringhashmap.h>
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
class ICommandArgs;
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
class ConsoleDetours :
|
class ConsoleDetours :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IFeatureProvider
|
public IFeatureProvider
|
||||||
@ -54,7 +58,7 @@ public:
|
|||||||
bool AddListener(IPluginFunction *fun, const char *command);
|
bool AddListener(IPluginFunction *fun, const char *command);
|
||||||
bool RemoveListener(IPluginFunction *fun, const char *command);
|
bool RemoveListener(IPluginFunction *fun, const char *command);
|
||||||
private:
|
private:
|
||||||
cell_t InternalDispatch(int client, const CCommand& args);
|
cell_t InternalDispatch(int client, const SourceMod::ICommandArgs *args);
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
|
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
|
||||||
#else
|
#else
|
||||||
|
@ -33,13 +33,20 @@
|
|||||||
#include "CoreConfig.h"
|
#include "CoreConfig.h"
|
||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include "compat_wrappers.h"
|
||||||
#include <sourcemod_version.h>
|
#include <sourcemod_version.h>
|
||||||
|
#include <amtl/os/am-path.h>
|
||||||
|
#include <amtl/os/am-fsutil.h>
|
||||||
|
#include <sh_list.h>
|
||||||
|
#include <IForwardSys.h>
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
|
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
|
||||||
@ -60,23 +67,12 @@ ConVar *g_ServerCfgFile = NULL;
|
|||||||
|
|
||||||
void CheckAndFinalizeConfigs();
|
void CheckAndFinalizeConfigs();
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
|
||||||
void Hook_ExecDispatchPre(const CCommandContext &context, const CCommand &cmd)
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
void Hook_ExecDispatchPre(const CCommand &cmd)
|
void Hook_ExecDispatchPre(const CCommand &cmd)
|
||||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
#else
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
void Hook_ExecDispatchPre()
|
void Hook_ExecDispatchPre()
|
||||||
#else
|
|
||||||
# if SH_IMPL_VERSION >= 4
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
# else
|
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
# endif
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
void Hook_ExecDispatchPre()
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
@ -91,9 +87,7 @@ void Hook_ExecDispatchPre()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void Hook_ExecDispatchPost(const CCommand &cmd)
|
void Hook_ExecDispatchPost(const CCommand &cmd)
|
||||||
#else
|
#else
|
||||||
void Hook_ExecDispatchPost()
|
void Hook_ExecDispatchPost()
|
||||||
@ -117,7 +111,7 @@ void CheckAndFinalizeConfigs()
|
|||||||
|
|
||||||
void CoreConfig::OnSourceModAllInitialized()
|
void CoreConfig::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
|
rootmenu->AddRootConsoleCommand3("config", "Set core configuration options", this);
|
||||||
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
||||||
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
||||||
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
||||||
@ -133,7 +127,7 @@ CoreConfig::~CoreConfig()
|
|||||||
|
|
||||||
void CoreConfig::OnSourceModShutdown()
|
void CoreConfig::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
rootmenu->RemoveRootConsoleCommand("config", this);
|
||||||
forwardsys->ReleaseForward(g_pOnServerCfg);
|
forwardsys->ReleaseForward(g_pOnServerCfg);
|
||||||
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
|
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
|
||||||
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
|
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
|
||||||
@ -183,44 +177,45 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
|||||||
g_bGotTrigger = false;
|
g_bGotTrigger = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
|
||||||
{
|
{
|
||||||
int argcount = command.ArgC();
|
int argcount = command->ArgC();
|
||||||
if (argcount >= 4)
|
if (argcount >= 4)
|
||||||
{
|
{
|
||||||
const char *option = command.Arg(2);
|
const char *option = command->Arg(2);
|
||||||
const char *value = command.Arg(3);
|
const char *value = command->Arg(3);
|
||||||
|
|
||||||
char error[255];
|
char error[255];
|
||||||
|
|
||||||
ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
|
ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
|
||||||
|
|
||||||
if (res == ConfigResult_Reject)
|
if (res == ConfigResult_Reject)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error);
|
UTIL_ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error);
|
||||||
} else if (res == ConfigResult_Ignore) {
|
|
||||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
|
||||||
} else {
|
} else {
|
||||||
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" successfully set to \"%s\".", option, value);
|
if (res == ConfigResult_Ignore) {
|
||||||
|
UTIL_ConsolePrint("[SM] WARNING: Config option \"%s\" is not registered.", option);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTIL_ConsolePrint("[SM] Config option \"%s\" set to \"%s\".", option, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (argcount >= 3) {
|
} else if (argcount >= 3) {
|
||||||
const char *option = command.Arg(2);
|
const char *option = command->Arg(2);
|
||||||
|
|
||||||
const char *value = GetCoreConfigValue(option);
|
const char *value = GetCoreConfigValue(option);
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
UTIL_ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
||||||
} else {
|
} else {
|
||||||
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
|
UTIL_ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]");
|
UTIL_ConsolePrint("[SM] Usage: sm config <option> [value]");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::Initialize()
|
void CoreConfig::Initialize()
|
||||||
@ -237,7 +232,7 @@ void CoreConfig::Initialize()
|
|||||||
*/
|
*/
|
||||||
if (corecfg)
|
if (corecfg)
|
||||||
{
|
{
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -246,11 +241,11 @@ void CoreConfig::Initialize()
|
|||||||
/* Format path to config file */
|
/* Format path to config file */
|
||||||
if (basepath)
|
if (basepath)
|
||||||
{
|
{
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +277,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
|||||||
|
|
||||||
ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
|
ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
ConfigResult result;
|
ConfigResult result = ConfigResult_Ignore;
|
||||||
|
|
||||||
/* Notify! */
|
/* Notify! */
|
||||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||||
@ -290,7 +285,7 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
|
|||||||
{
|
{
|
||||||
if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
|
if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
|
||||||
{
|
{
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
pBase = pBase->m_pGlobalClassNext;
|
pBase = pBase->m_pGlobalClassNext;
|
||||||
}
|
}
|
||||||
@ -298,7 +293,7 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
|
|||||||
ke::AString vstr(value);
|
ke::AString vstr(value);
|
||||||
m_KeyValues.replace(option, ke::Move(vstr));
|
m_KeyValues.replace(option, ke::Move(vstr));
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CoreConfig::GetCoreConfigValue(const char *key)
|
const char *CoreConfig::GetCoreConfigValue(const char *key)
|
||||||
@ -341,12 +336,12 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "cfg/%s", folder);
|
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "cfg/%s", folder);
|
||||||
|
|
||||||
if (!g_LibSys.IsPathDirectory(path))
|
if (!ke::file::IsDirectory(path))
|
||||||
{
|
{
|
||||||
char *cur_ptr = path;
|
char *cur_ptr = path;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
|
ke::path::Format(path, sizeof(path), "%s", folder);
|
||||||
len = g_SourceMod.BuildPath(Path_Game, build, sizeof(build), "cfg");
|
len = g_SourceMod.BuildPath(Path_Game, build, sizeof(build), "cfg");
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -367,14 +362,12 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
{
|
{
|
||||||
next_ptr = NULL;
|
next_ptr = NULL;
|
||||||
}
|
}
|
||||||
len += g_LibSys.PathFormat(&build[len],
|
len += ke::path::Format(&build[len],
|
||||||
sizeof(build)-len,
|
sizeof(build)-len,
|
||||||
"/%s",
|
"/%s",
|
||||||
cur_ptr);
|
cur_ptr);
|
||||||
if (!g_LibSys.CreateFolder(build))
|
if (!ke::file::CreateDirectory(build))
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
cur_ptr = next_ptr;
|
cur_ptr = next_ptr;
|
||||||
} while (cur_ptr);
|
} while (cur_ptr);
|
||||||
}
|
}
|
||||||
@ -386,13 +379,13 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
|
|
||||||
if (cfg->folder.size())
|
if (cfg->folder.size())
|
||||||
{
|
{
|
||||||
g_LibSys.PathFormat(local,
|
ke::path::Format(local,
|
||||||
sizeof(local),
|
sizeof(local),
|
||||||
"%s/%s.cfg",
|
"%s/%s.cfg",
|
||||||
cfg->folder.c_str(),
|
cfg->folder.c_str(),
|
||||||
cfg->autocfg.c_str());
|
cfg->autocfg.c_str());
|
||||||
} else {
|
} else {
|
||||||
g_LibSys.PathFormat(local,
|
ke::path::Format(local,
|
||||||
sizeof(local),
|
sizeof(local),
|
||||||
"%s.cfg",
|
"%s.cfg",
|
||||||
cfg->autocfg.c_str());
|
cfg->autocfg.c_str());
|
||||||
@ -400,7 +393,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, file, sizeof(file), "cfg/%s", local);
|
g_SourceMod.BuildPath(Path_Game, file, sizeof(file), "cfg/%s", local);
|
||||||
|
|
||||||
bool file_exists = g_LibSys.IsPathFile(file);
|
bool file_exists = ke::file::IsFile(file);
|
||||||
if (!file_exists && will_create)
|
if (!file_exists && will_create)
|
||||||
{
|
{
|
||||||
List<const ConVar *> *convars = NULL;
|
List<const ConVar *> *convars = NULL;
|
||||||
@ -419,8 +412,11 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
for (iter = convars->begin(); iter != convars->end(); iter++)
|
for (iter = convars->begin(); iter != convars->end(); iter++)
|
||||||
{
|
{
|
||||||
const ConVar *cvar = (*iter);
|
const ConVar *cvar = (*iter);
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
if ((cvar->GetFlags() & FCVAR_DONTRECORD) == FCVAR_DONTRECORD)
|
if (cvar->IsFlagSet(FCVAR_DONTRECORD))
|
||||||
|
#else
|
||||||
|
if (cvar->IsBitSet(FCVAR_DONTRECORD))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -429,7 +425,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
char *dptr = descr;
|
char *dptr = descr;
|
||||||
|
|
||||||
/* Print comments until there is no more */
|
/* Print comments until there is no more */
|
||||||
strncopy(descr, cvar->GetHelpText(), sizeof(descr));
|
ke::SafeStrcpy(descr, sizeof(descr), cvar->GetHelpText());
|
||||||
while (*dptr != '\0')
|
while (*dptr != '\0')
|
||||||
{
|
{
|
||||||
/* Find the next line */
|
/* Find the next line */
|
||||||
@ -478,7 +474,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
if (file_exists)
|
if (file_exists)
|
||||||
{
|
{
|
||||||
char cmd[255];
|
char cmd[255];
|
||||||
UTIL_Format(cmd, sizeof(cmd), "exec %s\n", local);
|
ke::SafeSprintf(cmd, sizeof(cmd), "exec %s\n", local);
|
||||||
engine->ServerCommand(cmd);
|
engine->ServerCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +529,7 @@ void SM_ExecuteForPlugin(IPluginContext *ctx)
|
|||||||
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
||||||
}
|
}
|
||||||
char cmd[255];
|
char cmd[255];
|
||||||
UTIL_Format(cmd, sizeof(cmd), "sm internal 2 %d\n", plugin->GetSerial());
|
ke::SafeSprintf(cmd, sizeof(cmd), "sm_internal 2 %d\n", plugin->GetSerial());
|
||||||
engine->ServerCommand(cmd);
|
engine->ServerCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -580,7 +576,24 @@ void SM_InternalCmdTrigger()
|
|||||||
{
|
{
|
||||||
/* Order is important here. We need to buffer things before we send the command out. */
|
/* Order is important here. We need to buffer things before we send the command out. */
|
||||||
g_pOnAutoConfigsBuffered->Execute(NULL);
|
g_pOnAutoConfigsBuffered->Execute(NULL);
|
||||||
engine->ServerCommand("sm internal 1\n");
|
engine->ServerCommand("sm_internal 1\n");
|
||||||
g_PendingInternalPush = false;
|
g_PendingInternalPush = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CON_COMMAND(sm_internal, "")
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
|
CCommand args;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (args.ArgC() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *arg = args.Arg(1);
|
||||||
|
if (strcmp(arg, "1") == 0) {
|
||||||
|
SM_ConfigsExecuted_Global();
|
||||||
|
} else if (strcmp(arg, "2") == 0) {
|
||||||
|
if (args.ArgC() >= 3)
|
||||||
|
SM_ConfigsExecuted_Plugin(atoi(args.Arg(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -55,7 +55,7 @@ public: // SMGlobalClass
|
|||||||
public: // ITextListener_SMC
|
public: // ITextListener_SMC
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||||
public: // IRootConsoleCommand
|
public: // IRootConsoleCommand
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Initializes CoreConfig by reading from core.cfg file
|
* Initializes CoreConfig by reading from core.cfg file
|
||||||
|
@ -1,199 +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 "sm_globals.h"
|
|
||||||
#include "sourcemm_api.h"
|
|
||||||
#include "Tlhelp32.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "minidump.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
bool HookImportAddrTable(BYTE *base, const char *func, DWORD hookfunc, char *err, size_t maxlength)
|
|
||||||
{
|
|
||||||
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)base;
|
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
{
|
|
||||||
UTIL_Format(err, maxlength, "%s", "Could not detect valid DOS signature");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
|
|
||||||
if (nt->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
UTIL_Format(err, maxlength, "%s", "Could not detect valid NT signature");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR *desc =
|
|
||||||
(IMAGE_IMPORT_DESCRIPTOR *)
|
|
||||||
(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
|
||||||
if (base == (BYTE *)desc)
|
|
||||||
{
|
|
||||||
UTIL_Format(err, maxlength, "%s", "Could not find IAT");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool entryFound = false;
|
|
||||||
while (desc->Name)
|
|
||||||
{
|
|
||||||
if (desc->FirstThunk != 0)
|
|
||||||
{
|
|
||||||
IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
|
|
||||||
DWORD *iat = (DWORD *)(base + desc->FirstThunk);
|
|
||||||
while (data->u1.Function)
|
|
||||||
{
|
|
||||||
if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
|
|
||||||
{
|
|
||||||
IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
|
|
||||||
if (strcmp((char *)import->Name, func) == 0)
|
|
||||||
{
|
|
||||||
DWORD oldprot, oldprot2;
|
|
||||||
VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
|
|
||||||
*iat = hookfunc;
|
|
||||||
VirtualProtect(iat, 4, oldprot, &oldprot2);
|
|
||||||
entryFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
iat++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entryFound)
|
|
||||||
{
|
|
||||||
UTIL_Format(err, maxlength, "Could not find IAT entry for %s", func);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
MiniDumpWriteDump2(
|
|
||||||
IN HANDLE hProcess,
|
|
||||||
IN DWORD ProcessId,
|
|
||||||
IN HANDLE hFile,
|
|
||||||
IN MINIDUMP_TYPE DumpType,
|
|
||||||
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
|
|
||||||
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
|
|
||||||
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DumpType = (MINIDUMP_TYPE)((int)DumpType|MiniDumpWithFullMemory|MiniDumpWithHandleData);
|
|
||||||
return MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType, ExceptionParam, UserStreamParam, CallbackParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
FARPROC WINAPI GetProcAddress2(HMODULE hModule, LPCSTR lpProcName)
|
|
||||||
{
|
|
||||||
if (strcmp(lpProcName, "MiniDumpWriteDump") == 0)
|
|
||||||
{
|
|
||||||
return (FARPROC)MiniDumpWriteDump2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetProcAddress(hModule, lpProcName);
|
|
||||||
}
|
|
||||||
|
|
||||||
HMODULE WINAPI LoadLibraryEx2(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
|
|
||||||
{
|
|
||||||
HMODULE lib = LoadLibraryEx(lpFileName, hFile, dwFlags);
|
|
||||||
|
|
||||||
/* Steam.dll seems to get loaded using an abs path, thus the use of stristr() */
|
|
||||||
if (stristr(lpFileName, "steam.dll"))
|
|
||||||
{
|
|
||||||
char err[64];
|
|
||||||
if (!HookImportAddrTable((BYTE *)lib, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
|
|
||||||
{
|
|
||||||
Error("[SM] %s in steam.dll\n", err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CrazyWindowsDebugger : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
|
||||||
MODULEENTRY32 me32;
|
|
||||||
BYTE *engine = NULL;
|
|
||||||
BYTE *steam = NULL;
|
|
||||||
char err[64];
|
|
||||||
|
|
||||||
me32.dwSize = sizeof(MODULEENTRY32);
|
|
||||||
|
|
||||||
if (!Module32First(hModuleList, &me32))
|
|
||||||
{
|
|
||||||
Error("Could not initialize crazy debugger!");
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (strcasecmp(me32.szModule, "engine.dll") == 0)
|
|
||||||
{
|
|
||||||
engine = me32.modBaseAddr;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(me32.szModule, "steam.dll") == 0)
|
|
||||||
{
|
|
||||||
steam = me32.modBaseAddr;
|
|
||||||
}
|
|
||||||
} while (Module32Next(hModuleList, &me32));
|
|
||||||
|
|
||||||
CloseHandle(hModuleList);
|
|
||||||
|
|
||||||
/* This really should not happen, but ... */
|
|
||||||
if (!engine)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not find engine.dll\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Steam.dll isn't loaded yet */
|
|
||||||
if (!steam)
|
|
||||||
{
|
|
||||||
if (!HookImportAddrTable(engine, "LoadLibraryExA", (DWORD)LoadLibraryEx2, err, sizeof(err)))
|
|
||||||
{
|
|
||||||
Error("[SM] %s in engine.dll)\n", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!HookImportAddrTable(steam, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
|
|
||||||
{
|
|
||||||
Error("[SM] %s in steam.dll)\n", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} s_CrazyDebugger;
|
|
@ -31,7 +31,10 @@
|
|||||||
|
|
||||||
#include "EventManager.h"
|
#include "EventManager.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
EventManager g_EventManager;
|
EventManager g_EventManager;
|
||||||
|
|
||||||
@ -155,7 +158,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
|||||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
int EventManager::GetEventDebugID()
|
int EventManager::GetEventDebugID()
|
||||||
{
|
{
|
||||||
return EVENT_DEBUG_ID_INIT;
|
return EVENT_DEBUG_ID_INIT;
|
||||||
@ -359,6 +362,13 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
|
|||||||
m_FreeEvents.push(pInfo);
|
m_FreeEvents.push(pInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
|
||||||
|
{
|
||||||
|
// The IClient vtable is +sizeof(void *) from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||||
|
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - sizeof(void *));
|
||||||
|
pGameClient->FireGameEvent(pInfo->pEvent);
|
||||||
|
}
|
||||||
|
|
||||||
void EventManager::CancelCreatedEvent(EventInfo *pInfo)
|
void EventManager::CancelCreatedEvent(EventInfo *pInfo)
|
||||||
{
|
{
|
||||||
/* Free event from IGameEventManager2 */
|
/* Free event from IGameEventManager2 */
|
||||||
@ -423,7 +433,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
m_EventCopies.push(gameevents->DuplicateEvent(pEvent));
|
m_EventCopies.push(gameevents->DuplicateEvent(pEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res)
|
if (res >= Pl_Handled)
|
||||||
{
|
{
|
||||||
gameevents->FreeEvent(pEvent);
|
gameevents->FreeEvent(pEvent);
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
|
|
||||||
|
class IClient;
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
struct EventInfo
|
struct EventInfo
|
||||||
@ -75,6 +77,10 @@ struct EventHook
|
|||||||
{
|
{
|
||||||
return strcmp(name, hook->name.chars()) == 0;
|
return strcmp(name, hook->name.chars()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EventHookMode
|
enum EventHookMode
|
||||||
@ -110,7 +116,7 @@ public: // IPluginsListener
|
|||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public: // IGameEventListener2
|
public: // IGameEventListener2
|
||||||
void FireGameEvent(IGameEvent *pEvent);
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
int GetEventDebugID();
|
int GetEventDebugID();
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
@ -126,6 +132,7 @@ public:
|
|||||||
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
|
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
|
||||||
EventInfo *CreateEvent(IPluginContext *pContext, const char *name, bool force=false);
|
EventInfo *CreateEvent(IPluginContext *pContext, const char *name, bool force=false);
|
||||||
void FireEvent(EventInfo *pInfo, bool bDontBroadcast=false);
|
void FireEvent(EventInfo *pInfo, bool bDontBroadcast=false);
|
||||||
|
void FireEventToClient(EventInfo *pInfo, IClient *pClient);
|
||||||
void CancelCreatedEvent(EventInfo *pInfo);
|
void CancelCreatedEvent(EventInfo *pInfo);
|
||||||
private: // IGameEventManager2 hooks
|
private: // IGameEventManager2 hooks
|
||||||
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
|
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
|
||||||
|
171
core/GameHooks.cpp
Normal file
171
core/GameHooks.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#include "GameHooks.h"
|
||||||
|
#include "sourcemod.h"
|
||||||
|
#include "ConVarManager.h"
|
||||||
|
#include "command_args.h"
|
||||||
|
#include "provider.h"
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
||||||
|
#else
|
||||||
|
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, 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
|
||||||
|
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
|
||||||
|
|
||||||
|
GameHooks::GameHooks()
|
||||||
|
: client_cvar_query_mode_(ClientCvarQueryMode::Unavailable),
|
||||||
|
last_command_client_(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHooks::Start()
|
||||||
|
{
|
||||||
|
// Hook ICvar::CallGlobalChangeCallbacks.
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#else
|
||||||
|
hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Episode 2 has this function by default, but the older versions do not.
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
if (g_SMAPI->GetGameDLLVersion() >= 6) {
|
||||||
|
hooks_ += SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false);
|
||||||
|
client_cvar_query_mode_ = ClientCvarQueryMode::DLL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hooks_ += SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &GameHooks::SetCommandClient), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHooks::OnVSPReceived()
|
||||||
|
{
|
||||||
|
if (client_cvar_query_mode_ != ClientCvarQueryMode::Unavailable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
hooks_ += SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false);
|
||||||
|
client_cvar_query_mode_ = ClientCvarQueryMode::VSP;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHooks::Shutdown()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < hooks_.length(); i++)
|
||||||
|
SH_REMOVE_HOOK_ID(hooks_[i]);
|
||||||
|
hooks_.clear();
|
||||||
|
|
||||||
|
client_cvar_query_mode_ = ClientCvarQueryMode::Unavailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||||
|
#else
|
||||||
|
void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||||
|
float flOldValue = atof(oldValue);
|
||||||
|
#endif
|
||||||
|
g_ConVarManager.OnConVarChanged(pConVar, oldValue, flOldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
void GameHooks::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
||||||
|
const char *cvarName, const char *cvarValue){
|
||||||
|
int client = IndexOfEdict(pPlayer);
|
||||||
|
|
||||||
|
# if SOURCE_ENGINE == SE_CSGO
|
||||||
|
if (g_Players.HandleConVarQuery(cookie, client, result, cvarName, cvarValue))
|
||||||
|
return;
|
||||||
|
# endif
|
||||||
|
g_ConVarManager.OnClientQueryFinished(cookie, client, result, cvarName, cvarValue);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ke::RefPtr<CommandHook>
|
||||||
|
GameHooks::AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
|
||||||
|
{
|
||||||
|
return new CommandHook(cmd, callback, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ke::RefPtr<CommandHook>
|
||||||
|
GameHooks::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
|
||||||
|
{
|
||||||
|
return new CommandHook(cmd, callback, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameHooks::SetCommandClient(int client)
|
||||||
|
{
|
||||||
|
last_command_client_ = client + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandHook::CommandHook(ConCommand *cmd, const Callback &callback, bool post)
|
||||||
|
: hook_id_(0),
|
||||||
|
callback_(callback)
|
||||||
|
{
|
||||||
|
hook_id_ = SH_ADD_HOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &CommandHook::Dispatch), post);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandHook::~CommandHook()
|
||||||
|
{
|
||||||
|
if (hook_id_)
|
||||||
|
SH_REMOVE_HOOK_ID(hook_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandHook::Dispatch(DISPATCH_ARGS)
|
||||||
|
{
|
||||||
|
DISPATCH_PROLOGUE;
|
||||||
|
EngineArgs args(command);
|
||||||
|
|
||||||
|
AddRef();
|
||||||
|
bool rval = callback_(sCoreProviderImpl.CommandClient(), &args);
|
||||||
|
Release();
|
||||||
|
if (rval)
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandHook::Zap()
|
||||||
|
{
|
||||||
|
hook_id_ = 0;
|
||||||
|
}
|
133
core/GameHooks.h
Normal file
133
core/GameHooks.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_
|
||||||
|
|
||||||
|
// Needed for CEntityIndex, edict_t, etc.
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <eiface.h>
|
||||||
|
#include <iserverplugin.h>
|
||||||
|
#include <amtl/am-refcounting.h>
|
||||||
|
#include <amtl/am-vector.h>
|
||||||
|
#include <amtl/am-function.h>
|
||||||
|
|
||||||
|
class ConVar;
|
||||||
|
class CCommand;
|
||||||
|
struct CCommandContext;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
# define DISPATCH_ARGS const CCommand &command
|
||||||
|
# define DISPATCH_PROLOGUE
|
||||||
|
#else
|
||||||
|
# define DISPATCH_ARGS
|
||||||
|
# define DISPATCH_PROLOGUE CCommand command
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SourceMod {
|
||||||
|
|
||||||
|
// Describes the mechanism in which client cvar queries are implemented.
|
||||||
|
enum class ClientCvarQueryMode {
|
||||||
|
Unavailable,
|
||||||
|
DLL,
|
||||||
|
VSP
|
||||||
|
};
|
||||||
|
|
||||||
|
class ICommandArgs;
|
||||||
|
|
||||||
|
class CommandHook : public ke::Refcounted<CommandHook>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// return false to RETURN_META(MRES_IGNORED), or true to SUPERCEDE.
|
||||||
|
typedef ke::Lambda<bool(int, const ICommandArgs *)> Callback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CommandHook(ConCommand *cmd, const Callback &callback, bool post);
|
||||||
|
~CommandHook();
|
||||||
|
void Dispatch(DISPATCH_ARGS);
|
||||||
|
void Zap();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int hook_id_;
|
||||||
|
Callback callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GameHooks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GameHooks();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Shutdown();
|
||||||
|
void OnVSPReceived();
|
||||||
|
|
||||||
|
ClientCvarQueryMode GetClientCvarQueryMode() const {
|
||||||
|
return client_cvar_query_mode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ke::RefPtr<CommandHook> AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
|
||||||
|
ke::RefPtr<CommandHook> AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
|
||||||
|
|
||||||
|
int CommandClient() const {
|
||||||
|
return last_command_client_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Static callback that Valve's ConVar object executes when the convar's value changes.
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||||
|
#else
|
||||||
|
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
void SetCommandClient(int client);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class HookList : public ke::Vector<int>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HookList &operator += (int hook_id) {
|
||||||
|
this->append(hook_id);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
HookList hooks_;
|
||||||
|
|
||||||
|
ClientCvarQueryMode client_cvar_query_mode_;
|
||||||
|
int last_command_client_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_
|
@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 sw=4 tw=99 noet :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -38,38 +38,20 @@
|
|||||||
#include <IGameConfigs.h>
|
#include <IGameConfigs.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
#include <Logger.h>
|
#include <Logger.h>
|
||||||
#include "LibrarySys.h"
|
#include <amtl/os/am-shared-library.h>
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
#include <tier0/mem.h>
|
#include <tier0/mem.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
#include <game/shared/protobuf/usermessages.pb.h>
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
#include <cstrike15_usermessages.pb.h>
|
#include <cstrike15_usermessages.pb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef ICommandLine *(*FakeGetCommandLine)();
|
typedef ICommandLine *(*FakeGetCommandLine)();
|
||||||
|
|
||||||
#if defined _WIN32
|
#define TIER0_NAME FORMAT_SOURCE_BIN_NAME("tier0")
|
||||||
#define TIER0_NAME "tier0.dll"
|
#define VSTDLIB_NAME FORMAT_SOURCE_BIN_NAME("vstdlib")
|
||||||
#define VSTDLIB_NAME "vstdlib.dll"
|
|
||||||
#elif defined __APPLE__
|
|
||||||
#define TIER0_NAME "libtier0.dylib"
|
|
||||||
#define VSTDLIB_NAME "libvstdlib.dylib"
|
|
||||||
#elif defined __linux__
|
|
||||||
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
|
||||||
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN
|
|
||||||
#define TIER0_NAME "libtier0_srv.so"
|
|
||||||
#define VSTDLIB_NAME "libvstdlib_srv.so"
|
|
||||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
|
||||||
#define TIER0_NAME "libtier0.so"
|
|
||||||
#define VSTDLIB_NAME "libvstdlib.so"
|
|
||||||
#else
|
|
||||||
#define TIER0_NAME "tier0_i486.so"
|
|
||||||
#define VSTDLIB_NAME "vstdlib_i486.so"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CHalfLife2 g_HL2;
|
CHalfLife2 g_HL2;
|
||||||
ConVar *sv_lan = NULL;
|
ConVar *sv_lan = NULL;
|
||||||
@ -112,24 +94,10 @@ CHalfLife2::~CHalfLife2()
|
|||||||
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
|
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
|
||||||
bool is_original_engine = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void CHalfLife2::OnSourceModStartup(bool late)
|
void CHalfLife2::OnSourceModStartup(bool late)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL && !g_pSharedChangeInfo)
|
||||||
/* The Ship currently is the only known game to use an older version of the engine */
|
|
||||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
|
||||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
|
||||||
#else
|
|
||||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
is_original_engine = true;
|
|
||||||
}
|
|
||||||
else if (g_pSharedChangeInfo == NULL)
|
|
||||||
{
|
{
|
||||||
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
|
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
|
||||||
}
|
}
|
||||||
@ -149,6 +117,59 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
|
|||||||
{
|
{
|
||||||
InitLogicalEntData();
|
InitLogicalEntData();
|
||||||
InitCommandLine();
|
InitCommandLine();
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
m_CSGOBadList.init();
|
||||||
|
m_CSGOBadList.add("m_iItemDefinitionIndex");
|
||||||
|
m_CSGOBadList.add("m_iEntityLevel");
|
||||||
|
m_CSGOBadList.add("m_iItemIDHigh");
|
||||||
|
m_CSGOBadList.add("m_iItemIDLow");
|
||||||
|
m_CSGOBadList.add("m_iAccountID");
|
||||||
|
m_CSGOBadList.add("m_iEntityQuality");
|
||||||
|
m_CSGOBadList.add("m_bInitialized");
|
||||||
|
m_CSGOBadList.add("m_szCustomName");
|
||||||
|
m_CSGOBadList.add("m_iAttributeDefinitionIndex");
|
||||||
|
m_CSGOBadList.add("m_iRawValue32");
|
||||||
|
m_CSGOBadList.add("m_iRawInitialValue32");
|
||||||
|
m_CSGOBadList.add("m_nRefundableCurrency");
|
||||||
|
m_CSGOBadList.add("m_bSetBonus");
|
||||||
|
m_CSGOBadList.add("m_OriginalOwnerXuidLow");
|
||||||
|
m_CSGOBadList.add("m_OriginalOwnerXuidHigh");
|
||||||
|
m_CSGOBadList.add("m_nFallbackPaintKit");
|
||||||
|
m_CSGOBadList.add("m_nFallbackSeed");
|
||||||
|
m_CSGOBadList.add("m_flFallbackWear");
|
||||||
|
m_CSGOBadList.add("m_nFallbackStatTrak");
|
||||||
|
m_CSGOBadList.add("m_iCompetitiveRanking");
|
||||||
|
m_CSGOBadList.add("m_iCompetitiveRankType");
|
||||||
|
m_CSGOBadList.add("m_nActiveCoinRank");
|
||||||
|
m_CSGOBadList.add("m_nMusicID");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *value,
|
||||||
|
ConfigSource source, char *error, size_t maxlength)
|
||||||
|
{
|
||||||
|
if (strcasecmp(key, "FollowCSGOServerGuidelines") == 0)
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
if (strcasecmp(value, "no") == 0)
|
||||||
|
{
|
||||||
|
m_bFollowCSGOServerGuidelines = false;
|
||||||
|
return ConfigResult_Accept;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(value, "yes") == 0)
|
||||||
|
{
|
||||||
|
m_bFollowCSGOServerGuidelines = true;
|
||||||
|
return ConfigResult_Accept;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||||
|
return ConfigResult_Reject;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConfigResult_Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHalfLife2::InitLogicalEntData()
|
void CHalfLife2::InitLogicalEntData()
|
||||||
@ -157,7 +178,9 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
|| SOURCE_ENGINE == SE_DODS \
|
|| SOURCE_ENGINE == SE_DODS \
|
||||||
|| SOURCE_ENGINE == SE_HL2DM \
|
|| SOURCE_ENGINE == SE_HL2DM \
|
||||||
|| SOURCE_ENGINE == SE_CSS \
|
|| SOURCE_ENGINE == SE_CSS \
|
||||||
|| SOURCE_ENGINE == SE_SDK2013
|
|| SOURCE_ENGINE == SE_SDK2013 \
|
||||||
|
|| SOURCE_ENGINE == SE_BMS \
|
||||||
|
|| SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||||
|
|
||||||
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
|
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
|
||||||
{
|
{
|
||||||
@ -205,7 +228,12 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||||
|
#elif defined PLATFORM_X64
|
||||||
|
int32_t varOffset = *reinterpret_cast<int32_t *>(addr + offset);
|
||||||
|
g_EntList = reinterpret_cast<void *>(addr + offset + sizeof(int32_t) + varOffset);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,34 +262,33 @@ void CHalfLife2::InitLogicalEntData()
|
|||||||
void CHalfLife2::InitCommandLine()
|
void CHalfLife2::InitCommandLine()
|
||||||
{
|
{
|
||||||
char error[256];
|
char error[256];
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
if (!is_original_engine)
|
if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL)
|
||||||
{
|
|
||||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
|
|
||||||
if (lib == NULL)
|
|
||||||
{
|
{
|
||||||
|
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(TIER0_NAME, error, sizeof(error));
|
||||||
|
if (!lib) {
|
||||||
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
|
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
|
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine_Tier0");
|
||||||
|
|
||||||
/* '_Tier0' dropped on Alien Swarm version */
|
/* '_Tier0' dropped on Alien Swarm version */
|
||||||
if (m_pGetCommandLine == NULL)
|
if (m_pGetCommandLine == NULL)
|
||||||
{
|
{
|
||||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
|
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
|
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(VSTDLIB_NAME, error, sizeof(error));
|
||||||
if (lib == NULL)
|
if (!lib) {
|
||||||
{
|
|
||||||
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
|
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pGetCommandLine == NULL)
|
if (m_pGetCommandLine == NULL)
|
||||||
@ -278,21 +305,10 @@ ICommandLine *CHalfLife2::GetValveCommandLine()
|
|||||||
return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))();
|
return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
|
||||||
bool CHalfLife2::IsOriginalEngine()
|
|
||||||
{
|
|
||||||
return is_original_engine;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
|
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
return engine->GetChangeAccessor( IndexOfEdict((const edict_t *)this) );
|
|
||||||
#else
|
|
||||||
return engine->GetChangeAccessor( (const edict_t *)this );
|
return engine->GetChangeAccessor( (const edict_t *)this );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -497,20 +513,10 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
|||||||
/* Use SayText user message instead */
|
/* Use SayText user message instead */
|
||||||
if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0)
|
if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0)
|
||||||
{
|
{
|
||||||
char buffer[192];
|
char buffer[253];
|
||||||
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
|
ke::SafeSprintf(buffer, sizeof(buffer), "%s\1\n", msg);
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
CUserMsg_SayText *pMsg;
|
|
||||||
if ((pMsg = (CUserMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMsg->set_client(0);
|
|
||||||
pMsg->set_text(buffer);
|
|
||||||
pMsg->set_chat(false);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
CCSUsrMsg_SayText *pMsg;
|
CCSUsrMsg_SayText *pMsg;
|
||||||
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||||
{
|
{
|
||||||
@ -537,16 +543,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
CUserMsg_TextMsg *pMsg;
|
|
||||||
if ((pMsg = (CUserMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMsg->set_dest(dest);
|
|
||||||
pMsg->add_param(msg);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
CCSUsrMsg_TextMsg *pMsg;
|
CCSUsrMsg_TextMsg *pMsg;
|
||||||
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||||
{
|
{
|
||||||
@ -568,6 +565,10 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
|||||||
|
|
||||||
pBitBuf->WriteByte(dest);
|
pBitBuf->WriteByte(dest);
|
||||||
pBitBuf->WriteString(msg);
|
pBitBuf->WriteString(msg);
|
||||||
|
pBitBuf->WriteString("");
|
||||||
|
pBitBuf->WriteString("");
|
||||||
|
pBitBuf->WriteString("");
|
||||||
|
pBitBuf->WriteString("");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_UserMsgs.EndMessage();
|
g_UserMsgs.EndMessage();
|
||||||
@ -579,15 +580,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
|||||||
{
|
{
|
||||||
cell_t players[] = {client};
|
cell_t players[] = {client};
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
CUserMsg_HintText *pMsg;
|
|
||||||
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMsg->set_message(msg);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
CCSUsrMsg_HintText *pMsg;
|
CCSUsrMsg_HintText *pMsg;
|
||||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||||
{
|
{
|
||||||
@ -617,15 +610,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
|||||||
|
|
||||||
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
CUserMsg_HintText *pMsg;
|
|
||||||
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMsg->set_message(msg);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
CCSUsrMsg_HintText *pMsg;
|
CCSUsrMsg_HintText *pMsg;
|
||||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||||
{
|
{
|
||||||
@ -660,13 +645,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
cell_t players[] = {client};
|
cell_t players[] = {client};
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
CUserMsg_VGUIMenu *pMsg;
|
|
||||||
if ((pMsg = (CUserMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
CCSUsrMsg_VGUIMenu *pMsg;
|
CCSUsrMsg_VGUIMenu *pMsg;
|
||||||
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||||
{
|
{
|
||||||
@ -691,18 +670,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
|||||||
SubKey = data->GetFirstSubKey();
|
SubKey = data->GetFirstSubKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
pMsg->set_name(name);
|
|
||||||
pMsg->set_show(show);
|
|
||||||
|
|
||||||
while (SubKey)
|
|
||||||
{
|
|
||||||
CUserMsg_VGUIMenu_Keys *key = pMsg->add_keys();
|
|
||||||
key->set_name(SubKey->GetName());
|
|
||||||
key->set_value(SubKey->GetString());
|
|
||||||
SubKey = SubKey->GetNextKey();
|
|
||||||
}
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
pMsg->set_name(name);
|
pMsg->set_name(name);
|
||||||
pMsg->set_show(show);
|
pMsg->set_show(show);
|
||||||
|
|
||||||
@ -758,11 +726,7 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
|
|||||||
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
|
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
|
||||||
{
|
{
|
||||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
engine->ClientCommand(pPlayer->GetIndex(), "%s", pFake->cmd.c_str());
|
|
||||||
#else
|
|
||||||
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
|
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CmdQueue.pop();
|
m_CmdQueue.pop();
|
||||||
@ -784,11 +748,7 @@ bool CHalfLife2::IsLANServer()
|
|||||||
|
|
||||||
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
|
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
|
||||||
{
|
{
|
||||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
|
||||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
||||||
#else
|
|
||||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
Assert(filesystem);
|
Assert(filesystem);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -823,19 +783,19 @@ bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHalfLife2::PushCommandStack(const CCommand *cmd)
|
void CHalfLife2::PushCommandStack(const ICommandArgs *cmd)
|
||||||
{
|
{
|
||||||
CachedCommandInfo info;
|
CachedCommandInfo info;
|
||||||
|
|
||||||
info.args = cmd;
|
info.args = cmd;
|
||||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd));
|
ke::SafeStrcpy(info.cmd, sizeof(info.cmd), cmd->Arg(0));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_CommandStack.push(info);
|
m_CommandStack.push(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CCommand *CHalfLife2::PeekCommandStack()
|
const ICommandArgs *CHalfLife2::PeekCommandStack()
|
||||||
{
|
{
|
||||||
if (m_CommandStack.empty())
|
if (m_CommandStack.empty())
|
||||||
{
|
{
|
||||||
@ -873,7 +833,7 @@ void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
|
|||||||
|
|
||||||
kick.client = client;
|
kick.client = client;
|
||||||
kick.userid = userid;
|
kick.userid = userid;
|
||||||
UTIL_Format(kick.buffer, sizeof(kick.buffer), "%s", msg);
|
ke::SafeStrcpy(kick.buffer, sizeof(kick.buffer), msg);
|
||||||
|
|
||||||
m_DelayedKicks.push(kick);
|
m_DelayedKicks.push(kick);
|
||||||
}
|
}
|
||||||
@ -1205,46 +1165,260 @@ const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
|
|||||||
return *(const char **)(((unsigned char *)pEntity) + offset);
|
return *(const char **)(((unsigned char *)pEntity) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
SMFindMapResult CHalfLife2::FindMap(char *pMapName, size_t nMapNameMax)
|
||||||
static bool ResolveFuzzyMapName(const char *fuzzyName, char *outFullname, int size)
|
{
|
||||||
|
return this->FindMap(pMapName, pMapName, nMapNameMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
bool CheckReservedFilename(const char *in, const char *reservedName)
|
||||||
|
{
|
||||||
|
size_t nameLen = strlen(reservedName);
|
||||||
|
for (size_t i = 0; i < nameLen; ++i)
|
||||||
|
{
|
||||||
|
if (reservedName[i] != tolower(in[i]))
|
||||||
{
|
{
|
||||||
static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel");
|
|
||||||
if (!pHelperCmd || !pHelperCmd->CanAutoComplete())
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in[nameLen] == '\0' || in[nameLen] == '.')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsWindowsReservedDeviceName(const char *pMapname)
|
||||||
|
{
|
||||||
|
static const char * const reservedDeviceNames[] = {
|
||||||
|
"con", "prn", "aux", "clock$", "nul", "com1",
|
||||||
|
"com2", "com3", "com4", "com5", "com6", "com7",
|
||||||
|
"com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4",
|
||||||
|
"lpt5", "lpt6", "lpt7", "lpt8", "lpt9"
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t reservedCount = sizeof(reservedDeviceNames) / sizeof(reservedDeviceNames[0]);
|
||||||
|
for (size_t i = 0; i < reservedCount; ++i)
|
||||||
|
{
|
||||||
|
if (CheckReservedFilename(pMapname, reservedDeviceNames[i]))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_t nMapNameMax)
|
||||||
|
{
|
||||||
|
/* We need to ensure user input does not contain reserved device names on windows */
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
if (IsWindowsReservedDeviceName(pMapName))
|
||||||
|
{
|
||||||
|
return SMFindMapResult::NotFound;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ke::SafeStrcpy(pFoundMap, nMapNameMax, pMapName);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
static char mapNameTmp[PLATFORM_MAX_PATH];
|
||||||
|
g_SourceMod.Format(mapNameTmp, sizeof(mapNameTmp), "maps%c%s.bsp", PLATFORM_SEP_CHAR, pMapName);
|
||||||
|
if (filesystem->FileExists(mapNameTmp, "GAME"))
|
||||||
|
{
|
||||||
|
// If this is already an exact match, don't attempt to autocomplete it further (de_dust -> de_dust2).
|
||||||
|
// ... but still check that map file is actually valid.
|
||||||
|
// We check FileExists first to avoid console message about IsMapValid with invalid map.
|
||||||
|
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel");
|
||||||
|
|
||||||
|
// This shouldn't happen.
|
||||||
|
if (!pHelperCmd || !pHelperCmd->CanAutoComplete())
|
||||||
|
{
|
||||||
|
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
|
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
|
||||||
|
|
||||||
CUtlVector<CUtlString> results;
|
CUtlVector<CUtlString> results;
|
||||||
pHelperCmd->AutoCompleteSuggest(fuzzyName, results);
|
pHelperCmd->AutoCompleteSuggest(pMapName, results);
|
||||||
if (results.Count() == 0)
|
if (results.Count() == 0)
|
||||||
return false;
|
return SMFindMapResult::NotFound;
|
||||||
|
|
||||||
// Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"),
|
// Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"),
|
||||||
// so skip ahead to start of map path/name
|
// so skip ahead to start of map path/name
|
||||||
|
|
||||||
// Like the engine, we're only going to deal with the first match.
|
// Like the engine, we're only going to deal with the first match.
|
||||||
|
|
||||||
strncopy(outFullname, &results[0][helperCmdLen + 1], size);
|
bool bExactMatch = Q_strcmp(pMapName, &results[0][helperCmdLen + 1]) == 0;
|
||||||
|
if (bExactMatch)
|
||||||
|
{
|
||||||
|
return SMFindMapResult::Found;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(pFoundMap, nMapNameMax, &results[0][helperCmdLen + 1]);
|
||||||
|
return SMFindMapResult::FuzzyMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM \
|
||||||
|
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS
|
||||||
|
static IVEngineServer *engine23 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer023", nullptr));
|
||||||
|
if (engine23)
|
||||||
|
{
|
||||||
|
static char szTemp[PLATFORM_MAX_PATH];
|
||||||
|
if (pFoundMap == NULL)
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName);
|
||||||
|
pFoundMap = szTemp;
|
||||||
|
nMapNameMax = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr));
|
||||||
|
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHalfLife2::GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax)
|
||||||
|
{
|
||||||
|
SMFindMapResult result = FindMap(pMapName, pDisplayname, nMapNameMax);
|
||||||
|
|
||||||
|
if (result == SMFindMapResult::NotFound)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *pPos;
|
||||||
|
if ((pPos = strrchr(pDisplayname, '/')) != NULL || (pPos = strrchr(pDisplayname, '\\')) != NULL)
|
||||||
|
ke::SafeStrcpy(pDisplayname, nMapNameMax, &pPos[1]);
|
||||||
|
|
||||||
|
if ((pPos = strstr(pDisplayname, ".ugc")) != NULL)
|
||||||
|
pPos[0] = '\0';
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool CHalfLife2::IsMapValid(const char *map)
|
bool CHalfLife2::IsMapValid(const char *map)
|
||||||
{
|
{
|
||||||
if (!map || !map[0])
|
if (!map || !map[0])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool ret = engine->IsMapValid(map);
|
return FindMap(map) == SMFindMapResult::Found;
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
static char szFuzzyName[PLATFORM_MAX_PATH];
|
|
||||||
if (ResolveFuzzyMapName(map, szFuzzyName, sizeof(szFuzzyName)))
|
|
||||||
{
|
|
||||||
ret = engine->IsMapValid(szFuzzyName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add ep1 support for this. (No IServerTools available there)
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
string_t CHalfLife2::AllocPooledString(const char *pszValue)
|
||||||
|
{
|
||||||
|
// This is admittedly a giant hack, but it's a relatively safe method for
|
||||||
|
// inserting a string into the game's string pool that isn't likely to break.
|
||||||
|
//
|
||||||
|
// We find the first valid ent (should always be worldspawn), save off it's
|
||||||
|
// current targetname string_t, set it to our string to insert via SetKeyValue,
|
||||||
|
// read back the new targetname value, restore the old value, and return the new one.
|
||||||
|
|
||||||
|
CBaseEntity *pEntity = ((IServerUnknown *) servertools->FirstEntity())->GetBaseEntity();
|
||||||
|
auto *pDataMap = GetDataMap(pEntity);
|
||||||
|
assert(pDataMap);
|
||||||
|
|
||||||
|
static int offset = -1;
|
||||||
|
if (offset == -1)
|
||||||
|
{
|
||||||
|
sm_datatable_info_t info;
|
||||||
|
bool found = FindDataMapInfo(pDataMap, "m_iName", &info);
|
||||||
|
assert(found);
|
||||||
|
offset = info.actual_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_t *pProp = (string_t *) ((intp) pEntity + offset);
|
||||||
|
string_t backup = *pProp;
|
||||||
|
servertools->SetKeyValue(pEntity, "targetname", pszValue);
|
||||||
|
string_t newString = *pProp;
|
||||||
|
*pProp = backup;
|
||||||
|
|
||||||
|
return newString;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
|
||||||
|
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
|
||||||
|
{
|
||||||
|
CSteamID sid((uint64)GetServerSteamId64());
|
||||||
|
|
||||||
|
switch (sid.GetEAccountType())
|
||||||
|
{
|
||||||
|
case k_EAccountTypeAnonGameServer:
|
||||||
|
ke::SafeSprintf(pszOut, len, "[A:%u:%u:%u]", sid.GetEUniverse(), sid.GetAccountID(), sid.GetUnAccountInstance());
|
||||||
|
break;
|
||||||
|
case k_EAccountTypeGameServer:
|
||||||
|
ke::SafeSprintf(pszOut, len, "[G:%u:%u]", sid.GetEUniverse(), sid.GetAccountID());
|
||||||
|
break;
|
||||||
|
case k_EAccountTypeInvalid:
|
||||||
|
ke::SafeSprintf(pszOut, len, "[I:%u:%u]", sid.GetEUniverse(), sid.GetAccountID());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined( PLATFORM_WINDOWS )
|
||||||
|
#define STEAM_LIB_PREFIX
|
||||||
|
#define STEAM_LIB_SUFFIX
|
||||||
|
#elif defined( PLATFORM_LINUX )
|
||||||
|
#define STEAM_LIB_PREFIX "lib"
|
||||||
|
#define STEAM_LIB_SUFFIX ".so"
|
||||||
|
#elif defined( PLATFORM_APPLE )
|
||||||
|
#define STEAM_LIB_PREFIX "lib"
|
||||||
|
#define STEAM_LIB_SUFFIX ".dylib"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint64_t CHalfLife2::GetServerSteamId64() const
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_BLADE \
|
||||||
|
|| SOURCE_ENGINE == SE_BMS \
|
||||||
|
|| SOURCE_ENGINE == SE_CSGO \
|
||||||
|
|| SOURCE_ENGINE == SE_CSS \
|
||||||
|
|| SOURCE_ENGINE == SE_DODS \
|
||||||
|
|| SOURCE_ENGINE == SE_EYE \
|
||||||
|
|| SOURCE_ENGINE == SE_HL2DM \
|
||||||
|
|| SOURCE_ENGINE == SE_INSURGENCY \
|
||||||
|
|| SOURCE_ENGINE == SE_DOI \
|
||||||
|
|| SOURCE_ENGINE == SE_SDK2013 \
|
||||||
|
|| SOURCE_ENGINE == SE_ALIENSWARM \
|
||||||
|
|| SOURCE_ENGINE == SE_TF2
|
||||||
|
const CSteamID *sid = engine->GetGameServerSteamID();
|
||||||
|
if (sid)
|
||||||
|
{
|
||||||
|
return sid->ConvertToUint64();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
typedef uint64_t(* GetServerSteamIdFn)(void);
|
||||||
|
static GetServerSteamIdFn fn = nullptr;
|
||||||
|
if (!fn)
|
||||||
|
{
|
||||||
|
ke::SharedLib steam_api(STEAM_LIB_PREFIX "steam_api" STEAM_LIB_SUFFIX);
|
||||||
|
if (steam_api.valid())
|
||||||
|
{
|
||||||
|
fn = (GetServerSteamIdFn)steam_api.lookup("SteamGameServer_GetSteamID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn)
|
||||||
|
{
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1ULL;
|
||||||
}
|
}
|
||||||
|
103
core/HalfLife2.h
103
core/HalfLife2.h
@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 sw=4 tw=99 noet :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -36,6 +36,7 @@
|
|||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_tinyhash.h>
|
#include <sh_tinyhash.h>
|
||||||
#include <am-utility.h>
|
#include <am-utility.h>
|
||||||
|
#include <am-hashset.h>
|
||||||
#include <am-hashmap.h>
|
#include <am-hashmap.h>
|
||||||
#include <sm_stringhashmap.h>
|
#include <sm_stringhashmap.h>
|
||||||
#include <sm_namehashset.h>
|
#include <sm_namehashset.h>
|
||||||
@ -47,11 +48,11 @@
|
|||||||
#include <datamap.h>
|
#include <datamap.h>
|
||||||
#include <ihandleentity.h>
|
#include <ihandleentity.h>
|
||||||
#include <tier0/icommandline.h>
|
#include <tier0/icommandline.h>
|
||||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
|
||||||
#include <string_t.h>
|
#include <string_t.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
class CCommand;
|
namespace SourceMod {
|
||||||
|
class ICommandArgs;
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@ -59,6 +60,33 @@ using namespace SourceMod;
|
|||||||
#define HUD_PRINTTALK 3
|
#define HUD_PRINTTALK 3
|
||||||
#define HUD_PRINTCENTER 4
|
#define HUD_PRINTCENTER 4
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
#define SOURCE_BIN_PREFIX ""
|
||||||
|
#define SOURCE_BIN_SUFFIX ""
|
||||||
|
#define SOURCE_BIN_EXT ".dll"
|
||||||
|
#elif defined __APPLE__
|
||||||
|
#define SOURCE_BIN_PREFIX ""
|
||||||
|
#define SOURCE_BIN_SUFFIX ""
|
||||||
|
#define SOURCE_BIN_EXT ".dylib"
|
||||||
|
#elif defined __linux__
|
||||||
|
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
||||||
|
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|
||||||
|
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
|
||||||
|
#define SOURCE_BIN_PREFIX "lib"
|
||||||
|
#define SOURCE_BIN_SUFFIX "_srv"
|
||||||
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
#define SOURCE_BIN_PREFIX "lib"
|
||||||
|
#define SOURCE_BIN_SUFFIX ""
|
||||||
|
#else
|
||||||
|
#define SOURCE_BIN_PREFIX ""
|
||||||
|
#define SOURCE_BIN_SUFFIX "_i486"
|
||||||
|
#endif
|
||||||
|
#define SOURCE_BIN_EXT ".so"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FORMAT_SOURCE_BIN_NAME(basename) \
|
||||||
|
(SOURCE_BIN_PREFIX basename SOURCE_BIN_SUFFIX SOURCE_BIN_EXT)
|
||||||
|
|
||||||
struct DataTableInfo
|
struct DataTableInfo
|
||||||
{
|
{
|
||||||
struct SendPropPolicy
|
struct SendPropPolicy
|
||||||
@ -67,12 +95,20 @@ struct DataTableInfo
|
|||||||
{
|
{
|
||||||
return strcmp(name, info.prop->GetName()) == 0;
|
return strcmp(name, info.prop->GetName()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool matches(const char *name, const DataTableInfo *info)
|
static inline bool matches(const char *name, const DataTableInfo *info)
|
||||||
{
|
{
|
||||||
return strcmp(name, info->sc->GetName()) == 0;
|
return strcmp(name, info->sc->GetName()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
|
|
||||||
DataTableInfo(ServerClass *sc)
|
DataTableInfo(ServerClass *sc)
|
||||||
: sc(sc)
|
: sc(sc)
|
||||||
@ -89,6 +125,10 @@ struct DataMapCachePolicy
|
|||||||
{
|
{
|
||||||
return strcmp(name, info.prop->fieldName) == 0;
|
return strcmp(name, info.prop->fieldName) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
|
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
|
||||||
@ -102,7 +142,7 @@ struct DelayedFakeCliCmd
|
|||||||
|
|
||||||
struct CachedCommandInfo
|
struct CachedCommandInfo
|
||||||
{
|
{
|
||||||
const CCommand *args;
|
const ICommandArgs *args;
|
||||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
char cmd[300];
|
char cmd[300];
|
||||||
#endif
|
#endif
|
||||||
@ -123,16 +163,27 @@ public:
|
|||||||
int m_SerialNumber;
|
int m_SerialNumber;
|
||||||
CEntInfo *m_pPrev;
|
CEntInfo *m_pPrev;
|
||||||
CEntInfo *m_pNext;
|
CEntInfo *m_pNext;
|
||||||
#if (SOURCE_ENGINE >= SE_PORTAL2) && (SOURCE_ENGINE != SE_DOTA)
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
string_t m_iName;
|
string_t m_iName;
|
||||||
string_t m_iClassName;
|
string_t m_iClassName;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Corresponds to TF2's eFindMapResult in eiface.h
|
||||||
|
// Not yet in other games, but eventually in others on same branch.
|
||||||
|
enum class SMFindMapResult : cell_t {
|
||||||
|
Found,
|
||||||
|
NotFound,
|
||||||
|
FuzzyMatch,
|
||||||
|
NonCanonical,
|
||||||
|
PossiblyAvailable
|
||||||
|
};
|
||||||
|
|
||||||
class CHalfLife2 :
|
class CHalfLife2 :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IGameHelpers
|
public IGameHelpers
|
||||||
{
|
{
|
||||||
|
friend class AutoEnterCommand;
|
||||||
public:
|
public:
|
||||||
CHalfLife2();
|
CHalfLife2();
|
||||||
~CHalfLife2();
|
~CHalfLife2();
|
||||||
@ -141,6 +192,8 @@ public:
|
|||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModAllInitialized_Post();
|
void OnSourceModAllInitialized_Post();
|
||||||
/*void OnSourceModAllShutdown();*/
|
/*void OnSourceModAllShutdown();*/
|
||||||
|
ConfigResult OnSourceModConfigChanged(const char *key, const char *value,
|
||||||
|
ConfigSource source, char *error, size_t maxlength) override;
|
||||||
public: //IGameHelpers
|
public: //IGameHelpers
|
||||||
SendProp *FindInSendTable(const char *classname, const char *offset);
|
SendProp *FindInSendTable(const char *classname, const char *offset);
|
||||||
bool FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info);
|
bool FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info);
|
||||||
@ -174,20 +227,25 @@ public: //IGameHelpers
|
|||||||
const char *GetEntityClassname(edict_t *pEdict);
|
const char *GetEntityClassname(edict_t *pEdict);
|
||||||
const char *GetEntityClassname(CBaseEntity *pEntity);
|
const char *GetEntityClassname(CBaseEntity *pEntity);
|
||||||
bool IsMapValid(const char *map);
|
bool IsMapValid(const char *map);
|
||||||
|
SMFindMapResult FindMap(char *pMapName, size_t nMapNameMax);
|
||||||
|
SMFindMapResult FindMap(const char *pMapName, char *pFoundMap = NULL, size_t nMapNameMax = 0);
|
||||||
|
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
string_t AllocPooledString(const char *pszValue);
|
||||||
|
#endif
|
||||||
|
bool GetServerSteam3Id(char *pszOut, size_t len) const override;
|
||||||
|
uint64_t GetServerSteamId64() const override;
|
||||||
public:
|
public:
|
||||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||||
void ProcessFakeCliCmdQueue();
|
void ProcessFakeCliCmdQueue();
|
||||||
public:
|
public:
|
||||||
void PushCommandStack(const CCommand *cmd);
|
const ICommandArgs *PeekCommandStack();
|
||||||
void PopCommandStack();
|
|
||||||
const CCommand *PeekCommandStack();
|
|
||||||
const char *CurrentCommandName();
|
const char *CurrentCommandName();
|
||||||
void AddDelayedKick(int client, int userid, const char *msg);
|
void AddDelayedKick(int client, int userid, const char *msg);
|
||||||
void ProcessDelayedKicks();
|
void ProcessDelayedKicks();
|
||||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
|
||||||
bool IsOriginalEngine();
|
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
|
void PushCommandStack(const ICommandArgs *cmd);
|
||||||
|
void PopCommandStack();
|
||||||
DataTableInfo *_FindServerClass(const char *classname);
|
DataTableInfo *_FindServerClass(const char *classname);
|
||||||
private:
|
private:
|
||||||
void InitLogicalEntData();
|
void InitLogicalEntData();
|
||||||
@ -206,10 +264,31 @@ private:
|
|||||||
CStack<CachedCommandInfo> m_CommandStack;
|
CStack<CachedCommandInfo> m_CommandStack;
|
||||||
Queue<DelayedKickInfo> m_DelayedKicks;
|
Queue<DelayedKickInfo> m_DelayedKicks;
|
||||||
void *m_pGetCommandLine;
|
void *m_pGetCommandLine;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
public:
|
||||||
|
bool CanSetCSGOEntProp(const char *pszPropName)
|
||||||
|
{
|
||||||
|
return !m_bFollowCSGOServerGuidelines || !m_CSGOBadList.has(pszPropName);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ke::HashSet<ke::AString, detail::StringHashMapPolicy> m_CSGOBadList;
|
||||||
|
bool m_bFollowCSGOServerGuidelines = true;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHalfLife2 g_HL2;
|
extern CHalfLife2 g_HL2;
|
||||||
|
|
||||||
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
|
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
|
||||||
|
|
||||||
|
class AutoEnterCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutoEnterCommand(const ICommandArgs *args) {
|
||||||
|
g_HL2.PushCommandStack(args);
|
||||||
|
}
|
||||||
|
~AutoEnterCommand() {
|
||||||
|
g_HL2.PopCommandStack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||||
|
@ -34,10 +34,10 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
#include <sourcemod_version.h>
|
#include <sourcemod_version.h>
|
||||||
|
#include <bridge/include/IProviderCallbacks.h>
|
||||||
|
|
||||||
bool g_in_game_log_hook = false;
|
bool g_in_game_log_hook = false;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
|
|||||||
static void HookLogPrint(const char *message)
|
static void HookLogPrint(const char *message)
|
||||||
{
|
{
|
||||||
g_in_game_log_hook = true;
|
g_in_game_log_hook = true;
|
||||||
bool stopped = logicore.OnLogPrint(message);
|
bool stopped = logicore.callbacks->OnLogPrint(message);
|
||||||
g_in_game_log_hook = false;
|
g_in_game_log_hook = false;
|
||||||
|
|
||||||
if (stopped)
|
if (stopped)
|
||||||
|
216
core/Makefile
216
core/Makefile
@ -1,216 +0,0 @@
|
|||||||
# (C)2004-2008 SourceMod Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMSDK = ..
|
|
||||||
HL2SDK_ORIG = ../../hl2sdk
|
|
||||||
HL2SDK_OB = ../../hl2sdk-ob
|
|
||||||
HL2SDK_CSS = ../../hl2sdk-css
|
|
||||||
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
|
|
||||||
HL2SDK_L4D = ../../hl2sdk-l4d
|
|
||||||
HL2SDK_L4D2 = ../../hl2sdk-l4d2
|
|
||||||
HL2SDK_CSGO = ../../hl2sdk-csgo
|
|
||||||
MMSOURCE = ../../mmsource-central
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
#####################################
|
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \
|
|
||||||
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \
|
|
||||||
sm_autonatives.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
|
||||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
|
||||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \
|
|
||||||
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \
|
|
||||||
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp
|
|
||||||
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|
||||||
smn_database.cpp smn_entities.cpp smn_events.cpp \
|
|
||||||
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \
|
|
||||||
smn_keyvalues.cpp smn_player.cpp \
|
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \
|
|
||||||
smn_hudtext.cpp smn_nextmap.cpp
|
|
||||||
OBJECTS += ExtensionSys.cpp \
|
|
||||||
ForwardSys.cpp \
|
|
||||||
HandleSys.cpp \
|
|
||||||
LibrarySys.cpp \
|
|
||||||
PluginInfoDatabase.cpp \
|
|
||||||
PluginSys.cpp \
|
|
||||||
ShareSys.cpp \
|
|
||||||
NativeInvoker.cpp
|
|
||||||
|
|
||||||
##############################################
|
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
|
||||||
##############################################
|
|
||||||
|
|
||||||
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
|
|
||||||
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
|
|
||||||
C_GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
CPP = gcc
|
|
||||||
|
|
||||||
override ENGSET = false
|
|
||||||
|
|
||||||
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
|
|
||||||
override ENGSET = true
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(ENGINE)" "original"
|
|
||||||
HL2SDK = $(HL2SDK_ORIG)
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=1
|
|
||||||
METAMOD = $(MMSOURCE)/core-legacy
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/dlls
|
|
||||||
BINARY = sourcemod.1.ep1.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "orangebox"
|
|
||||||
HL2SDK = $(HL2SDK_OB)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=3
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.ep2.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "css"
|
|
||||||
HL2SDK = $(HL2SDK_CSS)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=6
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.css.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "orangeboxvalve"
|
|
||||||
HL2SDK = $(HL2SDK_OB_VALVE)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=7
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.ep2v.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "left4dead"
|
|
||||||
HL2SDK = $(HL2SDK_L4D)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=8
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.l4d.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "left4dead2"
|
|
||||||
HL2SDK = $(HL2SDK_L4D2)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=9
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.l4d2.so
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "csgo"
|
|
||||||
HL2SDK = $(HL2SDK_CSGO)
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=12
|
|
||||||
METAMOD = $(MMSOURCE)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
BINARY = sourcemod.2.csgo.so
|
|
||||||
endif
|
|
||||||
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
|
|
||||||
OS := $(shell uname -s)
|
|
||||||
|
|
||||||
ifeq "$(OS)" "Darwin"
|
|
||||||
LIB_EXT = dylib
|
|
||||||
HL2LIB = $(HL2SDK)/lib/mac
|
|
||||||
else
|
|
||||||
LIB_EXT = so
|
|
||||||
ifeq "$(ENGINE)" "original"
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
else
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq (,$(filter original orangebox left4dead,$(ENGINE)))
|
|
||||||
LIB_SUFFIX = _i486.$(LIB_EXT)
|
|
||||||
else
|
|
||||||
LIB_PREFIX = lib
|
|
||||||
ifneq (,$(filter orangeboxvalve css,$(ENGINE)))
|
|
||||||
ifneq "$(OS)" "Darwin"
|
|
||||||
LIB_SUFFIX = _srv.$(LIB_EXT)
|
|
||||||
else
|
|
||||||
LIB_SUFFIX = .$(LIB_EXT)
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
LIB_SUFFIX = .$(LIB_EXT)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \
|
|
||||||
-DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \
|
|
||||||
-DSE_PORTAL2=11 -DSE_CSGO=12
|
|
||||||
|
|
||||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) \
|
|
||||||
$(LIB_PREFIX)tier0$(LIB_SUFFIX) -static-libgcc
|
|
||||||
|
|
||||||
ifeq "$(ENGINE)" "csgo"
|
|
||||||
LINK += $(HL2LIB)/interfaces_i486.a
|
|
||||||
endif
|
|
||||||
|
|
||||||
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \
|
|
||||||
-I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
|
|
||||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
|
||||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
|
|
||||||
-Wno-uninitialized -Wno-unused -Wno-switch -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H \
|
|
||||||
-DSM_DEFAULT_THREADER -m32 -DCOMPILER_GCC
|
|
||||||
CPPFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -fno-threadsafe-statics -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
################################################
|
|
||||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
|
||||||
################################################
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug.$(ENGINE)
|
|
||||||
CFLAGS += $(C_DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release.$(ENGINE)
|
|
||||||
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: check
|
|
||||||
mkdir -p $(BIN_DIR)
|
|
||||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX)
|
|
||||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX)
|
|
||||||
$(MAKE) -f Makefile sourcemod
|
|
||||||
|
|
||||||
check:
|
|
||||||
if [ "$(ENGSET)" = "false" ]; then \
|
|
||||||
echo "You must supply one of the following values for ENGINE:"; \
|
|
||||||
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
sourcemod: check $(OBJ_LINUX)
|
|
||||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) -f Makefile all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean: check
|
|
||||||
rm -rf $(BIN_DIR)/*.o
|
|
||||||
rm -rf $(BIN_DIR)/$(BINARY)
|
|
@ -308,7 +308,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
{
|
{
|
||||||
ItemDrawInfo &dr = drawItems[foundItems].draw;
|
ItemDrawInfo &dr = drawItems[foundItems].draw;
|
||||||
/* Is the item valid? */
|
/* Is the item valid? */
|
||||||
if (menu->GetItemInfo(i, &dr) != NULL)
|
if (menu->GetItemInfo(i, &dr, client) != NULL)
|
||||||
{
|
{
|
||||||
/* Ask the user to change the style, if necessary */
|
/* Ask the user to change the style, if necessary */
|
||||||
mh->OnMenuDrawItem(menu, client, i, dr.style);
|
mh->OnMenuDrawItem(menu, client, i, dr.style);
|
||||||
@ -398,7 +398,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
}
|
}
|
||||||
while (++lastItem < totalItems)
|
while (++lastItem < totalItems)
|
||||||
{
|
{
|
||||||
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
|
||||||
{
|
{
|
||||||
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
||||||
if (IsSlotItem(panel, dr.style))
|
if (IsSlotItem(panel, dr.style))
|
||||||
@ -420,7 +420,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
lastItem--;
|
lastItem--;
|
||||||
while (lastItem != 0)
|
while (lastItem != 0)
|
||||||
{
|
{
|
||||||
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
|
||||||
{
|
{
|
||||||
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
||||||
if (IsSlotItem(panel, dr.style))
|
if (IsSlotItem(panel, dr.style))
|
||||||
@ -446,7 +446,7 @@ skip_search:
|
|||||||
char text[50];
|
char text[50];
|
||||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "No Vote");
|
ke::SafeStrcpy(text, sizeof(text), "No Vote");
|
||||||
}
|
}
|
||||||
ItemDrawInfo dr(text, 0);
|
ItemDrawInfo dr(text, 0);
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@ -570,7 +570,7 @@ skip_search:
|
|||||||
/* If there are no control options,
|
/* If there are no control options,
|
||||||
* Instead just pad with invisible slots.
|
* Instead just pad with invisible slots.
|
||||||
*/
|
*/
|
||||||
if (!displayPrev && !displayPrev)
|
if (!displayNext && !displayPrev)
|
||||||
{
|
{
|
||||||
padItem.style = ITEMDRAW_NOTEXT;
|
padItem.style = ITEMDRAW_NOTEXT;
|
||||||
}
|
}
|
||||||
@ -606,7 +606,7 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Back");
|
ke::SafeStrcpy(text, sizeof(text), "Back");
|
||||||
}
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@ -616,7 +616,7 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Previous");
|
ke::SafeStrcpy(text, sizeof(text), "Previous");
|
||||||
}
|
}
|
||||||
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@ -637,7 +637,7 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Next");
|
ke::SafeStrcpy(text, sizeof(text), "Next");
|
||||||
}
|
}
|
||||||
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@ -668,7 +668,7 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Exit");
|
ke::SafeStrcpy(text, sizeof(text), "Exit");
|
||||||
}
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
|
@ -338,7 +338,8 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
#endif
|
#endif
|
||||||
0,
|
0,
|
||||||
PITCH_NORM,
|
PITCH_NORM,
|
||||||
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2
|
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
|
||||||
|
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2
|
||||||
0,
|
0,
|
||||||
#endif
|
#endif
|
||||||
&pos);
|
&pos);
|
||||||
@ -632,7 +633,7 @@ bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CItem item;
|
CItem item(m_items.length());
|
||||||
|
|
||||||
item.info = info;
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
@ -654,7 +655,7 @@ bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDr
|
|||||||
if (position >= m_items.length())
|
if (position >= m_items.length())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CItem item;
|
CItem item(position);
|
||||||
item.info = info;
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
item.display = new ke::AString(draw.display);
|
item.display = new ke::AString(draw.display);
|
||||||
@ -678,11 +679,16 @@ void CBaseMenu::RemoveAllItems()
|
|||||||
m_items.clear();
|
m_items.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */, int client/* =0 */)
|
||||||
{
|
{
|
||||||
if (position >= m_items.length())
|
if (position >= m_items.length())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (client > 0 && position < m_RandomMaps[client].length())
|
||||||
|
{
|
||||||
|
position = m_RandomMaps[client][position];
|
||||||
|
}
|
||||||
|
|
||||||
if (draw)
|
if (draw)
|
||||||
{
|
{
|
||||||
draw->display = m_items[position].display->chars();
|
draw->display = m_items[position].display->chars();
|
||||||
@ -692,6 +698,62 @@ const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =
|
|||||||
return m_items[position].info.chars();
|
return m_items[position].info.chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBaseMenu::ShufflePerClient(int start, int stop)
|
||||||
|
{
|
||||||
|
// limit map len to 255 items since it's using uint8
|
||||||
|
int length = MIN(GetItemCount(), 255);
|
||||||
|
if (stop >= 0)
|
||||||
|
length = MIN(length, stop);
|
||||||
|
|
||||||
|
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
|
||||||
|
{
|
||||||
|
// populate per-client map ...
|
||||||
|
m_RandomMaps[i].resize(length);
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
m_RandomMaps[i][j] = j;
|
||||||
|
|
||||||
|
// ... and random shuffle it
|
||||||
|
for (int j = length - 1; j > start; j--)
|
||||||
|
{
|
||||||
|
int x = rand() % (j - start + 1) + start;
|
||||||
|
uint8_t tmp = m_RandomMaps[i][x];
|
||||||
|
m_RandomMaps[i][x] = m_RandomMaps[i][j];
|
||||||
|
m_RandomMaps[i][j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBaseMenu::SetClientMapping(int client, int *array, int length)
|
||||||
|
{
|
||||||
|
length = MIN(length, 255);
|
||||||
|
m_RandomMaps[client].resize(length);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
m_RandomMaps[client][i] = array[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::IsPerClientShuffled()
|
||||||
|
{
|
||||||
|
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
|
||||||
|
{
|
||||||
|
if(m_RandomMaps[i].length() > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position)
|
||||||
|
{
|
||||||
|
if (client > 0 && position < m_RandomMaps[client].length())
|
||||||
|
{
|
||||||
|
position = m_RandomMaps[client][position];
|
||||||
|
return m_items[position].index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int CBaseMenu::GetItemCount()
|
unsigned int CBaseMenu::GetItemCount()
|
||||||
{
|
{
|
||||||
return m_items.length();
|
return m_items.length();
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <IMenuManager.h>
|
#include <IMenuManager.h>
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
|
#include <am-autoptr.h>
|
||||||
#include <am-string.h>
|
#include <am-string.h>
|
||||||
#include <am-vector.h>
|
#include <am-vector.h>
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
@ -43,36 +44,40 @@ using namespace SourceMod;
|
|||||||
class CItem
|
class CItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CItem()
|
CItem(unsigned int index)
|
||||||
{
|
{
|
||||||
|
this->index = index;
|
||||||
style = 0;
|
style = 0;
|
||||||
access = 0;
|
access = 0;
|
||||||
}
|
}
|
||||||
CItem(ke::Moveable<CItem> other)
|
CItem(CItem &&other)
|
||||||
: info(ke::Move(other->info)),
|
: info(ke::Move(other.info)),
|
||||||
display(ke::Move(other->display))
|
display(ke::Move(other.display))
|
||||||
{
|
{
|
||||||
style = other->style;
|
index = other.index;
|
||||||
access = other->access;
|
style = other.style;
|
||||||
|
access = other.access;
|
||||||
}
|
}
|
||||||
CItem & operator =(ke::Moveable<CItem> other)
|
CItem & operator =(CItem &&other)
|
||||||
{
|
{
|
||||||
info = ke::Move(other->info);
|
index = other.index;
|
||||||
display = ke::Move(other->display);
|
info = ke::Move(other.info);
|
||||||
style = other->style;
|
display = ke::Move(other.display);
|
||||||
access = other->access;
|
style = other.style;
|
||||||
|
access = other.access;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
unsigned int index;
|
||||||
ke::AString info;
|
ke::AString info;
|
||||||
ke::AutoPtr<ke::AString> display;
|
ke::AutoPtr<ke::AString> display;
|
||||||
unsigned int style;
|
unsigned int style;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CItem(const CItem &other) KE_DELETE;
|
CItem(const CItem &other) = delete;
|
||||||
CItem &operator =(const CItem &other) KE_DELETE;
|
CItem &operator =(const CItem &other) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CBaseMenuPlayer
|
class CBaseMenuPlayer
|
||||||
@ -137,7 +142,7 @@ public:
|
|||||||
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
|
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
|
||||||
virtual bool RemoveItem(unsigned int position);
|
virtual bool RemoveItem(unsigned int position);
|
||||||
virtual void RemoveAllItems();
|
virtual void RemoveAllItems();
|
||||||
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL);
|
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL, int client=0);
|
||||||
virtual unsigned int GetItemCount();
|
virtual unsigned int GetItemCount();
|
||||||
virtual bool SetPagination(unsigned int itemsPerPage);
|
virtual bool SetPagination(unsigned int itemsPerPage);
|
||||||
virtual unsigned int GetPagination();
|
virtual unsigned int GetPagination();
|
||||||
@ -151,6 +156,10 @@ public:
|
|||||||
virtual unsigned int GetMenuOptionFlags();
|
virtual unsigned int GetMenuOptionFlags();
|
||||||
virtual void SetMenuOptionFlags(unsigned int flags);
|
virtual void SetMenuOptionFlags(unsigned int flags);
|
||||||
virtual IMenuHandler *GetHandler();
|
virtual IMenuHandler *GetHandler();
|
||||||
|
virtual void ShufflePerClient(int start, int stop);
|
||||||
|
virtual void SetClientMapping(int client, int *array, int length);
|
||||||
|
virtual bool IsPerClientShuffled();
|
||||||
|
virtual unsigned int GetRealItemIndex(int client, unsigned int position);
|
||||||
unsigned int GetBaseMemUsage();
|
unsigned int GetBaseMemUsage();
|
||||||
private:
|
private:
|
||||||
void InternalDelete();
|
void InternalDelete();
|
||||||
@ -167,6 +176,7 @@ protected:
|
|||||||
Handle_t m_hHandle;
|
Handle_t m_hHandle;
|
||||||
IMenuHandler *m_pHandler;
|
IMenuHandler *m_pHandler;
|
||||||
unsigned int m_nFlags;
|
unsigned int m_nFlags;
|
||||||
|
ke::Vector<uint8_t> m_RandomMaps[SM_MAXPLAYERS+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_MENUSTYLE_BASE_H
|
#endif //_INCLUDE_MENUSTYLE_BASE_H
|
||||||
|
@ -83,6 +83,10 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_bRadioInit = true;
|
g_bRadioInit = true;
|
||||||
|
|
||||||
|
// Always register the style. Use IsSupported() to check for validity before use.
|
||||||
|
g_Menus.AddStyle(this);
|
||||||
|
|
||||||
const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
|
const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
|
||||||
if (!msg || msg[0] == '\0')
|
if (!msg || msg[0] == '\0')
|
||||||
{
|
{
|
||||||
@ -118,7 +122,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Menus.AddStyle(this);
|
|
||||||
g_Menus.SetDefaultStyle(this);
|
g_Menus.SetDefaultStyle(this);
|
||||||
|
|
||||||
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
||||||
@ -138,11 +141,7 @@ void CRadioStyle::OnSourceModShutdown()
|
|||||||
|
|
||||||
bool CRadioStyle::IsSupported()
|
bool CRadioStyle::IsSupported()
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
return (g_ShowMenuId != -1);
|
return (g_ShowMenuId != -1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
||||||
@ -173,10 +172,9 @@ void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFi
|
|||||||
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
int count = pFilter->GetRecipientCount();
|
int count = pFilter->GetRecipientCount();
|
||||||
|
|
||||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||||
#else
|
#else
|
||||||
bf_read br(bf->GetBasePointer(), 3);
|
bf_read br(bf->GetBasePointer(), 3);
|
||||||
@ -191,7 +189,6 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
|
|||||||
{
|
{
|
||||||
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
|
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRadioStyle::OnUserMessageSent(int msg_id)
|
void CRadioStyle::OnUserMessageSent(int msg_id)
|
||||||
@ -453,7 +450,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|||||||
{
|
{
|
||||||
if (title[0] != '\0')
|
if (title[0] != '\0')
|
||||||
{
|
{
|
||||||
display_len = UTIL_Format(display_pkt,
|
display_len = ke::SafeSprintf(display_pkt,
|
||||||
sizeof(display_pkt),
|
sizeof(display_pkt),
|
||||||
"%s\n%s",
|
"%s\n%s",
|
||||||
title,
|
title,
|
||||||
@ -461,9 +458,8 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
display_len = UTIL_Format(display_pkt,
|
display_len = ke::SafeStrcpy(display_pkt,
|
||||||
sizeof(display_pkt),
|
sizeof(display_pkt),
|
||||||
"%s",
|
|
||||||
text);
|
text);
|
||||||
}
|
}
|
||||||
display_keys = keys;
|
display_keys = keys;
|
||||||
@ -471,7 +467,6 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|||||||
|
|
||||||
void CRadioMenuPlayer::Radio_Refresh()
|
void CRadioMenuPlayer::Radio_Refresh()
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
cell_t players[1] = { (cell_t)m_index };
|
cell_t players[1] = { (cell_t)m_index };
|
||||||
char *ptr = display_pkt;
|
char *ptr = display_pkt;
|
||||||
char save = 0;
|
char save = 0;
|
||||||
@ -488,8 +483,7 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
// If or when we need to support multiple games per engine with this, we can switch to reflection
|
|
||||||
// TODO: find what happens past 240 on CS:GO
|
// TODO: find what happens past 240 on CS:GO
|
||||||
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||||
msg->set_bits_valid_slots(display_keys);
|
msg->set_bits_valid_slots(display_keys);
|
||||||
@ -525,7 +519,6 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
display_last_refresh = gpGlobals->curtime;
|
display_last_refresh = gpGlobals->curtime;
|
||||||
#endif // !DOTA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CRadioDisplay::GetAmountRemaining()
|
int CRadioDisplay::GetAmountRemaining()
|
||||||
@ -593,6 +586,7 @@ bool CRadioMenu::DisplayAtItem(int client,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoHandleRooter ahr(this->GetHandle());
|
||||||
return g_RadioMenuStyle.DoClientMenu(client,
|
return g_RadioMenuStyle.DoClientMenu(client,
|
||||||
this,
|
this,
|
||||||
start_item,
|
start_item,
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
|
#include "logic/common_logic.h"
|
||||||
|
#include "AutoHandleRooter.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -65,20 +65,16 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
|
|||||||
|
|
||||||
void ValveMenuStyle::OnSourceModAllInitialized()
|
void ValveMenuStyle::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
g_Players.AddClientListener(this);
|
g_Players.AddClientListener(this);
|
||||||
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValveMenuStyle::OnSourceModShutdown()
|
void ValveMenuStyle::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE != SE_DOTA
|
|
||||||
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
||||||
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_Players.RemoveClientListener(this);
|
g_Players.RemoveClientListener(this);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
||||||
@ -297,7 +293,7 @@ unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
|
ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
|
||||||
|
|
||||||
KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
|
KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
|
||||||
ki->SetString("command", g_OptionCmdTable[m_NextPos]);
|
ki->SetString("command", g_OptionCmdTable[m_NextPos]);
|
||||||
@ -382,7 +378,7 @@ bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
|||||||
{
|
{
|
||||||
if (option == MenuOption_IntroMessage)
|
if (option == MenuOption_IntroMessage)
|
||||||
{
|
{
|
||||||
strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
|
ke::SafeStrcpy(m_IntroMsg, sizeof(m_IntroMsg), (const char *)valuePtr);
|
||||||
return true;
|
return true;
|
||||||
} else if (option == MenuOption_IntroColor) {
|
} else if (option == MenuOption_IntroColor) {
|
||||||
unsigned int *array = (unsigned int *)valuePtr;
|
unsigned int *array = (unsigned int *)valuePtr;
|
||||||
@ -408,6 +404,7 @@ bool CValveMenu::DisplayAtItem(int client,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoHandleRooter ahr(this->GetHandle());
|
||||||
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
|
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#include "KeyValues.h"
|
#include "KeyValues.h"
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
|
#include "logic/common_logic.h"
|
||||||
|
#include "AutoHandleRooter.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
@ -514,15 +514,16 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
|
|||||||
/* Check by our item count, NOT the vote array size */
|
/* Check by our item count, NOT the vote array size */
|
||||||
if (item < m_Items)
|
if (item < m_Items)
|
||||||
{
|
{
|
||||||
m_ClientVotes[client] = item;
|
unsigned int index = menu->GetRealItemIndex(client, item);
|
||||||
m_Votes[item]++;
|
m_ClientVotes[client] = index;
|
||||||
|
m_Votes[index]++;
|
||||||
m_NumVotes++;
|
m_NumVotes++;
|
||||||
|
|
||||||
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
|
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
|
||||||
{
|
{
|
||||||
static char buffer[1024];
|
static char buffer[1024];
|
||||||
ItemDrawInfo dr;
|
ItemDrawInfo dr;
|
||||||
menu->GetItemInfo(item, &dr);
|
menu->GetItemInfo(item, &dr, client);
|
||||||
|
|
||||||
if (sm_vote_console.GetBool())
|
if (sm_vote_console.GetBool())
|
||||||
{
|
{
|
||||||
|
@ -35,8 +35,10 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "sourcehook.h"
|
#include "sourcehook.h"
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
#include "compat_wrappers.h"
|
||||||
|
#include <time.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
NextMapManager g_NextMap;
|
NextMapManager g_NextMap;
|
||||||
|
|
||||||
@ -46,24 +48,16 @@ SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, co
|
|||||||
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
|
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
#else
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
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
|
#endif
|
||||||
|
|
||||||
ConCommand *changeLevelCmd = NULL;
|
ConCommand *changeLevelCmd = NULL;
|
||||||
|
|
||||||
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
|
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
|
||||||
|
ConVar sm_maphistory_size("sm_maphistory_size", "20");
|
||||||
|
|
||||||
bool g_forcedChange = false;
|
bool g_forcedChange = false;
|
||||||
|
|
||||||
@ -144,8 +138,8 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
|||||||
|
|
||||||
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
|
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
|
||||||
|
|
||||||
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
|
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
|
||||||
@ -168,33 +162,36 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName )
|
|||||||
{
|
{
|
||||||
/* Something intercepted the mapchange */
|
/* Something intercepted the mapchange */
|
||||||
char newReason[255];
|
char newReason[255];
|
||||||
UTIL_Format(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
|
ke::SafeSprintf(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
|
||||||
m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime));
|
m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Should this be customizable? */
|
int historydiff = sm_maphistory_size.GetInt();
|
||||||
if (m_mapHistory.size() > 20)
|
if (historydiff > 0)
|
||||||
{
|
{
|
||||||
SourceHook::List<MapChangeData *>::iterator iter;
|
historydiff -= m_mapHistory.size();
|
||||||
iter = m_mapHistory.begin();
|
} else if (historydiff < 0)
|
||||||
|
{
|
||||||
|
historydiff = (m_mapHistory.size() * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SourceHook::List<MapChangeData *>::iterator iter = m_mapHistory.begin(); historydiff++ < 0; iter = m_mapHistory.erase(iter))
|
||||||
|
{
|
||||||
delete (MapChangeData *)*iter;
|
delete (MapChangeData *)*iter;
|
||||||
|
|
||||||
m_mapHistory.erase(iter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tempChangeInfo.m_mapName[0] ='\0';
|
m_tempChangeInfo.m_mapName[0] ='\0';
|
||||||
m_tempChangeInfo.m_changeReason[0] = '\0';
|
m_tempChangeInfo.m_changeReason[0] = '\0';
|
||||||
m_tempChangeInfo.startTime = time(NULL);
|
m_tempChangeInfo.startTime = time(NULL);
|
||||||
UTIL_Format(lastMap, sizeof(lastMap), "%s", mapName);
|
ke::SafeStrcpy(lastMap, sizeof(lastMap), mapName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
|
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
|
||||||
{
|
{
|
||||||
/* Store the mapname and reason */
|
/* Store the mapname and reason */
|
||||||
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName);
|
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
|
||||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason);
|
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
|
||||||
|
|
||||||
/* Change level and skip our hook */
|
/* Change level and skip our hook */
|
||||||
g_forcedChange = true;
|
g_forcedChange = true;
|
||||||
@ -208,10 +205,7 @@ NextMapManager::NextMapManager()
|
|||||||
m_mapHistory = SourceHook::List<MapChangeData *>();
|
m_mapHistory = SourceHook::List<MapChangeData *>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
|
|
||||||
{
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void CmdChangeLevelCallback(const CCommand &command)
|
void CmdChangeLevelCallback(const CCommand &command)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
@ -227,7 +221,7 @@ void CmdChangeLevelCallback()
|
|||||||
|
|
||||||
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
|
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
|
||||||
{
|
{
|
||||||
UTIL_Format(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
|
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
|
||||||
UTIL_Format(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
|
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,16 +33,17 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_NEXTMAP_H_
|
#define _INCLUDE_SOURCEMOD_NEXTMAP_H_
|
||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "eiface.h"
|
#include <eiface.h>
|
||||||
#include "sh_list.h"
|
#include "sh_list.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
struct MapChangeData
|
struct MapChangeData
|
||||||
{
|
{
|
||||||
MapChangeData(const char *mapName, const char *changeReason, time_t time)
|
MapChangeData(const char *mapName, const char *changeReason, time_t time)
|
||||||
{
|
{
|
||||||
UTIL_Format(m_mapName, sizeof(m_mapName), mapName);
|
ke::SafeStrcpy(m_mapName, sizeof(m_mapName), mapName);
|
||||||
UTIL_Format(m_changeReason, sizeof(m_changeReason), changeReason);
|
ke::SafeStrcpy(m_changeReason, sizeof(m_changeReason), changeReason);
|
||||||
startTime = time;
|
startTime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,9 +59,7 @@ struct MapChangeData
|
|||||||
time_t startTime;
|
time_t startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void CmdChangeLevelCallback(const CCommand &command);
|
void CmdChangeLevelCallback(const CCommand &command);
|
||||||
#else
|
#else
|
||||||
void CmdChangeLevelCallback();
|
void CmdChangeLevelCallback();
|
||||||
@ -71,9 +70,7 @@ class NextMapManager : public SMGlobalClass
|
|||||||
public:
|
public:
|
||||||
NextMapManager();
|
NextMapManager();
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
friend void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
friend void CmdChangeLevelCallback(const CCommand &command);
|
friend void CmdChangeLevelCallback(const CCommand &command);
|
||||||
#else
|
#else
|
||||||
friend void CmdChangeLevelCallback();
|
friend void CmdChangeLevelCallback();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -38,16 +38,20 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <IAdminSystem.h>
|
#include <IAdminSystem.h>
|
||||||
|
#include <ITranslator.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <am-string.h>
|
#include <am-string.h>
|
||||||
|
#include <am-deque.h>
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
|
|
||||||
#include <steam/steamclientpublic.h>
|
#include <steam/steamclientpublic.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
class IClient;
|
||||||
|
|
||||||
#define PLAYER_LIFE_UNKNOWN 0
|
#define PLAYER_LIFE_UNKNOWN 0
|
||||||
#define PLAYER_LIFE_ALIVE 1
|
#define PLAYER_LIFE_ALIVE 1
|
||||||
#define PLAYER_LIFE_DEAD 2
|
#define PLAYER_LIFE_DEAD 2
|
||||||
@ -104,6 +108,9 @@ public:
|
|||||||
void DoBasicAdminChecks();
|
void DoBasicAdminChecks();
|
||||||
void MarkAsBeingKicked();
|
void MarkAsBeingKicked();
|
||||||
int GetLifeState();
|
int GetLifeState();
|
||||||
|
|
||||||
|
// This can be NULL for fakeclients due to limitations in our impl
|
||||||
|
IClient *GetIClient() const;
|
||||||
private:
|
private:
|
||||||
void Initialize(const char *name, const char *ip, edict_t *pEntity);
|
void Initialize(const char *name, const char *ip, edict_t *pEntity);
|
||||||
void Connect();
|
void Connect();
|
||||||
@ -115,45 +122,52 @@ private:
|
|||||||
void Authorize_Post();
|
void Authorize_Post();
|
||||||
void DoPostConnectAuthorization();
|
void DoPostConnectAuthorization();
|
||||||
bool IsAuthStringValidated();
|
bool IsAuthStringValidated();
|
||||||
|
bool SetEngineString();
|
||||||
|
bool SetCSteamID();
|
||||||
|
void ClearNetchannelQueue(void);
|
||||||
private:
|
private:
|
||||||
bool m_IsConnected;
|
bool m_IsConnected = false;
|
||||||
bool m_IsInGame;
|
bool m_IsInGame = false;
|
||||||
bool m_IsAuthorized;
|
bool m_IsAuthorized = false;
|
||||||
bool m_bIsInKickQueue;
|
bool m_bIsInKickQueue = false;
|
||||||
String m_Name;
|
String m_Name;
|
||||||
String m_Ip;
|
String m_Ip;
|
||||||
String m_IpNoPort;
|
String m_IpNoPort;
|
||||||
ke::AString m_AuthID;
|
ke::AString m_AuthID;
|
||||||
ke::AString m_Steam2Id;
|
ke::AString m_Steam2Id;
|
||||||
ke::AString m_Steam3Id;
|
ke::AString m_Steam3Id;
|
||||||
AdminId m_Admin;
|
AdminId m_Admin = INVALID_ADMIN_ID;
|
||||||
bool m_TempAdmin;
|
bool m_TempAdmin = false;
|
||||||
edict_t *m_pEdict;
|
edict_t *m_pEdict = nullptr;
|
||||||
IPlayerInfo *m_Info;
|
IPlayerInfo *m_Info = nullptr;
|
||||||
|
IClient *m_pIClient = nullptr;
|
||||||
String m_LastPassword;
|
String m_LastPassword;
|
||||||
bool m_bAdminCheckSignalled;
|
bool m_bAdminCheckSignalled = false;
|
||||||
int m_iIndex;
|
int m_iIndex;
|
||||||
unsigned int m_LangId;
|
unsigned int m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||||
int m_UserId;
|
int m_UserId = -1;
|
||||||
bool m_bFakeClient;
|
bool m_bFakeClient = false;
|
||||||
bool m_bIsSourceTV;
|
bool m_bIsSourceTV = false;
|
||||||
bool m_bIsReplay;
|
bool m_bIsReplay = false;
|
||||||
serial_t m_Serial;
|
serial_t m_Serial;
|
||||||
CSteamID m_SteamId;
|
CSteamID m_SteamId;
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
QueryCvarCookie_t m_LanguageCookie;
|
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
|
||||||
#endif
|
#endif
|
||||||
|
ke::Deque<ke::AString> m_PrintfBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerManager :
|
class PlayerManager :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IPlayerManager
|
public IPlayerManager,
|
||||||
|
public IGameEventListener2
|
||||||
{
|
{
|
||||||
friend class CPlayer;
|
friend class CPlayer;
|
||||||
public:
|
public:
|
||||||
PlayerManager();
|
PlayerManager();
|
||||||
~PlayerManager();
|
~PlayerManager();
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
|
void OnSourceModStartup(bool late) override;
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
void OnSourceModLevelEnd();
|
void OnSourceModLevelEnd();
|
||||||
@ -163,16 +177,6 @@ public:
|
|||||||
CPlayer *GetPlayerByIndex(int client) const;
|
CPlayer *GetPlayerByIndex(int client) const;
|
||||||
void RunAuthChecks();
|
void RunAuthChecks();
|
||||||
public:
|
public:
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
|
||||||
bool OnClientConnect_Post(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
|
||||||
void OnClientPutInServer(CEntityIndex index, char const *playername);
|
|
||||||
void OnClientDisconnect(CEntityIndex index, int reason);
|
|
||||||
void OnClientDisconnect_Post(CEntityIndex index, int reason);
|
|
||||||
void OnClientCommand(CEntityIndex index, const CCommand &args);
|
|
||||||
void OnClientSettingsChanged(CEntityIndex index);
|
|
||||||
//void OnClientSettingsChanged_Pre(CEntityIndex client);
|
|
||||||
#else
|
|
||||||
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
||||||
@ -180,13 +184,18 @@ public:
|
|||||||
void OnClientDisconnect_Post(edict_t *pEntity);
|
void OnClientDisconnect_Post(edict_t *pEntity);
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void OnClientCommand(edict_t *pEntity, const CCommand &args);
|
void OnClientCommand(edict_t *pEntity, const CCommand &args);
|
||||||
|
#if SOURCE_ENGINE >= SE_EYE
|
||||||
|
void OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand);
|
||||||
|
void OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
void OnClientCommand(edict_t *pEntity);
|
void OnClientCommand(edict_t *pEntity);
|
||||||
#endif
|
#endif
|
||||||
void OnClientSettingsChanged(edict_t *pEntity);
|
void OnClientSettingsChanged(edict_t *pEntity);
|
||||||
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
||||||
#endif
|
|
||||||
void OnServerHibernationUpdate(bool bHibernating);
|
void OnServerHibernationUpdate(bool bHibernating);
|
||||||
|
void OnClientPrintf(edict_t *pEdict, const char *szMsg);
|
||||||
|
void OnPrintfFrameAction(unsigned int serial);
|
||||||
public: //IPlayerManager
|
public: //IPlayerManager
|
||||||
void AddClientListener(IClientListener *listener);
|
void AddClientListener(IClientListener *listener);
|
||||||
void RemoveClientListener(IClientListener *listener);
|
void RemoveClientListener(IClientListener *listener);
|
||||||
@ -194,6 +203,7 @@ public: //IPlayerManager
|
|||||||
IGamePlayer *GetGamePlayer(edict_t *pEdict);
|
IGamePlayer *GetGamePlayer(edict_t *pEdict);
|
||||||
int GetMaxClients();
|
int GetMaxClients();
|
||||||
int GetNumPlayers();
|
int GetNumPlayers();
|
||||||
|
int GetNumClients();
|
||||||
int GetClientOfUserId(int userid);
|
int GetClientOfUserId(int userid);
|
||||||
bool IsServerActivated();
|
bool IsServerActivated();
|
||||||
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
|
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
|
||||||
@ -204,6 +214,8 @@ public: //IPlayerManager
|
|||||||
int GetClientFromSerial(unsigned int serial);
|
int GetClientFromSerial(unsigned int serial);
|
||||||
void ClearAdminId(AdminId id);
|
void ClearAdminId(AdminId id);
|
||||||
void RecheckAnyAdmins();
|
void RecheckAnyAdmins();
|
||||||
|
public: // IGameEventListener2
|
||||||
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
public:
|
public:
|
||||||
inline int MaxClients()
|
inline int MaxClients()
|
||||||
{
|
{
|
||||||
@ -223,15 +235,15 @@ public:
|
|||||||
unsigned int GetReplyTo();
|
unsigned int GetReplyTo();
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
unsigned int SetReplyTo(unsigned int reply);
|
||||||
void MaxPlayersChanged(int newvalue = -1);
|
void MaxPlayersChanged(int newvalue = -1);
|
||||||
|
inline bool InClientCommandKeyValuesHook()
|
||||||
|
{
|
||||||
|
return m_bInCCKVHook;
|
||||||
|
}
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
bool HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
|
||||||
void OnServerActivate();
|
|
||||||
#else
|
|
||||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
#endif
|
|
||||||
void InvalidatePlayer(CPlayer *pPlayer);
|
void InvalidatePlayer(CPlayer *pPlayer);
|
||||||
private:
|
private:
|
||||||
List<IClientListener *> m_hooks;
|
List<IClientListener *> m_hooks;
|
||||||
@ -241,6 +253,8 @@ private:
|
|||||||
IForward *m_cldisconnect_post;
|
IForward *m_cldisconnect_post;
|
||||||
IForward *m_clputinserver;
|
IForward *m_clputinserver;
|
||||||
IForward *m_clcommand;
|
IForward *m_clcommand;
|
||||||
|
IForward *m_clcommandkv;
|
||||||
|
IForward *m_clcommandkv_post;
|
||||||
IForward *m_clinfochanged;
|
IForward *m_clinfochanged;
|
||||||
IForward *m_clauth;
|
IForward *m_clauth;
|
||||||
IForward *m_onActivate;
|
IForward *m_onActivate;
|
||||||
@ -250,7 +264,7 @@ private:
|
|||||||
int m_maxClients;
|
int m_maxClients;
|
||||||
int m_PlayerCount;
|
int m_PlayerCount;
|
||||||
int m_PlayersSinceActive;
|
int m_PlayersSinceActive;
|
||||||
bool m_FirstPass;
|
bool m_bServerActivated;
|
||||||
unsigned int *m_AuthQueue;
|
unsigned int *m_AuthQueue;
|
||||||
String m_PassInfoVar;
|
String m_PassInfoVar;
|
||||||
bool m_QueryLang;
|
bool m_QueryLang;
|
||||||
@ -261,11 +275,14 @@ private:
|
|||||||
bool m_bIsReplayActive;
|
bool m_bIsReplayActive;
|
||||||
int m_SourceTVUserId;
|
int m_SourceTVUserId;
|
||||||
int m_ReplayUserId;
|
int m_ReplayUserId;
|
||||||
|
bool m_bInCCKVHook;
|
||||||
|
int m_ClientCount;
|
||||||
|
private:
|
||||||
|
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
|
||||||
|
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0
|
||||||
};
|
};
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
|
|
||||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void CmdMaxplayersCallback(const CCommand &command);
|
void CmdMaxplayersCallback(const CCommand &command);
|
||||||
#else
|
#else
|
||||||
void CmdMaxplayersCallback();
|
void CmdMaxplayersCallback();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
|
||||||
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
#define GETCHECK_FIELD() \
|
#define GETCHECK_FIELD() \
|
||||||
const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
|
const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
|
||||||
@ -117,6 +118,13 @@ public:
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool HasField(const char *pszFieldName)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_NOT_REPEATED();
|
||||||
|
return msg->GetReflection()->HasField(*msg, field);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool GetInt32(const char *pszFieldName, int32 *out)
|
inline bool GetInt32(const char *pszFieldName, int32 *out)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -341,6 +349,20 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool GetInt64OrUnsigned(const char *pszFieldName, int64 *out)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||||
|
CHECK_FIELD_NOT_REPEATED();
|
||||||
|
|
||||||
|
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||||
|
*out = (int64)msg->GetReflection()->GetUInt64(*msg, field);
|
||||||
|
else
|
||||||
|
*out = msg->GetReflection()->GetInt64(*msg, field);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -367,6 +389,24 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool SetInt64OrUnsigned(const char *pszFieldName, int64 value)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||||
|
CHECK_FIELD_NOT_REPEATED();
|
||||||
|
|
||||||
|
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||||
|
{
|
||||||
|
msg->GetReflection()->SetUInt64(msg, field, (uint64)value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg->GetReflection()->SetInt64(msg, field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
|
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -384,6 +424,21 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool GetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 *out)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||||
|
CHECK_FIELD_REPEATED();
|
||||||
|
CHECK_REPEATED_ELEMENT(index);
|
||||||
|
|
||||||
|
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||||
|
*out = (int64)msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
|
||||||
|
else
|
||||||
|
*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
|
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -411,6 +466,25 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool SetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 value)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||||
|
CHECK_FIELD_REPEATED();
|
||||||
|
CHECK_REPEATED_ELEMENT(index);
|
||||||
|
|
||||||
|
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||||
|
{
|
||||||
|
msg->GetReflection()->SetRepeatedUInt64(msg, field, index, (uint64)value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg->GetReflection()->SetRepeatedInt64(msg, field, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -437,6 +511,24 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool AddInt64OrUnsigned(const char *pszFieldName, int64 value)
|
||||||
|
{
|
||||||
|
GETCHECK_FIELD();
|
||||||
|
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||||
|
CHECK_FIELD_REPEATED();
|
||||||
|
|
||||||
|
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||||
|
{
|
||||||
|
msg->GetReflection()->AddUInt64(msg, field, (uint64)value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg->GetReflection()->AddInt64(msg, field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool GetBool(const char *pszFieldName, bool *out)
|
inline bool GetBool(const char *pszFieldName, bool *out)
|
||||||
{
|
{
|
||||||
GETCHECK_FIELD();
|
GETCHECK_FIELD();
|
||||||
@ -672,7 +764,7 @@ public:
|
|||||||
CHECK_FIELD_NOT_REPEATED();
|
CHECK_FIELD_NOT_REPEATED();
|
||||||
|
|
||||||
std::string scratch;
|
std::string scratch;
|
||||||
strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &scratch).c_str(), size);
|
ke::SafeStrcpy(out, size, msg->GetReflection()->GetStringReference(*msg, field, &scratch).c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -695,7 +787,7 @@ public:
|
|||||||
CHECK_REPEATED_ELEMENT(index);
|
CHECK_REPEATED_ELEMENT(index);
|
||||||
|
|
||||||
std::string scratch;
|
std::string scratch;
|
||||||
strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
|
ke::SafeStrcpy(out, size, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,14 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
#include <dota_usermessage_helpers.h>
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
#include <cstrike15_usermessage_helpers.h>
|
#include <cstrike15_usermessage_helpers.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
UserMessages g_UserMsgs;
|
UserMessages g_UserMsgs;
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
||||||
#else
|
#else
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
@ -94,7 +93,7 @@ void UserMessages::OnSourceModAllShutdown()
|
|||||||
{
|
{
|
||||||
if (m_HookCount)
|
if (m_HookCount)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
#else
|
#else
|
||||||
@ -109,10 +108,7 @@ void UserMessages::OnSourceModAllShutdown()
|
|||||||
|
|
||||||
int UserMessages::GetMessageIndex(const char *msg)
|
int UserMessages::GetMessageIndex(const char *msg)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
// Can split this per engine and/or game later
|
|
||||||
return g_DotaUsermessageHelpers.GetIndex(msg);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
// Can split this per engine and/or game later
|
// Can split this per engine and/or game later
|
||||||
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||||
#else
|
#else
|
||||||
@ -150,15 +146,13 @@ int UserMessages::GetMessageIndex(const char *msg)
|
|||||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
||||||
{
|
{
|
||||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||||
#endif
|
#endif
|
||||||
if (!pszName)
|
if (!pszName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
strncopy(buffer, pszName, maxlength);
|
ke::SafeStrcpy(buffer, maxlength, pszName);
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
if (m_FallbackSearch)
|
if (m_FallbackSearch)
|
||||||
@ -171,7 +165,7 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
|
|||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
strncopy(buffer, msg, maxlength);
|
ke::SafeStrcpy(buffer, maxlength, msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +297,7 @@ bool UserMessages::EndMessage()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
{
|
{
|
||||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||||
@ -333,7 +327,7 @@ bool UserMessages::EndMessage()
|
|||||||
} else {
|
} else {
|
||||||
engine->MessageEnd();
|
engine->MessageEnd();
|
||||||
}
|
}
|
||||||
#endif // SE_CSGO || SE_DOTA
|
#endif // SE_CSGO
|
||||||
|
|
||||||
m_InExec = false;
|
m_InExec = false;
|
||||||
m_CurFlags = 0;
|
m_CurFlags = 0;
|
||||||
@ -418,7 +412,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
|
|||||||
|
|
||||||
if (!m_HookCount++)
|
if (!m_HookCount++)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
#else
|
#else
|
||||||
@ -442,9 +436,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
|
|||||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
|
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
return g_DotaUsermessageHelpers.GetPrototype(msg_type);
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
|
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -495,7 +487,7 @@ void UserMessages::_DecRefCounter()
|
|||||||
{
|
{
|
||||||
if (--m_HookCount == 0)
|
if (--m_HookCount == 0)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
#else
|
#else
|
||||||
@ -507,12 +499,10 @@ void UserMessages::_DecRefCounter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
OnStartMessage_Pre(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
#endif
|
#endif
|
||||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||||
@ -527,9 +517,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
|
|||||||
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
|
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
OnStartMessage_Post(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
|
|
||||||
#elif SOURCE_ENGINE == SE_CSGO
|
|
||||||
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -563,7 +551,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
|
|||||||
RETURN_META(res)
|
RETURN_META(res)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
@ -603,7 +591,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
|||||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
@ -768,7 +756,7 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
|
|
||||||
if (!handled && intercepted)
|
if (!handled && intercepted)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||||
#else
|
#else
|
||||||
bf_write *engine_bfw;
|
bf_write *engine_bfw;
|
||||||
@ -780,11 +768,11 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||||
ENGINE_CALL(MessageEnd)();
|
ENGINE_CALL(MessageEnd)();
|
||||||
#endif // SE_CSGO || SE_DOTA
|
#endif // SE_CSGO
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
int size = m_OrigBuffer->ByteSize();
|
int size = m_OrigBuffer->ByteSize();
|
||||||
uint8 *data = (uint8 *)stackalloc(size);
|
uint8 *data = (uint8 *)stackalloc(size);
|
||||||
m_OrigBuffer->SerializePartialToArray(data, size);
|
m_OrigBuffer->SerializePartialToArray(data, size);
|
||||||
@ -814,7 +802,7 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
delete pTempMsg;
|
delete pTempMsg;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
#define USE_PROTOBUF_USERMESSAGES
|
#define USE_PROTOBUF_USERMESSAGES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -102,12 +102,12 @@ public: //IUserMessages
|
|||||||
bool intercept=false);
|
bool intercept=false);
|
||||||
UserMessageType GetUserMessageType() const;
|
UserMessageType GetUserMessageType() const;
|
||||||
public:
|
public:
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||||
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
77
core/command_args.h
Normal file
77
core/command_args.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
// =============================================================================
|
||||||
|
// SourceMod
|
||||||
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
|
// =============================================================================
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
// Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CCOMMANDARGS_IMPL_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CCOMMANDARGS_IMPL_H_
|
||||||
|
|
||||||
|
#include "sourcemm_api.h"
|
||||||
|
#include <IRootConsoleMenu.h>
|
||||||
|
#include <compat_wrappers.h>
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE==SE_EPISODEONE || SOURCE_ENGINE==SE_DARKMESSIAH
|
||||||
|
class EngineArgs : public ICommandArgs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EngineArgs(const CCommand& _cmd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const char *Arg(int n) const
|
||||||
|
{
|
||||||
|
return engine->Cmd_Argv(n);
|
||||||
|
}
|
||||||
|
int ArgC() const
|
||||||
|
{
|
||||||
|
return engine->Cmd_Argc();
|
||||||
|
}
|
||||||
|
const char *ArgS() const
|
||||||
|
{
|
||||||
|
return engine->Cmd_Args();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class EngineArgs : public ICommandArgs
|
||||||
|
{
|
||||||
|
const CCommand *cmd;
|
||||||
|
public:
|
||||||
|
EngineArgs(const CCommand& _cmd) : cmd(&_cmd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const char *Arg(int n) const
|
||||||
|
{
|
||||||
|
return cmd->Arg(n);
|
||||||
|
}
|
||||||
|
int ArgC() const
|
||||||
|
{
|
||||||
|
return cmd->ArgC();
|
||||||
|
}
|
||||||
|
const char *ArgS() const
|
||||||
|
{
|
||||||
|
return cmd->ArgS();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_CCOMMANDARGS_IMPL_H_
|
@ -1,33 +1,29 @@
|
|||||||
/**
|
// vim: set ts=4 sw=4 tw=99 et:
|
||||||
* vim: set ts=4 :
|
// =============================================================================
|
||||||
* =============================================================================
|
// SourceMod
|
||||||
* SourceMod
|
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
// =============================================================================
|
||||||
* =============================================================================
|
//
|
||||||
*
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
// Free Software Foundation.
|
||||||
* Free Software Foundation.
|
//
|
||||||
*
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
// details.
|
||||||
* details.
|
//
|
||||||
*
|
// You should have received a copy of the GNU General Public License along with
|
||||||
* You should have received a copy of the GNU General Public License along with
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
||||||
*
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
@ -36,10 +32,15 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "compat_wrappers.h"
|
#include "compat_wrappers.h"
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
SH_DECL_HOOK2_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *, bool);
|
||||||
|
#else
|
||||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
|
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
|
||||||
#endif
|
#endif
|
||||||
@ -81,7 +82,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
void LinkConCommandBase(ConCommandBase *pBase, bool unknown)
|
||||||
|
#else
|
||||||
void LinkConCommandBase(ConCommandBase *pBase)
|
void LinkConCommandBase(ConCommandBase *pBase)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||||
while (listener)
|
while (listener)
|
||||||
@ -103,15 +108,13 @@ public:
|
|||||||
listener = listener->next;
|
listener = listener->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBase)
|
|
||||||
{
|
|
||||||
while (iter != tracked_bases.end())
|
while (iter != tracked_bases.end())
|
||||||
{
|
{
|
||||||
if ((*iter)->pBase == pBase)
|
if ((*iter)->pBase == pBase)
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
iter = tracked_bases.erase(iter);
|
iter = tracked_bases.erase(iter);
|
||||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
|
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName());
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -120,25 +123,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
while (iter != tracked_bases.end())
|
|
||||||
{
|
|
||||||
/* This is just god-awful! */
|
|
||||||
if (FindCommandBase((*iter)->name) != (*iter)->pBase)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
iter = tracked_bases.erase(iter);
|
|
||||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
||||||
{
|
{
|
||||||
@ -146,7 +130,7 @@ public:
|
|||||||
|
|
||||||
info->pBase = pBase;
|
info->pBase = pBase;
|
||||||
info->cls = cls;
|
info->cls = cls;
|
||||||
strncopy(info->name, pBase->GetName(), sizeof(info->name));
|
ke::SafeStrcpy(info->name, sizeof(info->name), pBase->GetName());
|
||||||
|
|
||||||
tracked_bases.push_back(info);
|
tracked_bases.push_back(info);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
class IConCommandTracker
|
class IConCommandTracker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
|
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||||
|
551
core/convar_sm.h
551
core/convar_sm.h
@ -1,551 +0,0 @@
|
|||||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $Workfile: $
|
|
||||||
// $Date: 2006-08-13 06:34:30 -0500 (Sun, 13 Aug 2006) $
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// $NoKeywords: $
|
|
||||||
//=============================================================================//
|
|
||||||
|
|
||||||
#ifndef CONVAR_H
|
|
||||||
#define CONVAR_H
|
|
||||||
#if _WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tier0/dbg.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
|
||||||
#elif _LINUX
|
|
||||||
#define FORCEINLINE_CVAR __inline__ FORCEINLINE
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The default, no flags at all
|
|
||||||
#define FCVAR_NONE 0
|
|
||||||
|
|
||||||
// Command to ConVars and ConCommands
|
|
||||||
// ConVar Systems
|
|
||||||
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
|
|
||||||
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
|
|
||||||
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
|
|
||||||
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
|
|
||||||
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
|
|
||||||
#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system.
|
|
||||||
#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system.
|
|
||||||
#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system.
|
|
||||||
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
|
|
||||||
#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library
|
|
||||||
#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library
|
|
||||||
#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll
|
|
||||||
#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system
|
|
||||||
// NOTE!! if you add a cvar system, add it here too!!!!
|
|
||||||
// the engine lacks a cvar flag, but needs it for xbox
|
|
||||||
// an engine cvar is thus a cvar not marked with any other system
|
|
||||||
#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM))
|
|
||||||
|
|
||||||
// ConVar only
|
|
||||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
|
||||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
|
||||||
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
|
|
||||||
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
|
|
||||||
#define FCVAR_USERINFO (1<<9) // changes the client's info string
|
|
||||||
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
|
|
||||||
|
|
||||||
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
|
||||||
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
|
||||||
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
|
|
||||||
|
|
||||||
// It's a ConVar that's shared between the client and the server.
|
|
||||||
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
|
|
||||||
// client, of course )
|
|
||||||
// If a change is requested it must come from the console (i.e., no remote client changes)
|
|
||||||
// If a value is changed while a server is active, it's replicated to all connected clients
|
|
||||||
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
|
|
||||||
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
|
|
||||||
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
|
|
||||||
|
|
||||||
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
|
|
||||||
|
|
||||||
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
|
|
||||||
|
|
||||||
|
|
||||||
// #define FCVAR_AVAILABLE (1<<27)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<28)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<29)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<30)
|
|
||||||
// #define FCVAR_AVAILABLE (1<<31)
|
|
||||||
|
|
||||||
|
|
||||||
class ConVar;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// You don't have to instantiate one of these, just call its
|
|
||||||
// OneTimeInit function when your executable is initializing.
|
|
||||||
class ConCommandBaseMgr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Call this ONCE when the executable starts up.
|
|
||||||
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
|
|
||||||
#ifdef _XBOX
|
|
||||||
static bool Fixup( ConCommandBase* pConCommandBase );
|
|
||||||
#ifndef _RETAIL
|
|
||||||
static void PublishCommands( bool bForce );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// Called when a ConVar changes value
|
|
||||||
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
|
|
||||||
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
typedef void ( *FnCommandCallback )( void );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( char const *pName, char const *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsBitSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
|
|
||||||
// Return name of cvar
|
|
||||||
virtual char const *GetName( void ) const;
|
|
||||||
|
|
||||||
// Return help text for cvar
|
|
||||||
virtual char const *GetHelpText( void ) const;
|
|
||||||
|
|
||||||
// Deal with next pointer
|
|
||||||
const ConCommandBase *GetNext( void ) const;
|
|
||||||
void SetNext( ConCommandBase *next );
|
|
||||||
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Global methods
|
|
||||||
static ConCommandBase const *GetCommands( void );
|
|
||||||
static void AddToList( ConCommandBase *var );
|
|
||||||
static void RemoveFlaggedCommands( int flag );
|
|
||||||
static void RevertFlaggedCvars( int flag );
|
|
||||||
static ConCommandBase const *FindCommand( char const *name );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Create( char const *pName, char const *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
// Internal copy routine ( uses new operator from correct module )
|
|
||||||
char *CopyString( char const *from );
|
|
||||||
|
|
||||||
// Next ConVar in chain
|
|
||||||
ConCommandBase *m_pNext;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Has the cvar been added to the global list?
|
|
||||||
bool m_bRegistered;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
char const *m_pszName;
|
|
||||||
char const *m_pszHelpString;
|
|
||||||
|
|
||||||
// ConVar flags
|
|
||||||
int m_nFlags;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
|
|
||||||
// all the console variables and registers them.
|
|
||||||
static ConCommandBase *s_pConCommandBases;
|
|
||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
|
||||||
|
|
||||||
public: // Hackalicous
|
|
||||||
inline int GetFlags() const
|
|
||||||
{
|
|
||||||
return m_nFlags;
|
|
||||||
}
|
|
||||||
inline void SetFlags(int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The console invoked command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
friend class G_ConCommand;
|
|
||||||
friend class C_ConCommand;
|
|
||||||
friend class M_ConCommand;
|
|
||||||
friend class S_ConCommand;
|
|
||||||
friend class D_ConCommand;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConCommand( void );
|
|
||||||
ConCommand( char const *pName, FnCommandCallback callback,
|
|
||||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommand( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
virtual bool CanAutoComplete( void );
|
|
||||||
|
|
||||||
// Invoke the function
|
|
||||||
virtual void Dispatch( void );
|
|
||||||
private:
|
|
||||||
virtual void Create( char const *pName, FnCommandCallback callback,
|
|
||||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
|
|
||||||
// Call this function when executing the command
|
|
||||||
FnCommandCallback m_fnCommandCallback;
|
|
||||||
|
|
||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
|
||||||
bool m_bHasCompletionCallback;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnCommandCallback GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnCommandCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: A console variable
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class ConCommandBaseMgr;
|
|
||||||
friend class CCvar;
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
friend class G_ConVar;
|
|
||||||
friend class C_ConVar;
|
|
||||||
friend class M_ConVar;
|
|
||||||
friend class S_ConVar;
|
|
||||||
friend class D_ConVar;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
|
|
||||||
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, FnChangeCallback callback );
|
|
||||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
|
||||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
|
||||||
FnChangeCallback callback );
|
|
||||||
|
|
||||||
virtual ~ConVar( void );
|
|
||||||
|
|
||||||
virtual bool IsBitSet( int flag ) const;
|
|
||||||
virtual char const* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
virtual char const *GetName( void ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Install a change callback (there shouldn't already be one....)
|
|
||||||
void InstallChangeCallback( FnChangeCallback 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;
|
|
||||||
|
|
||||||
// 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( char const *value );
|
|
||||||
virtual void SetValue( float value );
|
|
||||||
virtual void SetValue( int value );
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
char const *GetDefault( void ) const;
|
|
||||||
|
|
||||||
static void RevertAll( void );
|
|
||||||
private:
|
|
||||||
// Called by CCvar when the value of a var is changing.
|
|
||||||
virtual void InternalSetValue(char const *value);
|
|
||||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
|
||||||
virtual void InternalSetFloatValue( float fNewValue );
|
|
||||||
virtual void InternalSetIntValue( int nValue );
|
|
||||||
|
|
||||||
virtual bool ClampValue( float& value );
|
|
||||||
virtual void ChangeStringValue( char const *tempVal );
|
|
||||||
|
|
||||||
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
|
|
||||||
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
|
||||||
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
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
|
|
||||||
char const *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 m_fnChangeCallback;
|
|
||||||
public: // Hackalicous
|
|
||||||
inline FnChangeCallback 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 : char const *
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR char const *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 : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _STATIC_LINKED
|
|
||||||
// identifies subsystem via piggybacking constructors with flags
|
|
||||||
class G_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class C_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class M_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class S_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class D_ConCommand : public ConCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString );
|
|
||||||
typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString );
|
|
||||||
|
|
||||||
class G_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class C_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class M_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class S_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class D_ConVar : public ConVar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {}
|
|
||||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// redirect these declarations to their specific subsystem
|
|
||||||
#ifdef GAME_DLL
|
|
||||||
#define ConCommand G_ConCommand
|
|
||||||
#define ConVar G_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef CLIENT_DLL
|
|
||||||
#define ConCommand C_ConCommand
|
|
||||||
#define ConVar C_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef MATERIALSYSTEM_DLL
|
|
||||||
#define ConCommand M_ConCommand
|
|
||||||
#define ConVar M_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef STUDIORENDER_DLL
|
|
||||||
#define ConCommand S_ConCommand
|
|
||||||
#define ConVar S_ConVar
|
|
||||||
#endif
|
|
||||||
#ifdef DATACACHE_DLL
|
|
||||||
#define ConCommand D_ConCommand
|
|
||||||
#define ConVar D_ConVar
|
|
||||||
#endif
|
|
||||||
#endif // _STATIC_LINKED
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND( name, description ) \
|
|
||||||
static void name(); \
|
|
||||||
static ConCommand name##_command( #name, name, description ); \
|
|
||||||
static void name()
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND_F( name, description, flags ) \
|
|
||||||
static void name(); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags ); \
|
|
||||||
static void name()
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CONVAR_H
|
|
File diff suppressed because it is too large
Load Diff
@ -1,718 +0,0 @@
|
|||||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $Workfile: $
|
|
||||||
// $Date: $
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// $NoKeywords: $
|
|
||||||
//===========================================================================//
|
|
||||||
|
|
||||||
#ifndef CONVAR_H
|
|
||||||
#define CONVAR_H
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tier0/dbg.h"
|
|
||||||
#include "tier1/iconvar.h"
|
|
||||||
#include "tier1/utlvector.h"
|
|
||||||
#include "tier1/utlstring.h"
|
|
||||||
#include "icvar.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
|
||||||
#elif defined _LINUX || defined __APPLE__
|
|
||||||
#define FORCEINLINE_CVAR inline
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Forward declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar;
|
|
||||||
class CCommand;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
struct characterset_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helper method for console development
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined( _X360 ) && !defined( _RETAIL )
|
|
||||||
void ConVar_PublishToVXConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
|
||||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Interface version
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ICommandCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
|
||||||
friend void ConVar_PublishToVXConsole();
|
|
||||||
|
|
||||||
// FIXME: Remove when ConVar changes are done
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
// Remove flag
|
|
||||||
virtual void RemoveFlags( int flags );
|
|
||||||
// Get flags
|
|
||||||
virtual int GetFlags( void ) const;
|
|
||||||
|
|
||||||
// Return name of cvar
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
|
|
||||||
// Return help text for cvar
|
|
||||||
virtual const char *GetHelpText( void ) const;
|
|
||||||
|
|
||||||
// Deal with next pointer
|
|
||||||
const ConCommandBase *GetNext( void ) const;
|
|
||||||
ConCommandBase *GetNext( void );
|
|
||||||
|
|
||||||
inline void SetNext(ConCommandBase *pBase)
|
|
||||||
{
|
|
||||||
m_pNext = pBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Returns the DLL identifier
|
|
||||||
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Create( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize/shutdown
|
|
||||||
virtual void Init();
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// Internal copy routine ( uses new operator from correct module )
|
|
||||||
char *CopyString( const char *from );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Next ConVar in chain
|
|
||||||
// Prior to register, it points to the next convar in the DLL.
|
|
||||||
// Once registered, though, m_pNext is reset to point to the next
|
|
||||||
// convar in the global list
|
|
||||||
ConCommandBase *m_pNext;
|
|
||||||
|
|
||||||
// Has the cvar been added to the global list?
|
|
||||||
bool m_bRegistered;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
const char *m_pszName;
|
|
||||||
const char *m_pszHelpString;
|
|
||||||
|
|
||||||
// ConVar flags
|
|
||||||
int m_nFlags;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// ConVars add themselves to this list for the executable.
|
|
||||||
// Then ConVar_Register runs through all the console variables
|
|
||||||
// and registers them into a global list stored in vstdlib.dll
|
|
||||||
static ConCommandBase *s_pConCommandBases;
|
|
||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
|
||||||
public:
|
|
||||||
inline void SetFlags(int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Command tokenizer
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class CCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCommand();
|
|
||||||
CCommand( int nArgC, const char **ppArgV );
|
|
||||||
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
int ArgC() const;
|
|
||||||
const char **ArgV() const;
|
|
||||||
const char *ArgS() const; // All args that occur after the 0th arg, in string form
|
|
||||||
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
|
|
||||||
const char *operator[]( int nIndex ) const; // Gets at arguments
|
|
||||||
const char *Arg( int nIndex ) const; // Gets at arguments
|
|
||||||
|
|
||||||
// Helper functions to parse arguments to commands.
|
|
||||||
const char* FindArg( const char *pName ) const;
|
|
||||||
int FindArgInt( const char *pName, int nDefaultVal ) const;
|
|
||||||
|
|
||||||
static int MaxCommandLength();
|
|
||||||
static characterset_t* DefaultBreakSet();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
COMMAND_MAX_ARGC = 64,
|
|
||||||
COMMAND_MAX_LENGTH = 512,
|
|
||||||
};
|
|
||||||
|
|
||||||
int m_nArgc;
|
|
||||||
int m_nArgv0Size;
|
|
||||||
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int CCommand::MaxCommandLength()
|
|
||||||
{
|
|
||||||
return COMMAND_MAX_LENGTH - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int CCommand::ArgC() const
|
|
||||||
{
|
|
||||||
return m_nArgc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char **CCommand::ArgV() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? (const char**)m_ppArgv : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::ArgS() const
|
|
||||||
{
|
|
||||||
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::GetCommandString() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? m_pArgSBuffer : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::Arg( int nIndex ) const
|
|
||||||
{
|
|
||||||
// FIXME: Many command handlers appear to not be particularly careful
|
|
||||||
// about checking for valid argc range. For now, we're going to
|
|
||||||
// do the extra check and return an empty string if it's out of range
|
|
||||||
if ( nIndex < 0 || nIndex >= m_nArgc )
|
|
||||||
return "";
|
|
||||||
return m_ppArgv[nIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::operator[]( int nIndex ) const
|
|
||||||
{
|
|
||||||
return Arg( nIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The console invoked command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, FnCommandCallback_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, ICommandCallback *pCallback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommand( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
|
|
||||||
|
|
||||||
virtual bool CanAutoComplete( void );
|
|
||||||
|
|
||||||
// Invoke the function
|
|
||||||
virtual void Dispatch( const CCommand &command );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// NOTE: To maintain backward compat, we have to be very careful:
|
|
||||||
// All public virtual methods must appear in the same order always
|
|
||||||
// since engine code will be calling into this code, which *does not match*
|
|
||||||
// in the mod code; it's using slightly different, but compatible versions
|
|
||||||
// of this class. Also: Be very careful about adding new fields to this class.
|
|
||||||
// Those fields will not exist in the version of this class that is instanced
|
|
||||||
// in mod code.
|
|
||||||
|
|
||||||
// Call this function when executing the command
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
|
||||||
FnCommandCallback_t m_fnCommandCallback;
|
|
||||||
ICommandCallback *m_pCommandCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
|
||||||
ICommandCompletionCallback *m_pCommandCompletionCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool m_bHasCompletionCallback : 1;
|
|
||||||
bool m_bUsingNewCommandCallback : 1;
|
|
||||||
bool m_bUsingCommandCallbackInterface : 1;
|
|
||||||
public:
|
|
||||||
inline FnCommandCallback_t GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnCommandCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: A console variable
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar : public ConCommandBase, public IConVar
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVarRef;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, FnChangeCallback_t callback );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
|
||||||
FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
virtual ~ConVar( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual int GetFlags( void ) const;
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
virtual const char* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Install a change callback (there shouldn't already be one....)
|
|
||||||
void InstallChangeCallback( FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
// Retrieve value
|
|
||||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
|
||||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
|
||||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
|
||||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
virtual const char *GetBaseName( void ) const;
|
|
||||||
virtual int GetSplitScreenPlayerSlot ( void ) const;
|
|
||||||
|
|
||||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
|
||||||
// from alloc/free across dll/exe boundaries.
|
|
||||||
|
|
||||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
|
||||||
virtual void SetValue( const char *value );
|
|
||||||
virtual void SetValue( float value );
|
|
||||||
virtual void SetValue( int value );
|
|
||||||
#if SOURCE_ENGINE >= SE_NUCLEARDAWN
|
|
||||||
virtual void SetValue( Color value );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Reset to default value
|
|
||||||
void Revert( void );
|
|
||||||
|
|
||||||
// True if it has a min/max setting
|
|
||||||
bool GetMin( float& minVal ) const;
|
|
||||||
bool GetMax( float& maxVal ) const;
|
|
||||||
const char *GetDefault( void ) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Called by CCvar when the value of a var is changing.
|
|
||||||
virtual void InternalSetValue(const char *value);
|
|
||||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
|
||||||
virtual void InternalSetFloatValue( float fNewValue );
|
|
||||||
virtual void InternalSetIntValue( int nValue );
|
|
||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD2
|
|
||||||
virtual void InternalSetColorValue( Color value );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual bool ClampValue( float& value );
|
|
||||||
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
|
|
||||||
|
|
||||||
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
|
|
||||||
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
|
||||||
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// This either points to "this" or it points to the original declaration of a ConVar.
|
|
||||||
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
|
||||||
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
|
||||||
ConVar *m_pParent;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
const char *m_pszDefaultValue;
|
|
||||||
|
|
||||||
// Value
|
|
||||||
// Dynamically allocated
|
|
||||||
char *m_pszString;
|
|
||||||
int m_StringLength;
|
|
||||||
|
|
||||||
// Values
|
|
||||||
float m_fValue;
|
|
||||||
int m_nValue;
|
|
||||||
|
|
||||||
// Min/Max values
|
|
||||||
bool m_bHasMin;
|
|
||||||
float m_fMinVal;
|
|
||||||
bool m_bHasMax;
|
|
||||||
float m_fMaxVal;
|
|
||||||
|
|
||||||
// Call this function when ConVar changes
|
|
||||||
FnChangeCallback_t m_fnChangeCallback;
|
|
||||||
public:
|
|
||||||
inline FnChangeCallback_t GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnChangeCallback;
|
|
||||||
}
|
|
||||||
inline void SetMin(bool set, float min=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMin = set;
|
|
||||||
m_fMinVal = min;
|
|
||||||
}
|
|
||||||
inline void SetMax(bool set, float max=0.0)
|
|
||||||
{
|
|
||||||
m_bHasMax = set;
|
|
||||||
m_fMaxVal = max;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a float
|
|
||||||
// Output : float
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as an int
|
|
||||||
// Output : int
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
|
||||||
{
|
|
||||||
return m_pParent->m_nValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
|
||||||
// Output : const char *
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
|
|
||||||
{
|
|
||||||
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
|
||||||
return "FCVAR_NEVER_AS_STRING";
|
|
||||||
|
|
||||||
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Used to read/write convars that already exist (replaces the FindVar method)
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVarRef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConVarRef( const char *pName );
|
|
||||||
ConVarRef( const char *pName, bool bIgnoreMissing );
|
|
||||||
ConVarRef( IConVar *pConVar );
|
|
||||||
|
|
||||||
void Init( const char *pName, bool bIgnoreMissing );
|
|
||||||
bool IsValid() const;
|
|
||||||
bool IsFlagSet( int nFlags ) const;
|
|
||||||
IConVar *GetLinkedConVar();
|
|
||||||
|
|
||||||
// Get/Set value
|
|
||||||
float GetFloat( void ) const;
|
|
||||||
int GetInt( void ) const;
|
|
||||||
bool GetBool() const { return !!GetInt(); }
|
|
||||||
const char *GetString( void ) const;
|
|
||||||
|
|
||||||
void SetValue( const char *pValue );
|
|
||||||
void SetValue( float flValue );
|
|
||||||
void SetValue( int nValue );
|
|
||||||
void SetValue( bool bValue );
|
|
||||||
|
|
||||||
const char *GetName() const;
|
|
||||||
|
|
||||||
const char *GetDefault() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// High-speed method to read convar data
|
|
||||||
IConVar *m_pConVar;
|
|
||||||
ConVar *m_pConVarState;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Did we find an existing convar of that name?
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
|
|
||||||
{
|
|
||||||
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
|
|
||||||
{
|
|
||||||
return m_pConVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
|
|
||||||
{
|
|
||||||
return m_pConVar->GetName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a float
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_fValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as an int
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_nValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
|
|
||||||
{
|
|
||||||
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
|
|
||||||
return m_pConVarState->m_pszString;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( pValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( flValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( nValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
|
|
||||||
{
|
|
||||||
m_pConVar->SetValue( bValue ? 1 : 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
|
|
||||||
{
|
|
||||||
return m_pConVarState->m_pszDefaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called by the framework to register ConCommands with the ICVar
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
|
|
||||||
void ConVar_Unregister( );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Utility methods
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void ConVar_PrintFlags( const ConCommandBase *var );
|
|
||||||
void ConVar_PrintDescription( const ConCommandBase *pVar );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility class to quickly allow ConCommands to call member methods
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning (disable : 4355 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template< class T >
|
|
||||||
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
typedef ConCommand BaseClass;
|
|
||||||
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
|
|
||||||
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
|
|
||||||
|
|
||||||
public:
|
|
||||||
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
|
|
||||||
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
|
|
||||||
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
|
|
||||||
{
|
|
||||||
m_pOwner = pOwner;
|
|
||||||
m_Func = callback;
|
|
||||||
m_CompletionFunc = completionFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CConCommandMemberAccessor()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetOwner( T* pOwner )
|
|
||||||
{
|
|
||||||
m_pOwner = pOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void CommandCallback( const CCommand &command )
|
|
||||||
{
|
|
||||||
Assert( m_pOwner && m_Func );
|
|
||||||
(m_pOwner->*m_Func)( command );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
|
|
||||||
{
|
|
||||||
Assert( m_pOwner && m_CompletionFunc );
|
|
||||||
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* m_pOwner;
|
|
||||||
FnMemberCommandCallback_t m_Func;
|
|
||||||
FnMemberCommandCompletionCallback_t m_CompletionFunc;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning ( default : 4355 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: Utility macros to quicky generate a simple console command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define CON_COMMAND( name, description ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_F( name, description, flags ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
|
|
||||||
static void name( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, name, description, flags, completion ); \
|
|
||||||
static void name( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, _funcname, description ); \
|
|
||||||
void _funcname( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
static ConCommand name##_command( #name, _funcname, description, flags ); \
|
|
||||||
void _funcname( const CCommand &args )
|
|
||||||
|
|
||||||
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
|
|
||||||
void _funcname( const CCommand &args ); \
|
|
||||||
friend class CCommandMemberInitializer_##_funcname; \
|
|
||||||
class CCommandMemberInitializer_##_funcname \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
|
|
||||||
{ \
|
|
||||||
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
|
|
||||||
} \
|
|
||||||
private: \
|
|
||||||
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CONVAR_H
|
|
@ -1,709 +0,0 @@
|
|||||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
||||||
//
|
|
||||||
// Purpose:
|
|
||||||
//
|
|
||||||
// $Workfile: $
|
|
||||||
// $Date: $
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// $NoKeywords: $
|
|
||||||
//===========================================================================//
|
|
||||||
|
|
||||||
#ifndef CONVAR_H
|
|
||||||
#define CONVAR_H
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tier0/dbg.h"
|
|
||||||
#include "tier1/iconvar.h"
|
|
||||||
#include "tier1/utlvector.h"
|
|
||||||
#include "tier1/utlstring.h"
|
|
||||||
#include "icvar.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
|
||||||
#elif defined _LINUX || defined __APPLE__
|
|
||||||
#define FORCEINLINE_CVAR inline
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Forward declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar;
|
|
||||||
class CCommand;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
struct characterset_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helper method for console development
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined( _X360 ) && !defined( _RETAIL )
|
|
||||||
void ConVar_PublishToVXConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
|
||||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Interface version
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ICommandCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
|
||||||
friend void ConVar_PublishToVXConsole();
|
|
||||||
|
|
||||||
// FIXME: Remove when ConVar changes are done
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
|
|
||||||
// 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 );
|
|
||||||
|
|
||||||
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: // Hackalicous
|
|
||||||
inline int GetFlags() const
|
|
||||||
{
|
|
||||||
return m_nFlags;
|
|
||||||
}
|
|
||||||
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: // Hackalicous
|
|
||||||
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 IsFlagSet( int flag ) const;
|
|
||||||
virtual const char* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual bool IsCommand( 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;
|
|
||||||
|
|
||||||
// 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 );
|
|
||||||
|
|
||||||
// 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 );
|
|
||||||
|
|
||||||
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 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
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: // Hackalicous
|
|
||||||
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
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined _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;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined _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
@ -1,11 +1,14 @@
|
|||||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
import os
|
import os
|
||||||
|
|
||||||
binary = SM.Library(builder, 'sourcemod.logic')
|
for arch in SM.archs:
|
||||||
|
binary = SM.Library(builder, 'sourcemod.logic', arch)
|
||||||
binary.compiler.cxxincludes += [
|
binary.compiler.cxxincludes += [
|
||||||
|
builder.sourcePath,
|
||||||
os.path.join(builder.sourcePath, 'core', 'logic'),
|
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||||
os.path.join(builder.sourcePath, 'public'),
|
os.path.join(builder.sourcePath, 'public'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||||
]
|
]
|
||||||
@ -14,15 +17,15 @@ binary.compiler.defines += [
|
|||||||
'SM_LOGIC'
|
'SM_LOGIC'
|
||||||
]
|
]
|
||||||
|
|
||||||
if builder.target_platform == 'linux':
|
if builder.target.platform == 'linux':
|
||||||
binary.compiler.postlink += ['-lpthread', '-lrt']
|
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||||
elif builder.target_platform == 'mac':
|
elif builder.target.platform == 'mac':
|
||||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||||
|
|
||||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||||
binary.compiler.cxxflags += ['-fno-rtti']
|
binary.compiler.cxxflags += ['-fno-rtti']
|
||||||
elif binary.compiler.vendor == 'msvc':
|
elif binary.compiler.family == 'msvc':
|
||||||
binary.compiler.cxxflags += ['/GR-']
|
binary.compiler.cxxflags += ['/GR-']
|
||||||
|
|
||||||
binary.sources += [
|
binary.sources += [
|
||||||
@ -62,7 +65,6 @@ binary.sources += [
|
|||||||
'PluginSys.cpp',
|
'PluginSys.cpp',
|
||||||
'HandleSys.cpp',
|
'HandleSys.cpp',
|
||||||
'NativeOwner.cpp',
|
'NativeOwner.cpp',
|
||||||
'NativeInvoker.cpp',
|
|
||||||
'ExtensionSys.cpp',
|
'ExtensionSys.cpp',
|
||||||
'DebugReporter.cpp',
|
'DebugReporter.cpp',
|
||||||
'Database.cpp',
|
'Database.cpp',
|
||||||
@ -75,8 +77,21 @@ binary.sources += [
|
|||||||
'Logger.cpp',
|
'Logger.cpp',
|
||||||
'smn_core.cpp',
|
'smn_core.cpp',
|
||||||
'smn_menus.cpp',
|
'smn_menus.cpp',
|
||||||
|
'sprintf.cpp',
|
||||||
|
'LibrarySys.cpp',
|
||||||
|
'RootConsoleMenu.cpp',
|
||||||
|
'CDataPack.cpp',
|
||||||
|
'frame_tasks.cpp',
|
||||||
|
'smn_halflife.cpp',
|
||||||
|
'FrameIterator.cpp',
|
||||||
|
'DatabaseConfBuilder.cpp',
|
||||||
|
'NativeInvoker.cpp',
|
||||||
]
|
]
|
||||||
if builder.target_platform == 'windows':
|
|
||||||
|
if arch == 'x64':
|
||||||
|
binary.sources += ['PseudoAddrManager.cpp']
|
||||||
|
|
||||||
|
if builder.target.platform == 'windows':
|
||||||
binary.sources += ['thread/WinThreads.cpp']
|
binary.sources += ['thread/WinThreads.cpp']
|
||||||
else:
|
else:
|
||||||
binary.sources += ['thread/PosixThreads.cpp']
|
binary.sources += ['thread/PosixThreads.cpp']
|
||||||
|
@ -39,15 +39,19 @@
|
|||||||
#include "AdminCache.h"
|
#include "AdminCache.h"
|
||||||
#include "Translator.h"
|
#include "Translator.h"
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
#include "stringutil.h"
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
#include <bridge/include/IVEngineServerBridge.h>
|
||||||
|
|
||||||
#define LEVEL_STATE_NONE 0
|
#define LEVEL_STATE_NONE 0
|
||||||
#define LEVEL_STATE_LEVELS 1
|
#define LEVEL_STATE_LEVELS 1
|
||||||
#define LEVEL_STATE_FLAGS 2
|
#define LEVEL_STATE_FLAGS 2
|
||||||
|
|
||||||
AdminCache g_Admins;
|
AdminCache g_Admins;
|
||||||
char g_ReverseFlags[26];
|
char g_ReverseFlags[AdminFlags_TOTAL];
|
||||||
AdminFlag g_FlagLetters[26];
|
AdminFlag g_FlagLetters[26];
|
||||||
bool g_FlagSet[26];
|
bool g_FlagCharSet[26];
|
||||||
|
|
||||||
/* Default flags */
|
/* Default flags */
|
||||||
AdminFlag g_DefaultFlags[26] =
|
AdminFlag g_DefaultFlags[26] =
|
||||||
@ -71,9 +75,9 @@ public:
|
|||||||
memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
|
memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
|
||||||
for (unsigned int i=0; i<20; i++)
|
for (unsigned int i=0; i<20; i++)
|
||||||
{
|
{
|
||||||
g_FlagSet[i] = true;
|
g_FlagCharSet[i] = true;
|
||||||
}
|
}
|
||||||
g_FlagSet[25] = true;
|
g_FlagCharSet[25] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -103,7 +107,7 @@ private:
|
|||||||
{
|
{
|
||||||
m_LevelState = LEVEL_STATE_NONE;
|
m_LevelState = LEVEL_STATE_NONE;
|
||||||
m_IgnoreLevel = 0;
|
m_IgnoreLevel = 0;
|
||||||
memset(g_FlagSet, 0, sizeof(g_FlagSet));
|
memset(g_FlagCharSet, 0, sizeof(g_FlagCharSet));
|
||||||
}
|
}
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
|
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||||
{
|
{
|
||||||
@ -163,7 +167,7 @@ private:
|
|||||||
return SMCResult_Continue;
|
return SMCResult_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_FlagSet[c] = true;
|
g_FlagCharSet[c] = true;
|
||||||
|
|
||||||
return SMCResult_Continue;
|
return SMCResult_Continue;
|
||||||
}
|
}
|
||||||
@ -267,6 +271,21 @@ void AdminCache::OnSourceModStartup(bool late)
|
|||||||
NameFlag("custom4", Admin_Custom4);
|
NameFlag("custom4", Admin_Custom4);
|
||||||
NameFlag("custom5", Admin_Custom5);
|
NameFlag("custom5", Admin_Custom5);
|
||||||
NameFlag("custom6", Admin_Custom6);
|
NameFlag("custom6", Admin_Custom6);
|
||||||
|
|
||||||
|
auto sm_dump_admcache = [this] (int client, const ICommandArgs *args) -> bool {
|
||||||
|
char buffer[PLATFORM_MAX_PATH];
|
||||||
|
g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
|
||||||
|
|
||||||
|
if (!DumpCache(buffer)) {
|
||||||
|
bridge->ConsolePrint("Could not open file for writing: %s", buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bridge->ConsolePrint("Admin cache dumped to: %s", buffer);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
bridge->DefineCommand("sm_dump_admcache", "Dumps the admin cache for debugging", sm_dump_admcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminCache::OnSourceModAllInitialized()
|
void AdminCache::OnSourceModAllInitialized()
|
||||||
@ -327,7 +346,7 @@ void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
map->insert(cmd, flags);
|
map->insert(cmd, flags);
|
||||||
smcore.UpdateAdminCmdFlags(cmd, type, flags, false);
|
bridge->UpdateAdminCmdFlags(cmd, type, flags, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
|
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
|
||||||
@ -356,13 +375,13 @@ void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
|
|||||||
void AdminCache::_UnsetCommandGroupOverride(const char *group)
|
void AdminCache::_UnsetCommandGroupOverride(const char *group)
|
||||||
{
|
{
|
||||||
m_CmdGrpOverrides.remove(group);
|
m_CmdGrpOverrides.remove(group);
|
||||||
smcore.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
|
bridge->UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminCache::_UnsetCommandOverride(const char *cmd)
|
void AdminCache::_UnsetCommandOverride(const char *cmd)
|
||||||
{
|
{
|
||||||
m_CmdOverrides.remove(cmd);
|
m_CmdOverrides.remove(cmd);
|
||||||
smcore.UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
|
bridge->UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminCache::DumpCommandOverrideCache(OverrideType type)
|
void AdminCache::DumpCommandOverrideCache(OverrideType type)
|
||||||
@ -981,7 +1000,6 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
|
|||||||
{
|
{
|
||||||
List<IAdminListener *>::iterator iter;
|
List<IAdminListener *>::iterator iter;
|
||||||
IAdminListener *pListener;
|
IAdminListener *pListener;
|
||||||
cell_t result;
|
|
||||||
|
|
||||||
if (part == AdminCache_Overrides)
|
if (part == AdminCache_Overrides)
|
||||||
{
|
{
|
||||||
@ -995,7 +1013,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
|
|||||||
pListener->OnRebuildOverrideCache();
|
pListener->OnRebuildOverrideCache();
|
||||||
}
|
}
|
||||||
m_pCacheFwd->PushCell(part);
|
m_pCacheFwd->PushCell(part);
|
||||||
m_pCacheFwd->Execute(&result);
|
m_pCacheFwd->Execute();
|
||||||
}
|
}
|
||||||
} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
|
} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
|
||||||
if (part == AdminCache_Groups)
|
if (part == AdminCache_Groups)
|
||||||
@ -1009,7 +1027,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
|
|||||||
pListener->OnRebuildGroupCache();
|
pListener->OnRebuildGroupCache();
|
||||||
}
|
}
|
||||||
m_pCacheFwd->PushCell(part);
|
m_pCacheFwd->PushCell(part);
|
||||||
m_pCacheFwd->Execute(&result);
|
m_pCacheFwd->Execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InvalidateAdminCache(true);
|
InvalidateAdminCache(true);
|
||||||
@ -1021,7 +1039,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
|
|||||||
pListener->OnRebuildAdminCache((part == AdminCache_Groups));
|
pListener->OnRebuildAdminCache((part == AdminCache_Groups));
|
||||||
}
|
}
|
||||||
m_pCacheFwd->PushCell(AdminCache_Admins);
|
m_pCacheFwd->PushCell(AdminCache_Admins);
|
||||||
m_pCacheFwd->Execute(&result);
|
m_pCacheFwd->Execute();
|
||||||
playerhelpers->RecheckAnyAdmins();
|
playerhelpers->RecheckAnyAdmins();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1063,22 +1081,29 @@ bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
|
|||||||
bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen)
|
bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen)
|
||||||
{
|
{
|
||||||
int len = strlen(ident);
|
int len = strlen(ident);
|
||||||
/* If the id was a steam id strip off the STEAM_*: part */
|
if (!strcmp(ident, "BOT"))
|
||||||
if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
|
|
||||||
{
|
{
|
||||||
// non-bot/lan Steam2 Id
|
// Bots
|
||||||
snprintf(out, maxlen, "%s", &ident[8]);
|
strncopy(out, ident, maxlen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
|
||||||
|
{
|
||||||
|
// non-bot/lan Steam2 Id, strip off the STEAM_* part
|
||||||
|
ke::SafeStrcpy(out, maxlen, &ident[8]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
|
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
|
||||||
{
|
{
|
||||||
// Steam3 Id
|
// Steam3 Id, replicate the Steam2 Post-"STEAM_" part
|
||||||
uint32_t accountId = strtoul(&ident[5], nullptr, 10);
|
uint32_t accountId = strtoul(&ident[5], nullptr, 10);
|
||||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// 64-bit CSteamID, replicate the Steam2 Post-"STEAM_" part
|
||||||
|
|
||||||
// some constants from steamclientpublic.h
|
// some constants from steamclientpublic.h
|
||||||
static const uint32_t k_EAccountTypeIndividual = 1;
|
static const uint32_t k_EAccountTypeIndividual = 1;
|
||||||
static const int k_EUniverseInvalid = 0;
|
static const int k_EUniverseInvalid = 0;
|
||||||
@ -1099,7 +1124,7 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
|
|||||||
&& accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance
|
&& accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1509,7 +1534,7 @@ bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Fourth, if the targeted admin is immune from targeting admin. */
|
/** Fourth, if the targeted admin is immune from targeting admin. */
|
||||||
int mode = smcore.GetImmunityMode();
|
int mode = bridge->GetImmunityMode();
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -1577,7 +1602,7 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
|
|||||||
{
|
{
|
||||||
if (c < 'a'
|
if (c < 'a'
|
||||||
|| c > 'z'
|
|| c > 'z'
|
||||||
|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
|
|| !g_FlagCharSet[(unsigned)c - (unsigned)'a'])
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1592,17 +1617,13 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
|
|||||||
|
|
||||||
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
|
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
|
||||||
{
|
{
|
||||||
if (!g_FlagSet[flag])
|
char flagchar = g_ReverseFlags[flag];
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
*c = g_ReverseFlags[flag];
|
*c = flagchar;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return flagchar != '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
|
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
|
||||||
@ -1650,7 +1671,7 @@ bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
|
|||||||
cmd++;
|
cmd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!smcore.LookForCommandAdminFlags(cmd, &bits))
|
if (!bridge->LookForCommandAdminFlags(cmd, &bits))
|
||||||
{
|
{
|
||||||
if (!GetCommandOverride(cmd, otype, &bits))
|
if (!GetCommandOverride(cmd, otype, &bits))
|
||||||
{
|
{
|
||||||
@ -1725,7 +1746,7 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o
|
|||||||
bool found_command = false;
|
bool found_command = false;
|
||||||
if (!override_only)
|
if (!override_only)
|
||||||
{
|
{
|
||||||
found_command = smcore.LookForCommandAdminFlags(cmd, &bits);
|
found_command = bridge->LookForCommandAdminFlags(cmd, &bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_command)
|
if (!found_command)
|
||||||
|
@ -82,6 +82,10 @@ struct AuthMethod
|
|||||||
{
|
{
|
||||||
return strcmp(name, method->name.c_str()) == 0;
|
return strcmp(name, method->name.c_str()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UserAuth
|
struct UserAuth
|
||||||
|
244
core/logic/CDataPack.cpp
Normal file
244
core/logic/CDataPack.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "CDataPack.h"
|
||||||
|
#include <amtl/am-autoptr.h>
|
||||||
|
|
||||||
|
CDataPack::CDataPack()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
CDataPack::~CDataPack()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ke::Vector<ke::AutoPtr<CDataPack>> sDataPackCache;
|
||||||
|
|
||||||
|
CDataPack *CDataPack::New()
|
||||||
|
{
|
||||||
|
if (sDataPackCache.empty())
|
||||||
|
return new CDataPack();
|
||||||
|
|
||||||
|
CDataPack *pack = sDataPackCache.back().take();
|
||||||
|
sDataPackCache.pop();
|
||||||
|
pack->Initialize();
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CDataPack::Free(CDataPack *pack)
|
||||||
|
{
|
||||||
|
sDataPackCache.append(static_cast<CDataPack *>(pack));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::Initialize()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
} while (this->RemoveItem());
|
||||||
|
|
||||||
|
elements.clear();
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::ResetSize()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||||
|
{
|
||||||
|
InternalPack val;
|
||||||
|
val.type = CDataPackType::Raw;
|
||||||
|
val.pData.vval = new uint8_t[size + sizeof(size)];
|
||||||
|
reinterpret_cast<size_t *>(val.pData.vval)[0] = size;
|
||||||
|
elements.insert(position, val);
|
||||||
|
|
||||||
|
return position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::PackCell(cell_t cell)
|
||||||
|
{
|
||||||
|
InternalPack val;
|
||||||
|
val.type = CDataPackType::Cell;
|
||||||
|
val.pData.cval = cell;
|
||||||
|
elements.insert(position++, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::PackFunction(cell_t function)
|
||||||
|
{
|
||||||
|
InternalPack val;
|
||||||
|
val.type = CDataPackType::Function;
|
||||||
|
val.pData.cval = function;
|
||||||
|
elements.insert(position++, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::PackFloat(float floatval)
|
||||||
|
{
|
||||||
|
InternalPack val;
|
||||||
|
val.type = CDataPackType::Float;
|
||||||
|
val.pData.fval = floatval;
|
||||||
|
elements.insert(position++, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::PackString(const char *string)
|
||||||
|
{
|
||||||
|
InternalPack val;
|
||||||
|
val.type = CDataPackType::String;
|
||||||
|
ke::AString *sval = new ke::AString(string);
|
||||||
|
val.pData.sval = sval;
|
||||||
|
elements.insert(position++, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDataPack::Reset() const
|
||||||
|
{
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CDataPack::GetPosition() const
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDataPack::SetPosition(size_t pos) const
|
||||||
|
{
|
||||||
|
if (pos > elements.length())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
position = pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t CDataPack::ReadCell() const
|
||||||
|
{
|
||||||
|
if (!IsReadable() || elements[position].type != CDataPackType::Cell)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return elements[position++].pData.cval;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t CDataPack::ReadFunction() const
|
||||||
|
{
|
||||||
|
if (!IsReadable() || elements[position].type != CDataPackType::Function)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return elements[position++].pData.cval;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CDataPack::ReadFloat() const
|
||||||
|
{
|
||||||
|
if (!IsReadable() || elements[position].type != CDataPackType::Float)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return elements[position++].pData.fval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDataPack::IsReadable(size_t bytes) const
|
||||||
|
{
|
||||||
|
return (position < elements.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CDataPack::ReadString(size_t *len) const
|
||||||
|
{
|
||||||
|
if (!IsReadable() || elements[position].type != CDataPackType::String)
|
||||||
|
{
|
||||||
|
if (len)
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ke::AString &val = *elements[position++].pData.sval;
|
||||||
|
if (len)
|
||||||
|
*len = val.length();
|
||||||
|
|
||||||
|
return val.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CDataPack::ReadMemory(size_t *size) const
|
||||||
|
{
|
||||||
|
void *ptr = nullptr;
|
||||||
|
if (!IsReadable() || elements[position].type != CDataPackType::Raw)
|
||||||
|
return ptr;
|
||||||
|
|
||||||
|
size_t *val = reinterpret_cast<size_t *>(elements[position].pData.vval);
|
||||||
|
ptr = &(val[1]);
|
||||||
|
++position;
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = val[0]; /* Egor!!!! */
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDataPack::RemoveItem(size_t pos)
|
||||||
|
{
|
||||||
|
if (!elements.length())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == static_cast<size_t>(-1))
|
||||||
|
{
|
||||||
|
pos = position;
|
||||||
|
}
|
||||||
|
if (pos >= elements.length())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos < position) // we're deleting under us, step back
|
||||||
|
{
|
||||||
|
--position;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (elements[pos].type)
|
||||||
|
{
|
||||||
|
case CDataPackType::Raw:
|
||||||
|
{
|
||||||
|
delete elements[pos].pData.vval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CDataPackType::String:
|
||||||
|
{
|
||||||
|
delete elements[pos].pData.sval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.remove(pos);
|
||||||
|
return true;
|
||||||
|
}
|
196
core/logic/CDataPack.h
Normal file
196
core/logic/CDataPack.h
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/**
|
||||||
|
* 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_CDATAPACK_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||||
|
|
||||||
|
#include <ISourceMod.h>
|
||||||
|
#include <amtl/am-vector.h>
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
enum CDataPackType {
|
||||||
|
Raw,
|
||||||
|
Cell,
|
||||||
|
Float,
|
||||||
|
String,
|
||||||
|
Function
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDataPack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDataPack();
|
||||||
|
~CDataPack();
|
||||||
|
|
||||||
|
static CDataPack *New();
|
||||||
|
static void Free(CDataPack *pack);
|
||||||
|
|
||||||
|
public: // Originally IDataReader
|
||||||
|
/**
|
||||||
|
* @brief Resets the position in the data stream to the beginning.
|
||||||
|
*/
|
||||||
|
void Reset() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the current stream position.
|
||||||
|
*
|
||||||
|
* @return Index into the stream.
|
||||||
|
*/
|
||||||
|
size_t GetPosition() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current stream position.
|
||||||
|
*
|
||||||
|
* @param pos Index to set the stream at.
|
||||||
|
* @return True if succeeded, false if out of bounds.
|
||||||
|
*/
|
||||||
|
bool SetPosition(size_t pos) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads one cell from the data stream.
|
||||||
|
*
|
||||||
|
* @return A cell read from the current position.
|
||||||
|
*/
|
||||||
|
cell_t ReadCell() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads one float from the data stream.
|
||||||
|
*
|
||||||
|
* @return A float read from the current position.
|
||||||
|
*/
|
||||||
|
float ReadFloat() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether or not a specified number of bytes from the current stream
|
||||||
|
* position to the end can be read.
|
||||||
|
*
|
||||||
|
* @param bytes Number of bytes to simulate reading.
|
||||||
|
* @return True if can be read, false otherwise.
|
||||||
|
*/
|
||||||
|
bool IsReadable(size_t bytes = 0) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a string from the data stream.
|
||||||
|
*
|
||||||
|
* @param len Optional pointer to store the string length.
|
||||||
|
* @return Pointer to the string, or NULL if out of bounds.
|
||||||
|
*/
|
||||||
|
const char *ReadString(size_t *len) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the current position as a generic data type.
|
||||||
|
*
|
||||||
|
* @param size Optional pointer to store the size of the data type.
|
||||||
|
* @return Pointer to the data, or NULL if out of bounds.
|
||||||
|
*/
|
||||||
|
void *ReadMemory(size_t *size) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a function pointer from the data stream.
|
||||||
|
*
|
||||||
|
* @return A function pointer read from the current position.
|
||||||
|
*/
|
||||||
|
cell_t ReadFunction() const;
|
||||||
|
|
||||||
|
public: // Originally IDataPack
|
||||||
|
/**
|
||||||
|
* @brief Resets the used size of the stream back to zero.
|
||||||
|
*/
|
||||||
|
void ResetSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs one cell into the data stream.
|
||||||
|
*
|
||||||
|
* @param cell Cell value to write.
|
||||||
|
*/
|
||||||
|
void PackCell(cell_t cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs one float into the data stream.
|
||||||
|
*
|
||||||
|
* @param val Float value to write.
|
||||||
|
*/
|
||||||
|
void PackFloat(float val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs one string into the data stream.
|
||||||
|
* The length is recorded as well for buffer overrun protection.
|
||||||
|
*
|
||||||
|
* @param string String to write.
|
||||||
|
*/
|
||||||
|
void PackString(const char *string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a generic block of memory in the stream.
|
||||||
|
*
|
||||||
|
* Note that the pointer it returns can be invalidated on further
|
||||||
|
* writing, since the stream size may grow. You may need to double back
|
||||||
|
* and fetch the pointer again.
|
||||||
|
*
|
||||||
|
* @param size Size of the memory to create in the stream.
|
||||||
|
* @param addr Optional pointer to store the relocated memory address.
|
||||||
|
* @return Current position of the stream beforehand.
|
||||||
|
*/
|
||||||
|
size_t CreateMemory(size_t size, void **addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs one function pointer into the data stream.
|
||||||
|
*
|
||||||
|
* @param function The function pointer to write.
|
||||||
|
*/
|
||||||
|
void PackFunction(cell_t function);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Initialize();
|
||||||
|
inline size_t GetCapacity() const { return this->elements.length(); };
|
||||||
|
inline CDataPackType GetCurrentType(void) const { return this->elements[this->position].type; };
|
||||||
|
bool RemoveItem(size_t pos = -1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef union {
|
||||||
|
cell_t cval;
|
||||||
|
float fval;
|
||||||
|
uint8_t *vval;
|
||||||
|
ke::AString *sval;
|
||||||
|
} InternalPackValue;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
InternalPackValue pData;
|
||||||
|
CDataPackType type;
|
||||||
|
} InternalPack;
|
||||||
|
|
||||||
|
ke::Vector<InternalPack> elements;
|
||||||
|
mutable size_t position;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
@ -34,10 +34,11 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ICellArray.h>
|
||||||
|
|
||||||
extern HandleType_t htCellArray;
|
extern HandleType_t htCellArray;
|
||||||
|
|
||||||
class CellArray
|
class CellArray : public ICellArray
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
|
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
|
||||||
@ -49,6 +50,31 @@ public:
|
|||||||
free(m_Data);
|
free(m_Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a cell array object.
|
||||||
|
*
|
||||||
|
* @param blocksize The number of cells each member of the array can
|
||||||
|
* hold. For example, 32 cells is equivalent to:
|
||||||
|
* new Array[X][32]
|
||||||
|
* @return A new ICellArray object.
|
||||||
|
*/
|
||||||
|
static ICellArray *New(size_t blocksize)
|
||||||
|
{
|
||||||
|
return new CellArray(blocksize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases a cell array's resources.
|
||||||
|
*
|
||||||
|
* @param pack An ICellArray object to release.
|
||||||
|
*/
|
||||||
|
static void Free(ICellArray *arr)
|
||||||
|
{
|
||||||
|
delete arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICellArray
|
||||||
|
public:
|
||||||
size_t size() const
|
size_t size() const
|
||||||
{
|
{
|
||||||
return m_Size;
|
return m_Size;
|
||||||
@ -154,12 +180,18 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellArray *clone()
|
ICellArray *clone()
|
||||||
{
|
{
|
||||||
CellArray *array = new CellArray(m_BlockSize);
|
CellArray *array = new CellArray(m_BlockSize);
|
||||||
array->m_AllocSize = m_AllocSize;
|
array->m_AllocSize = m_AllocSize;
|
||||||
array->m_Size = m_Size;
|
array->m_Size = m_Size;
|
||||||
array->m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
array->m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
||||||
|
if (!array->m_Data)
|
||||||
|
{
|
||||||
|
delete array;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(array->m_Data, m_Data, sizeof(cell_t) * m_BlockSize * m_Size);
|
memcpy(array->m_Data, m_Data, sizeof(cell_t) * m_BlockSize * m_Size);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@ -195,11 +227,17 @@ private:
|
|||||||
/* finally, allocate the new block */
|
/* finally, allocate the new block */
|
||||||
if (m_Data)
|
if (m_Data)
|
||||||
{
|
{
|
||||||
m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
cell_t *data = static_cast<cell_t*>(realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize));
|
||||||
} else {
|
if (!data) // allocation failure
|
||||||
m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return (m_Data != NULL);
|
|
||||||
|
m_Data = data;
|
||||||
|
} else {
|
||||||
|
m_Data = static_cast<cell_t*>(malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize));
|
||||||
|
}
|
||||||
|
return (m_Data != nullptr);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
cell_t *m_Data;
|
cell_t *m_Data;
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#include "PluginSys.h"
|
#include "PluginSys.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <IThreader.h>
|
#include <IThreader.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
|
||||||
#define DBPARSE_LEVEL_NONE 0
|
#define DBPARSE_LEVEL_NONE 0
|
||||||
#define DBPARSE_LEVEL_MAIN 1
|
#define DBPARSE_LEVEL_MAIN 1
|
||||||
@ -46,8 +48,6 @@ static bool s_OneTimeThreaderErrorMsg = false;
|
|||||||
|
|
||||||
DBManager::DBManager()
|
DBManager::DBManager()
|
||||||
: m_Terminate(false),
|
: m_Terminate(false),
|
||||||
m_ParseLevel(0),
|
|
||||||
m_ParseState(0),
|
|
||||||
m_pDefault(NULL)
|
m_pDefault(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -71,31 +71,22 @@ void DBManager::OnSourceModAllInitialized()
|
|||||||
g_ShareSys.AddInterface(NULL, this);
|
g_ShareSys.AddInterface(NULL, this);
|
||||||
|
|
||||||
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
||||||
|
m_Builder.SetPath(m_Filename);
|
||||||
|
|
||||||
g_PluginSys.AddPluginsListener(this);
|
g_PluginSys.AddPluginsListener(this);
|
||||||
|
|
||||||
g_pSM->AddGameFrameHook(&FrameHook);
|
g_pSM->AddGameFrameHook(&FrameHook);
|
||||||
|
|
||||||
|
auto sm_reload_databases = [this] (int client, const ICommandArgs *args) -> bool {
|
||||||
|
m_Builder.StartParse();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bridge->DefineCommand("sm_reload_databases", "Reparse database configurations file", sm_reload_databases);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnSourceModLevelChange(const char *mapName)
|
void DBManager::OnSourceModLevelChange(const char *mapName)
|
||||||
{
|
{
|
||||||
SMCError err;
|
m_Builder.StartParse();
|
||||||
SMCStates states = {0, 0};
|
|
||||||
|
|
||||||
/* We lock and don't give up the lock until we're done.
|
|
||||||
* This way the thread's search won't be searching through a
|
|
||||||
* potentially empty/corrupt list, which would be very bad.
|
|
||||||
*/
|
|
||||||
ke::AutoLock lock(&m_ConfigLock);
|
|
||||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
|
||||||
{
|
|
||||||
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
|
||||||
if (err != SMCError_Custom)
|
|
||||||
{
|
|
||||||
const char *txt = textparsers->GetSMCErrorString(err);
|
|
||||||
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnSourceModShutdown()
|
void DBManager::OnSourceModShutdown()
|
||||||
@ -105,7 +96,6 @@ void DBManager::OnSourceModShutdown()
|
|||||||
g_PluginSys.RemovePluginsListener(this);
|
g_PluginSys.RemovePluginsListener(this);
|
||||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
||||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
||||||
ClearConfigs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DBManager::GetInterfaceVersion()
|
unsigned int DBManager::GetInterfaceVersion()
|
||||||
@ -133,136 +123,10 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::ReadSMC_ParseStart()
|
|
||||||
{
|
|
||||||
ClearConfigs();
|
|
||||||
m_ParseLevel = 0;
|
|
||||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
m_ParseLevel++;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_NONE)
|
|
||||||
{
|
|
||||||
if (strcmp(name, "Databases") == 0)
|
|
||||||
{
|
|
||||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
|
||||||
} else {
|
|
||||||
m_ParseLevel++;
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
|
||||||
s_CurInfo = ConfDbInfo();
|
|
||||||
s_CurInfo.name = name;
|
|
||||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
|
||||||
m_ParseLevel++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_MAIN)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "driver_default") == 0)
|
|
||||||
{
|
|
||||||
m_DefDriver.assign(value);
|
|
||||||
}
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
|
||||||
if (strcmp(key, "driver") == 0)
|
|
||||||
{
|
|
||||||
if (strcmp(value, "default") != 0)
|
|
||||||
{
|
|
||||||
s_CurInfo.driver = value;
|
|
||||||
}
|
|
||||||
} else if (strcmp(key, "database") == 0) {
|
|
||||||
s_CurInfo.database = value;
|
|
||||||
} else if (strcmp(key, "host") == 0) {
|
|
||||||
s_CurInfo.host = value;
|
|
||||||
} else if (strcmp(key, "user") == 0) {
|
|
||||||
s_CurInfo.user = value;
|
|
||||||
} else if (strcmp(key, "pass") == 0) {
|
|
||||||
s_CurInfo.pass = value;
|
|
||||||
} else if (strcmp(key, "timeout") == 0) {
|
|
||||||
s_CurInfo.info.maxTimeout = atoi(value);
|
|
||||||
} else if (strcmp(key, "port") == 0) {
|
|
||||||
s_CurInfo.info.port = atoi(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
|
||||||
{
|
|
||||||
if (m_ParseLevel)
|
|
||||||
{
|
|
||||||
m_ParseLevel--;
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
|
||||||
{
|
|
||||||
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(cdb);
|
|
||||||
|
|
||||||
/* Go up one level */
|
|
||||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
|
||||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
|
||||||
return SMCResult_Halt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
|
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
ConfDbInfo *pInfo = GetDatabaseConf(name);
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
|
ke::RefPtr<ConfDbInfo> pInfo = list->GetDatabaseConf(name);
|
||||||
|
|
||||||
if (!pInfo)
|
if (!pInfo)
|
||||||
{
|
{
|
||||||
@ -281,11 +145,12 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
|||||||
/* Try to assign a real driver pointer */
|
/* Try to assign a real driver pointer */
|
||||||
if (pInfo->info.driver[0] == '\0')
|
if (pInfo->info.driver[0] == '\0')
|
||||||
{
|
{
|
||||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
ke::AString defaultDriver = list->GetDefaultDriver();
|
||||||
|
if (!m_pDefault && defaultDriver.length() > 0)
|
||||||
{
|
{
|
||||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
m_pDefault = FindOrLoadDriver(defaultDriver.chars());
|
||||||
}
|
}
|
||||||
dname = m_DefDriver.size() ? m_DefDriver.c_str() : "default";
|
dname = defaultDriver.length() ? defaultDriver.chars() : "default";
|
||||||
pInfo->realDriver = m_pDefault;
|
pInfo->realDriver = m_pDefault;
|
||||||
} else {
|
} else {
|
||||||
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
|
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
|
||||||
@ -309,7 +174,6 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
|||||||
*pdb = NULL;
|
*pdb = NULL;
|
||||||
|
|
||||||
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
|
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,17 +206,17 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure NOTHING references this! */
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
List<ConfDbInfo *>::iterator iter;
|
for (size_t i = 0; i < list->length(); i++)
|
||||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
|
||||||
{
|
{
|
||||||
ConfDbInfo &db = *(*iter);
|
ke::RefPtr<ConfDbInfo> current = list->at(i);
|
||||||
if (db.realDriver == pDriver)
|
if (current->realDriver == pDriver)
|
||||||
{
|
{
|
||||||
db.realDriver = NULL;
|
current->realDriver = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Someone unloaded the default driver? Silly.. */
|
/* Someone unloaded the default driver? Silly.. */
|
||||||
if (pDriver == m_pDefault)
|
if (pDriver == m_pDefault)
|
||||||
{
|
{
|
||||||
@ -388,9 +252,11 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
|||||||
|
|
||||||
IDBDriver *DBManager::GetDefaultDriver()
|
IDBDriver *DBManager::GetDefaultDriver()
|
||||||
{
|
{
|
||||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
|
ke::AString defaultDriver = list->GetDefaultDriver();
|
||||||
|
if (!m_pDefault && defaultDriver.length() > 0)
|
||||||
{
|
{
|
||||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
m_pDefault = FindOrLoadDriver(defaultDriver.chars());
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_pDefault;
|
return m_pDefault;
|
||||||
@ -453,29 +319,26 @@ IDBDriver *DBManager::GetDriver(unsigned int index)
|
|||||||
|
|
||||||
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
||||||
{
|
{
|
||||||
ConfDbInfo *info = GetDatabaseConf(name);
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
|
ke::RefPtr<ConfDbInfo> info = list->GetDatabaseConf(name);
|
||||||
|
if (!info)
|
||||||
|
{
|
||||||
|
// couldn't find requested conf, return default if exists
|
||||||
|
info = list->GetDefaultConfiguration();
|
||||||
if (!info)
|
if (!info)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &info->info;
|
return &info->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
||||||
{
|
{
|
||||||
List<ConfDbInfo *>::iterator iter;
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
|
ke::RefPtr<ConfDbInfo> info(list->GetDatabaseConf(name));
|
||||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
return info;
|
||||||
{
|
|
||||||
ConfDbInfo &conf = *(*iter);
|
|
||||||
if (conf.name == name)
|
|
||||||
{
|
|
||||||
return &conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
||||||
@ -519,7 +382,7 @@ void DBManager::KillWorkerThread()
|
|||||||
m_QueueEvent.Notify();
|
m_QueueEvent.Notify();
|
||||||
}
|
}
|
||||||
m_Worker->Join();
|
m_Worker->Join();
|
||||||
m_Worker = NULL;
|
m_Worker = nullptr;
|
||||||
s_OneTimeThreaderErrorMsg = false;
|
s_OneTimeThreaderErrorMsg = false;
|
||||||
m_Terminate = false;
|
m_Terminate = false;
|
||||||
}
|
}
|
||||||
@ -536,7 +399,9 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
|||||||
|
|
||||||
if (!m_Worker)
|
if (!m_Worker)
|
||||||
{
|
{
|
||||||
m_Worker = new ke::Thread(this, "SM SQL Worker");
|
m_Worker = new ke::Thread([this]() -> void {
|
||||||
|
Run();
|
||||||
|
}, "SM SQL Worker");
|
||||||
if (!m_Worker->Succeeded())
|
if (!m_Worker->Succeeded())
|
||||||
{
|
{
|
||||||
if (!s_OneTimeThreaderErrorMsg)
|
if (!s_OneTimeThreaderErrorMsg)
|
||||||
@ -544,7 +409,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
|||||||
logger->LogError("[SM] Unable to create db threader (error unknown)");
|
logger->LogError("[SM] Unable to create db threader (error unknown)");
|
||||||
s_OneTimeThreaderErrorMsg = true;
|
s_OneTimeThreaderErrorMsg = true;
|
||||||
}
|
}
|
||||||
m_Worker = NULL;
|
m_Worker = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,7 +557,7 @@ void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
|||||||
s_pAddBlock = NULL;
|
s_pAddBlock = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnPluginUnloaded(IPlugin *plugin)
|
void DBManager::OnPluginWillUnload(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
/* Kill the thread so we can flush everything into the think queue... */
|
/* Kill the thread so we can flush everything into the think queue... */
|
||||||
KillWorkerThread();
|
KillWorkerThread();
|
||||||
@ -718,9 +583,7 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = templist.begin();
|
for (iter = templist.begin(); iter != templist.end(); iter++)
|
||||||
iter != templist.end();
|
|
||||||
iter++)
|
|
||||||
{
|
{
|
||||||
IDBThreadOperation *op = (*iter);
|
IDBThreadOperation *op = (*iter);
|
||||||
op->RunThinkPart();
|
op->RunThinkPart();
|
||||||
@ -728,23 +591,13 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::LockConfig()
|
ke::AString DBManager::GetDefaultDriverName()
|
||||||
{
|
{
|
||||||
m_ConfigLock.Lock();
|
ConfDbInfoList *list = m_Builder.GetConfigList();
|
||||||
}
|
return list->GetDefaultDriver();
|
||||||
|
|
||||||
void DBManager::UnlockConfig()
|
|
||||||
{
|
|
||||||
m_ConfigLock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *DBManager::GetDefaultDriverName()
|
|
||||||
{
|
|
||||||
return m_DefDriver.c_str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
|
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
|
||||||
{
|
{
|
||||||
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
|
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,41 +32,25 @@
|
|||||||
#ifndef _INCLUDE_DATABASE_MANAGER_H_
|
#ifndef _INCLUDE_DATABASE_MANAGER_H_
|
||||||
#define _INCLUDE_DATABASE_MANAGER_H_
|
#define _INCLUDE_DATABASE_MANAGER_H_
|
||||||
|
|
||||||
#include <IDBDriver.h>
|
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sh_string.h>
|
#include <am-string.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <ITextParsers.h>
|
|
||||||
#include <IThreader.h>
|
#include <IThreader.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include <am-thread-utils.h>
|
#include <am-thread-utils.h>
|
||||||
#include "sm_simple_prioqueue.h"
|
#include "sm_simple_prioqueue.h"
|
||||||
|
#include <am-refcounting.h>
|
||||||
|
#include "DatabaseConfBuilder.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
struct ConfDbInfo
|
|
||||||
{
|
|
||||||
ConfDbInfo() : realDriver(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
String name;
|
|
||||||
String driver;
|
|
||||||
String host;
|
|
||||||
String user;
|
|
||||||
String pass;
|
|
||||||
String database;
|
|
||||||
IDBDriver *realDriver;
|
|
||||||
DatabaseInfo info;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DBManager :
|
class DBManager :
|
||||||
public IDBManager,
|
public IDBManager,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IHandleTypeDispatch,
|
public IHandleTypeDispatch,
|
||||||
public ITextListener_SMC,
|
public IPluginsListener
|
||||||
public IPluginsListener,
|
|
||||||
public ke::IRunnable
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DBManager();
|
DBManager();
|
||||||
@ -84,6 +68,7 @@ public: //IDBManager
|
|||||||
void AddDriver(IDBDriver *pDrivera);
|
void AddDriver(IDBDriver *pDrivera);
|
||||||
void RemoveDriver(IDBDriver *pDriver);
|
void RemoveDriver(IDBDriver *pDriver);
|
||||||
const DatabaseInfo *FindDatabaseConf(const char *name);
|
const DatabaseInfo *FindDatabaseConf(const char *name);
|
||||||
|
ConfDbInfo *GetDatabaseConf(const char *name);
|
||||||
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
|
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
|
||||||
unsigned int GetDriverCount();
|
unsigned int GetDriverCount();
|
||||||
IDBDriver *GetDriver(unsigned int index);
|
IDBDriver *GetDriver(unsigned int index);
|
||||||
@ -91,25 +76,16 @@ public: //IDBManager
|
|||||||
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
||||||
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
||||||
void AddDependency(IExtension *myself, IDBDriver *driver);
|
void AddDependency(IExtension *myself, IDBDriver *driver);
|
||||||
public: //ITextListener_SMC
|
|
||||||
void ReadSMC_ParseStart();
|
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
|
||||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
|
||||||
public: //ke::IRunnable
|
public: //ke::IRunnable
|
||||||
void Run();
|
void Run();
|
||||||
void ThreadMain();
|
void ThreadMain();
|
||||||
public: //IPluginsListener
|
public: //IPluginsListener
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginWillUnload(IPlugin *plugin);
|
||||||
public:
|
public:
|
||||||
ConfDbInfo *GetDatabaseConf(const char *name);
|
|
||||||
IDBDriver *FindOrLoadDriver(const char *name);
|
IDBDriver *FindOrLoadDriver(const char *name);
|
||||||
IDBDriver *GetDefaultDriver();
|
IDBDriver *GetDefaultDriver();
|
||||||
const char *GetDefaultDriverName();
|
ke::AString GetDefaultDriverName();
|
||||||
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
|
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
|
||||||
void LockConfig();
|
|
||||||
void UnlockConfig();
|
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
inline HandleType_t GetDatabaseType()
|
inline HandleType_t GetDatabaseType()
|
||||||
{
|
{
|
||||||
@ -127,17 +103,13 @@ private:
|
|||||||
CVector<bool> m_drSafety; /* which drivers are safe? */
|
CVector<bool> m_drSafety; /* which drivers are safe? */
|
||||||
ke::AutoPtr<ke::Thread> m_Worker;
|
ke::AutoPtr<ke::Thread> m_Worker;
|
||||||
ke::ConditionVariable m_QueueEvent;
|
ke::ConditionVariable m_QueueEvent;
|
||||||
ke::Mutex m_ConfigLock;
|
|
||||||
ke::Mutex m_ThinkLock;
|
ke::Mutex m_ThinkLock;
|
||||||
bool m_Terminate;
|
bool m_Terminate;
|
||||||
|
|
||||||
List<ConfDbInfo *> m_confs;
|
DatabaseConfBuilder m_Builder;
|
||||||
HandleType_t m_DriverType;
|
HandleType_t m_DriverType;
|
||||||
HandleType_t m_DatabaseType;
|
HandleType_t m_DatabaseType;
|
||||||
String m_DefDriver;
|
|
||||||
char m_Filename[PLATFORM_MAX_PATH];
|
char m_Filename[PLATFORM_MAX_PATH];
|
||||||
unsigned int m_ParseLevel;
|
|
||||||
unsigned int m_ParseState;
|
|
||||||
IDBDriver *m_pDefault;
|
IDBDriver *m_pDefault;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
184
core/logic/DatabaseConfBuilder.cpp
Normal file
184
core/logic/DatabaseConfBuilder.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2018 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 "DatabaseConfBuilder.h"
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
|
#define DBPARSE_LEVEL_NONE 0
|
||||||
|
#define DBPARSE_LEVEL_MAIN 1
|
||||||
|
#define DBPARSE_LEVEL_DATABASE 2
|
||||||
|
|
||||||
|
DatabaseConfBuilder::DatabaseConfBuilder()
|
||||||
|
: m_ParseList(nullptr),
|
||||||
|
m_InfoList(new ConfDbInfoList())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseConfBuilder::SetPath(char *str)
|
||||||
|
{
|
||||||
|
m_Filename = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseConfBuilder::~DatabaseConfBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfDbInfoList *DatabaseConfBuilder::GetConfigList()
|
||||||
|
{
|
||||||
|
return m_InfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseConfBuilder::StartParse()
|
||||||
|
{
|
||||||
|
SMCError err;
|
||||||
|
SMCStates states = {0, 0};
|
||||||
|
if ((err = textparsers->ParseFile_SMC(m_Filename.chars(), this, &states)) != SMCError_Okay)
|
||||||
|
{
|
||||||
|
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename.chars());
|
||||||
|
if (err != SMCError_Custom)
|
||||||
|
{
|
||||||
|
const char *txt = textparsers->GetSMCErrorString(err);
|
||||||
|
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseConfBuilder::ReadSMC_ParseStart()
|
||||||
|
{
|
||||||
|
m_ParseLevel = 0;
|
||||||
|
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||||
|
|
||||||
|
m_ParseList = new ConfDbInfoList();
|
||||||
|
}
|
||||||
|
|
||||||
|
SMCResult DatabaseConfBuilder::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||||
|
{
|
||||||
|
if (m_ParseLevel)
|
||||||
|
{
|
||||||
|
m_ParseLevel++;
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ParseState == DBPARSE_LEVEL_NONE)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "Databases") == 0)
|
||||||
|
{
|
||||||
|
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||||
|
} else {
|
||||||
|
m_ParseLevel++;
|
||||||
|
}
|
||||||
|
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||||
|
m_ParseCurrent = new ConfDbInfo();
|
||||||
|
m_ParseCurrent->name = name;
|
||||||
|
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||||
|
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||||
|
m_ParseLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SMCResult DatabaseConfBuilder::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
if (m_ParseLevel)
|
||||||
|
{
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ParseState == DBPARSE_LEVEL_MAIN)
|
||||||
|
{
|
||||||
|
if (strcmp(key, "driver_default") == 0)
|
||||||
|
{
|
||||||
|
m_ParseList->SetDefaultDriver(value);
|
||||||
|
}
|
||||||
|
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||||
|
if (strcmp(key, "driver") == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(value, "default") != 0)
|
||||||
|
{
|
||||||
|
m_ParseCurrent->driver = value;
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "database") == 0) {
|
||||||
|
m_ParseCurrent->database = value;
|
||||||
|
} else if (strcmp(key, "host") == 0) {
|
||||||
|
m_ParseCurrent->host = value;
|
||||||
|
} else if (strcmp(key, "user") == 0) {
|
||||||
|
m_ParseCurrent->user = value;
|
||||||
|
} else if (strcmp(key, "pass") == 0) {
|
||||||
|
m_ParseCurrent->pass = value;
|
||||||
|
} else if (strcmp(key, "timeout") == 0) {
|
||||||
|
m_ParseCurrent->info.maxTimeout = atoi(value);
|
||||||
|
} else if (strcmp(key, "port") == 0) {
|
||||||
|
m_ParseCurrent->info.port = atoi(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SMCResult DatabaseConfBuilder::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
|
{
|
||||||
|
if (m_ParseLevel)
|
||||||
|
{
|
||||||
|
m_ParseLevel--;
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||||
|
{
|
||||||
|
m_ParseCurrent->info.driver = m_ParseCurrent->driver.chars();
|
||||||
|
m_ParseCurrent->info.database = m_ParseCurrent->database.chars();
|
||||||
|
m_ParseCurrent->info.host = m_ParseCurrent->host.chars();
|
||||||
|
m_ParseCurrent->info.user = m_ParseCurrent->user.chars();
|
||||||
|
m_ParseCurrent->info.pass = m_ParseCurrent->pass.chars();
|
||||||
|
|
||||||
|
/* Save it.. */
|
||||||
|
m_ParseCurrent->AddRef();
|
||||||
|
m_ParseList->append(m_ParseCurrent);
|
||||||
|
m_ParseCurrent = nullptr;
|
||||||
|
|
||||||
|
/* Go up one level */
|
||||||
|
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||||
|
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||||
|
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||||
|
return SMCResult_Halt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SMCResult_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseConfBuilder::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||||
|
{
|
||||||
|
m_InfoList->ReleaseMembers();
|
||||||
|
delete m_InfoList;
|
||||||
|
m_InfoList = m_ParseList;
|
||||||
|
|
||||||
|
m_ParseList = nullptr;
|
||||||
|
}
|
129
core/logic/DatabaseConfBuilder.h
Normal file
129
core/logic/DatabaseConfBuilder.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2018 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_DATABASE_CONF_BUILDER_H_
|
||||||
|
#define _INCLUDE_DATABASE_CONF_BUILDER_H_
|
||||||
|
|
||||||
|
#include <IDBDriver.h>
|
||||||
|
#include <ITextParsers.h>
|
||||||
|
#include "common_logic.h"
|
||||||
|
|
||||||
|
#include <am-vector.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <am-refcounting-threadsafe.h>
|
||||||
|
|
||||||
|
class ConfDbInfo : public ke::RefcountedThreadsafe<ConfDbInfo>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConfDbInfo() : realDriver(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ke::AString name;
|
||||||
|
ke::AString driver;
|
||||||
|
ke::AString host;
|
||||||
|
ke::AString user;
|
||||||
|
ke::AString pass;
|
||||||
|
ke::AString database;
|
||||||
|
IDBDriver *realDriver;
|
||||||
|
DatabaseInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConfDbInfoList : public ke::Vector<ConfDbInfo *>
|
||||||
|
{
|
||||||
|
/* Allow internal usage of ConfDbInfoList */
|
||||||
|
friend class DBManager;
|
||||||
|
friend class DatabaseConfBuilder;
|
||||||
|
private:
|
||||||
|
ke::AString& GetDefaultDriver() {
|
||||||
|
return m_DefDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfDbInfo *GetDatabaseConf(const char *name) {
|
||||||
|
for (size_t i = 0; i < this->length(); i++)
|
||||||
|
{
|
||||||
|
ConfDbInfo *current = this->at(i);
|
||||||
|
/* If we run into the default configuration, then we'll save it
|
||||||
|
* for the next call to GetDefaultConfiguration */
|
||||||
|
if (strcmp(current->name.chars(), "default") == 0)
|
||||||
|
{
|
||||||
|
m_DefaultConfig = current;
|
||||||
|
}
|
||||||
|
if (strcmp(current->name.chars(), name) == 0)
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ConfDbInfo *GetDefaultConfiguration() {
|
||||||
|
return m_DefaultConfig;
|
||||||
|
}
|
||||||
|
void SetDefaultDriver(const char *input) {
|
||||||
|
m_DefDriver = ke::AString(input);
|
||||||
|
}
|
||||||
|
void ReleaseMembers() {
|
||||||
|
for (size_t i = 0; i < this->length(); i++) {
|
||||||
|
ConfDbInfo *current = this->at(i);
|
||||||
|
current->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ConfDbInfo *m_DefaultConfig;
|
||||||
|
ke::AString m_DefDriver;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseConfBuilder : public ITextListener_SMC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DatabaseConfBuilder();
|
||||||
|
~DatabaseConfBuilder();
|
||||||
|
void StartParse();
|
||||||
|
void SetPath(char* path);
|
||||||
|
ConfDbInfoList *GetConfigList();
|
||||||
|
public: //ITextListener_SMC
|
||||||
|
void ReadSMC_ParseStart();
|
||||||
|
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||||
|
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||||
|
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||||
|
void ReadSMC_ParseEnd(bool halted, bool failed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_ParseLevel;
|
||||||
|
unsigned int m_ParseState;
|
||||||
|
ConfDbInfo *m_ParseCurrent;
|
||||||
|
ConfDbInfoList *m_ParseList;
|
||||||
|
private:
|
||||||
|
ke::AString m_Filename;
|
||||||
|
ConfDbInfoList *m_InfoList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_DATABASE_CONF_BUILDER_H_
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -29,6 +29,7 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ISourceMod.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "DebugReporter.h"
|
#include "DebugReporter.h"
|
||||||
@ -47,7 +48,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
|
|||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
g_Logger.LogMessage("[SM] %s", buffer);
|
g_Logger.LogMessage("[SM] %s", buffer);
|
||||||
@ -65,7 +66,7 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
|
|||||||
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
|
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
|
||||||
{
|
{
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
|
ke::SafeVsprintf(buffer, sizeof(buffer), message, ap);
|
||||||
|
|
||||||
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||||
const char *error = g_pSourcePawn2->GetErrorString(err);
|
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||||
@ -99,7 +100,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
|
||||||
va_start(ap, message);
|
va_start(ap, message);
|
||||||
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
|
ke::SafeVsprintf(buffer, sizeof(buffer), message, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename();
|
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename();
|
||||||
@ -132,51 +133,6 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
|
|
||||||
{
|
|
||||||
const char *lastname;
|
|
||||||
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
|
||||||
int n_err = error->GetErrorCode();
|
|
||||||
|
|
||||||
if (n_err != SP_ERROR_NATIVE)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
|
|
||||||
n_err,
|
|
||||||
error->GetErrorString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lastname=error->GetLastNative(NULL)) != NULL)
|
|
||||||
{
|
|
||||||
const char *custerr;
|
|
||||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
|
||||||
} else {
|
|
||||||
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error->DebugInfoAvailable())
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
|
||||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
|
||||||
_GetPluginIndex(ctx));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallStackInfo stk_info;
|
|
||||||
int i = 0;
|
|
||||||
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
|
||||||
while (error->GetTraceInfo(&stk_info))
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
|
||||||
i++,
|
|
||||||
stk_info.line,
|
|
||||||
stk_info.filename,
|
|
||||||
stk_info.function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
||||||
{
|
{
|
||||||
int id = 1;
|
int id = 1;
|
||||||
@ -199,3 +155,92 @@ int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
|||||||
return pluginsys->GetPluginCount() + 1;
|
return pluginsys->GetPluginCount() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
|
||||||
|
{
|
||||||
|
// Don't log an error if a function wasn't runnable.
|
||||||
|
// This is necassary due to the way SM is handling and exposing
|
||||||
|
// scripted functions. It's too late to change that now.
|
||||||
|
if (report.Code() == SP_ERROR_NOT_RUNNABLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *blame = nullptr;
|
||||||
|
if (report.Blame())
|
||||||
|
{
|
||||||
|
blame = report.Blame()->DebugName();
|
||||||
|
} else {
|
||||||
|
// Find the nearest plugin to blame.
|
||||||
|
for (; !iter.Done(); iter.Next())
|
||||||
|
{
|
||||||
|
if (iter.IsScriptedFrame())
|
||||||
|
{
|
||||||
|
IPlugin *plugin = pluginsys->FindPluginByContext(iter.Context()->GetContext());
|
||||||
|
if (plugin)
|
||||||
|
{
|
||||||
|
blame = plugin->GetFilename();
|
||||||
|
} else {
|
||||||
|
blame = iter.Context()->GetRuntime()->GetFilename();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iter.Reset();
|
||||||
|
|
||||||
|
g_Logger.LogError("[SM] Exception reported: %s", report.Message());
|
||||||
|
|
||||||
|
if (blame)
|
||||||
|
{
|
||||||
|
g_Logger.LogError("[SM] Blaming: %s", blame);
|
||||||
|
}
|
||||||
|
|
||||||
|
ke::Vector<ke::AString> arr = GetStackTrace(&iter);
|
||||||
|
for (size_t i = 0; i < arr.length(); i++)
|
||||||
|
{
|
||||||
|
g_Logger.LogError("%s", arr[i].chars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ke::Vector<ke::AString> DebugReport::GetStackTrace(IFrameIterator *iter)
|
||||||
|
{
|
||||||
|
char temp[3072];
|
||||||
|
ke::Vector<ke::AString> trace;
|
||||||
|
iter->Reset();
|
||||||
|
|
||||||
|
if (!iter->Done())
|
||||||
|
{
|
||||||
|
trace.append("[SM] Call stack trace:");
|
||||||
|
|
||||||
|
for (int index = 0; !iter->Done(); iter->Next(), index++)
|
||||||
|
{
|
||||||
|
const char *fn = iter->FunctionName();
|
||||||
|
if (!fn)
|
||||||
|
{
|
||||||
|
fn = "<unknown function>";
|
||||||
|
}
|
||||||
|
if (iter->IsNativeFrame())
|
||||||
|
{
|
||||||
|
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
|
||||||
|
trace.append(temp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (iter->IsScriptedFrame())
|
||||||
|
{
|
||||||
|
const char *file = iter->FilePath();
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
file = "<unknown>";
|
||||||
|
}
|
||||||
|
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] Line %d, %s::%s",
|
||||||
|
index,
|
||||||
|
iter->LineNumber(),
|
||||||
|
file,
|
||||||
|
fn);
|
||||||
|
|
||||||
|
trace.append(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
#include "sp_vm_api.h"
|
#include "sp_vm_api.h"
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
#include <am-vector.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
|
||||||
class DebugReport :
|
class DebugReport :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
@ -42,12 +44,13 @@ class DebugReport :
|
|||||||
public: // SMGlobalClass
|
public: // SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
public: // IDebugListener
|
public: // IDebugListener
|
||||||
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
|
void ReportError(const IErrorReport &report, IFrameIterator &iter);
|
||||||
void OnDebugSpew(const char *msg, ...);
|
void OnDebugSpew(const char *msg, ...);
|
||||||
public:
|
public:
|
||||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
||||||
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
|
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
|
||||||
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
||||||
|
ke::Vector<ke::AString> GetStackTrace(IFrameIterator *iter);
|
||||||
private:
|
private:
|
||||||
int _GetPluginIndex(IPluginContext *ctx);
|
int _GetPluginIndex(IPluginContext *ctx);
|
||||||
};
|
};
|
||||||
|
@ -36,12 +36,16 @@
|
|||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include "PluginSys.h"
|
#include "PluginSys.h"
|
||||||
#include <am-utility.h>
|
#include <am-utility.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
CExtensionManager g_Extensions;
|
CExtensionManager g_Extensions;
|
||||||
IdentityType_t g_ExtType;
|
IdentityType_t g_ExtType;
|
||||||
|
|
||||||
void CExtension::Initialize(const char *filename, const char *path)
|
void CExtension::Initialize(const char *filename, const char *path, bool bRequired)
|
||||||
{
|
{
|
||||||
|
m_bRequired = bRequired;
|
||||||
m_pAPI = NULL;
|
m_pAPI = NULL;
|
||||||
m_pIdentToken = NULL;
|
m_pIdentToken = NULL;
|
||||||
unload_code = 0;
|
unload_code = 0;
|
||||||
@ -59,7 +63,7 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
|
|||||||
m_pAPI = pAPI;
|
m_pAPI = pAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLocalExtension::CLocalExtension(const char *filename)
|
CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
|
||||||
{
|
{
|
||||||
m_PlId = 0;
|
m_PlId = 0;
|
||||||
m_pLib = NULL;
|
m_pLib = NULL;
|
||||||
@ -69,26 +73,28 @@ CLocalExtension::CLocalExtension(const char *filename)
|
|||||||
/* Special case for new bintools binary */
|
/* Special case for new bintools binary */
|
||||||
if (strcmp(filename, "bintools.ext") == 0)
|
if (strcmp(filename, "bintools.ext") == 0)
|
||||||
{
|
{
|
||||||
goto normal;
|
g_pSM->BuildPath(Path_SM,
|
||||||
|
path,
|
||||||
|
PLATFORM_MAX_PATH,
|
||||||
|
"extensions/%s." PLATFORM_LIB_EXT,
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Zeroth, see if there is an engine specific build in the new place. */
|
/* Zeroth, see if there is an engine specific build in the new place. */
|
||||||
g_pSM->BuildPath(Path_SM,
|
g_pSM->BuildPath(Path_SM,
|
||||||
path,
|
path,
|
||||||
PLATFORM_MAX_PATH,
|
PLATFORM_MAX_PATH,
|
||||||
"extensions/%s.%s." PLATFORM_LIB_EXT,
|
"extensions/%s.%s." PLATFORM_LIB_EXT,
|
||||||
filename,
|
filename,
|
||||||
smcore.gamesuffix);
|
bridge->gamesuffix);
|
||||||
|
|
||||||
if (libsys->IsPathFile(path))
|
if (!libsys->IsPathFile(path))
|
||||||
{
|
{
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
|
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
|
||||||
if (strcmp(smcore.gamesuffix, "2.tf2") == 0
|
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|
||||||
|| strcmp(smcore.gamesuffix, "2.dods") == 0
|
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|
||||||
|| strcmp(smcore.gamesuffix, "2.hl2dm") == 0
|
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
g_pSM->BuildPath(Path_SM,
|
g_pSM->BuildPath(Path_SM,
|
||||||
@ -96,47 +102,40 @@ CLocalExtension::CLocalExtension(const char *filename)
|
|||||||
PLATFORM_MAX_PATH,
|
PLATFORM_MAX_PATH,
|
||||||
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
|
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
if (libsys->IsPathFile(path))
|
|
||||||
{
|
|
||||||
goto found;
|
|
||||||
}
|
}
|
||||||
}
|
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
|
||||||
else if (strcmp(smcore.gamesuffix, "2.nd") == 0)
|
|
||||||
{
|
{
|
||||||
g_pSM->BuildPath(Path_SM,
|
g_pSM->BuildPath(Path_SM,
|
||||||
path,
|
path,
|
||||||
PLATFORM_MAX_PATH,
|
PLATFORM_MAX_PATH,
|
||||||
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
|
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
|
||||||
filename);
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
if (libsys->IsPathFile(path))
|
//Try further
|
||||||
|
if (!libsys->IsPathFile(path))
|
||||||
{
|
{
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First see if there is an engine specific build! */
|
/* First see if there is an engine specific build! */
|
||||||
g_pSM->BuildPath(Path_SM,
|
g_pSM->BuildPath(Path_SM,
|
||||||
path,
|
path,
|
||||||
PLATFORM_MAX_PATH,
|
PLATFORM_MAX_PATH,
|
||||||
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
|
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
|
||||||
filename,
|
filename,
|
||||||
smcore.gamesuffix);
|
bridge->gamesuffix);
|
||||||
|
|
||||||
/* Try the "normal" version */
|
/* Try the "normal" version */
|
||||||
if (!libsys->IsPathFile(path))
|
if (!libsys->IsPathFile(path))
|
||||||
{
|
{
|
||||||
normal:
|
|
||||||
g_pSM->BuildPath(Path_SM,
|
g_pSM->BuildPath(Path_SM,
|
||||||
path,
|
path,
|
||||||
PLATFORM_MAX_PATH,
|
PLATFORM_MAX_PATH,
|
||||||
"extensions/%s." PLATFORM_LIB_EXT,
|
"extensions/%s." PLATFORM_LIB_EXT,
|
||||||
filename);
|
filename);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
found:
|
}
|
||||||
Initialize(filename, path);
|
}
|
||||||
|
Initialize(filename, path, bRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRemoteExtension::Load(char *error, size_t maxlength)
|
bool CRemoteExtension::Load(char *error, size_t maxlength)
|
||||||
@ -172,7 +171,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
m_pLib->CloseLibrary();
|
m_pLib->CloseLibrary();
|
||||||
m_pLib = NULL;
|
m_pLib = NULL;
|
||||||
snprintf(error, maxlength, "Unable to find extension entry point");
|
ke::SafeStrcpy(error, maxlength, "Unable to find extension entry point");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +190,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
|
|||||||
if (m_pAPI->IsMetamodExtension())
|
if (m_pAPI->IsMetamodExtension())
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
m_PlId = smcore.LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength);
|
m_PlId = bridge->LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength);
|
||||||
|
|
||||||
if (!m_PlId || !ok)
|
if (!m_PlId || !ok)
|
||||||
{
|
{
|
||||||
@ -208,7 +207,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
if (m_PlId)
|
if (m_PlId)
|
||||||
{
|
{
|
||||||
smcore.UnloadMMSPlugin(m_PlId);
|
bridge->UnloadMMSPlugin(m_PlId);
|
||||||
m_PlId = 0;
|
m_PlId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +228,7 @@ void CLocalExtension::Unload()
|
|||||||
{
|
{
|
||||||
if (m_pAPI != NULL && m_PlId)
|
if (m_pAPI != NULL && m_PlId)
|
||||||
{
|
{
|
||||||
smcore.UnloadMMSPlugin(m_PlId);
|
bridge->UnloadMMSPlugin(m_PlId);
|
||||||
m_PlId = 0;
|
m_PlId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +241,7 @@ void CLocalExtension::Unload()
|
|||||||
|
|
||||||
bool CRemoteExtension::Reload(char *error, size_t maxlength)
|
bool CRemoteExtension::Reload(char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "Remote extensions do not support reloading");
|
ke::SafeStrcpy(error, maxlength, "Remote extensions do not support reloading");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,13 +275,13 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
if (!m_pAPI)
|
if (!m_pAPI)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "No IExtensionInterface instance provided");
|
ke::SafeStrcpy(error, maxlength, "No IExtensionInterface instance provided");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION)
|
if (m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
|
ke::SafeSprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,19 +291,18 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
|
|||||||
bool CExtension::Load(char *error, size_t maxlength)
|
bool CExtension::Load(char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
CreateIdentity();
|
CreateIdentity();
|
||||||
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !smcore.IsMapLoading()))
|
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !bridge->IsMapLoading()))
|
||||||
{
|
{
|
||||||
|
g_ShareSys.RemoveInterfaces(this);
|
||||||
DestroyIdentity();
|
DestroyIdentity();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Check if we're past load time */
|
/* Check if we're past load time */
|
||||||
if (!smcore.IsMapLoading())
|
if (!bridge->IsMapLoading())
|
||||||
{
|
{
|
||||||
m_pAPI->OnExtensionsAllLoaded();
|
m_pAPI->OnExtensionsAllLoaded();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -418,65 +416,20 @@ void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
|
|||||||
m_ChildDeps.push_back(info);
|
m_ChildDeps.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: dependency iteration deprecated since 1.10
|
||||||
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
|
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
|
||||||
{
|
{
|
||||||
List<IfaceInfo>::iterator iter = m_Deps.begin();
|
return nullptr;
|
||||||
|
|
||||||
if (iter == m_Deps.end())
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pOwner)
|
|
||||||
{
|
|
||||||
*pOwner = (*iter).owner;
|
|
||||||
}
|
|
||||||
if (pInterface)
|
|
||||||
{
|
|
||||||
*pInterface = (*iter).iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
|
|
||||||
|
|
||||||
return (ITERATOR *)pIter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
|
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
|
||||||
{
|
|
||||||
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
|
|
||||||
List<IfaceInfo>::iterator _iter;
|
|
||||||
|
|
||||||
if (_iter == m_Deps.end())
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_iter++;
|
|
||||||
|
|
||||||
if (pOwner)
|
|
||||||
{
|
|
||||||
*pOwner = (*_iter).owner;
|
|
||||||
}
|
|
||||||
if (pInterface)
|
|
||||||
{
|
|
||||||
*pInterface = (*_iter).iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pIter = _iter;
|
|
||||||
|
|
||||||
if (_iter == m_Deps.end())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CExtension::FreeDependencyIterator(ITERATOR *iter)
|
void CExtension::FreeDependencyIterator(ITERATOR *iter)
|
||||||
{
|
{
|
||||||
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
|
|
||||||
|
|
||||||
delete pIter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CExtension::AddInterface(SMInterface *pInterface)
|
void CExtension::AddInterface(SMInterface *pInterface)
|
||||||
@ -490,7 +443,7 @@ bool CExtension::IsRunning(char *error, size_t maxlength)
|
|||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
snprintf(error, maxlength, "%s", m_Error.c_str());
|
ke::SafeStrcpy(error, maxlength, m_Error.c_str());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -503,6 +456,11 @@ void CExtension::AddLibrary(const char *library)
|
|||||||
m_Libraries.push_back(library);
|
m_Libraries.push_back(library);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CExtension::IsRequired()
|
||||||
|
{
|
||||||
|
return m_bRequired;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* EXTENSION MANAGER *
|
* EXTENSION MANAGER *
|
||||||
*********************/
|
*********************/
|
||||||
@ -511,7 +469,7 @@ void CExtensionManager::OnSourceModAllInitialized()
|
|||||||
{
|
{
|
||||||
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
|
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
|
||||||
pluginsys->AddPluginsListener(this);
|
pluginsys->AddPluginsListener(this);
|
||||||
rootmenu->AddRootConsoleCommand("exts", "Manage extensions", this);
|
rootmenu->AddRootConsoleCommand3("exts", "Manage extensions", this);
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
g_ShareSys.AddInterface(NULL, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +525,7 @@ void CExtensionManager::TryAutoload()
|
|||||||
}
|
}
|
||||||
|
|
||||||
char file[PLATFORM_MAX_PATH];
|
char file[PLATFORM_MAX_PATH];
|
||||||
len = smcore.Format(file, sizeof(file), "%s", lfile);
|
len = ke::SafeStrcpy(file, sizeof(file), lfile);
|
||||||
strcpy(&file[len - 9], ".ext");
|
strcpy(&file[len - 9], ".ext");
|
||||||
|
|
||||||
LoadAutoExtension(file);
|
LoadAutoExtension(file);
|
||||||
@ -583,7 +541,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
|||||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||||
{
|
{
|
||||||
char path2[PLATFORM_MAX_PATH];
|
char path2[PLATFORM_MAX_PATH];
|
||||||
smcore.Format(path2, sizeof(path2), "%s", path);
|
ke::SafeStrcpy(path2, sizeof(path2), path);
|
||||||
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||||
return LoadAutoExtension(path2, bErrorOnMissing);
|
return LoadAutoExtension(path2, bErrorOnMissing);
|
||||||
}
|
}
|
||||||
@ -595,7 +553,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
|||||||
}
|
}
|
||||||
|
|
||||||
char error[256];
|
char error[256];
|
||||||
CExtension *p = new CLocalExtension(path);
|
CExtension *p = new CLocalExtension(path, bErrorOnMissing);
|
||||||
|
|
||||||
/* We put us in the list beforehand so extensions that check for each other
|
/* We put us in the list beforehand so extensions that check for each other
|
||||||
* won't recursively load each other.
|
* won't recursively load each other.
|
||||||
@ -675,7 +633,7 @@ IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size
|
|||||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||||
{
|
{
|
||||||
char path2[PLATFORM_MAX_PATH];
|
char path2[PLATFORM_MAX_PATH];
|
||||||
smcore.Format(path2, sizeof(path2), "%s", file);
|
ke::SafeStrcpy(path2, sizeof(path2), file);
|
||||||
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||||
return LoadExtension(path2, error, maxlength);
|
return LoadExtension(path2, error, maxlength);
|
||||||
}
|
}
|
||||||
@ -928,17 +886,18 @@ void CExtensionManager::AddDependency(IExtension *pSource, const char *file, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
|
||||||
{
|
{
|
||||||
int argcount = smcore.Argc(command);
|
int argcount = command->ArgC();
|
||||||
if (argcount >= 3)
|
if (argcount >= 3)
|
||||||
{
|
{
|
||||||
const char *cmd = smcore.Arg(command, 2);
|
const char *cmd = command->Arg(2);
|
||||||
if (strcmp(cmd, "list") == 0)
|
if (strcmp(cmd, "list") == 0)
|
||||||
{
|
{
|
||||||
List<CExtension *>::iterator iter;
|
List<CExtension *>::iterator iter;
|
||||||
CExtension *pExt;
|
CExtension *pExt;
|
||||||
unsigned int num = 1;
|
unsigned int num = 1;
|
||||||
|
|
||||||
switch (m_Libs.size())
|
switch (m_Libs.size())
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -975,9 +934,15 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
const char *descr = pAPI->GetExtensionDescription();
|
const char *descr = pAPI->GetExtensionDescription();
|
||||||
rootmenu->ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
|
rootmenu->ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else if(pExt->IsRequired() || libsys->PathExists(pExt->GetPath()))
|
||||||
|
{
|
||||||
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
|
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rootmenu->ConsolePrint("[%02d] <OPTIONAL> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -989,11 +954,11 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *filename = smcore.Arg(command, 3);
|
const char *filename = command->Arg(3);
|
||||||
char path[PLATFORM_MAX_PATH];
|
char path[PLATFORM_MAX_PATH];
|
||||||
char error[256];
|
char error[256];
|
||||||
|
|
||||||
smcore.Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
|
ke::SafeSprintf(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
|
||||||
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
|
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
|
||||||
|
|
||||||
if (FindExtensionByFile(path) != NULL)
|
if (FindExtensionByFile(path) != NULL)
|
||||||
@ -1020,7 +985,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *sId = smcore.Arg(command, 3);
|
const char *sId = command->Arg(3);
|
||||||
unsigned int id = atoi(sId);
|
unsigned int id = atoi(sId);
|
||||||
if (id <= 0)
|
if (id <= 0)
|
||||||
{
|
{
|
||||||
@ -1105,7 +1070,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *arg = smcore.Arg(command, 3);
|
const char *arg = command->Arg(3);
|
||||||
unsigned int num = atoi(arg);
|
unsigned int num = atoi(arg);
|
||||||
CExtension *pExt = FindByOrder(num);
|
CExtension *pExt = FindByOrder(num);
|
||||||
|
|
||||||
@ -1117,11 +1082,11 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
|
|
||||||
if (argcount > 4 && pExt->unload_code)
|
if (argcount > 4 && pExt->unload_code)
|
||||||
{
|
{
|
||||||
const char *unload = smcore.Arg(command, 4);
|
const char *unload = command->Arg(4);
|
||||||
if (pExt->unload_code == (unsigned)atoi(unload))
|
if (pExt->unload_code == (unsigned)atoi(unload))
|
||||||
{
|
{
|
||||||
char filename[PLATFORM_MAX_PATH];
|
char filename[PLATFORM_MAX_PATH];
|
||||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||||
UnloadExtension(pExt);
|
UnloadExtension(pExt);
|
||||||
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
||||||
}
|
}
|
||||||
@ -1136,7 +1101,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
|| (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size()))
|
|| (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size()))
|
||||||
{
|
{
|
||||||
char filename[PLATFORM_MAX_PATH];
|
char filename[PLATFORM_MAX_PATH];
|
||||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||||
UnloadExtension(pExt);
|
UnloadExtension(pExt);
|
||||||
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
||||||
return;
|
return;
|
||||||
@ -1171,7 +1136,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
/* Will our dependent care? */
|
/* Will our dependent care? */
|
||||||
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
|
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
|
||||||
{
|
{
|
||||||
rootmenu->ConsolePrint(" -> %s", pExt->GetFilename());
|
rootmenu->ConsolePrint(" -> %s", pOther->GetFilename());
|
||||||
/* Add to plugin unload list */
|
/* Add to plugin unload list */
|
||||||
List<CPlugin *>::iterator p_iter;
|
List<CPlugin *>::iterator p_iter;
|
||||||
for (p_iter=pOther->m_Dependents.begin();
|
for (p_iter=pOther->m_Dependents.begin();
|
||||||
@ -1222,7 +1187,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *arg = smcore.Arg(command, 3);
|
const char *arg = command->Arg(3);
|
||||||
unsigned int num = atoi(arg);
|
unsigned int num = atoi(arg);
|
||||||
CExtension *pExt = FindByOrder(num);
|
CExtension *pExt = FindByOrder(num);
|
||||||
|
|
||||||
@ -1237,7 +1202,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
|||||||
char filename[PLATFORM_MAX_PATH];
|
char filename[PLATFORM_MAX_PATH];
|
||||||
char error[255];
|
char error[255];
|
||||||
|
|
||||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||||
|
|
||||||
if (pExt->Reload(error, sizeof(error)))
|
if (pExt->Reload(error, sizeof(error)))
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include "NativeOwner.h"
|
#include "NativeOwner.h"
|
||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
|
#include <bridge/include/IExtensionBridge.h>
|
||||||
|
|
||||||
class CPlayer;
|
class CPlayer;
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ public:
|
|||||||
void AddPlugin(CPlugin *pPlugin);
|
void AddPlugin(CPlugin *pPlugin);
|
||||||
void MarkAllLoaded();
|
void MarkAllLoaded();
|
||||||
void AddLibrary(const char *library);
|
void AddLibrary(const char *library);
|
||||||
|
bool IsRequired();
|
||||||
public:
|
public:
|
||||||
virtual bool Load(char *error, size_t maxlength);
|
virtual bool Load(char *error, size_t maxlength);
|
||||||
virtual bool IsLoaded() =0;
|
virtual bool IsLoaded() =0;
|
||||||
@ -86,7 +88,7 @@ public:
|
|||||||
virtual bool Reload(char *error, size_t maxlength) =0;
|
virtual bool Reload(char *error, size_t maxlength) =0;
|
||||||
virtual bool IsSameFile(const char* file) =0;
|
virtual bool IsSameFile(const char* file) =0;
|
||||||
protected:
|
protected:
|
||||||
void Initialize(const char *filename, const char *path);
|
void Initialize(const char *filename, const char *path, bool bRequired = true);
|
||||||
bool PerformAPICheck(char *error, size_t maxlength);
|
bool PerformAPICheck(char *error, size_t maxlength);
|
||||||
void CreateIdentity();
|
void CreateIdentity();
|
||||||
void DestroyIdentity();
|
void DestroyIdentity();
|
||||||
@ -103,12 +105,13 @@ protected:
|
|||||||
List<String> m_Libraries;
|
List<String> m_Libraries;
|
||||||
unsigned int unload_code;
|
unsigned int unload_code;
|
||||||
bool m_bFullyLoaded;
|
bool m_bFullyLoaded;
|
||||||
|
bool m_bRequired;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CLocalExtension : public CExtension
|
class CLocalExtension : public CExtension
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CLocalExtension(const char *filename);
|
CLocalExtension(const char *filename, bool bRequired = true);
|
||||||
public:
|
public:
|
||||||
bool Load(char *error, size_t maxlength);
|
bool Load(char *error, size_t maxlength);
|
||||||
bool IsLoaded();
|
bool IsLoaded();
|
||||||
@ -161,7 +164,7 @@ public: //IExtensionManager
|
|||||||
public: //IPluginsListener
|
public: //IPluginsListener
|
||||||
void OnPluginDestroyed(IPlugin *plugin);
|
void OnPluginDestroyed(IPlugin *plugin);
|
||||||
public: //IRootConsoleCommand
|
public: //IRootConsoleCommand
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
|
||||||
public:
|
public:
|
||||||
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
|
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
|
||||||
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
||||||
|
@ -1,33 +1,29 @@
|
|||||||
/**
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* vim: set ts=4 sw=4 tw=99 noet :
|
// =============================================================================
|
||||||
* =============================================================================
|
// SourceMod
|
||||||
* SourceMod
|
// Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
// =============================================================================
|
||||||
* =============================================================================
|
//
|
||||||
*
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
// Free Software Foundation.
|
||||||
* Free Software Foundation.
|
//
|
||||||
*
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
// details.
|
||||||
* details.
|
//
|
||||||
*
|
// You should have received a copy of the GNU General Public License along with
|
||||||
* You should have received a copy of the GNU General Public License along with
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
||||||
*
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -35,30 +31,16 @@
|
|||||||
#include "ForwardSys.h"
|
#include "ForwardSys.h"
|
||||||
#include "DebugReporter.h"
|
#include "DebugReporter.h"
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
#include <ReentrantList.h>
|
||||||
|
|
||||||
|
using namespace ke;
|
||||||
|
|
||||||
CForwardManager g_Forwards;
|
CForwardManager g_Forwards;
|
||||||
|
|
||||||
/**
|
// Genesis turns to its source, reduction occurs stepwise although the essence
|
||||||
* Genesis turns to its source, reduction occurs stepwise although the essence is all one.
|
// is all one. End of line. FTL system check.
|
||||||
* End of line. FTL system check.
|
|
||||||
*
|
|
||||||
* :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
|
|
||||||
* VARARG FUNCTIONS:
|
|
||||||
* - Pushing no varargs
|
|
||||||
*/
|
|
||||||
|
|
||||||
// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
|
|
||||||
// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
|
|
||||||
|
|
||||||
CForwardManager::~CForwardManager()
|
|
||||||
{
|
|
||||||
CStack<CForward *>::iterator iter;
|
|
||||||
for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
|
|
||||||
{
|
|
||||||
delete (*iter);
|
|
||||||
}
|
|
||||||
m_FreeForwards.popall();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CForwardManager::OnSourceModAllInitialized()
|
void CForwardManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
@ -68,11 +50,10 @@ void CForwardManager::OnSourceModAllInitialized()
|
|||||||
|
|
||||||
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
|
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
|
||||||
{
|
{
|
||||||
CForward *fwd;
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, types);
|
va_start(ap, types);
|
||||||
|
|
||||||
fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
CForward *fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@ -80,7 +61,7 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
|
|||||||
{
|
{
|
||||||
scripts->AddFunctionsToForward(name, fwd);
|
scripts->AddFunctionsToForward(name, fwd);
|
||||||
|
|
||||||
m_managed.push_back(fwd);
|
m_managed.append(fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fwd;
|
return fwd;
|
||||||
@ -88,17 +69,16 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
|
|||||||
|
|
||||||
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
|
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
|
||||||
{
|
{
|
||||||
CForward *fwd;
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, types);
|
va_start(ap, types);
|
||||||
|
|
||||||
fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
CForward *fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (fwd)
|
if (fwd)
|
||||||
{
|
{
|
||||||
m_unmanaged.push_back(fwd);
|
m_unmanaged.append(fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fwd;
|
return fwd;
|
||||||
@ -107,105 +87,59 @@ IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType
|
|||||||
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
|
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
/* Attach any globally managed forwards */
|
/* Attach any globally managed forwards */
|
||||||
List<CForward *>::iterator iter;
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
CForward *fwd;
|
CForward *fwd = (*iter);
|
||||||
|
|
||||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
|
||||||
{
|
|
||||||
fwd = (*iter);
|
|
||||||
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||||
if (pFunc)
|
if (pFunc)
|
||||||
{
|
|
||||||
fwd->AddFunction(pFunc);
|
fwd->AddFunction(pFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
List<CForward *>::iterator iter;
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
CForward *fwd;
|
CForward *fwd = (*iter);
|
||||||
|
|
||||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
|
||||||
{
|
|
||||||
fwd = (*iter);
|
|
||||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
|
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
|
||||||
{
|
CForward *fwd = (*iter);
|
||||||
fwd = (*iter);
|
|
||||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
|
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
|
||||||
{
|
{
|
||||||
List<CForward *>::iterator iter;
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
CForward *fwd;
|
CForward *fwd = (*iter);
|
||||||
|
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
||||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
|
||||||
{
|
|
||||||
fwd = (*iter);
|
|
||||||
if (strcmp(fwd->GetForwardName(), name) == 0)
|
|
||||||
{
|
|
||||||
if (ifchng)
|
if (ifchng)
|
||||||
{
|
|
||||||
*ifchng = NULL;
|
*ifchng = NULL;
|
||||||
}
|
|
||||||
return fwd;
|
return fwd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
|
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
|
||||||
{
|
CForward *fwd = (*iter);
|
||||||
fwd = (*iter);
|
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
||||||
if (strcmp(fwd->GetForwardName(), name) == 0)
|
|
||||||
{
|
|
||||||
if (ifchng)
|
if (ifchng)
|
||||||
{
|
|
||||||
*ifchng = fwd;
|
*ifchng = fwd;
|
||||||
}
|
|
||||||
return fwd;
|
return fwd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifchng)
|
if (ifchng)
|
||||||
{
|
|
||||||
*ifchng = NULL;
|
*ifchng = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardManager::ReleaseForward(IForward *forward)
|
void CForwardManager::ReleaseForward(IForward *aForward)
|
||||||
{
|
{
|
||||||
ForwardFree(static_cast<CForward *>(forward));
|
CForward *fwd = static_cast<CForward *>(aForward);
|
||||||
}
|
|
||||||
|
|
||||||
void CForwardManager::ForwardFree(CForward *fwd)
|
|
||||||
{
|
|
||||||
if (fwd == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_FreeForwards.push(fwd);
|
|
||||||
m_managed.remove(fwd);
|
m_managed.remove(fwd);
|
||||||
m_unmanaged.remove(fwd);
|
m_unmanaged.remove(fwd);
|
||||||
}
|
delete fwd;
|
||||||
|
|
||||||
CForward *CForwardManager::ForwardMake()
|
|
||||||
{
|
|
||||||
CForward *fwd;
|
|
||||||
if (m_FreeForwards.empty())
|
|
||||||
{
|
|
||||||
fwd = new CForward;
|
|
||||||
} else {
|
|
||||||
fwd = m_FreeForwards.front();
|
|
||||||
m_FreeForwards.pop();
|
|
||||||
}
|
|
||||||
return fwd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
||||||
@ -214,12 +148,8 @@ void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Attach any globally managed forwards */
|
/* Attach any globally managed forwards */
|
||||||
List<CForward *>::iterator iter;
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
CForward *fwd;
|
CForward *fwd = (*iter);
|
||||||
|
|
||||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
|
||||||
{
|
|
||||||
fwd = (*iter);
|
|
||||||
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||||
// Only add functions, if they aren't registered yet!
|
// Only add functions, if they aren't registered yet!
|
||||||
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
|
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
|
||||||
@ -233,6 +163,27 @@ void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
|||||||
* ACTUAL FORWARD API IMPLEMENTATION *
|
* ACTUAL FORWARD API IMPLEMENTATION *
|
||||||
*************************************/
|
*************************************/
|
||||||
|
|
||||||
|
CForward::CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params)
|
||||||
|
: m_numparams(0),
|
||||||
|
m_varargs(0),
|
||||||
|
m_ExecType(et),
|
||||||
|
m_curparam(0),
|
||||||
|
m_errstate(SP_ERROR_NONE)
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(m_name, sizeof(m_name), name ? name : "");
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_params; i++)
|
||||||
|
m_types[i] = types[i];
|
||||||
|
|
||||||
|
if (num_params && types[num_params - 1] == Param_VarArgs) {
|
||||||
|
m_varargs = num_params;
|
||||||
|
m_numparams = num_params - 1;
|
||||||
|
} else {
|
||||||
|
m_varargs = 0;
|
||||||
|
m_numparams = num_params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
|
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
|
||||||
{
|
{
|
||||||
ParamType _types[SP_MAX_EXEC_PARAMS];
|
ParamType _types[SP_MAX_EXEC_PARAMS];
|
||||||
@ -270,30 +221,7 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CForward *pForward = g_Forwards.ForwardMake();
|
return new CForward(et, name, _types, num_params);
|
||||||
pForward->m_IterGuard = NULL;
|
|
||||||
pForward->m_curparam = 0;
|
|
||||||
pForward->m_ExecType = et;
|
|
||||||
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<num_params; i++)
|
|
||||||
{
|
|
||||||
pForward->m_types[i] = _types[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_params && _types[num_params-1] == Param_VarArgs)
|
|
||||||
{
|
|
||||||
pForward->m_varargs = num_params--;
|
|
||||||
} else {
|
|
||||||
pForward->m_varargs = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pForward->m_numparams = num_params;
|
|
||||||
pForward->m_errstate = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
pForward->m_functions.clear();
|
|
||||||
|
|
||||||
return pForward;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||||
@ -305,8 +233,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncIter iter = m_functions.begin();
|
|
||||||
IPluginFunction *func;
|
|
||||||
cell_t cur_result = 0;
|
cell_t cur_result = 0;
|
||||||
cell_t high_result = 0;
|
cell_t high_result = 0;
|
||||||
cell_t low_result = 0;
|
cell_t low_result = 0;
|
||||||
@ -314,54 +240,38 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
unsigned int success=0;
|
unsigned int success=0;
|
||||||
unsigned int num_params = m_curparam;
|
unsigned int num_params = m_curparam;
|
||||||
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||||
FwdParamInfo *param;
|
|
||||||
ParamType type;
|
|
||||||
|
|
||||||
/* Save local, reset */
|
/* Save local, reset */
|
||||||
memcpy(temp_info, m_params, sizeof(m_params));
|
memcpy(temp_info, m_params, sizeof(m_params));
|
||||||
m_curparam = 0;
|
m_curparam = 0;
|
||||||
|
|
||||||
FuncIteratorGuard guard(&m_IterGuard, &iter);
|
for (FuncIter iter(m_functions); !iter.done(); iter.next())
|
||||||
|
|
||||||
while (iter != m_functions.end())
|
|
||||||
{
|
{
|
||||||
func = (*iter);
|
IPluginFunction *func = (*iter);
|
||||||
|
|
||||||
if (filter)
|
if (filter)
|
||||||
filter->Preprocess(func, temp_info);
|
filter->Preprocess(func, temp_info);
|
||||||
|
|
||||||
|
if (func->GetParentRuntime()->IsPaused())
|
||||||
|
continue;
|
||||||
|
|
||||||
for (unsigned int i=0; i<num_params; i++)
|
for (unsigned int i=0; i<num_params; i++)
|
||||||
{
|
{
|
||||||
int err = SP_ERROR_PARAM;
|
int err = SP_ERROR_PARAM;
|
||||||
param = &temp_info[i];
|
FwdParamInfo *param = &temp_info[i];
|
||||||
|
|
||||||
|
ParamType type;
|
||||||
if (i >= m_numparams || m_types[i] == Param_Any)
|
if (i >= m_numparams || m_types[i] == Param_Any)
|
||||||
{
|
|
||||||
type = param->pushedas;
|
type = param->pushedas;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
type = m_types[i];
|
type = m_types[i];
|
||||||
}
|
|
||||||
|
|
||||||
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
|
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
|
||||||
{
|
{
|
||||||
/* If we're byref or we're vararg, we always push everything by ref.
|
/* If we're byref or we're vararg, we always push everything by ref.
|
||||||
* Even if they're byval, we must push them byref.
|
* Even if they're byval, we must push them byref.
|
||||||
*/
|
*/
|
||||||
if (type == Param_String)
|
err = _ExecutePushRef(func, type, param);
|
||||||
{
|
|
||||||
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
|
||||||
}
|
|
||||||
else if (type == Param_Float || type == Param_Cell)
|
|
||||||
{
|
|
||||||
err = func->PushCellByRef(¶m->val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
|
||||||
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -421,9 +331,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!guard.Triggered())
|
|
||||||
iter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -463,6 +370,58 @@ done:
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CForward::_ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param)
|
||||||
|
{
|
||||||
|
/* If we're byref or we're vararg, we always push everything by ref.
|
||||||
|
* Even if they're byval, we must push them byref.
|
||||||
|
*/
|
||||||
|
int err;
|
||||||
|
IPluginRuntime *runtime = func->GetParentRuntime();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Param_String:
|
||||||
|
// Normal string was pushed.
|
||||||
|
if (!param->isnull)
|
||||||
|
return func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
||||||
|
|
||||||
|
// If NULL_STRING was pushed, push the reference to the pubvar of the callee instead.
|
||||||
|
uint32_t null_string_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
cell_t null_string;
|
||||||
|
err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return func->PushCell(null_string);
|
||||||
|
|
||||||
|
case Param_Float:
|
||||||
|
case Param_Cell:
|
||||||
|
return func->PushCellByRef(¶m->val);
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
||||||
|
// No NULL_VECTOR was pushed.
|
||||||
|
if (type != Param_Array || !param->isnull)
|
||||||
|
return func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
||||||
|
|
||||||
|
// If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead.
|
||||||
|
uint32_t null_vector_idx;
|
||||||
|
err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
cell_t null_vector;
|
||||||
|
err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return func->PushCell(null_vector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int CForward::PushCell(cell_t cell)
|
int CForward::PushCell(cell_t cell)
|
||||||
{
|
{
|
||||||
if (m_curparam < m_numparams)
|
if (m_curparam < m_numparams)
|
||||||
@ -481,6 +440,7 @@ int CForward::PushCell(cell_t cell)
|
|||||||
m_params[m_curparam].pushedas = Param_Cell;
|
m_params[m_curparam].pushedas = Param_Cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
m_params[m_curparam++].val = cell;
|
m_params[m_curparam++].val = cell;
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
@ -504,6 +464,7 @@ int CForward::PushFloat(float number)
|
|||||||
m_params[m_curparam].pushedas = Param_Float;
|
m_params[m_curparam].pushedas = Param_Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
m_params[m_curparam++].val = *(cell_t *)&number;
|
m_params[m_curparam++].val = *(cell_t *)&number;
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
@ -562,15 +523,23 @@ void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
|
|||||||
m_params[m_curparam].byref.cells = cells;
|
m_params[m_curparam].byref.cells = cells;
|
||||||
m_params[m_curparam].byref.flags = flags;
|
m_params[m_curparam].byref.flags = flags;
|
||||||
m_params[m_curparam].byref.orig_addr = inarray;
|
m_params[m_curparam].byref.orig_addr = inarray;
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
|
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
|
||||||
{
|
{
|
||||||
/* We don't allow this here */
|
/* Push a reference to the NULL_VECTOR pubvar if NULL was passed. */
|
||||||
if (!inarray)
|
if (!inarray)
|
||||||
{
|
{
|
||||||
|
/* Make sure this was intentional. */
|
||||||
|
if (cells == 3)
|
||||||
|
{
|
||||||
|
return PushNullVector();
|
||||||
|
} else {
|
||||||
|
/* We don't allow this here */
|
||||||
return SetError(SP_ERROR_PARAM);
|
return SetError(SP_ERROR_PARAM);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_curparam < m_numparams)
|
if (m_curparam < m_numparams)
|
||||||
{
|
{
|
||||||
@ -601,10 +570,17 @@ void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags
|
|||||||
m_params[m_curparam].byref.flags = cp_flags;
|
m_params[m_curparam].byref.flags = cp_flags;
|
||||||
m_params[m_curparam].byref.orig_addr = inarray;
|
m_params[m_curparam].byref.orig_addr = inarray;
|
||||||
m_params[m_curparam].byref.sz_flags = sz_flags;
|
m_params[m_curparam].byref.sz_flags = sz_flags;
|
||||||
|
m_params[m_curparam].isnull = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CForward::PushString(const char *string)
|
int CForward::PushString(const char *string)
|
||||||
{
|
{
|
||||||
|
/* Push a reference to the NULL_STRING pubvar if NULL was passed. */
|
||||||
|
if (!string)
|
||||||
|
{
|
||||||
|
return PushNullString();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_curparam < m_numparams)
|
if (m_curparam < m_numparams)
|
||||||
{
|
{
|
||||||
if (m_types[m_curparam] == Param_Any)
|
if (m_types[m_curparam] == Param_Any)
|
||||||
@ -651,6 +627,52 @@ int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_fla
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CForward::PushNullString()
|
||||||
|
{
|
||||||
|
if (m_curparam < m_numparams)
|
||||||
|
{
|
||||||
|
if (m_types[m_curparam] == Param_Any)
|
||||||
|
{
|
||||||
|
m_params[m_curparam].pushedas = Param_String;
|
||||||
|
} else if (m_types[m_curparam] != Param_String) {
|
||||||
|
return SetError(SP_ERROR_PARAM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||||
|
{
|
||||||
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
|
}
|
||||||
|
m_params[m_curparam].pushedas = Param_String;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam++].isnull = true;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CForward::PushNullVector()
|
||||||
|
{
|
||||||
|
if (m_curparam < m_numparams)
|
||||||
|
{
|
||||||
|
if (m_types[m_curparam] == Param_Any)
|
||||||
|
{
|
||||||
|
m_params[m_curparam].pushedas = Param_Array;
|
||||||
|
} else if (m_types[m_curparam] != Param_Array) {
|
||||||
|
return SetError(SP_ERROR_PARAM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||||
|
{
|
||||||
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
|
}
|
||||||
|
m_params[m_curparam].pushedas = Param_Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_params[m_curparam++].isnull = true;
|
||||||
|
|
||||||
|
return SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void CForward::Cancel()
|
void CForward::Cancel()
|
||||||
{
|
{
|
||||||
if (!m_curparam)
|
if (!m_curparam)
|
||||||
@ -688,94 +710,66 @@ bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
|
|||||||
|
|
||||||
bool CForward::RemoveFunction(IPluginFunction *func)
|
bool CForward::RemoveFunction(IPluginFunction *func)
|
||||||
{
|
{
|
||||||
bool found = false;
|
ReentrantList<IPluginFunction *> *lst;
|
||||||
FuncIter iter;
|
|
||||||
List<IPluginFunction *> *lst;
|
|
||||||
|
|
||||||
if (func->IsRunnable())
|
if (func->IsRunnable())
|
||||||
{
|
|
||||||
lst = &m_functions;
|
lst = &m_functions;
|
||||||
} else {
|
else
|
||||||
lst = &m_paused;
|
lst = &m_paused;
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=lst->begin(); iter!=lst->end(); iter++)
|
bool found = false;
|
||||||
{
|
for (FuncIter iter(lst); !iter.done(); iter.next()) {
|
||||||
if ((*iter) == func)
|
if (*iter == func) {
|
||||||
{
|
iter.remove();
|
||||||
m_IterGuard->FixIteratorChain(iter);
|
|
||||||
found = true;
|
found = true;
|
||||||
lst->erase(iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel a call, if any */
|
/* Cancel a call, if any */
|
||||||
if (found || m_curparam)
|
if (found || m_curparam)
|
||||||
{
|
|
||||||
func->Cancel();
|
func->Cancel();
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
|
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
FuncIter iter;
|
|
||||||
IPluginFunction *func;
|
|
||||||
unsigned int removed = 0;
|
unsigned int removed = 0;
|
||||||
IPluginContext *pContext = plugin->GetBaseContext();
|
for (FuncIter iter(m_functions); !iter.done(); iter.next()) {
|
||||||
for (iter=m_functions.begin(); iter!=m_functions.end();)
|
IPluginFunction *func = *iter;
|
||||||
{
|
if (func->GetParentContext() == plugin->GetBaseContext()) {
|
||||||
func = (*iter);
|
iter.remove();
|
||||||
if (func->GetParentContext() == pContext)
|
|
||||||
{
|
|
||||||
iter = m_functions.erase(iter);
|
|
||||||
removed++;
|
removed++;
|
||||||
} else {
|
|
||||||
iter++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CForward::AddFunction(IPluginFunction *func)
|
bool CForward::AddFunction(IPluginFunction *func)
|
||||||
{
|
{
|
||||||
if (m_curparam)
|
if (m_curparam)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (func->IsRunnable())
|
if (func->IsRunnable())
|
||||||
{
|
m_functions.append(func);
|
||||||
m_functions.push_back(func);
|
else
|
||||||
} else {
|
m_paused.append(func);
|
||||||
m_paused.push_back(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
||||||
{
|
{
|
||||||
FuncIter iter;
|
ReentrantList<IPluginFunction *> *lst;
|
||||||
List<IPluginFunction *> *lst;
|
|
||||||
|
|
||||||
if (func->IsRunnable())
|
if (func->IsRunnable())
|
||||||
{
|
|
||||||
lst = &m_functions;
|
lst = &m_functions;
|
||||||
} else {
|
else
|
||||||
lst = &m_paused;
|
lst = &m_paused;
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
for (FuncIter iter(lst); !iter.done(); iter.next()) {
|
||||||
{
|
|
||||||
if ((*iter) == func)
|
if ((*iter) == func)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,7 +780,7 @@ const char *CForward::GetForwardName()
|
|||||||
|
|
||||||
unsigned int CForward::GetFunctionCount()
|
unsigned int CForward::GetFunctionCount()
|
||||||
{
|
{
|
||||||
return m_functions.size();
|
return m_functions.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecType CForward::GetExecType()
|
ExecType CForward::GetExecType()
|
||||||
|
@ -1,33 +1,29 @@
|
|||||||
/**
|
// vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* vim: set ts=4 :
|
// =============================================================================
|
||||||
* =============================================================================
|
// SourceMod
|
||||||
* SourceMod
|
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
// =============================================================================
|
||||||
* =============================================================================
|
//
|
||||||
*
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
// Free Software Foundation.
|
||||||
* Free Software Foundation.
|
//
|
||||||
*
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
// details.
|
||||||
* details.
|
//
|
||||||
*
|
// You should have received a copy of the GNU General Public License along with
|
||||||
* You should have received a copy of the GNU General Public License along with
|
// this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
||||||
*
|
// As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
// code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
// by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
// all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
// this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
// or <http://www.sourcemod.net/license.php>.
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
#ifndef _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
||||||
#define _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
#define _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
||||||
@ -35,61 +31,14 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include "ISourceMod.h"
|
#include "ISourceMod.h"
|
||||||
|
#include "ReentrantList.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
typedef ReentrantList<IPluginFunction *>::iterator FuncIter;
|
||||||
|
|
||||||
typedef List<IPluginFunction *>::iterator FuncIter;
|
|
||||||
|
|
||||||
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
|
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
|
||||||
#define FORWARDS_NAME_MAX 64
|
#define FORWARDS_NAME_MAX 64
|
||||||
|
|
||||||
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
|
class CForward : public IChangeableForward
|
||||||
{
|
{
|
||||||
public: //ICallable
|
public: //ICallable
|
||||||
@ -120,6 +69,12 @@ public:
|
|||||||
va_list ap);
|
va_list ap);
|
||||||
bool IsFunctionRegistered(IPluginFunction *func);
|
bool IsFunctionRegistered(IPluginFunction *func);
|
||||||
private:
|
private:
|
||||||
|
CForward(ExecType et, const char *name,
|
||||||
|
const ParamType *types, unsigned num_params);
|
||||||
|
|
||||||
|
int PushNullString();
|
||||||
|
int PushNullVector();
|
||||||
|
int _ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param);
|
||||||
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
|
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
|
||||||
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
|
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
|
||||||
inline int SetError(int err)
|
inline int SetError(int err)
|
||||||
@ -128,12 +83,8 @@ private:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
/* :TODO: I want a caching list type here.
|
mutable ReentrantList<IPluginFunction *> m_functions;
|
||||||
* Destroying these things and using new/delete for their members feels bad.
|
mutable ReentrantList<IPluginFunction *> m_paused;
|
||||||
*/
|
|
||||||
mutable List<IPluginFunction *> m_functions;
|
|
||||||
mutable List<IPluginFunction *> m_paused;
|
|
||||||
FuncIteratorGuard *m_IterGuard;
|
|
||||||
|
|
||||||
/* Type and name information */
|
/* Type and name information */
|
||||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||||
@ -154,8 +105,6 @@ class CForwardManager :
|
|||||||
public SMGlobalClass
|
public SMGlobalClass
|
||||||
{
|
{
|
||||||
friend class CForward;
|
friend class CForward;
|
||||||
public:
|
|
||||||
~CForwardManager();
|
|
||||||
public: //IForwardManager
|
public: //IForwardManager
|
||||||
IForward *CreateForward(const char *name,
|
IForward *CreateForward(const char *name,
|
||||||
ExecType et,
|
ExecType et,
|
||||||
@ -175,13 +124,11 @@ public: //IPluginsListener
|
|||||||
void OnPluginPauseChange(IPlugin *plugin, bool paused);
|
void OnPluginPauseChange(IPlugin *plugin, bool paused);
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
protected:
|
|
||||||
CForward *ForwardMake();
|
|
||||||
void ForwardFree(CForward *fwd);
|
|
||||||
private:
|
private:
|
||||||
CStack<CForward *> m_FreeForwards;
|
ReentrantList<CForward *> m_managed;
|
||||||
List<CForward *> m_managed;
|
ReentrantList<CForward *> m_unmanaged;
|
||||||
List<CForward *> m_unmanaged;
|
|
||||||
|
typedef ReentrantList<CForward *>::iterator ForwardIter;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CForwardManager g_Forwards;
|
extern CForwardManager g_Forwards;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourcePawn
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -29,37 +29,63 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
#include "FrameIterator.h"
|
||||||
#define _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
|
||||||
|
|
||||||
/**
|
SafeFrameIterator::SafeFrameIterator(IFrameIterator *it)
|
||||||
* @file sp_typeutil.h
|
|
||||||
* @brief Defines type utility functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sp_vm_types.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reinterpret-casts a float to a cell (requires -fno-strict-aliasing for GCC).
|
|
||||||
*
|
|
||||||
* @param val Float value.
|
|
||||||
* @return Cell typed version.
|
|
||||||
*/
|
|
||||||
inline cell_t sp_ftoc(float val)
|
|
||||||
{
|
{
|
||||||
return *(cell_t *)&val;
|
while (!it->Done())
|
||||||
|
{
|
||||||
|
FrameInfo info = FrameInfo(it);
|
||||||
|
frames.append(info);
|
||||||
|
it->Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
it->Reset();
|
||||||
* @brief Reinterpret-casts a cell to a float (requires -fno-strict-aliasing for GCC).
|
current = 0;
|
||||||
*
|
|
||||||
* @param val Cell-packed float value.
|
|
||||||
* @return Float typed version.
|
|
||||||
*/
|
|
||||||
inline float sp_ctof(cell_t val)
|
|
||||||
{
|
|
||||||
return *(float *)&val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
bool SafeFrameIterator::Done() const
|
||||||
|
{
|
||||||
|
return current >= frames.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SafeFrameIterator::Next()
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
return !this->Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SafeFrameIterator::Reset()
|
||||||
|
{
|
||||||
|
current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SafeFrameIterator::LineNumber() const
|
||||||
|
{
|
||||||
|
if (this->Done())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)frames[current].LineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SafeFrameIterator::FunctionName() const
|
||||||
|
{
|
||||||
|
if (this->Done())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frames[current].FunctionName.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SafeFrameIterator::FilePath() const
|
||||||
|
{
|
||||||
|
if (this->Done())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frames[current].FilePath.chars();
|
||||||
|
}
|
77
core/logic/FrameIterator.h
Normal file
77
core/logic/FrameIterator.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2017 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 <am-vector.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
|
||||||
|
using namespace SourcePawn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frame iterator cache which is safe for plugins to hold handles to,
|
||||||
|
* unlike what you'd recieve from IPluginContext::CreateFrameIterator.
|
||||||
|
*/
|
||||||
|
class SafeFrameIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct which holds all of the cached values for each individual frame.
|
||||||
|
*/
|
||||||
|
struct FrameInfo
|
||||||
|
{
|
||||||
|
ke::AString FunctionName;
|
||||||
|
ke::AString FilePath;
|
||||||
|
unsigned LineNumber;
|
||||||
|
|
||||||
|
FrameInfo(IFrameIterator *it)
|
||||||
|
{
|
||||||
|
LineNumber = it->LineNumber();
|
||||||
|
|
||||||
|
FunctionName = it->FunctionName();
|
||||||
|
FilePath = it->FilePath();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SafeFrameIterator(IFrameIterator *);
|
||||||
|
|
||||||
|
bool Done() const;
|
||||||
|
bool Next();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
int LineNumber() const;
|
||||||
|
const char *FunctionName() const;
|
||||||
|
const char *FilePath() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t current;
|
||||||
|
ke::Vector<FrameInfo> frames;
|
||||||
|
};
|
@ -39,9 +39,13 @@
|
|||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <IMemoryUtils.h>
|
#include <IMemoryUtils.h>
|
||||||
#include <ISourceMod.h>
|
#include <ISourceMod.h>
|
||||||
|
#include <IRootConsoleMenu.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include "sm_crc32.h"
|
#include "sm_crc32.h"
|
||||||
#include "MemoryUtils.h"
|
#include "MemoryUtils.h"
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
|
||||||
#if defined PLATFORM_POSIX
|
#if defined PLATFORM_POSIX
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@ -62,26 +66,33 @@ static const char *g_pParseEngine = NULL;
|
|||||||
#define PSTATE_GAMEDEFS_OFFSETS 3
|
#define PSTATE_GAMEDEFS_OFFSETS 3
|
||||||
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
|
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
|
||||||
#define PSTATE_GAMEDEFS_KEYS 5
|
#define PSTATE_GAMEDEFS_KEYS 5
|
||||||
#define PSTATE_GAMEDEFS_SUPPORTED 6
|
#define PSTATE_GAMEDEFS_KEYS_PLATFORM 6
|
||||||
#define PSTATE_GAMEDEFS_SIGNATURES 7
|
#define PSTATE_GAMEDEFS_SUPPORTED 7
|
||||||
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
|
#define PSTATE_GAMEDEFS_SIGNATURES 8
|
||||||
#define PSTATE_GAMEDEFS_CRC 9
|
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 9
|
||||||
#define PSTATE_GAMEDEFS_CRC_BINARY 10
|
#define PSTATE_GAMEDEFS_CRC 10
|
||||||
#define PSTATE_GAMEDEFS_CUSTOM 11
|
#define PSTATE_GAMEDEFS_CRC_BINARY 11
|
||||||
#define PSTATE_GAMEDEFS_ADDRESSES 12
|
#define PSTATE_GAMEDEFS_CUSTOM 12
|
||||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13
|
#define PSTATE_GAMEDEFS_ADDRESSES 13
|
||||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14
|
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 14
|
||||||
|
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 15
|
||||||
|
|
||||||
|
#if defined PLATFORM_X86
|
||||||
|
#define PLATFORM_ARCH_SUFFIX ""
|
||||||
|
#elif defined PLATFORM_X64
|
||||||
|
#define PLATFORM_ARCH_SUFFIX "64"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
#define PLATFORM_NAME "windows"
|
#define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
|
||||||
#define PLATFORM_SERVER_BINARY "server.dll"
|
#define PLATFORM_SERVER_BINARY "server.dll"
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX
|
||||||
#define PLATFORM_NAME "linux"
|
#define PLATFORM_NAME "linux" PLATFORM_ARCH_SUFFIX
|
||||||
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
|
#define PLATFORM_COMPAT_ALT "mac" PLATFORM_ARCH_SUFFIX /* Alternate platform name if game data is missing for primary one */
|
||||||
#define PLATFORM_SERVER_BINARY "server_i486.so"
|
#define PLATFORM_SERVER_BINARY "server_i486.so"
|
||||||
#elif defined PLATFORM_APPLE
|
#elif defined PLATFORM_APPLE
|
||||||
#define PLATFORM_NAME "mac"
|
#define PLATFORM_NAME "mac" PLATFORM_ARCH_SUFFIX
|
||||||
#define PLATFORM_COMPAT_ALT "linux"
|
#define PLATFORM_COMPAT_ALT "linux" PLATFORM_ARCH_SUFFIX
|
||||||
#define PLATFORM_SERVER_BINARY "server.dylib"
|
#define PLATFORM_SERVER_BINARY "server.dylib"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -150,7 +161,7 @@ CGameConfig::CGameConfig(const char *file, const char *engine)
|
|||||||
m_CustomHandler = NULL;
|
m_CustomHandler = NULL;
|
||||||
|
|
||||||
if (!engine)
|
if (!engine)
|
||||||
m_pEngine = smcore.GetSourceEngineName();
|
m_pEngine = bridge->GetSourceEngineName();
|
||||||
else
|
else
|
||||||
m_pEngine = engine;
|
m_pEngine = engine;
|
||||||
|
|
||||||
@ -248,6 +259,13 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PSTATE_GAMEDEFS_KEYS:
|
||||||
|
{
|
||||||
|
strncopy(m_Key, name, sizeof(m_Key));
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_KEYS_PLATFORM;
|
||||||
|
matched_platform = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PSTATE_GAMEDEFS_OFFSETS:
|
case PSTATE_GAMEDEFS_OFFSETS:
|
||||||
{
|
{
|
||||||
m_Prop[0] = '\0';
|
m_Prop[0] = '\0';
|
||||||
@ -271,7 +289,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
error[0] = '\0';
|
error[0] = '\0';
|
||||||
if (strcmp(name, "server") != 0)
|
if (strcmp(name, "server") != 0)
|
||||||
{
|
{
|
||||||
smcore.Format(error, sizeof(error), "Unrecognized library \"%s\"", name);
|
ke::SafeSprintf(error, sizeof(error), "Unrecognized library \"%s\"", name);
|
||||||
}
|
}
|
||||||
else if (!s_ServerBinCRC_Ok)
|
else if (!s_ServerBinCRC_Ok)
|
||||||
{
|
{
|
||||||
@ -281,7 +299,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "bin/" PLATFORM_SERVER_BINARY);
|
g_pSM->BuildPath(Path_Game, path, sizeof(path), "bin/" PLATFORM_SERVER_BINARY);
|
||||||
if ((fp = fopen(path, "rb")) == NULL)
|
if ((fp = fopen(path, "rb")) == NULL)
|
||||||
{
|
{
|
||||||
smcore.Format(error, sizeof(error), "Could not open binary: %s", path);
|
ke::SafeSprintf(error, sizeof(error), "Could not open binary: %s", path);
|
||||||
} else {
|
} else {
|
||||||
size_t size;
|
size_t size;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
@ -319,6 +337,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
m_Address[0] = '\0';
|
m_Address[0] = '\0';
|
||||||
m_AddressSignature[0] = '\0';
|
m_AddressSignature[0] = '\0';
|
||||||
m_AddressReadCount = 0;
|
m_AddressReadCount = 0;
|
||||||
|
m_AddressLastIsOffset = false;
|
||||||
|
|
||||||
strncopy(m_Address, name, sizeof(m_Address));
|
strncopy(m_Address, name, sizeof(m_Address));
|
||||||
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
|
||||||
@ -333,7 +352,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
|
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0 &&
|
||||||
|
strcmp(name, "linux64") != 0 && strcmp(name, "windows64") != 0 && strcmp(name, "mac64") != 0)
|
||||||
{
|
{
|
||||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||||
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||||
@ -344,7 +364,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
}
|
}
|
||||||
/* No sub-sections allowed:
|
/* No sub-sections allowed:
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||||
case PSTATE_GAMEDEFS_KEYS:
|
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
|
||||||
case PSTATE_GAMEDEFS_SUPPORTED:
|
case PSTATE_GAMEDEFS_SUPPORTED:
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
||||||
case PSTATE_GAMEDEFS_CRC_BINARY:
|
case PSTATE_GAMEDEFS_CRC_BINARY:
|
||||||
@ -381,6 +401,13 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
|||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
|
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
|
||||||
ke::AString vstr(value);
|
ke::AString vstr(value);
|
||||||
m_Keys.replace(key, ke::Move(vstr));
|
m_Keys.replace(key, ke::Move(vstr));
|
||||||
|
}
|
||||||
|
else if (m_ParseState == PSTATE_GAMEDEFS_KEYS_PLATFORM) {
|
||||||
|
if (IsPlatformCompatible(key, &matched_platform))
|
||||||
|
{
|
||||||
|
ke::AString vstr(value);
|
||||||
|
m_Keys.replace(m_Key, ke::Move(vstr));
|
||||||
|
}
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
|
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
|
||||||
if (strcmp(key, "game") == 0)
|
if (strcmp(key, "game") == 0)
|
||||||
{
|
{
|
||||||
@ -426,10 +453,18 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
|
} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
|
||||||
if (strcmp(key, "read") == 0) {
|
if (strcmp(key, "read") == 0 || strcmp(key, "offset") == 0) {
|
||||||
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
|
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
|
||||||
if (m_AddressReadCount < limit)
|
if (m_AddressLastIsOffset)
|
||||||
{
|
{
|
||||||
|
logger->LogError("[SM] Error parsing Address \"%s\", 'offset' entry must be the last entry (gameconf \"%s\")", m_Address, m_CurFile);
|
||||||
|
}
|
||||||
|
else if (m_AddressReadCount < limit)
|
||||||
|
{
|
||||||
|
if (strcmp(key, "offset") == 0)
|
||||||
|
{
|
||||||
|
m_AddressLastIsOffset = true;
|
||||||
|
}
|
||||||
m_AddressRead[m_AddressReadCount] = atoi(value);
|
m_AddressRead[m_AddressReadCount] = atoi(value);
|
||||||
m_AddressReadCount++;
|
m_AddressReadCount++;
|
||||||
}
|
}
|
||||||
@ -486,6 +521,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_KEYS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||||
{
|
{
|
||||||
/* Parse the offset... */
|
/* Parse the offset... */
|
||||||
@ -547,11 +587,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
void *addrInBase = NULL;
|
void *addrInBase = NULL;
|
||||||
if (strcmp(s_TempSig.library, "server") == 0)
|
if (strcmp(s_TempSig.library, "server") == 0)
|
||||||
{
|
{
|
||||||
addrInBase = smcore.serverFactory;
|
addrInBase = bridge->serverFactory;
|
||||||
} else if (strcmp(s_TempSig.library, "engine") == 0) {
|
} else if (strcmp(s_TempSig.library, "engine") == 0) {
|
||||||
addrInBase = smcore.engineFactory;
|
addrInBase = bridge->engineFactory;
|
||||||
} else if (strcmp(s_TempSig.library, "matchmaking_ds") == 0) {
|
} else if (strcmp(s_TempSig.library, "matchmaking_ds") == 0) {
|
||||||
addrInBase = smcore.matchmakingDSFactory;
|
addrInBase = bridge->matchmakingDSFactory;
|
||||||
}
|
}
|
||||||
void *final_addr = NULL;
|
void *final_addr = NULL;
|
||||||
if (addrInBase == NULL)
|
if (addrInBase == NULL)
|
||||||
@ -579,7 +619,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
if (smcore.SymbolsAreHidden())
|
if (bridge->SymbolsAreHidden())
|
||||||
final_addr = g_MemUtils.ResolveSymbol(handle, &s_TempSig.sig[1]);
|
final_addr = g_MemUtils.ResolveSymbol(handle, &s_TempSig.sig[1]);
|
||||||
else
|
else
|
||||||
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
||||||
@ -633,7 +673,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
|
|
||||||
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
|
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
|
||||||
{
|
{
|
||||||
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
|
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead, m_AddressLastIsOffset);
|
||||||
m_Addresses.replace(m_Address, addrConf);
|
m_Addresses.replace(m_Address, addrConf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +831,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
if (!libsys->PathExists(path))
|
if (!libsys->PathExists(path))
|
||||||
{
|
{
|
||||||
/* Nope, use the old mechanism. */
|
/* Nope, use the old mechanism. */
|
||||||
smcore.Format(path, sizeof(path), "%s.txt", m_File);
|
ke::SafeSprintf(path, sizeof(path), "%s.txt", m_File);
|
||||||
if (!EnterFile(path, error, maxlength))
|
if (!EnterFile(path, error, maxlength))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -801,8 +841,13 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "gamedata/custom/%s.txt", m_File);
|
g_pSM->BuildPath(Path_SM, path, sizeof(path), "gamedata/custom/%s.txt", m_File);
|
||||||
if (libsys->PathExists(path))
|
if (libsys->PathExists(path))
|
||||||
{
|
{
|
||||||
smcore.Format(path, sizeof(path), "custom/%s.txt", m_File);
|
ke::SafeSprintf(path, sizeof(path), "custom/%s.txt", m_File);
|
||||||
return EnterFile(path, error, maxlength);
|
bool success = EnterFile(path, error, maxlength);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
rootmenu->ConsolePrint("[SM] Parsed custom gamedata override file: %s", path);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -841,7 +886,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
List<String>::iterator iter;
|
List<String>::iterator iter;
|
||||||
for (iter = fileList.begin(); iter != fileList.end(); iter++)
|
for (iter = fileList.begin(); iter != fileList.end(); iter++)
|
||||||
{
|
{
|
||||||
smcore.Format(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
|
ke::SafeSprintf(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
|
||||||
if (!EnterFile(path, error, maxlength))
|
if (!EnterFile(path, error, maxlength))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -875,13 +920,15 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
smcore.Format(path, sizeof(path), "%s/custom/%s", m_File, curFile);
|
ke::SafeSprintf(path, sizeof(path), "%s/custom/%s", m_File, curFile);
|
||||||
if (!EnterFile(path, error, maxlength))
|
if (!EnterFile(path, error, maxlength))
|
||||||
{
|
{
|
||||||
libsys->CloseDirectory(customDir);
|
libsys->CloseDirectory(customDir);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootmenu->ConsolePrint("[SM] Parsed custom gamedata override file: %s", path);
|
||||||
|
|
||||||
customDir->NextEntry();
|
customDir->NextEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,8 +1038,13 @@ bool CGameConfig::GetAddress(const char *key, void **retaddr)
|
|||||||
*retaddr = NULL;
|
*retaddr = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//If lastIsOffset is set and this is the last iteration of the loop, don't deref
|
||||||
|
if (addrConf.lastIsOffset && i == addrConf.readCount-1) {
|
||||||
|
addr = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(addr) + offset);
|
||||||
|
} else {
|
||||||
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
|
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*retaddr = addr;
|
*retaddr = addr;
|
||||||
return true;
|
return true;
|
||||||
@ -1003,13 +1055,17 @@ static inline unsigned minOf(unsigned a, unsigned b)
|
|||||||
return a <= b ? a : b;
|
return a <= b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read)
|
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset)
|
||||||
{
|
{
|
||||||
unsigned readLimit = minOf(readCount, sizeof(this->read) / sizeof(this->read[0]));
|
unsigned readLimit = minOf(readCount, sizeof(this->read) / sizeof(this->read[0]));
|
||||||
|
|
||||||
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
|
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
|
||||||
this->readCount = readLimit;
|
this->readCount = readLimit;
|
||||||
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
|
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
|
||||||
|
|
||||||
|
//For safety: if the readLimit isn't the same as the readCount, then the
|
||||||
|
//last read value was definitely discarded, so lastIsOffset should be ignored
|
||||||
|
this->lastIsOffset = readLimit < readCount ? false : lastIsOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendProp *CGameConfig::GetSendProp(const char *key)
|
SendProp *CGameConfig::GetSendProp(const char *key)
|
||||||
@ -1038,8 +1094,8 @@ void GameConfigManager::OnSourceModStartup(bool late)
|
|||||||
LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
|
LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
|
||||||
|
|
||||||
strncopy(g_Game, g_pSM->GetGameFolderName(), sizeof(g_Game));
|
strncopy(g_Game, g_pSM->GetGameFolderName(), sizeof(g_Game));
|
||||||
strncopy(g_GameDesc + 1, smcore.GetGameDescription(), sizeof(g_GameDesc) - 1);
|
strncopy(g_GameDesc + 1, bridge->GetGameDescription(), sizeof(g_GameDesc) - 1);
|
||||||
smcore.GetGameName(g_GameName + 1, sizeof(g_GameName) - 1);
|
bridge->GetGameName(g_GameName + 1, sizeof(g_GameName) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameConfigManager::OnSourceModAllInitialized()
|
void GameConfigManager::OnSourceModAllInitialized()
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include <sm_namehashset.h>
|
#include <sm_namehashset.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class SendProp;
|
class SendProp;
|
||||||
|
|
||||||
@ -73,6 +72,10 @@ public: //NameHashSet
|
|||||||
{
|
{
|
||||||
return strcmp(key, value->m_File) == 0;
|
return strcmp(key, value->m_File) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
char m_File[PLATFORM_MAX_PATH];
|
char m_File[PLATFORM_MAX_PATH];
|
||||||
char m_CurFile[PLATFORM_MAX_PATH];
|
char m_CurFile[PLATFORM_MAX_PATH];
|
||||||
@ -87,6 +90,7 @@ private:
|
|||||||
char m_Prop[64];
|
char m_Prop[64];
|
||||||
char m_offset[64];
|
char m_offset[64];
|
||||||
char m_Game[256];
|
char m_Game[256];
|
||||||
|
char m_Key[64];
|
||||||
bool bShouldBeReadingDefault;
|
bool bShouldBeReadingDefault;
|
||||||
bool had_game;
|
bool had_game;
|
||||||
bool matched_game;
|
bool matched_game;
|
||||||
@ -104,8 +108,9 @@ private:
|
|||||||
char signatureName[64];
|
char signatureName[64];
|
||||||
int readCount;
|
int readCount;
|
||||||
int read[8];
|
int read[8];
|
||||||
|
bool lastIsOffset;
|
||||||
|
|
||||||
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
|
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset);
|
||||||
|
|
||||||
AddressConf() {}
|
AddressConf() {}
|
||||||
};
|
};
|
||||||
@ -114,6 +119,7 @@ private:
|
|||||||
char m_AddressSignature[64];
|
char m_AddressSignature[64];
|
||||||
int m_AddressReadCount;
|
int m_AddressReadCount;
|
||||||
int m_AddressRead[8];
|
int m_AddressRead[8];
|
||||||
|
bool m_AddressLastIsOffset;
|
||||||
StringHashMap<AddressConf> m_Addresses;
|
StringHashMap<AddressConf> m_Addresses;
|
||||||
const char *m_pEngine;
|
const char *m_pEngine;
|
||||||
const char *m_pBaseEngine;
|
const char *m_pBaseEngine;
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
#include "ExtensionSys.h"
|
#include "ExtensionSys.h"
|
||||||
#include "PluginSys.h"
|
#include "PluginSys.h"
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
HandleSystem g_HandleSys;
|
HandleSystem g_HandleSys;
|
||||||
|
|
||||||
@ -1064,11 +1066,23 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
|||||||
return scripts->UnloadPlugin(highest_owner);
|
return scripts->UnloadPlugin(highest_owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleSystem::Dump(HANDLE_REPORTER rep)
|
static void rep(const HandleReporter &fn, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ke::SafeVsprintf(buffer, sizeof(buffer), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
fn(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleSystem::Dump(const HandleReporter &fn)
|
||||||
{
|
{
|
||||||
unsigned int total_size = 0;
|
unsigned int total_size = 0;
|
||||||
rep("%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
|
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
|
||||||
rep("--------------------------------------------------------------------------");
|
rep(fn, "--------------------------------------------------------------------------");
|
||||||
for (unsigned int i = 1; i <= m_HandleTail; i++)
|
for (unsigned int i = 1; i <= m_HandleTail; i++)
|
||||||
{
|
{
|
||||||
if (m_Handles[i].set != HandleSet_Used)
|
if (m_Handles[i].set != HandleSet_Used)
|
||||||
@ -1139,16 +1153,16 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
|
|||||||
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|
||||||
|| !bresult)
|
|| !bresult)
|
||||||
{
|
{
|
||||||
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
|
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
smcore.Format(buffer, sizeof(buffer), "%d", size);
|
ke::SafeSprintf(buffer, sizeof(buffer), "%d", size);
|
||||||
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
|
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
|
||||||
total_size += size;
|
total_size += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rep("-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
|
rep(fn, "-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,12 @@
|
|||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sm_namehashset.h>
|
#include <sm_namehashset.h>
|
||||||
#include <am-string.h>
|
#include <amtl/am-autoptr.h>
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
#include <amtl/am-function.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
|
||||||
#define HANDLESYS_MAX_HANDLES (1<<14)
|
#define HANDLESYS_MAX_HANDLES (1<<15)
|
||||||
#define HANDLESYS_MAX_TYPES (1<<9)
|
#define HANDLESYS_MAX_TYPES (1<<9)
|
||||||
#define HANDLESYS_MAX_SUBTYPES 0xF
|
#define HANDLESYS_MAX_SUBTYPES 0xF
|
||||||
#define HANDLESYS_SUBTYPE_MASK 0xF
|
#define HANDLESYS_SUBTYPE_MASK 0xF
|
||||||
@ -109,9 +111,13 @@ struct QHandleType
|
|||||||
{
|
{
|
||||||
return type->name && type->name->compare(key) == 0;
|
return type->name && type->name->compare(key) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (HANDLE_REPORTER)(const char *str, ...);
|
typedef ke::Lambda<void(const char *)> HandleReporter;
|
||||||
|
|
||||||
class HandleSystem :
|
class HandleSystem :
|
||||||
public IHandleSys
|
public IHandleSys
|
||||||
@ -163,7 +169,7 @@ public: //IHandleSystem
|
|||||||
const HandleAccess *pAccess,
|
const HandleAccess *pAccess,
|
||||||
HandleError *err);
|
HandleError *err);
|
||||||
|
|
||||||
void Dump(HANDLE_REPORTER rep);
|
void Dump(const HandleReporter &reporter);
|
||||||
|
|
||||||
/* Bypasses security checks. */
|
/* Bypasses security checks. */
|
||||||
Handle_t FastCloneHandle(Handle_t hndl);
|
Handle_t FastCloneHandle(Handle_t hndl);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -34,27 +34,16 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sm_platform.h>
|
#include <sm_platform.h>
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "LibrarySys.h"
|
#include "LibrarySys.h"
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
#include <amtl/os/am-path.h>
|
||||||
|
#include <amtl/os/am-fsutil.h>
|
||||||
|
|
||||||
LibrarySystem g_LibSys;
|
LibrarySystem g_LibSys;
|
||||||
|
|
||||||
CLibrary::~CLibrary()
|
CLibrary::CLibrary(ke::RefPtr<ke::SharedLib> lib)
|
||||||
|
: lib_(lib)
|
||||||
{
|
{
|
||||||
if (m_lib)
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
FreeLibrary(m_lib);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
dlclose(m_lib);
|
|
||||||
#endif
|
|
||||||
m_lib = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CLibrary::CLibrary(LibraryHandle me)
|
|
||||||
{
|
|
||||||
m_lib = me;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLibrary::CloseLibrary()
|
void CLibrary::CloseLibrary()
|
||||||
@ -64,11 +53,7 @@ void CLibrary::CloseLibrary()
|
|||||||
|
|
||||||
void *CLibrary::GetSymbolAddress(const char *symname)
|
void *CLibrary::GetSymbolAddress(const char *symname)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
return lib_->lookup(symname);
|
||||||
return GetProcAddress(m_lib, symname);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
return dlsym(m_lib, symname);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -81,7 +66,7 @@ CDirectory::CDirectory(const char *path)
|
|||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
char newpath[PLATFORM_MAX_PATH];
|
char newpath[PLATFORM_MAX_PATH];
|
||||||
snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
||||||
m_dir = FindFirstFileA(newpath, &m_fd);
|
m_dir = FindFirstFileA(newpath, &m_fd);
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
{
|
{
|
||||||
@ -93,7 +78,7 @@ CDirectory::CDirectory(const char *path)
|
|||||||
{
|
{
|
||||||
/* :TODO: we need to read past "." and ".."! */
|
/* :TODO: we need to read past "." and ".."! */
|
||||||
ep = readdir(m_dir);
|
ep = readdir(m_dir);
|
||||||
snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
|
ke::SafeStrcpy(m_origpath, PLATFORM_MAX_PATH, path);
|
||||||
} else {
|
} else {
|
||||||
ep = NULL;
|
ep = NULL;
|
||||||
}
|
}
|
||||||
@ -140,8 +125,10 @@ bool CDirectory::IsEntryDirectory()
|
|||||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
char temppath[PLATFORM_MAX_PATH];
|
char temppath[PLATFORM_MAX_PATH];
|
||||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||||
return g_LibSys.IsPathDirectory(temppath);
|
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||||
|
return false;
|
||||||
|
return ke::file::IsDirectory(temppath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,8 +138,10 @@ bool CDirectory::IsEntryFile()
|
|||||||
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
|
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
char temppath[PLATFORM_MAX_PATH];
|
char temppath[PLATFORM_MAX_PATH];
|
||||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||||
return g_LibSys.IsPathFile(temppath);
|
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||||
|
return false;
|
||||||
|
return ke::file::IsFile(temppath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,75 +176,17 @@ bool CDirectory::IsValid()
|
|||||||
|
|
||||||
bool LibrarySystem::PathExists(const char *path)
|
bool LibrarySystem::PathExists(const char *path)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
return ke::file::PathExists(path);
|
||||||
DWORD attr = GetFileAttributesA(path);
|
|
||||||
|
|
||||||
return (attr != INVALID_FILE_ATTRIBUTES);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
return (stat(path, &s) == 0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibrarySystem::IsPathFile(const char *path)
|
bool LibrarySystem::IsPathFile(const char *path)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
return ke::file::IsFile(path);
|
||||||
DWORD attr = GetFileAttributes(path);
|
|
||||||
|
|
||||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
if (stat(path, &s) != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_ISREG(s.st_mode) ? true : false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibrarySystem::IsPathDirectory(const char *path)
|
bool LibrarySystem::IsPathDirectory(const char *path)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
return ke::file::IsDirectory(path);
|
||||||
DWORD attr = GetFileAttributes(path);
|
|
||||||
|
|
||||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
if (stat(path, &s) != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR(s.st_mode))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IDirectory *LibrarySystem::OpenDirectory(const char *path)
|
IDirectory *LibrarySystem::OpenDirectory(const char *path)
|
||||||
@ -293,13 +224,13 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
|
|||||||
maxlength,
|
maxlength,
|
||||||
NULL) == 0)
|
NULL) == 0)
|
||||||
{
|
{
|
||||||
UTIL_Format(error, maxlength, "error code %08x", code);
|
ke::SafeSprintf(error, maxlength, "error code %08x", code);
|
||||||
}
|
}
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX
|
||||||
const char *ae = strerror_r(code, error, maxlength);
|
const char *ae = strerror_r(code, error, maxlength);
|
||||||
if (ae != error)
|
if (ae != error)
|
||||||
{
|
{
|
||||||
UTIL_Format(error, maxlength, "%s", ae);
|
ke::SafeStrcpy(error, maxlength, ae);
|
||||||
}
|
}
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
strerror_r(code, error, maxlength);
|
strerror_r(code, error, maxlength);
|
||||||
@ -307,18 +238,6 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibrarySystem::GetLoaderError(char *buffer, size_t maxlength)
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
GetPlatformError(buffer, maxlength);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
if (buffer != NULL && maxlength)
|
|
||||||
{
|
|
||||||
strncopy(buffer, dlerror(), maxlength);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void LibrarySystem::CloseDirectory(IDirectory *dir)
|
void LibrarySystem::CloseDirectory(IDirectory *dir)
|
||||||
{
|
{
|
||||||
delete dir;
|
delete dir;
|
||||||
@ -326,19 +245,9 @@ void LibrarySystem::CloseDirectory(IDirectory *dir)
|
|||||||
|
|
||||||
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
|
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
LibraryHandle lib;
|
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(path, error, maxlength);
|
||||||
#if defined PLATFORM_WINDOWS
|
if (!lib)
|
||||||
lib = LoadLibraryA(path);
|
return nullptr;
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
lib = dlopen(path, RTLD_NOW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (lib == NULL)
|
|
||||||
{
|
|
||||||
GetLoaderError(error, maxlength);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CLibrary(lib);
|
return new CLibrary(lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,23 +255,8 @@ size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
size_t mylen = vsnprintf(buffer, len, fmt, ap);
|
size_t mylen = ke::path::FormatVa(buffer, len, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (mylen >= len)
|
|
||||||
{
|
|
||||||
mylen = len - 1;
|
|
||||||
buffer[mylen] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<mylen; i++)
|
|
||||||
{
|
|
||||||
if (buffer[i] == PLATFORM_SEP_ALTCHAR)
|
|
||||||
{
|
|
||||||
buffer[i] = PLATFORM_SEP_CHAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mylen;
|
return mylen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,11 +292,7 @@ const char *LibrarySystem::GetFileExtension(const char *filename)
|
|||||||
|
|
||||||
bool LibrarySystem::CreateFolder(const char *path)
|
bool LibrarySystem::CreateFolder(const char *path)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
return ke::file::CreateDirectory(path, 0775);
|
||||||
return (mkdir(path) != -1);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
return (mkdir(path, 0775) != -1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path)
|
size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path)
|
||||||
@ -419,12 +309,12 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return UTIL_Format(buffer, maxlength, "%s", &path[i+1]);
|
return ke::SafeStrcpy(buffer, maxlength, &path[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We scanned and found no path separator */
|
/* We scanned and found no path separator */
|
||||||
return UTIL_Format(buffer, maxlength, "%s", path);
|
return ke::SafeStrcpy(buffer, maxlength, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)
|
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
@ -33,16 +33,11 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
|
#define _INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
|
||||||
|
|
||||||
#include <ILibrarySys.h>
|
#include <ILibrarySys.h>
|
||||||
|
#include <amtl/os/am-shared-library.h>
|
||||||
#include "sm_platform.h"
|
#include "sm_platform.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
typedef HMODULE LibraryHandle;
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
typedef void * LibraryHandle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CDirectory : public IDirectory
|
class CDirectory : public IDirectory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -71,13 +66,12 @@ private:
|
|||||||
class CLibrary : public ILibrary
|
class CLibrary : public ILibrary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CLibrary(LibraryHandle me);
|
CLibrary(ke::RefPtr<ke::SharedLib> lib);
|
||||||
~CLibrary();
|
|
||||||
public:
|
public:
|
||||||
void CloseLibrary();
|
void CloseLibrary() override;
|
||||||
void *GetSymbolAddress(const char *symname);
|
void *GetSymbolAddress(const char *symname) override;
|
||||||
private:
|
private:
|
||||||
LibraryHandle m_lib;
|
ke::RefPtr<ke::SharedLib> lib_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LibrarySystem : public ILibrarySys
|
class LibrarySystem : public ILibrarySys
|
||||||
@ -96,7 +90,6 @@ public:
|
|||||||
bool CreateFolder(const char *path);
|
bool CreateFolder(const char *path);
|
||||||
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
|
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
|
||||||
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
|
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
|
||||||
void GetLoaderError(char *buffer, size_t maxlength);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern LibrarySystem g_LibSys;
|
extern LibrarySystem g_LibSys;
|
@ -34,13 +34,12 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <sourcemod_version.h>
|
#include <sourcemod_version.h>
|
||||||
#include <ISourceMod.h>
|
#include <ISourceMod.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <ILibrarySys.h>
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
|
|
||||||
Logger g_Logger;
|
Logger g_Logger;
|
||||||
|
|
||||||
/**
|
|
||||||
* :TODO: This should be creating the log folder if it doesn't exist
|
|
||||||
*/
|
|
||||||
|
|
||||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||||
const char *value,
|
const char *value,
|
||||||
ConfigSource source,
|
ConfigSource source,
|
||||||
@ -57,7 +56,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|||||||
} else if (strcasecmp(value, "off") == 0) {
|
} else if (strcasecmp(value, "off") == 0) {
|
||||||
state = false;
|
state = false;
|
||||||
} else {
|
} else {
|
||||||
smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||||
return ConfigResult_Reject;
|
return ConfigResult_Reject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|||||||
{
|
{
|
||||||
state ? EnableLogging() : DisableLogging();
|
state ? EnableLogging() : DisableLogging();
|
||||||
} else {
|
} else {
|
||||||
m_InitialState = state;
|
m_Active = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConfigResult_Accept;
|
return ConfigResult_Accept;
|
||||||
@ -78,7 +77,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|||||||
} else if (strcasecmp(value, "game") == 0) {
|
} else if (strcasecmp(value, "game") == 0) {
|
||||||
m_Mode = LoggingMode_Game;
|
m_Mode = LoggingMode_Game;
|
||||||
} else {
|
} else {
|
||||||
smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]");
|
ke::SafeStrcpy(error, maxlength, "Invalid value: must be [daily|map|game]");
|
||||||
return ConfigResult_Reject;
|
return ConfigResult_Reject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +89,12 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|||||||
|
|
||||||
void Logger::OnSourceModStartup(bool late)
|
void Logger::OnSourceModStartup(bool late)
|
||||||
{
|
{
|
||||||
InitLogger(m_Mode);
|
char buff[PLATFORM_MAX_PATH];
|
||||||
|
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs");
|
||||||
|
if (!libsys->IsPathDirectory(buff))
|
||||||
|
{
|
||||||
|
libsys->CreateFolder(buff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::OnSourceModAllShutdown()
|
void Logger::OnSourceModAllShutdown()
|
||||||
@ -100,127 +104,7 @@ void Logger::OnSourceModAllShutdown()
|
|||||||
|
|
||||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
void Logger::OnSourceModLevelChange(const char *mapName)
|
||||||
{
|
{
|
||||||
MapChange(mapName);
|
_MapChange(mapName);
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::_NewMapFile()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append "Log file closed" to previous log file */
|
|
||||||
_CloseFile();
|
|
||||||
|
|
||||||
char _filename[256];
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
|
||||||
FILE *fp = fopen(_filename, "r");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
|
|
||||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
libsys->GetPlatformError(error, sizeof(error));
|
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
return;
|
|
||||||
} 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, SOURCEMOD_VERSION);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::_CloseFile()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = NULL;
|
|
||||||
if (!m_NrmFileName.empty())
|
|
||||||
{
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
LogMessage("Log file closed.");
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
m_NrmFileName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_ErrMapStart)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
LogError("Error log file session closed.");
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
m_ErrFileName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::InitLogger(LoggingMode mode)
|
|
||||||
{
|
|
||||||
m_Mode = mode;
|
|
||||||
m_Active = m_InitialState;
|
|
||||||
|
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
m_NrmCurDay = curtime->tm_mday;
|
|
||||||
m_ErrCurDay = curtime->tm_mday;
|
|
||||||
|
|
||||||
char _filename[256];
|
|
||||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
|
|
||||||
switch (m_Mode)
|
|
||||||
{
|
|
||||||
case LoggingMode_PerMap:
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
m_DelayedStart = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LoggingMode_Daily:
|
|
||||||
{
|
|
||||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_DailyPrintHdr = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* do nothing... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::CloseLogger()
|
void Logger::CloseLogger()
|
||||||
@ -228,6 +112,13 @@ void Logger::CloseLogger()
|
|||||||
_CloseFile();
|
_CloseFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::_CloseFile()
|
||||||
|
{
|
||||||
|
_CloseNormal();
|
||||||
|
_CloseError();
|
||||||
|
_CloseFatal();
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
||||||
{
|
{
|
||||||
if (!m_Active)
|
if (!m_Active)
|
||||||
@ -256,15 +147,10 @@ void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
|||||||
|
|
||||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
if (!m_Active)
|
static ConVar *sv_logecho = bridge->FindConVar("sv_logecho");
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
|
|
||||||
|
|
||||||
char buffer[3072];
|
char buffer[3072];
|
||||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
|
||||||
|
|
||||||
char date[32];
|
char date[32];
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
@ -273,30 +159,27 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
|||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||||
|
|
||||||
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
|
if (!sv_logecho || bridge->GetCvarBool(sv_logecho))
|
||||||
{
|
{
|
||||||
static char conBuffer[4096];
|
static char conBuffer[4096];
|
||||||
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
|
ke::SafeSprintf(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
|
||||||
smcore.ConPrint(conBuffer);
|
bridge->ConPrint(conBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fflush(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[3072];
|
char buffer[3072];
|
||||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
|
||||||
|
|
||||||
char date[32];
|
char date[32];
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
tm *curtime = localtime(&t);
|
tm *curtime = localtime(&t);
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||||
|
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,63 +204,14 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_DelayedStart)
|
FILE *pFile = _OpenNormal();
|
||||||
|
if (!pFile)
|
||||||
{
|
{
|
||||||
m_DelayedStart = false;
|
|
||||||
_NewMapFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
FILE *fp = NULL;
|
|
||||||
if (m_Mode == LoggingMode_PerMap)
|
|
||||||
{
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
_NewMapFile();
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
goto print_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (m_NrmCurDay != curtime->tm_mday)
|
|
||||||
{
|
|
||||||
char _filename[256];
|
|
||||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_NrmCurDay = curtime->tm_mday;
|
|
||||||
m_DailyPrintHdr = true;
|
|
||||||
}
|
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
if (m_DailyPrintHdr)
|
|
||||||
{
|
|
||||||
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, SOURCEMOD_VERSION);
|
|
||||||
}
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
fclose(fp);
|
|
||||||
} else {
|
|
||||||
goto print_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
print_error:
|
}
|
||||||
char error[255];
|
|
||||||
libsys->GetPlatformError(error, sizeof(error));
|
LogToOpenFileEx(pFile, vafmt, ap);
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
fclose(pFile);
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogError(const char *vafmt, ...)
|
void Logger::LogError(const char *vafmt, ...)
|
||||||
@ -395,72 +229,20 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t t = g_pSM->GetAdjustedTime();
|
FILE *pFile = _OpenError();
|
||||||
tm *curtime = localtime(&t);
|
if (!pFile)
|
||||||
|
|
||||||
if (curtime->tm_mday != m_ErrCurDay)
|
|
||||||
{
|
{
|
||||||
char _filename[256];
|
|
||||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
m_ErrCurDay = curtime->tm_mday;
|
|
||||||
m_ErrMapStart = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
if (!m_ErrMapStart)
|
|
||||||
{
|
|
||||||
char date[32];
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
libsys->GetPlatformError(error, sizeof(error));
|
|
||||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
|
||||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
|
||||||
LogFatal("[SM] Logging has been disabled.");
|
|
||||||
m_Active = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogToOpenFileEx(pFile, vafmt, ap);
|
||||||
|
fclose(pFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::MapChange(const char *mapname)
|
void Logger::_MapChange(const char *mapname)
|
||||||
{
|
{
|
||||||
m_CurMapName.assign(mapname);
|
m_CurrentMapName = mapname;
|
||||||
|
_UpdateFiles(true);
|
||||||
switch (m_Mode)
|
|
||||||
{
|
|
||||||
case LoggingMode_Daily:
|
|
||||||
{
|
|
||||||
LogMessage("-------- Mapchange to %s --------", mapname);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LoggingMode_PerMap:
|
|
||||||
{
|
|
||||||
_NewMapFile();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* Do nothing... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ErrMapStart)
|
|
||||||
{
|
|
||||||
LogError("Error log file session closed.");
|
|
||||||
}
|
|
||||||
m_ErrMapStart = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
||||||
@ -474,31 +256,7 @@ void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
|||||||
msg[len++] = '\n';
|
msg[len++] = '\n';
|
||||||
msg[len] = '\0';
|
msg[len] = '\0';
|
||||||
|
|
||||||
smcore.LogToGame(msg);
|
bridge->LogToGame(msg);
|
||||||
}
|
|
||||||
|
|
||||||
const char *Logger::GetLogFileName(LogType type) const
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case LogType_Normal:
|
|
||||||
{
|
|
||||||
return m_NrmFileName.c_str();
|
|
||||||
}
|
|
||||||
case LogType_Error:
|
|
||||||
{
|
|
||||||
return m_ErrFileName.c_str();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingMode Logger::GetLoggingMode() const
|
|
||||||
{
|
|
||||||
return m_Mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::EnableLogging()
|
void Logger::EnableLogging()
|
||||||
@ -536,16 +294,161 @@ void Logger::LogFatalEx(const char *msg, va_list ap)
|
|||||||
* It's already implemented twice which is bad.
|
* It's already implemented twice which is bad.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
FILE *pFile = _OpenFatal();
|
||||||
|
if (!pFile)
|
||||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
|
||||||
|
|
||||||
FILE *fp = fopen(path, "at");
|
|
||||||
if (fp)
|
|
||||||
{
|
{
|
||||||
m_Active = true;
|
return;
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
}
|
||||||
m_Active = false;
|
|
||||||
fclose(fp);
|
LogToOpenFileEx(pFile, msg, ap);
|
||||||
|
fclose(pFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::_UpdateFiles(bool bLevelChange)
|
||||||
|
{
|
||||||
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
|
tm *curtime = localtime(&t);
|
||||||
|
|
||||||
|
if (!bLevelChange && curtime->tm_mday == m_Day)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Day = curtime->tm_mday;
|
||||||
|
|
||||||
|
char buff[PLATFORM_MAX_PATH];
|
||||||
|
ke::SafeSprintf(buff, sizeof(buff), "%04d%02d%02d", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||||
|
|
||||||
|
ke::AString currentDate(buff);
|
||||||
|
|
||||||
|
if (m_Mode == LoggingMode_PerMap)
|
||||||
|
{
|
||||||
|
if (bLevelChange)
|
||||||
|
{
|
||||||
|
for (size_t iter = 0; iter < static_cast<size_t>(-1); ++iter)
|
||||||
|
{
|
||||||
|
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s%u.log", currentDate.chars(), iter);
|
||||||
|
if (!libsys->IsPathFile(buff))
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(buff, sizeof(buff), m_NormalFileName.chars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s.log", currentDate.chars());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_NormalFileName.compare(buff))
|
||||||
|
{
|
||||||
|
_CloseNormal();
|
||||||
|
m_NormalFileName = buff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bLevelChange)
|
||||||
|
{
|
||||||
|
LogMessage("-------- Mapchange to %s --------", m_CurrentMapName.chars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/errors_%s.log", currentDate.chars());
|
||||||
|
if (bLevelChange || m_ErrorFileName.compare(buff))
|
||||||
|
{
|
||||||
|
_CloseError();
|
||||||
|
m_ErrorFileName = buff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *Logger::_OpenNormal()
|
||||||
|
{
|
||||||
|
_UpdateFiles();
|
||||||
|
|
||||||
|
FILE *pFile = fopen(m_NormalFileName.chars(), "a+");
|
||||||
|
if (pFile == NULL)
|
||||||
|
{
|
||||||
|
_LogFatalOpen(m_NormalFileName);
|
||||||
|
return pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_DamagedNormalFile)
|
||||||
|
{
|
||||||
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
|
tm *curtime = localtime(&t);
|
||||||
|
char date[32];
|
||||||
|
|
||||||
|
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||||
|
fprintf(pFile, "L %s: SourceMod log file session started (file \"%s\") (Version \"%s\")\n", date, m_NormalFileName.chars(), SOURCEMOD_VERSION);
|
||||||
|
m_DamagedNormalFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *Logger::_OpenError()
|
||||||
|
{
|
||||||
|
_UpdateFiles();
|
||||||
|
|
||||||
|
FILE *pFile = fopen(m_ErrorFileName.chars(), "a+");
|
||||||
|
if (pFile == NULL)
|
||||||
|
{
|
||||||
|
_LogFatalOpen(m_ErrorFileName);
|
||||||
|
return pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_DamagedErrorFile)
|
||||||
|
{
|
||||||
|
time_t t = g_pSM->GetAdjustedTime();
|
||||||
|
tm *curtime = localtime(&t);
|
||||||
|
|
||||||
|
char date[32];
|
||||||
|
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||||
|
fprintf(pFile, "L %s: SourceMod error session started\n", date);
|
||||||
|
fprintf(pFile, "L %s: Info (map \"%s\") (file \"%s\")\n", date, m_CurrentMapName.chars(), m_ErrorFileName.chars());
|
||||||
|
m_DamagedErrorFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *Logger::_OpenFatal()
|
||||||
|
{
|
||||||
|
char path[PLATFORM_MAX_PATH];
|
||||||
|
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||||
|
return fopen(path, "at");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::_LogFatalOpen(ke::AString &str)
|
||||||
|
{
|
||||||
|
char error[255];
|
||||||
|
libsys->GetPlatformError(error, sizeof(error));
|
||||||
|
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", str.chars());
|
||||||
|
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::_CloseNormal()
|
||||||
|
{
|
||||||
|
if (m_DamagedNormalFile)
|
||||||
|
{
|
||||||
|
LogMessage("Log file closed.");
|
||||||
|
m_DamagedNormalFile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::_CloseError()
|
||||||
|
{
|
||||||
|
if (m_DamagedErrorFile)
|
||||||
|
{
|
||||||
|
LogError("Error log file session closed.");
|
||||||
|
m_DamagedErrorFile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::_CloseFatal()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -32,12 +32,10 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
|
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
|
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
#include <stdio.h>
|
||||||
using namespace SourceHook;
|
#include <amtl/am-string.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
enum LogType
|
enum LogType
|
||||||
{
|
{
|
||||||
@ -55,9 +53,7 @@ enum LoggingMode
|
|||||||
class Logger : public SMGlobalClass, public ILogger
|
class Logger : public SMGlobalClass, public ILogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
Logger() : m_Day(-1), m_Mode(LoggingMode_Daily), m_Active(true), m_DamagedNormalFile(false), m_DamagedErrorFile(false)
|
||||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
|
||||||
m_InitialState(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
@ -70,7 +66,6 @@ public: //SMGlobalClass
|
|||||||
void OnSourceModAllShutdown();
|
void OnSourceModAllShutdown();
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
void OnSourceModLevelChange(const char *mapName);
|
||||||
public:
|
public:
|
||||||
void InitLogger(LoggingMode mode);
|
|
||||||
void CloseLogger();
|
void CloseLogger();
|
||||||
void EnableLogging();
|
void EnableLogging();
|
||||||
void DisableLogging();
|
void DisableLogging();
|
||||||
@ -85,25 +80,32 @@ public:
|
|||||||
/* This version does not print to console, and is thus thread-safe */
|
/* This version does not print to console, and is thus thread-safe */
|
||||||
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
||||||
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
||||||
void MapChange(const char *mapname);
|
|
||||||
const char *GetLogFileName(LogType type) const;
|
|
||||||
LoggingMode GetLoggingMode() const;
|
|
||||||
private:
|
private:
|
||||||
|
void _MapChange(const char *mapname);
|
||||||
|
|
||||||
void _CloseFile();
|
void _CloseFile();
|
||||||
void _NewMapFile();
|
void _CloseNormal();
|
||||||
|
void _CloseError();
|
||||||
|
void _CloseFatal();
|
||||||
|
|
||||||
|
FILE *_OpenNormal();
|
||||||
|
FILE *_OpenError();
|
||||||
|
FILE *_OpenFatal();
|
||||||
|
|
||||||
|
void _LogFatalOpen(ke::AString &str);
|
||||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
void _PrintToGameLog(const char *fmt, va_list ap);
|
||||||
|
void _UpdateFiles(bool bLevelChange = false);
|
||||||
private:
|
private:
|
||||||
String m_NrmFileName;
|
ke::AString m_NormalFileName;
|
||||||
String m_ErrFileName;
|
ke::AString m_ErrorFileName;
|
||||||
String m_CurMapName;
|
ke::AString m_CurrentMapName;
|
||||||
|
|
||||||
|
int m_Day;
|
||||||
|
|
||||||
LoggingMode m_Mode;
|
LoggingMode m_Mode;
|
||||||
int m_NrmCurDay;
|
|
||||||
int m_ErrCurDay;
|
|
||||||
bool m_ErrMapStart;
|
|
||||||
bool m_Active;
|
bool m_Active;
|
||||||
bool m_DelayedStart;
|
bool m_DamagedNormalFile;
|
||||||
bool m_DailyPrintHdr;
|
bool m_DamagedErrorFile;
|
||||||
bool m_InitialState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Logger g_Logger;
|
extern Logger g_Logger;
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
# (C)2004-2008 SourceMod Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMSDK = ../..
|
|
||||||
MMSOURCE17 = ../../../mmsource-1.7
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
#####################################
|
|
||||||
|
|
||||||
BINARY = sourcemod.logic.so
|
|
||||||
|
|
||||||
OBJECTS = \
|
|
||||||
common_logic.cpp \
|
|
||||||
smn_adt_array.cpp \
|
|
||||||
smn_sorting.cpp \
|
|
||||||
smn_maplists.cpp \
|
|
||||||
smn_adt_stack.cpp \
|
|
||||||
thread/ThreadWorker.cpp \
|
|
||||||
thread/BaseWorker.cpp \
|
|
||||||
thread/PosixThreads.cpp \
|
|
||||||
ThreadSupport.cpp \
|
|
||||||
smn_float.cpp \
|
|
||||||
TextParsers.cpp \
|
|
||||||
smn_textparse.cpp \
|
|
||||||
smn_adt_trie.cpp \
|
|
||||||
Profiler.cpp \
|
|
||||||
smn_functions.cpp \
|
|
||||||
sm_crc32.cpp \
|
|
||||||
smn_timers.cpp \
|
|
||||||
MemoryUtils.cpp \
|
|
||||||
smn_admin.cpp \
|
|
||||||
smn_banning.cpp \
|
|
||||||
stringutil.cpp \
|
|
||||||
Translator.cpp \
|
|
||||||
PhraseCollection.cpp \
|
|
||||||
smn_lang.cpp \
|
|
||||||
smn_string.cpp \
|
|
||||||
smn_handles.cpp \
|
|
||||||
smn_datapacks.cpp \
|
|
||||||
smn_gameconfigs.cpp \
|
|
||||||
GameConfigs.cpp \
|
|
||||||
smn_players.cpp \
|
|
||||||
smn_profiler.cpp
|
|
||||||
|
|
||||||
##############################################
|
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
|
||||||
##############################################
|
|
||||||
|
|
||||||
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
|
|
||||||
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
|
|
||||||
C_GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
CPP = gcc
|
|
||||||
|
|
||||||
LINK += -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE += -I. -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
|
||||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
|
|
||||||
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 \
|
|
||||||
-DSM_LOGIC
|
|
||||||
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
################################################
|
|
||||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
|
||||||
################################################
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug
|
|
||||||
CFLAGS += $(C_DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release
|
|
||||||
CFLAGS += $(C_OPT_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
|
||||||
CFLAGS += $(C_GCC4_FLAGS)
|
|
||||||
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
|
||||||
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.cpp
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.c
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
all:
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
|
||||||
$(MAKE) -f Makefile sourcemod
|
|
||||||
|
|
||||||
sourcemod: $(OBJ_LINUX)
|
|
||||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o $(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) -f Makefile all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(BIN_DIR)/*.o
|
|
||||||
rm -rf $(BIN_DIR)/thread/*.o
|
|
||||||
rm -rf $(BIN_DIR)/$(BINARY)
|
|
@ -43,18 +43,6 @@
|
|||||||
#include <mach-o/dyld_images.h>
|
#include <mach-o/dyld_images.h>
|
||||||
#include <mach-o/loader.h>
|
#include <mach-o/loader.h>
|
||||||
#include <mach-o/nlist.h>
|
#include <mach-o/nlist.h>
|
||||||
|
|
||||||
/* Define things from 10.6 SDK for older SDKs */
|
|
||||||
#ifndef MAC_OS_X_VERSION_10_6
|
|
||||||
struct task_dyld_info
|
|
||||||
{
|
|
||||||
mach_vm_address_t all_image_info_addr;
|
|
||||||
mach_vm_size_t all_image_info_size;
|
|
||||||
};
|
|
||||||
typedef struct task_dyld_info task_dyld_info_data_t;
|
|
||||||
#define TASK_DYLD_INFO 17
|
|
||||||
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
|
|
||||||
#endif // MAC_OS_X_VERSION_10_6
|
|
||||||
#endif // PLATFORM_APPLE
|
#endif // PLATFORM_APPLE
|
||||||
|
|
||||||
MemoryUtils g_MemUtils;
|
MemoryUtils g_MemUtils;
|
||||||
@ -63,25 +51,10 @@ MemoryUtils::MemoryUtils()
|
|||||||
{
|
{
|
||||||
#ifdef PLATFORM_APPLE
|
#ifdef PLATFORM_APPLE
|
||||||
|
|
||||||
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
|
|
||||||
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
|
|
||||||
|
|
||||||
/* Get pointer to struct that describes all loaded mach-o images in process */
|
|
||||||
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
|
|
||||||
{
|
|
||||||
task_dyld_info_data_t dyld_info;
|
task_dyld_info_data_t dyld_info;
|
||||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct nlist list[2];
|
|
||||||
memset(list, 0, sizeof(list));
|
|
||||||
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
|
|
||||||
nlist("/usr/lib/dyld", list);
|
|
||||||
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -147,13 +120,25 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
|
typedef Elf32_Ehdr ElfHeader;
|
||||||
|
typedef Elf32_Shdr ElfSHeader;
|
||||||
|
typedef Elf32_Sym ElfSymbol;
|
||||||
|
#define ELF_SYM_TYPE ELF32_ST_TYPE
|
||||||
|
#else
|
||||||
|
typedef Elf64_Ehdr ElfHeader;
|
||||||
|
typedef Elf64_Shdr ElfSHeader;
|
||||||
|
typedef Elf64_Sym ElfSymbol;
|
||||||
|
#define ELF_SYM_TYPE ELF64_ST_TYPE
|
||||||
|
#endif
|
||||||
|
|
||||||
struct link_map *dlmap;
|
struct link_map *dlmap;
|
||||||
struct stat dlstat;
|
struct stat dlstat;
|
||||||
int dlfile;
|
int dlfile;
|
||||||
uintptr_t map_base;
|
uintptr_t map_base;
|
||||||
Elf32_Ehdr *file_hdr;
|
ElfHeader *file_hdr;
|
||||||
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
ElfSHeader *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||||
Elf32_Sym *symtab;
|
ElfSymbol *symtab;
|
||||||
const char *shstrtab, *strtab;
|
const char *shstrtab, *strtab;
|
||||||
uint16_t section_count;
|
uint16_t section_count;
|
||||||
uint32_t symbol_count;
|
uint32_t symbol_count;
|
||||||
@ -204,7 +189,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Map library file into memory */
|
/* Map library file into memory */
|
||||||
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
file_hdr = (ElfHeader *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||||
map_base = (uintptr_t)file_hdr;
|
map_base = (uintptr_t)file_hdr;
|
||||||
if (file_hdr == MAP_FAILED)
|
if (file_hdr == MAP_FAILED)
|
||||||
{
|
{
|
||||||
@ -219,7 +204,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
|
sections = (ElfSHeader *)(map_base + file_hdr->e_shoff);
|
||||||
section_count = file_hdr->e_shnum;
|
section_count = file_hdr->e_shnum;
|
||||||
/* Get ELF section header string table */
|
/* Get ELF section header string table */
|
||||||
shstrtab_hdr = §ions[file_hdr->e_shstrndx];
|
shstrtab_hdr = §ions[file_hdr->e_shstrndx];
|
||||||
@ -228,7 +213,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
/* Iterate sections while looking for ELF symbol table and string table */
|
/* Iterate sections while looking for ELF symbol table and string table */
|
||||||
for (uint16_t i = 0; i < section_count; i++)
|
for (uint16_t i = 0; i < section_count; i++)
|
||||||
{
|
{
|
||||||
Elf32_Shdr &hdr = sections[i];
|
ElfSHeader &hdr = sections[i];
|
||||||
const char *section_name = shstrtab + hdr.sh_name;
|
const char *section_name = shstrtab + hdr.sh_name;
|
||||||
|
|
||||||
if (strcmp(section_name, ".symtab") == 0)
|
if (strcmp(section_name, ".symtab") == 0)
|
||||||
@ -248,15 +233,15 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
|
symtab = (ElfSymbol *)(map_base + symtab_hdr->sh_offset);
|
||||||
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
|
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
|
||||||
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
||||||
|
|
||||||
/* Iterate symbol table starting from the position we were at last time */
|
/* Iterate symbol table starting from the position we were at last time */
|
||||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||||
{
|
{
|
||||||
Elf32_Sym &sym = symtab[i];
|
ElfSymbol &sym = symtab[i];
|
||||||
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
|
unsigned char sym_type = ELF_SYM_TYPE(sym.st_info);
|
||||||
const char *sym_name = strtab + sym.st_name;
|
const char *sym_name = strtab + sym.st_name;
|
||||||
Symbol *cur_sym;
|
Symbol *cur_sym;
|
||||||
|
|
||||||
@ -281,13 +266,28 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
|
|
||||||
#elif defined PLATFORM_APPLE
|
#elif defined PLATFORM_APPLE
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
|
typedef struct mach_header MachHeader;
|
||||||
|
typedef struct segment_command MachSegment;
|
||||||
|
typedef struct nlist MachSymbol;
|
||||||
|
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||||
|
#else
|
||||||
|
typedef struct mach_header_64 MachHeader;
|
||||||
|
typedef struct segment_command_64 MachSegment;
|
||||||
|
typedef struct nlist_64 MachSymbol;
|
||||||
|
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct load_command MachLoadCmd;
|
||||||
|
typedef struct symtab_command MachSymHeader;
|
||||||
|
|
||||||
uintptr_t dlbase, linkedit_addr;
|
uintptr_t dlbase, linkedit_addr;
|
||||||
uint32_t image_count;
|
uint32_t image_count;
|
||||||
struct mach_header *file_hdr;
|
MachHeader *file_hdr;
|
||||||
struct load_command *loadcmds;
|
MachLoadCmd *loadcmds;
|
||||||
struct segment_command *linkedit_hdr;
|
MachSegment *linkedit_hdr;
|
||||||
struct symtab_command *symtab_hdr;
|
MachSymHeader *symtab_hdr;
|
||||||
struct nlist *symtab;
|
MachSymbol *symtab;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
uint32_t loadcmd_count;
|
uint32_t loadcmd_count;
|
||||||
uint32_t symbol_count;
|
uint32_t symbol_count;
|
||||||
@ -357,16 +357,16 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
|
|
||||||
/* If symbol isn't in our table, then we have to locate it in memory */
|
/* If symbol isn't in our table, then we have to locate it in memory */
|
||||||
|
|
||||||
file_hdr = (struct mach_header *)dlbase;
|
file_hdr = (MachHeader *)dlbase;
|
||||||
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
|
loadcmds = (MachLoadCmd *)(dlbase + sizeof(MachHeader));
|
||||||
loadcmd_count = file_hdr->ncmds;
|
loadcmd_count = file_hdr->ncmds;
|
||||||
|
|
||||||
/* Loop through load commands until we find the ones for the symbol table */
|
/* Loop through load commands until we find the ones for the symbol table */
|
||||||
for (uint32_t i = 0; i < loadcmd_count; i++)
|
for (uint32_t i = 0; i < loadcmd_count; i++)
|
||||||
{
|
{
|
||||||
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
|
if (loadcmds->cmd == MACH_LOADCMD_SEGMENT && !linkedit_hdr)
|
||||||
{
|
{
|
||||||
struct segment_command *seg = (struct segment_command *)loadcmds;
|
MachSegment *seg = (MachSegment *)loadcmds;
|
||||||
if (strcmp(seg->segname, "__LINKEDIT") == 0)
|
if (strcmp(seg->segname, "__LINKEDIT") == 0)
|
||||||
{
|
{
|
||||||
linkedit_hdr = seg;
|
linkedit_hdr = seg;
|
||||||
@ -378,7 +378,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
}
|
}
|
||||||
else if (loadcmds->cmd == LC_SYMTAB)
|
else if (loadcmds->cmd == LC_SYMTAB)
|
||||||
{
|
{
|
||||||
symtab_hdr = (struct symtab_command *)loadcmds;
|
symtab_hdr = (MachSymHeader *)loadcmds;
|
||||||
if (linkedit_hdr)
|
if (linkedit_hdr)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -386,7 +386,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load commands are not of a fixed size which is why we add the size */
|
/* Load commands are not of a fixed size which is why we add the size */
|
||||||
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
loadcmds = (MachLoadCmd *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
|
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
|
||||||
@ -396,14 +396,14 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
|
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
|
||||||
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
symtab = (MachSymbol *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||||
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
|
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
|
||||||
symbol_count = symtab_hdr->nsyms;
|
symbol_count = symtab_hdr->nsyms;
|
||||||
|
|
||||||
/* Iterate symbol table starting from the position we were at last time */
|
/* Iterate symbol table starting from the position we were at last time */
|
||||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||||
{
|
{
|
||||||
struct nlist &sym = symtab[i];
|
MachSymbol &sym = symtab[i];
|
||||||
/* Ignore the prepended underscore on all symbols, so +1 here */
|
/* Ignore the prepended underscore on all symbols, so +1 here */
|
||||||
const char *sym_name = strtab + sym.n_un.n_strx + 1;
|
const char *sym_name = strtab + sym.n_un.n_strx + 1;
|
||||||
Symbol *cur_sym;
|
Symbol *cur_sym;
|
||||||
@ -440,6 +440,12 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
|
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
|
||||||
|
#else
|
||||||
|
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
|
||||||
|
#endif
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
MEMORY_BASIC_INFORMATION info;
|
||||||
IMAGE_DOS_HEADER *dos;
|
IMAGE_DOS_HEADER *dos;
|
||||||
IMAGE_NT_HEADERS *pe;
|
IMAGE_NT_HEADERS *pe;
|
||||||
@ -465,10 +471,8 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check architecture, which is 32-bit/x86 right now
|
/* Check architecture */
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
if (file->Machine != PE_FILE_MACHINE)
|
||||||
*/
|
|
||||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -484,9 +488,21 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
|
typedef Elf32_Ehdr ElfHeader;
|
||||||
|
typedef Elf32_Phdr ElfPHeader;
|
||||||
|
const unsigned char ELF_CLASS = ELFCLASS32;
|
||||||
|
const uint16_t ELF_MACHINE = EM_386;
|
||||||
|
#else
|
||||||
|
typedef Elf64_Ehdr ElfHeader;
|
||||||
|
typedef Elf64_Phdr ElfPHeader;
|
||||||
|
const unsigned char ELF_CLASS = ELFCLASS64;
|
||||||
|
const uint16_t ELF_MACHINE = EM_X86_64;
|
||||||
|
#endif
|
||||||
|
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
Elf32_Ehdr *file;
|
ElfHeader *file;
|
||||||
Elf32_Phdr *phdr;
|
ElfPHeader *phdr;
|
||||||
uint16_t phdrCount;
|
uint16_t phdrCount;
|
||||||
|
|
||||||
if (!dladdr(libPtr, &info))
|
if (!dladdr(libPtr, &info))
|
||||||
@ -501,7 +517,7 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
|
|
||||||
/* This is for our insane sanity checks :o */
|
/* This is for our insane sanity checks :o */
|
||||||
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
|
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
|
||||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
file = reinterpret_cast<ElfHeader *>(baseAddr);
|
||||||
|
|
||||||
/* Check ELF magic */
|
/* Check ELF magic */
|
||||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
||||||
@ -515,10 +531,14 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
/* Check ELF endianness */
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
if (file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
*/
|
{
|
||||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check ELF architecture */
|
||||||
|
if (file->e_ident[EI_CLASS] != ELF_CLASS || file->e_machine != ELF_MACHINE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -530,11 +550,11 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
}
|
}
|
||||||
|
|
||||||
phdrCount = file->e_phnum;
|
phdrCount = file->e_phnum;
|
||||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
phdr = reinterpret_cast<ElfPHeader *>(baseAddr + file->e_phoff);
|
||||||
|
|
||||||
for (uint16_t i = 0; i < phdrCount; i++)
|
for (uint16_t i = 0; i < phdrCount; i++)
|
||||||
{
|
{
|
||||||
Elf32_Phdr &hdr = phdr[i];
|
ElfPHeader &hdr = phdr[i];
|
||||||
|
|
||||||
/* We only really care about the segment with executable code */
|
/* We only really care about the segment with executable code */
|
||||||
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
||||||
@ -553,9 +573,25 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
|
|
||||||
#elif defined PLATFORM_APPLE
|
#elif defined PLATFORM_APPLE
|
||||||
|
|
||||||
|
#ifdef PLATFORM_X86
|
||||||
|
typedef struct mach_header MachHeader;
|
||||||
|
typedef struct segment_command MachSegment;
|
||||||
|
const uint32_t MACH_MAGIC = MH_MAGIC;
|
||||||
|
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||||
|
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_I386;
|
||||||
|
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_I386_ALL;
|
||||||
|
#else
|
||||||
|
typedef struct mach_header_64 MachHeader;
|
||||||
|
typedef struct segment_command_64 MachSegment;
|
||||||
|
const uint32_t MACH_MAGIC = MH_MAGIC_64;
|
||||||
|
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||||
|
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_X86_64;
|
||||||
|
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_X86_64_ALL;
|
||||||
|
#endif
|
||||||
|
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
struct mach_header *file;
|
MachHeader *file;
|
||||||
struct segment_command *seg;
|
MachSegment *seg;
|
||||||
uint32_t cmd_count;
|
uint32_t cmd_count;
|
||||||
|
|
||||||
if (!dladdr(libPtr, &info))
|
if (!dladdr(libPtr, &info))
|
||||||
@ -570,16 +606,16 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
|
|
||||||
/* This is for our insane sanity checks :o */
|
/* This is for our insane sanity checks :o */
|
||||||
baseAddr = (uintptr_t)info.dli_fbase;
|
baseAddr = (uintptr_t)info.dli_fbase;
|
||||||
file = (struct mach_header *)baseAddr;
|
file = (MachHeader *)baseAddr;
|
||||||
|
|
||||||
/* Check Mach-O magic */
|
/* Check Mach-O magic */
|
||||||
if (file->magic != MH_MAGIC)
|
if (file->magic != MACH_MAGIC)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check architecture (32-bit/x86) */
|
/* Check architecture */
|
||||||
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
|
if (file->cputype != MACH_CPU_TYPE || file->cpusubtype != MACH_CPU_SUBTYPE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -591,17 +627,17 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd_count = file->ncmds;
|
cmd_count = file->ncmds;
|
||||||
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
|
seg = (MachSegment *)(baseAddr + sizeof(MachHeader));
|
||||||
|
|
||||||
/* Add up memory sizes of mapped segments */
|
/* Add up memory sizes of mapped segments */
|
||||||
for (uint32_t i = 0; i < cmd_count; i++)
|
for (uint32_t i = 0; i < cmd_count; i++)
|
||||||
{
|
{
|
||||||
if (seg->cmd == LC_SEGMENT)
|
if (seg->cmd == MACH_LOADCMD_SEGMENT)
|
||||||
{
|
{
|
||||||
lib.memorySize += seg->vmsize;
|
lib.memorySize += seg->vmsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
|
seg = (MachSegment *)((uintptr_t)seg + seg->cmdsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,11 +33,15 @@
|
|||||||
|
|
||||||
#include <IShareSys.h>
|
#include <IShareSys.h>
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
|
#include <am-autoptr.h>
|
||||||
#include <am-string.h>
|
#include <am-string.h>
|
||||||
#include <am-utility.h>
|
#include <am-utility.h>
|
||||||
#include <am-refcounting.h>
|
#include <am-refcounting.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
|
||||||
|
class CNativeOwner;
|
||||||
|
|
||||||
struct FakeNative
|
struct FakeNative
|
||||||
{
|
{
|
||||||
FakeNative(const char *name, IPluginFunction *fun)
|
FakeNative(const char *name, IPluginFunction *fun)
|
||||||
@ -87,10 +91,14 @@ struct Native : public ke::Refcounted<Native>
|
|||||||
return fake->name.chars();
|
return fake->name.chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool matches(const char *name, const ke::Ref<Native> &entry)
|
static inline bool matches(const char *name, const ke::RefPtr<Native> &entry)
|
||||||
{
|
{
|
||||||
return strcmp(name, entry->name()) == 0;
|
return strcmp(name, entry->name()) == 0;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,96 +1,53 @@
|
|||||||
/**
|
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||||
* vim: set ts=4 sw=4 tw=99 noet :
|
//
|
||||||
* =============================================================================
|
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||||
* SourcePawn
|
//
|
||||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||||
* =============================================================================
|
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||||
*
|
// License as published by the Free Software Foundation, either version 3 of
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
// the License, or (at your option) any later version.
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
//
|
||||||
* Free Software Foundation.
|
// You should have received a copy of the GNU General Public License along with
|
||||||
*
|
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||||
* 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "NativeInvoker.h"
|
#include "NativeInvoker.h"
|
||||||
#include "ShareSys.h"
|
|
||||||
|
|
||||||
NativeInterface g_NInvoke;
|
/********************
|
||||||
|
* FUNCTION CALLING *
|
||||||
|
********************/
|
||||||
|
|
||||||
NativeInvoker::NativeInvoker()
|
NativeInvoker::NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native)
|
||||||
|
: context_(pContext),
|
||||||
|
m_curparam(0),
|
||||||
|
m_errorstate(SP_ERROR_NONE),
|
||||||
|
native_(native)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeInvoker::~NativeInvoker()
|
NativeInvoker::~NativeInvoker()
|
||||||
{
|
{
|
||||||
|
Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *NativeInterface::GetInterfaceName()
|
bool
|
||||||
|
NativeInvoker::IsRunnable()
|
||||||
{
|
{
|
||||||
return SMINTERFACE_NINVOKE_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NativeInterface::GetInterfaceVersion()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_NINVOKE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeInterface::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ke::Ref<Native> entry = g_ShareSys.FindNative(name);
|
|
||||||
if (!entry)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!entry->owner)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
native_ = entry->func();
|
|
||||||
context_ = pContext;
|
|
||||||
|
|
||||||
m_curparam = 0;
|
|
||||||
m_errorstate = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t NativeInvoker::PushCell(cell_t cell)
|
IPluginContext *
|
||||||
|
NativeInvoker::GetParentContext()
|
||||||
|
{
|
||||||
|
return context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NativeInvoker::PushCell(cell_t cell)
|
||||||
{
|
{
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||||
{
|
|
||||||
return SetError(SP_ERROR_PARAMS_MAX);
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
}
|
|
||||||
|
|
||||||
m_info[m_curparam].marked = false;
|
m_info[m_curparam].marked = false;
|
||||||
m_params[m_curparam] = cell;
|
m_params[m_curparam] = cell;
|
||||||
@ -99,24 +56,28 @@ cell_t NativeInvoker::PushCell(cell_t cell)
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
|
int
|
||||||
|
NativeInvoker::PushCellByRef(cell_t *cell, int flags)
|
||||||
{
|
{
|
||||||
return PushArray(cell, 1, flags);
|
return PushArray(cell, 1, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::PushFloat(float number)
|
int
|
||||||
|
NativeInvoker::PushFloat(float number)
|
||||||
{
|
{
|
||||||
cell_t val = *(cell_t *)&number;
|
cell_t val = sp::FloatCellUnion(number).cell;
|
||||||
|
|
||||||
return PushCell(val);
|
return PushCell(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::PushFloatByRef(float *number, int flags)
|
int
|
||||||
|
NativeInvoker::PushFloatByRef(float *number, int flags)
|
||||||
{
|
{
|
||||||
return PushCellByRef((cell_t *)number, flags);
|
return PushCellByRef((cell_t *)number, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
|
int
|
||||||
|
NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
|
||||||
{
|
{
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||||
{
|
{
|
||||||
@ -136,22 +97,23 @@ int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::PushString(const char *string)
|
int
|
||||||
|
NativeInvoker::PushString(const char *string)
|
||||||
{
|
{
|
||||||
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
|
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)
|
int
|
||||||
|
NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
|
||||||
{
|
{
|
||||||
return _PushString(buffer, sz_flags, cp_flags, length);
|
return _PushString(buffer, sz_flags, cp_flags, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
|
int
|
||||||
|
NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
|
||||||
{
|
{
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||||
{
|
|
||||||
return SetError(SP_ERROR_PARAMS_MAX);
|
return SetError(SP_ERROR_PARAMS_MAX);
|
||||||
}
|
|
||||||
|
|
||||||
ParamInfo *info = &m_info[m_curparam];
|
ParamInfo *info = &m_info[m_curparam];
|
||||||
|
|
||||||
@ -167,52 +129,67 @@ int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, s
|
|||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeInvoker::Cancel()
|
void
|
||||||
|
NativeInvoker::Cancel()
|
||||||
{
|
{
|
||||||
if (context_ == NULL)
|
if (!m_curparam)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_errorstate = SP_ERROR_NONE;
|
m_errorstate = SP_ERROR_NONE;
|
||||||
m_curparam = 0;
|
m_curparam = 0;
|
||||||
context_ = NULL;
|
|
||||||
native_ = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::SetError(int err)
|
int
|
||||||
|
NativeInvoker::Execute(cell_t *result, cell_t buffer, cell_t size)
|
||||||
{
|
{
|
||||||
m_errorstate = err;
|
context_->ClearLastNativeError();
|
||||||
return err;
|
|
||||||
|
// For backward compatibility, we have to clear the exception state.
|
||||||
|
// Otherwise code like this:
|
||||||
|
//
|
||||||
|
// static cell_t native(cx, params) {
|
||||||
|
// for (auto callback : callbacks) {
|
||||||
|
// callback->Execute();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Could unintentionally leak a pending exception back to the caller,
|
||||||
|
// which wouldn't have happened before the Great Exception Refactoring.
|
||||||
|
|
||||||
|
SourcePawn::ExceptionHandler eh(context_);
|
||||||
|
eh.Debug(!size);
|
||||||
|
|
||||||
|
if (!Invoke(result)) {
|
||||||
|
if(size)
|
||||||
|
context_->StringToLocalUTF8(buffer, size, eh.Message(), NULL);
|
||||||
|
int Err = context_->GetLastNativeError();
|
||||||
|
context_->ClearLastNativeError();
|
||||||
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeInvoker::Invoke(cell_t *result)
|
return SP_ERROR_NONE;
|
||||||
{
|
}
|
||||||
int err = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
if (context_ == NULL)
|
bool
|
||||||
return SP_ERROR_INVALID_NATIVE;
|
NativeInvoker::Invoke(cell_t *result)
|
||||||
|
|
||||||
if (m_errorstate != SP_ERROR_NONE)
|
|
||||||
{
|
{
|
||||||
err = m_errorstate;
|
if (!IsRunnable()) {
|
||||||
Cancel();
|
Cancel();
|
||||||
return err;
|
context_->ReportErrorNumber(SP_ERROR_NOT_RUNNABLE);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
if (int err = m_errorstate) {
|
||||||
cell_t tresult;
|
Cancel();
|
||||||
|
context_->ReportErrorNumber(err);
|
||||||
if (result == NULL)
|
return false;
|
||||||
{
|
|
||||||
result = &tresult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is for re-entrancy!
|
//This is for re-entrancy!
|
||||||
IPluginContext *ctx = context_;
|
|
||||||
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
|
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
|
||||||
cell_t *temp_params = &_temp_params[1];
|
cell_t *temp_params = &_temp_params[1];
|
||||||
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||||
unsigned int numparams = m_curparam;
|
unsigned int numparams = m_curparam;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool docopies = true;
|
|
||||||
|
|
||||||
if (numparams)
|
if (numparams)
|
||||||
{
|
{
|
||||||
@ -220,59 +197,55 @@ int NativeInvoker::Invoke(cell_t *result)
|
|||||||
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
|
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
|
||||||
}
|
}
|
||||||
m_curparam = 0;
|
m_curparam = 0;
|
||||||
context_ = NULL;
|
|
||||||
|
|
||||||
/* Initialize 0th parameter */
|
/* Initialize 0th parameter */
|
||||||
_temp_params[0] = numparams;
|
_temp_params[0] = numparams;
|
||||||
|
|
||||||
/* Browse the parameters and build arrays */
|
/* Browse the parameters and build arrays */
|
||||||
for (i = 0; i < numparams; i++)
|
bool ok = true;
|
||||||
{
|
for (i=0; i<numparams; i++) {
|
||||||
/* Is this marked as an array? */
|
/* Is this marked as an array? */
|
||||||
if (temp_info[i].marked)
|
if (temp_info[i].marked) {
|
||||||
{
|
if (!temp_info[i].str.is_sz) {
|
||||||
if (!temp_info[i].str.is_sz)
|
|
||||||
{
|
|
||||||
/* Allocate a normal/generic array */
|
/* Allocate a normal/generic array */
|
||||||
if ((err = ctx->HeapAlloc(temp_info[i].size,
|
int err = context_->HeapAlloc(
|
||||||
&temp_info[i].local_addr,
|
temp_info[i].size,
|
||||||
&temp_info[i].phys_addr))
|
&(temp_info[i].local_addr),
|
||||||
!= SP_ERROR_NONE)
|
&(temp_info[i].phys_addr));
|
||||||
{
|
if (err != SP_ERROR_NONE) {
|
||||||
|
context_->ReportErrorNumber(err);
|
||||||
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (temp_info[i].orig_addr)
|
if (temp_info[i].orig_addr)
|
||||||
{
|
{
|
||||||
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
|
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Calculate cells required for the string */
|
/* Calculate cells required for the string */
|
||||||
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
||||||
|
|
||||||
/* Allocate the buffer */
|
/* Allocate the buffer */
|
||||||
if ((err = ctx->HeapAlloc(cells,
|
int err = context_->HeapAlloc(
|
||||||
&temp_info[i].local_addr,
|
cells,
|
||||||
&temp_info[i].phys_addr))
|
&(temp_info[i].local_addr),
|
||||||
!= SP_ERROR_NONE)
|
&(temp_info[i].phys_addr));
|
||||||
{
|
if (err != SP_ERROR_NONE) {
|
||||||
|
context_->ReportErrorNumber(err);
|
||||||
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy original string if necessary */
|
/* Copy original string if necessary */
|
||||||
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
|
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
|
||||||
{
|
{
|
||||||
/* Cut off UTF-8 properly */
|
/* Cut off UTF-8 properly */
|
||||||
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) {
|
||||||
{
|
context_->StringToLocalUTF8(
|
||||||
if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
|
temp_info[i].local_addr,
|
||||||
temp_info[i].size,
|
temp_info[i].size,
|
||||||
(const char *)temp_info[i].orig_addr,
|
(const char *)temp_info[i].orig_addr,
|
||||||
NULL))
|
NULL);
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Copy a binary blob */
|
/* Copy a binary blob */
|
||||||
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
|
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
|
||||||
@ -282,66 +255,42 @@ int NativeInvoker::Invoke(cell_t *result)
|
|||||||
/* Copy ASCII characters */
|
/* Copy ASCII characters */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((err = ctx->StringToLocal(temp_info[i].local_addr,
|
context_->StringToLocal(
|
||||||
|
temp_info[i].local_addr,
|
||||||
temp_info[i].size,
|
temp_info[i].size,
|
||||||
(const char *)temp_info[i].orig_addr))
|
(const char *)temp_info[i].orig_addr);
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* End array/string calculation */
|
} /* End array/string calculation */
|
||||||
/* Update the pushed parameter with the byref local address */
|
/* Update the pushed parameter with the byref local address */
|
||||||
temp_params[i] = temp_info[i].local_addr;
|
temp_params[i] = temp_info[i].local_addr;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Just copy the value normally */
|
/* Just copy the value normally */
|
||||||
temp_params[i] = m_params[i];
|
temp_params[i] = m_params[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the call if we can */
|
/* Make the call if we can */
|
||||||
if (err == SP_ERROR_NONE)
|
if (ok)
|
||||||
{
|
{
|
||||||
*result = native_(ctx, _temp_params);
|
*result = native_->func()(context_, _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 */
|
/* i should be equal to the last valid parameter + 1 */
|
||||||
while (i--)
|
bool docopies = ok;
|
||||||
{
|
while (i--) {
|
||||||
if (!temp_info[i].marked)
|
if (!temp_info[i].marked)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
|
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) {
|
||||||
{
|
if (temp_info[i].orig_addr) {
|
||||||
if (temp_info[i].orig_addr)
|
if (temp_info[i].str.is_sz) {
|
||||||
{
|
|
||||||
if (temp_info[i].str.is_sz)
|
|
||||||
{
|
|
||||||
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
|
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
if (temp_info[i].size == 1) {
|
||||||
{
|
|
||||||
if (temp_info[i].size == 1)
|
|
||||||
{
|
|
||||||
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
|
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(temp_info[i].orig_addr,
|
memcpy(temp_info[i].orig_addr,
|
||||||
temp_info[i].phys_addr,
|
temp_info[i].phys_addr,
|
||||||
temp_info[i].size * sizeof(cell_t));
|
temp_info[i].size * sizeof(cell_t));
|
||||||
@ -350,11 +299,23 @@ int NativeInvoker::Invoke(cell_t *result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
|
if (int err = context_->HeapPop(temp_info[i].local_addr))
|
||||||
|
context_->ReportErrorNumber(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context_->GetLastNativeError() == SP_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
NativeInvoker::SetError(int err)
|
||||||
{
|
{
|
||||||
return err;
|
m_errorstate = err;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NativeInvoker::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
|
||||||
|
funcid_t NativeInvoker::GetFunctionID() { return 0; }
|
||||||
|
int NativeInvoker::Execute2(IPluginContext *ctx, cell_t *result) { return 0; }
|
||||||
|
int NativeInvoker::CallFunction2(IPluginContext *ctx, const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
|
||||||
|
IPluginRuntime *NativeInvoker::GetParentRuntime() { return NULL; }
|
||||||
|
@ -1,43 +1,22 @@
|
|||||||
/**
|
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||||
* vim: set ts=4 :
|
//
|
||||||
* =============================================================================
|
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||||
* SourceMod
|
//
|
||||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||||
* =============================================================================
|
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||||
*
|
// License as published by the Free Software Foundation, either version 3 of
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
// the License, or (at your option) any later version.
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
//
|
||||||
* Free Software Foundation.
|
// You should have received a copy of the GNU General Public License along with
|
||||||
*
|
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||||
* 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_
|
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||||
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||||
|
|
||||||
#include <sp_vm_api.h>
|
#include <sp_vm_api.h>
|
||||||
#include <INativeInvoker.h>
|
#include <amtl/am-autoptr.h>
|
||||||
#include "common_logic.h"
|
#include <amtl/am-refcounting.h>
|
||||||
|
#include "Native.h"
|
||||||
using namespace SourceMod;
|
|
||||||
using namespace SourcePawn;
|
|
||||||
|
|
||||||
struct ParamInfo
|
struct ParamInfo
|
||||||
{
|
{
|
||||||
@ -47,56 +26,54 @@ struct ParamInfo
|
|||||||
cell_t *phys_addr; /* Physical address of our copy */
|
cell_t *phys_addr; /* Physical address of our copy */
|
||||||
cell_t *orig_addr; /* Original address to copy back to */
|
cell_t *orig_addr; /* Original address to copy back to */
|
||||||
ucell_t size; /* Size of array in bytes */
|
ucell_t size; /* Size of array in bytes */
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
bool is_sz; /* is a string */
|
bool is_sz; /* is a string */
|
||||||
int sz_flags; /* has sz flags */
|
int sz_flags; /* has sz flags */
|
||||||
} str;
|
} str;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeInvoker : public INativeInvoker
|
class NativeInvoker : public IPluginFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NativeInvoker();
|
NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native);
|
||||||
~NativeInvoker();
|
virtual ~NativeInvoker();
|
||||||
public: /* ICallable */
|
|
||||||
|
public:
|
||||||
int PushCell(cell_t cell);
|
int PushCell(cell_t cell);
|
||||||
int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
|
int PushCellByRef(cell_t *cell, int flags);
|
||||||
int PushFloat(float number);
|
int PushFloat(float number);
|
||||||
int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
|
int PushFloatByRef(float *number, int flags);
|
||||||
int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
|
int PushArray(cell_t *inarray, unsigned int cells, int copyback);
|
||||||
int PushString(const char *string);
|
int PushString(const char *string);
|
||||||
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
|
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
|
||||||
|
int Execute(cell_t *result, cell_t buffer=0, cell_t size=0);
|
||||||
void Cancel();
|
void Cancel();
|
||||||
public: /* INativeInvoker */
|
int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
|
||||||
bool Start(IPluginContext *pContext, const char *name);
|
IPluginContext *GetParentContext();
|
||||||
int Invoke(cell_t *result);
|
bool Invoke(cell_t *result);
|
||||||
|
bool IsRunnable();
|
||||||
|
funcid_t GetFunctionID();
|
||||||
|
int Execute2(IPluginContext *ctx, cell_t *result);
|
||||||
|
int CallFunction2(IPluginContext *ctx,
|
||||||
|
const cell_t *params,
|
||||||
|
unsigned int num_params,
|
||||||
|
cell_t *result);
|
||||||
|
IPluginRuntime *GetParentRuntime();
|
||||||
|
const char *DebugName() {
|
||||||
|
return native_->name();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
||||||
int SetError(int err);
|
int SetError(int err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPluginContext *context_;
|
IPluginContext *context_;
|
||||||
SPVM_NATIVE_FUNC native_;
|
|
||||||
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
||||||
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
||||||
unsigned int m_curparam;
|
unsigned int m_curparam;
|
||||||
int m_errorstate;
|
int m_errorstate;
|
||||||
|
ke::RefPtr<Native> native_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeInterface :
|
#endif //_INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||||
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_ */
|
|
||||||
|
@ -48,6 +48,7 @@ unsigned int CNativeOwner::GetMarkSerial()
|
|||||||
|
|
||||||
void CNativeOwner::AddDependent(CPlugin *pPlugin)
|
void CNativeOwner::AddDependent(CPlugin *pPlugin)
|
||||||
{
|
{
|
||||||
|
if (m_Dependents.find(pPlugin) == m_Dependents.end())
|
||||||
m_Dependents.push_back(pPlugin);
|
m_Dependents.push_back(pPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,31 +65,16 @@ void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
|
|||||||
m_natives.append(natives);
|
m_natives.append(natives);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNativeOwner::PropagateMarkSerial(unsigned int serial)
|
|
||||||
{
|
|
||||||
CNativeOwner *pOwner;
|
|
||||||
List<CPlugin *>::iterator iter;
|
|
||||||
|
|
||||||
for (iter = m_Dependents.begin();
|
|
||||||
iter != m_Dependents.end();
|
|
||||||
iter++)
|
|
||||||
{
|
|
||||||
pOwner = (*iter);
|
|
||||||
pOwner->SetMarkSerial(serial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
|
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
|
||||||
{
|
{
|
||||||
sp_native_t *native;
|
|
||||||
IPluginContext *pContext;
|
IPluginContext *pContext;
|
||||||
|
|
||||||
pContext = ref.pl->GetBaseContext();
|
pContext = ref.pl->GetBaseContext();
|
||||||
if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
|
pContext->GetRuntime()->UpdateNativeBinding(
|
||||||
{
|
ref.idx,
|
||||||
native->status = SP_NATIVE_UNBOUND;
|
nullptr,
|
||||||
native->pfn = NULL;
|
SP_NTVFLAG_OPTIONAL,
|
||||||
}
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNativeOwner::DropEverything()
|
void CNativeOwner::DropEverything()
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <am-vector.h>
|
#include <am-vector.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include "Native.h"
|
#include "Native.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
struct Native;
|
struct Native;
|
||||||
class CPlugin;
|
class CPlugin;
|
||||||
@ -68,7 +69,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
void SetMarkSerial(unsigned int serial);
|
void SetMarkSerial(unsigned int serial);
|
||||||
unsigned int GetMarkSerial();
|
unsigned int GetMarkSerial();
|
||||||
void PropagateMarkSerial(unsigned int serial);
|
|
||||||
public:
|
public:
|
||||||
void AddDependent(CPlugin *pPlugin);
|
void AddDependent(CPlugin *pPlugin);
|
||||||
void AddWeakRef(const WeakNative & ref);
|
void AddWeakRef(const WeakNative & ref);
|
||||||
@ -81,7 +81,7 @@ protected:
|
|||||||
unsigned int m_nMarkSerial;
|
unsigned int m_nMarkSerial;
|
||||||
List<WeakNative> m_WeakRefs;
|
List<WeakNative> m_WeakRefs;
|
||||||
ke::Vector<const sp_nativeinfo_t *> m_natives;
|
ke::Vector<const sp_nativeinfo_t *> m_natives;
|
||||||
ke::Vector<ke::Ref<Native> > m_fakes;
|
ke::Vector<ke::RefPtr<Native> > m_fakes;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CNativeOwner g_CoreNatives;
|
extern CNativeOwner g_CoreNatives;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user