Compare commits
3778
Commits
| 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 | ||
|
|
7304747f79 | ||
|
|
17fcd5a37f | ||
|
|
d413a6bd2f | ||
|
|
154d84668b | ||
|
|
01f4b204c9 | ||
|
|
f40bfbf762 | ||
|
|
ccf5aa6b54 | ||
|
|
032dde7be9 | ||
|
|
2d5b71c832 | ||
|
|
58194c5d99 | ||
|
|
8272151d78 | ||
|
|
844fad263a | ||
|
|
1b79252947 | ||
|
|
bc4d6b7104 | ||
|
|
46839b9752 | ||
|
|
e250eb66d1 | ||
|
|
20ed5c338c | ||
|
|
b4199e5aa3 | ||
|
|
b60ef1669c | ||
|
|
7e8473b61a | ||
|
|
ed87e048b4 | ||
|
|
0d67bcc5ba | ||
|
|
03abafce3d | ||
|
|
67fcd9e2c6 | ||
|
|
bab1110bc0 | ||
|
|
d51a57cc34 | ||
|
|
de12f64c14 | ||
|
|
b1cb06c5ce | ||
|
|
88cb74213c | ||
|
|
5a814c40b3 | ||
|
|
1328984e0b | ||
|
|
722a23c818 | ||
|
|
5959d6ed54 | ||
|
|
28eb663f9b | ||
|
|
939b10bd8e | ||
|
|
b607bfeca9 | ||
|
|
f9d92b0eba | ||
|
|
61bf7de101 | ||
|
|
5b69efe5d4 | ||
|
|
afeae84340 | ||
|
|
46d620cb6a | ||
|
|
0295f817b8 | ||
|
|
18cc1b414b | ||
|
|
a9e252314d | ||
|
|
bc4081718b | ||
|
|
1ee3067575 | ||
|
|
94bed806fe | ||
|
|
9c98edd104 | ||
|
|
0375aedd47 | ||
|
|
09060c265f | ||
|
|
8a8917ba2e | ||
|
|
f27c33cd18 | ||
|
|
d2e01da287 | ||
|
|
3ef2bdcb8d | ||
|
|
25859e29ca | ||
|
|
a91d5bf754 | ||
|
|
68e0645813 | ||
|
|
cb4fdf1aa9 | ||
|
|
157549e119 | ||
|
|
9f5c8b60ae | ||
|
|
e7e43e38a5 | ||
|
|
19f2f46655 | ||
|
|
50898d7a4f | ||
|
|
ced026cecc | ||
|
|
62c243f0a5 | ||
|
|
b0ceac9d74 | ||
|
|
673ff572c5 | ||
|
|
f573bdf784 | ||
|
|
b7036de9e9 | ||
|
|
08388de7dd | ||
|
|
be6da2f810 | ||
|
|
f38fd6a550 | ||
|
|
0511543c76 | ||
|
|
db434acd27 | ||
|
|
50400cf029 | ||
|
|
b85f4d776e | ||
|
|
79143d8b6e | ||
|
|
f25953bb6c | ||
|
|
461dc3af3d | ||
|
|
5e362ec169 | ||
|
|
e46d5d211d | ||
|
|
758a7c955c | ||
|
|
4cb29eb054 | ||
|
|
d3a4c972e2 | ||
|
|
1cf43b4ec2 | ||
|
|
a369d51f23 | ||
|
|
849df7895b | ||
|
|
ea86eee74e | ||
|
|
f42a1fe0e4 | ||
|
|
5a9b5e5e21 | ||
|
|
1562530cdd | ||
|
|
cd304dc800 | ||
|
|
93470fbdc6 | ||
|
|
f55bc6719d | ||
|
|
d6533e3219 | ||
|
|
cfa0d9341e | ||
|
|
2cfe54f34b | ||
|
|
4a66b67d81 | ||
|
|
110440988d | ||
|
|
4a14b776db | ||
|
|
fb5b552f86 | ||
|
|
614fa86311 | ||
|
|
9980930dff | ||
|
|
e68c228a36 | ||
|
|
8fd0cbecf7 | ||
|
|
c425305cde | ||
|
|
59fbeb4f2c | ||
|
|
d68eea6dea | ||
|
|
86d4cdc0c4 | ||
|
|
16330d1c4c | ||
|
|
65dfd3cdd1 | ||
|
|
9886eea487 | ||
|
|
affff9eeb7 | ||
|
|
6b714dafe3 | ||
|
|
801b7ec9e2 | ||
|
|
4bc7b9243a | ||
|
|
8479c2f067 | ||
|
|
53a1dbdafd | ||
|
|
4802d4bae2 | ||
|
|
6e045ef43c | ||
|
|
f3fcdeda9d | ||
|
|
c37174cb97 | ||
|
|
22df518ab5 | ||
|
|
c228be83d6 | ||
|
|
046f167b6e | ||
|
|
099f299113 | ||
|
|
4c377f21f9 | ||
|
|
704e9579f7 | ||
|
|
686cf9c5ba | ||
|
|
7609d19e32 | ||
|
|
6ba4bcb955 | ||
|
|
3cc5c198b4 | ||
|
|
919a31df57 | ||
|
|
cd0ac3ae37 | ||
|
|
17b9ee91e6 | ||
|
|
f020b5682e | ||
|
|
78687080b1 | ||
|
|
f16501d34a | ||
|
|
3c13c87f1c | ||
|
|
b7c4faf063 | ||
|
|
0d24804839 | ||
|
|
dbee1bcd08 | ||
|
|
512cbc73a0 | ||
|
|
039572060e | ||
|
|
f08e53f5d2 | ||
|
|
6d507ceb27 | ||
|
|
70e095f320 | ||
|
|
a8796543af | ||
|
|
2c31b99ce3 | ||
|
|
9175c081ee | ||
|
|
b89bd36335 | ||
|
|
3579977b28 | ||
|
|
21ea3c03b5 | ||
|
|
e7ec41e872 | ||
|
|
b76c948c95 | ||
|
|
159f2c8335 | ||
|
|
66bfd126b2 | ||
|
|
e7f6a99087 | ||
|
|
89e7d1c45c | ||
|
|
b2e957db83 | ||
|
|
67f9069382 | ||
|
|
3fff07b33d | ||
|
|
87a21c7ff8 | ||
|
|
a463ed5cf2 | ||
|
|
0f9d2203a4 | ||
|
|
89f6e4736f | ||
|
|
04578dfee9 | ||
|
|
7f36ef65a9 | ||
|
|
286d484207 | ||
|
|
cdc2b11a09 | ||
|
|
c7109ca651 | ||
|
|
8c8d9b072a | ||
|
|
9c6c0f37ed | ||
|
|
613b06f6c0 | ||
|
|
97c3a2bc6e | ||
|
|
91a863c20c | ||
|
|
b97335ccb0 | ||
|
|
67d839e568 | ||
|
|
5484f35dfb | ||
|
|
749bf80bcb | ||
|
|
0a545b12a4 | ||
|
|
eaff5c9364 | ||
|
|
f0dd129344 | ||
|
|
749701014d | ||
|
|
10cee734dc | ||
|
|
72c18cc3d9 | ||
|
|
350dd2ebc7 | ||
|
|
5d78a5ff93 | ||
|
|
c15470b583 | ||
|
|
e5eb291b67 | ||
|
|
7ddced67cb | ||
|
|
a7303568d6 | ||
|
|
e7fc06910b | ||
|
|
86ddf1fea0 | ||
|
|
c9696ca230 | ||
|
|
4dcc1590bb | ||
|
|
585786b465 | ||
|
|
3ec1b3a271 | ||
|
|
de045b5ab6 | ||
|
|
9021b23bc2 | ||
|
|
dca15ebabf | ||
|
|
5874709407 | ||
|
|
ba0d41a69d | ||
|
|
76d26044f6 | ||
|
|
75335dbef3 | ||
|
|
6bd1285d66 | ||
|
|
f8ffe23c6e | ||
|
|
77dc5ac7ed | ||
|
|
37c29775d4 | ||
|
|
5ce46e1537 | ||
|
|
a580f8c270 | ||
|
|
d702371b15 | ||
|
|
a3336b1dcf | ||
|
|
bba2a714a6 | ||
|
|
512fae4c25 | ||
|
|
d76f62b863 | ||
|
|
2aba6d9d42 | ||
|
|
f2a80e33fd | ||
|
|
ac96bb177a | ||
|
|
909d523da0 | ||
|
|
02aad65d21 | ||
|
|
0a9cabdecd | ||
|
|
9eb1b3e73e | ||
|
|
0f6063af60 | ||
|
|
d4fb74ef9a | ||
|
|
55a5c745d4 | ||
|
|
a80e049352 | ||
|
|
981ffdfc82 | ||
|
|
3ffd4cd835 | ||
|
|
570570f7a0 | ||
|
|
e72ff963f5 | ||
|
|
af273e8e66 | ||
|
|
a82dd5e0c3 | ||
|
|
e4569cb2b9 | ||
|
|
47450bb98c | ||
|
|
c62e7458f9 | ||
|
|
d493bc701d | ||
|
|
f0fe427fee | ||
|
|
7f0b163b31 | ||
|
|
49c22a404d | ||
|
|
e6fd19fb8c | ||
|
|
96f8d635c3 | ||
|
|
9a9446400d | ||
|
|
8a1c6bd833 | ||
|
|
e0c25cfe08 | ||
|
|
6d7115d62f | ||
|
|
96fbb7ecda | ||
|
|
775a35c5ab | ||
|
|
9e6fcc7673 | ||
|
|
acdd9e12ea | ||
|
|
a597277a64 | ||
|
|
b3dada65fa | ||
|
|
8a9a793453 | ||
|
|
d1aa9a3513 | ||
|
|
06f52aa7ce | ||
|
|
60eb8ca4bd | ||
|
|
5b85f41fec | ||
|
|
cd4978d60e | ||
|
|
07acec6550 | ||
|
|
66ab609000 | ||
|
|
29d428adc2 | ||
|
|
5b1caec738 | ||
|
|
ad7d920ce0 | ||
|
|
7fff73ad64 | ||
|
|
215bbb8324 | ||
|
|
1bf4eb80bd | ||
|
|
f1dc24c089 | ||
|
|
892edd9650 | ||
|
|
ec46e12c50 | ||
|
|
37638ba6fd | ||
|
|
8da4179c64 | ||
|
|
a1dc1101f7 | ||
|
|
a00adaf9fb | ||
|
|
8686957dee | ||
|
|
e6e90fb8b8 | ||
|
|
6068d341c8 | ||
|
|
105cd27d19 | ||
|
|
e608057304 | ||
|
|
448c55c0f2 | ||
|
|
a7cdf17d90 | ||
|
|
b2b82f4a86 | ||
|
|
6da7219f9f | ||
|
|
7f3656215b | ||
|
|
be55587d70 | ||
|
|
40b1067ef7 | ||
|
|
01d1c0c806 | ||
|
|
3fba1d2817 | ||
|
|
e6ff9c36ed | ||
|
|
e11fec9ba1 | ||
|
|
d0c701793c | ||
|
|
eafd6626ec | ||
|
|
e3b87a5ca4 | ||
|
|
8c89b72fbc | ||
|
|
cae1d0dec1 | ||
|
|
88c6d3d9a7 | ||
|
|
e9e35979a4 | ||
|
|
9d337dd1a9 | ||
|
|
e093c7f72a | ||
|
|
ac121ec4d2 | ||
|
|
b81c44cf49 | ||
|
|
a136049392 | ||
|
|
a1b7c32b29 | ||
|
|
302dc1cb8a | ||
|
|
6db4f31a10 | ||
|
|
63e5ab18ff | ||
|
|
d230711e4d | ||
|
|
74908098f4 | ||
|
|
078ee76491 | ||
|
|
98ec07a419 | ||
|
|
c4056aea5d | ||
|
|
7a51d5d549 | ||
|
|
89f5d6ecfb | ||
|
|
9267d0c803 | ||
|
|
0cf8eb2854 | ||
|
|
d20ba38d6b | ||
|
|
4d42fa0305 | ||
|
|
860a5db5ea | ||
|
|
666b6b97ee | ||
|
|
d562593d31 | ||
|
|
27c3866b90 | ||
|
|
50f3ec8da2 | ||
|
|
f42651a813 | ||
|
|
91f0f1001b | ||
|
|
51d32bca77 | ||
|
|
9d6fea857b | ||
|
|
8d60fecb96 | ||
|
|
73115f7afa | ||
|
|
b95e7ff145 | ||
|
|
e1158889e5 | ||
|
|
a09735a4c7 | ||
|
|
6291374b35 | ||
|
|
dcd246c7ef | ||
|
|
29fbbade69 | ||
|
|
48d228e2b1 | ||
|
|
4608050bd2 | ||
|
|
234b4907ed | ||
|
|
9c005d93ed | ||
|
|
3eb1faa470 | ||
|
|
142fbaafdd | ||
|
|
afd6009fda | ||
|
|
3e8157c6bc | ||
|
|
2ba4fb180e | ||
|
|
261188fd1b | ||
|
|
5a4c50ce55 | ||
|
|
c70543839f | ||
|
|
f5efdbf6f5 | ||
|
|
25241fa278 | ||
|
|
225954a27c | ||
|
|
3e1495d692 | ||
|
|
5716927cbf | ||
|
|
09250f89cc | ||
|
|
233aa5d2df | ||
|
|
1f51393e26 | ||
|
|
d91d69f72e | ||
|
|
96a73eb86f | ||
|
|
e5e2c1fa3d | ||
|
|
942a3cd155 | ||
|
|
8dc4fcc728 | ||
|
|
385d3708a3 | ||
|
|
5cf2475e2e | ||
|
|
9f2a0f6748 | ||
|
|
e9ba251c1c | ||
|
|
e4645332aa | ||
|
|
56cf6e723e | ||
|
|
cef9d9d162 | ||
|
|
1ca837ea2c | ||
|
|
2037cfc36d | ||
|
|
8ffdfb6a0c | ||
|
|
766b6e1770 | ||
|
|
31087dcb57 | ||
|
|
d873b20573 | ||
|
|
486910a9a1 | ||
|
|
17d5af0e2f | ||
|
|
f570fa414b | ||
|
|
4b8e26463a | ||
|
|
b92efc1df1 | ||
|
|
25f8570279 | ||
|
|
901890e36d | ||
|
|
0bde28cc17 | ||
|
|
2ba0b794ea | ||
|
|
7a88386568 | ||
|
|
4e5b1a58ce | ||
|
|
3edd1ce658 | ||
|
|
84e5e20362 | ||
|
|
dfba8757f7 | ||
|
|
15304a0059 | ||
|
|
ccc818d06e | ||
|
|
000cb2b4dd | ||
|
|
ad376ff0b8 | ||
|
|
09edda93ad | ||
|
|
bfcfbbe107 | ||
|
|
f2b19e6c87 | ||
|
|
836cde4e21 | ||
|
|
14823723bd | ||
|
|
601aac440e | ||
|
|
573aea20fb | ||
|
|
5e7e7ce551 | ||
|
|
c116353285 | ||
|
|
678e743819 | ||
|
|
ff5ec0ea28 | ||
|
|
8d5fe316e0 | ||
|
|
c4a1e3c819 | ||
|
|
ab72841704 | ||
|
|
75d5b0c972 | ||
|
|
dd7a1764e4 | ||
|
|
eab6ac748f | ||
|
|
b979d707db | ||
|
|
4a400d9569 | ||
|
|
ba0406930d | ||
|
|
be79dee6e0 | ||
|
|
97610edda4 | ||
|
|
803a54b773 | ||
|
|
fad5c590b6 | ||
|
|
2553d02698 | ||
|
|
da71cfed5a | ||
|
|
34e57b77b1 | ||
|
|
fa446f74a1 | ||
|
|
94b64cd6fc | ||
|
|
abcd106273 | ||
|
|
97e821dd6f | ||
|
|
6e48ded1a6 | ||
|
|
1cc6120741 | ||
|
|
2a46f8f881 | ||
|
|
3fc05056b0 | ||
|
|
f41b3a2b06 | ||
|
|
654dcd8ff0 | ||
|
|
6a2ec15041 | ||
|
|
59efdafbaf | ||
|
|
f3671e55db | ||
|
|
b6d8cb9fcf | ||
|
|
2a99eecdb6 | ||
|
|
57303f4310 | ||
|
|
88c614c1ba | ||
|
|
b1c400190a | ||
|
|
686890ec10 | ||
|
|
8aa28e2c8d | ||
|
|
16177e9ecc | ||
|
|
2b74f1bd61 | ||
|
|
5daa420aed | ||
|
|
d2c7064e2b | ||
|
|
4051756576 | ||
|
|
51f97d1298 | ||
|
|
8436a3ea6c | ||
|
|
b0e98b16ec | ||
|
|
7948755b3b | ||
|
|
f79f5df5ab | ||
|
|
b84b70d0f1 | ||
|
|
beeb848724 | ||
|
|
805b66e539 | ||
|
|
8125faeb70 | ||
|
|
84344c1592 | ||
|
|
ac371aa639 | ||
|
|
1181144e57 | ||
|
|
3a2f2e621d | ||
|
|
9c6b82f3a5 | ||
|
|
2ea9ec50b5 | ||
|
|
58a3cb4a06 | ||
|
|
a8a64cabee | ||
|
|
71fb0d1d18 | ||
|
|
cd6997cd0b | ||
|
|
5dd5b5131b | ||
|
|
1a83ca57fc | ||
|
|
21d3a7f93e | ||
|
|
294fdee1e6 | ||
|
|
3d3e5c40c2 | ||
|
|
9e1fef9775 | ||
|
|
b0bfec0f8f | ||
|
|
919e859a6d | ||
|
|
c47cfa6fa8 | ||
|
|
c38b4a4d1d | ||
|
|
44b2b02a1e | ||
|
|
31a79231f8 | ||
|
|
d4c676aed2 | ||
|
|
0b5e587db9 | ||
|
|
f7a64167fc | ||
|
|
3a94bd4fef | ||
|
|
d9420cab49 | ||
|
|
226c0a456d | ||
|
|
1e0155ad17 | ||
|
|
aa299d187b | ||
|
|
02b7f42811 | ||
|
|
e76f553957 | ||
|
|
d2b7126e1d | ||
|
|
3fe22687e9 | ||
|
|
2ade122cd2 | ||
|
|
e57a323dc8 | ||
|
|
af791a30df | ||
|
|
ff31d8df49 | ||
|
|
8e5992685a | ||
|
|
af557fdd5e | ||
|
|
27d5ce45f5 | ||
|
|
44316d63cc | ||
|
|
97e0c84e6d | ||
|
|
76edcb16ac | ||
|
|
63aeeb8672 | ||
|
|
312f003031 | ||
|
|
dbedd6712a | ||
|
|
f18a83e03e | ||
|
|
1277bbd50e | ||
|
|
a7de88dd42 | ||
|
|
e5b1b630bb | ||
|
|
db9ee5326a | ||
|
|
9ae3256bc0 | ||
|
|
a7342f3fa2 | ||
|
|
49380620e0 | ||
|
|
9ff38bcf80 | ||
|
|
fc54903fd0 | ||
|
|
68ab7f0a12 | ||
|
|
fece28935e | ||
|
|
6864bf0068 | ||
|
|
3c079bcca0 | ||
|
|
3f220bca0d | ||
|
|
96bbd4d7e0 | ||
|
|
da33c79d8b | ||
|
|
bfc65b086a | ||
|
|
680a8e0283 | ||
|
|
0e4b913312 | ||
|
|
f62769108c | ||
|
|
9a2bdd3792 | ||
|
|
386b178ef3 | ||
|
|
79d9a49d28 | ||
|
|
376eb9725e | ||
|
|
5d753c2697 | ||
|
|
1c41f905f9 | ||
|
|
dfa9a8f134 | ||
|
|
49eee8c04e | ||
|
|
58b9fd57b2 | ||
|
|
7e770908fb | ||
|
|
3cf9e56a19 | ||
|
|
ffa1887c48 | ||
|
|
878a82a6e5 | ||
|
|
19815d42c3 | ||
|
|
966841afbd | ||
|
|
e1d4ed0e34 | ||
|
|
cde927112a | ||
|
|
3254f6f362 | ||
|
|
932a8028ca | ||
|
|
bdb5ef506b | ||
|
|
d25ab6349c | ||
|
|
438fade64f | ||
|
|
a15153e9b8 | ||
|
|
ed4cca0225 | ||
|
|
86cd906371 | ||
|
|
cb46de97e1 | ||
|
|
153bbba641 | ||
|
|
e46c49abe0 | ||
|
|
10c8b78a16 | ||
|
|
db98c98a1a | ||
|
|
d4f4a7eed0 | ||
|
|
e6f6e6df70 | ||
|
|
eeba5b93c5 | ||
|
|
84f9b2bf35 | ||
|
|
b1da6958ff | ||
|
|
5e596819c5 | ||
|
|
415b6ea174 | ||
|
|
0e015027fc | ||
|
|
9c1dd0565f | ||
|
|
beb557aa56 | ||
|
|
6f3b08bbae | ||
|
|
553b07b722 | ||
|
|
c2c7f090ba | ||
|
|
909c6ec594 | ||
|
|
aedd1eb49c | ||
|
|
6e34a530b4 | ||
|
|
367c557a77 | ||
|
|
3022b665dd | ||
|
|
5cf0c08165 | ||
|
|
b8bd7c517e | ||
|
|
6a5da160ad | ||
|
|
99f4cdb3e4 | ||
|
|
2ae04ee1df | ||
|
|
b26552d74c | ||
|
|
f9defa7b37 | ||
|
|
fac52a2897 | ||
|
|
ec61d4d188 | ||
|
|
99c0879086 | ||
|
|
b064556081 | ||
|
|
2724659be8 | ||
|
|
3983dc10ed | ||
|
|
c5e2d49b8f | ||
|
|
bbdf40160c | ||
|
|
de0f49248d | ||
|
|
92ace5497f | ||
|
|
8005009420 | ||
|
|
4ee04b8a7b | ||
|
|
d7b66c2515 | ||
|
|
123c7f6b06 | ||
|
|
a17ad1c5a5 | ||
|
|
dbcfbdb21a | ||
|
|
50b0019302 | ||
|
|
b6eb3b041b | ||
|
|
354022888f | ||
|
|
3ba47a71fd | ||
|
|
b64551e984 | ||
|
|
90e8607586 | ||
|
|
ffd97a1fd0 | ||
|
|
5b12f456ac | ||
|
|
c4f2b8348e | ||
|
|
8f6c13b220 | ||
|
|
10a511a35e | ||
|
|
861953d736 | ||
|
|
63ad5eff18 | ||
|
|
f3299b2c8c | ||
|
|
fe485836f1 | ||
|
|
1daf629a42 | ||
|
|
151c6d246e | ||
|
|
210759907d | ||
|
|
8b7ce5eed2 | ||
|
|
4a75be1c92 | ||
|
|
3d114e5506 | ||
|
|
58158ce607 | ||
|
|
0f39825699 | ||
|
|
291ef6fdc4 | ||
|
|
75254bbf25 | ||
|
|
b0e466edae | ||
|
|
e95309a603 | ||
|
|
9af7eefe07 | ||
|
|
b5c5aba588 | ||
|
|
633f219cf7 | ||
|
|
13f27821ad | ||
|
|
7553106eee | ||
|
|
5cf73385c5 | ||
|
|
7a96467045 | ||
|
|
86c1660ee9 | ||
|
|
8e4836f83a | ||
|
|
00c09584c7 | ||
|
|
7677e8af79 | ||
|
|
69cb941fa4 | ||
|
|
17a7d4802d | ||
|
|
0b2610e3b3 | ||
|
|
51a02652d8 | ||
|
|
e7870da5ff | ||
|
|
a697e81427 | ||
|
|
5f8288dc70 | ||
|
|
feb5050df1 | ||
|
|
0d79b7a542 | ||
|
|
e4328f9211 | ||
|
|
70518a8e49 | ||
|
|
6ac897f9f3 | ||
|
|
ec9791b183 | ||
|
|
d5c267b291 | ||
|
|
3de533a73e | ||
|
|
f1f135adb6 | ||
|
|
91077fdc91 | ||
|
|
f250461648 | ||
|
|
6a98e40643 | ||
|
|
36c342fc7b | ||
|
|
39ff3f9993 | ||
|
|
7026e68b06 | ||
|
|
25ea80890d | ||
|
|
2379c76b03 | ||
|
|
e6d8416f0e | ||
|
|
cb16a78681 | ||
|
|
2930fb1963 | ||
|
|
d7b49f7706 | ||
|
|
695fc802a9 | ||
|
|
c37dbe131e | ||
|
|
88af898285 | ||
|
|
cd106a7eb6 | ||
|
|
975fc93e1f | ||
|
|
6c37a5d9f3 | ||
|
|
7b59b7f384 | ||
|
|
0ca218931a | ||
|
|
1d9f769a42 | ||
|
|
083edcedc7 | ||
|
|
fb5c3c86da | ||
|
|
3c89f2b1c2 | ||
|
|
4c7cf6ce06 | ||
|
|
195104487e | ||
|
|
39993c7019 | ||
|
|
897aa42135 | ||
|
|
abdf7d5b07 | ||
|
|
9f8f879590 | ||
|
|
db14d2d00a | ||
|
|
a0f3410f3b | ||
|
|
4159e1a177 | ||
|
|
4f7b0ff487 | ||
|
|
891ebe4480 | ||
|
|
859be35b34 | ||
|
|
88c452581b | ||
|
|
b0ccc87638 | ||
|
|
1e6843f8db | ||
|
|
76a589f689 | ||
|
|
e7621ad8a7 | ||
|
|
c4232510a1 | ||
|
|
e2878d3df8 | ||
|
|
5cb10441d7 | ||
|
|
6ee42dc7fe | ||
|
|
e0f6544c86 | ||
|
|
ab68e70998 | ||
|
|
8be1feadc1 | ||
|
|
beb3f8c1d4 | ||
|
|
35784c018d | ||
|
|
dc4c3f2f1a | ||
|
|
9ff6cdef8c | ||
|
|
dbc881143b | ||
|
|
556d5e0949 | ||
|
|
6456b937be | ||
|
|
05d8622ea9 | ||
|
|
f1387c892e | ||
|
|
cae5d48d31 | ||
|
|
d83d72fd88 | ||
|
|
ff42e854bb | ||
|
|
a462feee61 | ||
|
|
5eef4bccd3 | ||
|
|
609fa50763 | ||
|
|
7868767dde | ||
|
|
6ac013376f | ||
|
|
cfde247ef7 | ||
|
|
ac11eb8910 | ||
|
|
cd0d31805c | ||
|
|
cf617a4d20 | ||
|
|
84de0f6b85 | ||
|
|
914a0a7fc1 | ||
|
|
f82420b601 | ||
|
|
5193b70ada | ||
|
|
4b2b50a3df | ||
|
|
9ed3a55ade | ||
|
|
53a8d5ac30 | ||
|
|
b4144d2cff | ||
|
|
5bbcc7322c | ||
|
|
3f81397a84 | ||
|
|
c744b39c6d | ||
|
|
1a97d37215 | ||
|
|
2bc7e4736f | ||
|
|
5681b99fd8 | ||
|
|
9a5efc2de2 | ||
|
|
692af52ea7 | ||
|
|
ee51295d22 | ||
|
|
3c7a08afc2 | ||
|
|
ed9ca9e943 | ||
|
|
fbaa3a804f | ||
|
|
9f0308530c | ||
|
|
2e89d91a86 | ||
|
|
e20e4677df | ||
|
|
97c581f72c | ||
|
|
c079a3b58a | ||
|
|
c6de58aa05 | ||
|
|
4fd0e3acd8 | ||
|
|
3145daa46a | ||
|
|
3c52840dd8 | ||
|
|
8ed66980c0 | ||
|
|
365da7fef6 | ||
|
|
9af5023a8f | ||
|
|
878201c631 | ||
|
|
e65d11f4de | ||
|
|
1a89edec47 | ||
|
|
1143b3f56f | ||
|
|
1b4017c6b7 | ||
|
|
15224c6df5 | ||
|
|
e831757313 | ||
|
|
a47388ff76 | ||
|
|
71f4f36f8c | ||
|
|
a4e387331a | ||
|
|
defdc617b3 | ||
|
|
61b6a32631 | ||
|
|
1fdf1c0264 | ||
|
|
32f019c70c | ||
|
|
9c62e94239 | ||
|
|
b4ff034ac2 | ||
|
|
6b27a7fe46 | ||
|
|
adc9569e23 | ||
|
|
4cd6c37ab5 | ||
|
|
f15234e4f8 | ||
|
|
29ff05bd62 | ||
|
|
e9b4a6e96c | ||
|
|
530078b3ae | ||
|
|
5149205109 | ||
|
|
55b77a1925 | ||
|
|
bc5691c4b6 | ||
|
|
0513f93f9d | ||
|
|
b5decd8a50 | ||
|
|
b1901da79f | ||
|
|
6f47b1a89d | ||
|
|
cec703a059 | ||
|
|
217eb68455 | ||
|
|
f0d6fd1912 | ||
|
|
b0061ece62 | ||
|
|
0b6603ab2b | ||
|
|
09546b0d2a | ||
|
|
799ee7b9c6 | ||
|
|
b0b28b7a6e | ||
|
|
bbe7a9dd6a | ||
|
|
ecec7dbef3 | ||
|
|
d66a7b0ee0 | ||
|
|
61c4d2b805 | ||
|
|
73d8072693 | ||
|
|
c64edf31fc | ||
|
|
cb32e3d8f9 | ||
|
|
e69e9eddc7 | ||
|
|
aa85a1866e | ||
|
|
623925a1cf | ||
|
|
b6792a2c8c | ||
|
|
7248ad9aba | ||
|
|
d44b8aa853 | ||
|
|
f8d6ecbc02 | ||
|
|
bd76558b94 | ||
|
|
63451b7b6b | ||
|
|
edc42800ba | ||
|
|
0608d47219 | ||
|
|
5efb5068cd | ||
|
|
14f31006c1 | ||
|
|
90c8440f17 | ||
|
|
c3e9d7de41 | ||
|
|
9badb14c3a | ||
|
|
655994cd09 | ||
|
|
217ca928d5 | ||
|
|
fdae6cf1b0 | ||
|
|
e708cdf28c | ||
|
|
2d616a5995 | ||
|
|
563dd617af | ||
|
|
2c399ec441 | ||
|
|
57067d38fe | ||
|
|
2f6b64e92e | ||
|
|
00b06313c9 | ||
|
|
2b015a1d5b | ||
|
|
010220ea25 | ||
|
|
95a56972a1 | ||
|
|
a8ff00bc34 | ||
|
|
9abac06e85 | ||
|
|
ee595978f8 | ||
|
|
49d769282b | ||
|
|
451c90b932 | ||
|
|
9215ddcf8a | ||
|
|
fb0fd0c6d2 | ||
|
|
9c1902b0e3 | ||
|
|
cf8d05ae98 | ||
|
|
8c513faad5 | ||
|
|
6e8d9ff788 | ||
|
|
0e6cbf989e | ||
|
|
d6bbb765c1 | ||
|
|
b411b60ed7 | ||
|
|
692cafa784 | ||
|
|
6600a8c60b | ||
|
|
cebede3a79 | ||
|
|
db756f482b | ||
|
|
cd349946e8 | ||
|
|
b4156a19c3 | ||
|
|
b3e2647dc4 | ||
|
|
e9f0d1f513 | ||
|
|
21cae97820 | ||
|
|
74989d925e | ||
|
|
b402d77ff9 | ||
|
|
8431925577 | ||
|
|
22e8b53029 | ||
|
|
aa75fd24d8 | ||
|
|
f8f4cebe9e | ||
|
|
7d7db6d5bb | ||
|
|
38bbb8580f | ||
|
|
8a7af5ba0d | ||
|
|
a98d277cf3 | ||
|
|
3c6dd2cb79 | ||
|
|
5b96047ce8 | ||
|
|
692f597808 | ||
|
|
10f878d8c7 | ||
|
|
8987a34078 | ||
|
|
ba99d0154b | ||
|
|
977bf4d583 | ||
|
|
06efa7c52b | ||
|
|
84d58ff421 | ||
|
|
c679b97e5f | ||
|
|
b99ab3d1d2 | ||
|
|
ce6b993954 | ||
|
|
e95c2ba0b9 | ||
|
|
ab6971656b | ||
|
|
01fc010719 | ||
|
|
37c84448a9 | ||
|
|
d259be7b1f | ||
|
|
9be71eea2f | ||
|
|
a4d841655b | ||
|
|
162c69bfda | ||
|
|
c5f496670d | ||
|
|
53a0acc2e3 | ||
|
|
75d950e4b0 | ||
|
|
5abd9edf62 | ||
|
|
e00e879af5 | ||
|
|
8476832dc2 | ||
|
|
0ab8f4a1bd | ||
|
|
79f825cc44 | ||
|
|
f351e20de3 | ||
|
|
925d514224 | ||
|
|
36cc7610a1 | ||
|
|
06d2017a95 | ||
|
|
0da68844a5 | ||
|
|
1f6733562d | ||
|
|
4093fa0588 | ||
|
|
39c82d6ea0 | ||
|
|
03c7a9d5f3 | ||
|
|
65b32b8ced | ||
|
|
41f74d1a5c | ||
|
|
13e65a73a4 | ||
|
|
dc1234ddfb | ||
|
|
5d8f5c890d | ||
|
|
e2eabc7a96 | ||
|
|
a33977c71c | ||
|
|
9de1a1ddfa | ||
|
|
7dcdaf0319 | ||
|
|
b3d64d1121 | ||
|
|
52ff6fd5f8 | ||
|
|
af7b8cd9a3 | ||
|
|
b0ee5ce485 | ||
|
|
4a65e38d54 | ||
|
|
097d2d902c | ||
|
|
9d15512f3b | ||
|
|
3bbb48ce9e | ||
|
|
a709307fab | ||
|
|
06c73813ca | ||
|
|
5acc7209b2 | ||
|
|
9fe11f9c36 | ||
|
|
fb734e4124 | ||
|
|
7c1fb6e5b9 | ||
|
|
40d03f78cf | ||
|
|
7f8c6a9fd6 | ||
|
|
832187be31 | ||
|
|
a2f8f1e70d | ||
|
|
3f3343e945 | ||
|
|
4e077402e5 | ||
|
|
ad5740f8a7 | ||
|
|
310f77d96a | ||
|
|
121c3973d6 | ||
|
|
17212616d7 | ||
|
|
876ba3bef5 | ||
|
|
9a0918a354 | ||
|
|
cfad3b26ca | ||
|
|
a55b000273 | ||
|
|
b69b0de234 | ||
|
|
6d320163a1 | ||
|
|
ae21f29ad9 | ||
|
|
f82224eba0 | ||
|
|
c2cfe60102 | ||
|
|
75e622e879 | ||
|
|
9c19f6efb7 | ||
|
|
58995fc829 | ||
|
|
54ed1807c0 | ||
|
|
e1a820dcf9 | ||
|
|
b749bbf42b | ||
|
|
bdbc3c3b58 | ||
|
|
b83810b986 | ||
|
|
462b543816 | ||
|
|
29ddb9f4d9 | ||
|
|
398b05afed | ||
|
|
f0e4fe66ba | ||
|
|
fa057e76f3 | ||
|
|
47906fbcb7 | ||
|
|
5df8c9290f | ||
|
|
1938be9e28 | ||
|
|
839e292819 | ||
|
|
056f64ad40 | ||
|
|
c13a0a2e7a | ||
|
|
1cf12085fc | ||
|
|
d9946b49c4 | ||
|
|
c5ca58a95b | ||
|
|
591255c793 | ||
|
|
2ea5e6d090 | ||
|
|
e01fc5e697 | ||
|
|
0775976165 | ||
|
|
d2f719171d | ||
|
|
c9c147a814 | ||
|
|
31aa230cba | ||
|
|
880be015ae | ||
|
|
96d6cf8def | ||
|
|
66dd3f08b1 | ||
|
|
2175e561cc | ||
|
|
35191745ca | ||
|
|
661af1c5e2 | ||
|
|
bd1ee1f805 | ||
|
|
9e926bdb1d | ||
|
|
edab49c4ef | ||
|
|
bbbbc8b311 | ||
|
|
d5c1111fda | ||
|
|
26a76365f4 | ||
|
|
3a20ae16e1 | ||
|
|
e0746e1ab8 | ||
|
|
24c623c2fa | ||
|
|
5e1d207eae | ||
|
|
3e15966c3e | ||
|
|
ff54fb431f | ||
|
|
1ba6b2653a | ||
|
|
1d1b5d1c6d | ||
|
|
9027d15211 | ||
|
|
5bde264c43 | ||
|
|
67a2fe3751 | ||
|
|
e3cb33bbda | ||
|
|
3174fb7d19 | ||
|
|
1836f69cf0 | ||
|
|
985b7831cf | ||
|
|
fbc851ceae | ||
|
|
55bf8ec095 | ||
|
|
39e955c412 | ||
|
|
f8c065c182 | ||
|
|
ed6fe7519a | ||
|
|
d808d6d8a5 | ||
|
|
b471109c08 | ||
|
|
9978b07956 | ||
|
|
1b3ff094fa | ||
|
|
75ce4c395a | ||
|
|
427e93c573 | ||
|
|
46327563f2 | ||
|
|
3308f0644c | ||
|
|
cb128162e6 | ||
|
|
f9f4c7dcd6 | ||
|
|
2dae228f10 | ||
|
|
b917c540aa | ||
|
|
67ce8aff61 | ||
|
|
ba927964c8 | ||
|
|
435f2b8e39 | ||
|
|
a25f9010cc | ||
|
|
4500964394 | ||
|
|
3da646f913 | ||
|
|
140436c2cb | ||
|
|
0e677fb3a2 | ||
|
|
4dc5d0e12f | ||
|
|
a260e92266 | ||
|
|
9a86be24a7 | ||
|
|
e620d973f4 | ||
|
|
7ad43a5b11 | ||
|
|
124ede82b3 | ||
|
|
da9debda67 | ||
|
|
1c40d77b14 | ||
|
|
f1b0c29815 | ||
|
|
b261dde858 | ||
|
|
88fdec6dd5 | ||
|
|
e8ce238eb7 | ||
|
|
404b1c5ed0 | ||
|
|
dde1deb6bc | ||
|
|
c80e0a964f | ||
|
|
d9f23a8af2 | ||
|
|
fd9e657196 | ||
|
|
693c4024d6 | ||
|
|
d7eee4191f | ||
|
|
b8c61f89fa | ||
|
|
d05feabcd6 | ||
|
|
c30b7c111f | ||
|
|
f6255c72d1 | ||
|
|
cd68567ce3 | ||
|
|
e6f39eb9b6 | ||
|
|
2c1a398292 | ||
|
|
0f52f6931b | ||
|
|
51dc097266 | ||
|
|
8e99b342a4 | ||
|
|
bc51c3e5b1 | ||
|
|
d5177fdc74 | ||
|
|
80eba57e6b | ||
|
|
3985dd639a | ||
|
|
3000445af9 | ||
|
|
0235d57625 | ||
|
|
77c7b312ea | ||
|
|
3850765759 | ||
|
|
0b8e2fd5c9 | ||
|
|
ebe9ee8114 | ||
|
|
a8ab617ee9 | ||
|
|
414440589e | ||
|
|
544b6d94aa | ||
|
|
0144062126 | ||
|
|
db1b7a8067 | ||
|
|
a9905ec95e | ||
|
|
7e2afacf34 | ||
|
|
2b6257e94e | ||
|
|
d14b5fe00b | ||
|
|
04bb2d1066 | ||
|
|
3b9037397a | ||
|
|
ea3e602835 | ||
|
|
96e971084a | ||
|
|
9bf78a96cc | ||
|
|
ba55ef0b2e | ||
|
|
0c00f7393c | ||
|
|
1824826474 | ||
|
|
57e1c7d55f | ||
|
|
e489b4a570 | ||
|
|
83dc7f0855 | ||
|
|
90a2d1bb39 | ||
|
|
da650606e3 | ||
|
|
bc789d7c1a | ||
|
|
5999b50e10 | ||
|
|
e5428a3c27 | ||
|
|
cf39bc97a5 | ||
|
|
4d43374fde | ||
|
|
dac42ee272 | ||
|
|
f7991185ba | ||
|
|
5954f15989 | ||
|
|
4d2eb7af30 | ||
|
|
50083048f6 | ||
|
|
dab2932550 | ||
|
|
a8cebbe3fd | ||
|
|
d6a6194e68 | ||
|
|
c373527851 | ||
|
|
de8726ab73 | ||
|
|
94d33a4ef1 | ||
|
|
d79b41e4a7 | ||
|
|
754a6e1177 | ||
|
|
b972ea4781 | ||
|
|
45856816c1 | ||
|
|
582162460f | ||
|
|
e970c36419 | ||
|
|
c48cc0afdc | ||
|
|
3d6d4f5464 | ||
|
|
61bc6ec825 | ||
|
|
6f0f6676db | ||
|
|
fc240d4dfa | ||
|
|
6dc0861740 | ||
|
|
45cabd756c | ||
|
|
5fc854ab4f | ||
|
|
caa3343dea | ||
|
|
3ac43497b9 | ||
|
|
74f1b800c2 | ||
|
|
7d431e55df | ||
|
|
575962569f | ||
|
|
01ef0e93aa | ||
|
|
439f4f6f0e | ||
|
|
00b1f33725 | ||
|
|
1204eec8ac | ||
|
|
f3ac8f6649 | ||
|
|
7db280a666 | ||
|
|
a4b7ad0d42 | ||
|
|
2b88905b40 | ||
|
|
ef5263ef9e | ||
|
|
9206512c38 | ||
|
|
82e16db275 | ||
|
|
97fc093eef | ||
|
|
b9cd424186 | ||
|
|
6af85409f1 | ||
|
|
86c699dd36 | ||
|
|
3d4e1ffd64 | ||
|
|
b39fcebe65 | ||
|
|
04129a0841 | ||
|
|
a7658f013e | ||
|
|
2822bf7a65 | ||
|
|
87ccd272ee | ||
|
|
18275ce2c9 | ||
|
|
5935070dfa | ||
|
|
8391c83121 | ||
|
|
4255ee105f | ||
|
|
e3c45bd1f7 | ||
|
|
449617474b | ||
|
|
ce542ac5f6 | ||
|
|
d0e18ed0ba | ||
|
|
70952282f0 | ||
|
|
bf325b72f1 | ||
|
|
f031ad23f6 | ||
|
|
9e56725406 | ||
|
|
ad543c909c | ||
|
|
36b8b81914 | ||
|
|
5d76ffef88 | ||
|
|
37316fed84 | ||
|
|
ecd568510d | ||
|
|
5ec9cf7089 | ||
|
|
aad1b5dc9f | ||
|
|
1b13f0a2ec | ||
|
|
29108ea8ad | ||
|
|
0e167ee85b | ||
|
|
8fe6d09613 | ||
|
|
fa0df413f4 | ||
|
|
1a8be6344a | ||
|
|
fff8455903 | ||
|
|
80d94e1aa3 | ||
|
|
a36c266e7d | ||
|
|
636c100b6b | ||
|
|
28f85aae7f | ||
|
|
dfa11f64ef | ||
|
|
3f92d2f300 | ||
|
|
cc0bf88a5f | ||
|
|
b3c0b964b5 | ||
|
|
4661e5a10b | ||
|
|
220a35b492 | ||
|
|
351142f93f | ||
|
|
29bc273e58 | ||
|
|
b96e0c8713 | ||
|
|
7e0c0d79bc | ||
|
|
1f88f1f3f6 | ||
|
|
69d8b1c30d | ||
|
|
5a5d8d2d07 | ||
|
|
0e25540a89 | ||
|
|
21169f4e9a | ||
|
|
1fbed9f7d0 | ||
|
|
c230cf5aab | ||
|
|
2d65ed352e | ||
|
|
5fa81d4273 | ||
|
|
5ec32bdd2f | ||
|
|
d39aa10da1 | ||
|
|
0d763052fb | ||
|
|
ee62e33dd0 | ||
|
|
a22de48e40 | ||
|
|
7b5708a8b4 | ||
|
|
71c1767790 | ||
|
|
5fb0115d06 | ||
|
|
c8e6128720 | ||
|
|
55583540a8 | ||
|
|
9b5d0228be | ||
|
|
325d05b59c | ||
|
|
d1500dc99b | ||
|
|
157c8d5e54 | ||
|
|
0533b5cefc | ||
|
|
7816085868 | ||
|
|
178a5f0645 | ||
|
|
dfb8527e50 | ||
|
|
0a581154d1 | ||
|
|
efabf18162 | ||
|
|
56737ac523 | ||
|
|
702885ebb2 | ||
|
|
a12b83de59 | ||
|
|
3b83356825 | ||
|
|
c2aad7a71d | ||
|
|
ef4edc6ff1 | ||
|
|
614967ccc1 | ||
|
|
e8dc1480eb | ||
|
|
8fb87df0f0 | ||
|
|
bb7cfd2493 | ||
|
|
1b19622ab8 | ||
|
|
68ab7e2e3e | ||
|
|
157a286d1b | ||
|
|
0eb199a9a8 | ||
|
|
77a928cef9 | ||
|
|
290388159a | ||
|
|
d0551a3ede | ||
|
|
1e0d0429d0 | ||
|
|
37ad913086 | ||
|
|
3755ad7515 | ||
|
|
369e141ea8 | ||
|
|
39c9e69d8a | ||
|
|
30be1ea16e | ||
|
|
a450361956 | ||
|
|
df48ad6b61 | ||
|
|
264de34c31 | ||
|
|
70444b46b9 | ||
|
|
a79e552ab4 | ||
|
|
1b5faef097 | ||
|
|
fe61f583e6 | ||
|
|
4031ad354b | ||
|
|
46b9ae4174 | ||
|
|
c0d1aaa8a0 | ||
|
|
a963427967 | ||
|
|
d5ec523584 | ||
|
|
c0c3fceaad | ||
|
|
c52d7c9126 | ||
|
|
6cb67a19e7 | ||
|
|
9b5ca124ab | ||
|
|
4a0a509dd8 | ||
|
|
6f2184901d | ||
|
|
201e5e59da | ||
|
|
2cb5778cfa | ||
|
|
006016322b | ||
|
|
4191856034 | ||
|
|
97f7b4f59f | ||
|
|
ea441b3d70 | ||
|
|
045ee262a8 | ||
|
|
502c6f0dae | ||
|
|
bc31dfbbd1 | ||
|
|
a1319f4231 | ||
|
|
ce365abab6 | ||
|
|
48a623f062 | ||
|
|
a727dfb3b0 | ||
|
|
52ba76fcb2 | ||
|
|
70e29d4f20 | ||
|
|
08d83eb8da | ||
|
|
eacff1f0b4 | ||
|
|
4806d71ca2 | ||
|
|
085b87dd02 | ||
|
|
35cd7eb2be | ||
|
|
ec716f0c58 | ||
|
|
0d97198f88 | ||
|
|
2c7537b4cd | ||
|
|
e364937353 | ||
|
|
877ef76540 | ||
|
|
519e8c5fcd | ||
|
|
305d53f094 | ||
|
|
5625ad76b9 | ||
|
|
4c722bf623 | ||
|
|
8fe22c33bf | ||
|
|
d866c061a3 | ||
|
|
f8fed31918 | ||
|
|
e487007960 | ||
|
|
b46f2d1527 | ||
|
|
e162fb0e80 | ||
|
|
91ea3ba090 | ||
|
|
e84f6e4afd | ||
|
|
9b65900df0 | ||
|
|
9659340d7f | ||
|
|
63175aa3cb | ||
|
|
986aa2a477 | ||
|
|
07d7a8eeff | ||
|
|
3c9e84d380 | ||
|
|
0f62a8ec2f | ||
|
|
4e7a9cf30b | ||
|
|
5077703400 | ||
|
|
77fef18590 | ||
|
|
6ce00034a2 | ||
|
|
ed6d8521e6 | ||
|
|
d24c751eef | ||
|
|
54012523bc | ||
|
|
5286f43133 | ||
|
|
ca1e9a2976 | ||
|
|
5951cbf7b9 | ||
|
|
e2b519a21e | ||
|
|
cf0401fea7 | ||
|
|
14a8f4a728 | ||
|
|
3e41d9b794 | ||
|
|
148867bf47 | ||
|
|
ef6c454137 | ||
|
|
093f8cb89b | ||
|
|
707e820af6 | ||
|
|
0c7696da65 | ||
|
|
9e540eb1c4 | ||
|
|
306828480f | ||
|
|
42b415952b | ||
|
|
e155e258cb | ||
|
|
6f45794574 | ||
|
|
1d30f00806 | ||
|
|
52e9ec10bf | ||
|
|
8da56ff98c | ||
|
|
d44e334524 | ||
|
|
e814e65fcb | ||
|
|
c2f7d600aa | ||
|
|
5d942265f9 | ||
|
|
6b07625192 | ||
|
|
19b56361b9 | ||
|
|
7d93eba321 | ||
|
|
7b42aba5ea | ||
|
|
be4ac7ca61 | ||
|
|
28e25ea718 | ||
|
|
b2e6e6155f | ||
|
|
f5e1ff3f1f | ||
|
|
3fda82b5f8 | ||
|
|
822a4896da | ||
|
|
7f2bf03d7e | ||
|
|
1e8a6e878d | ||
|
|
5f0a55057e | ||
|
|
7814acb9f8 | ||
|
|
b296af6fe4 | ||
|
|
14b9902f6d | ||
|
|
f2d54b7728 | ||
|
|
8950a693db | ||
|
|
fd3b9095ba | ||
|
|
030e1b9130 | ||
|
|
a040c237bc | ||
|
|
a62fafd4ed | ||
|
|
666703e8cf | ||
|
|
52cd52ca54 | ||
|
|
ef825d8a94 | ||
|
|
6775898712 | ||
|
|
d3dd82f190 | ||
|
|
95409f7ec7 | ||
|
|
1141a73945 | ||
|
|
176c003658 | ||
|
|
74aafaa72f | ||
|
|
0ac7867b3d | ||
|
|
c1b65f52be | ||
|
|
1d242ee161 | ||
|
|
230e4e3a32 | ||
|
|
7ff4724e28 | ||
|
|
0015d00243 | ||
|
|
5ca8967375 | ||
|
|
4e0c1f97ac | ||
|
|
191c3dabdb | ||
|
|
cd9a28864a | ||
|
|
c2ecb7363c | ||
|
|
e20e272ee1 | ||
|
|
8dc7f78b0f | ||
|
|
c4331c4795 | ||
|
|
d071ecc17c | ||
|
|
7c03276b50 | ||
|
|
ee8b180341 | ||
|
|
5258a1dc85 | ||
|
|
e74d5593a8 | ||
|
|
18285ca751 | ||
|
|
764a04a201 | ||
|
|
1e5a375203 | ||
|
|
3a2504dc18 | ||
|
|
7bc4c10660 | ||
|
|
0fcfead475 | ||
|
|
ab9c1217e4 | ||
|
|
e9f002e9c5 | ||
|
|
a9b6bcf779 | ||
|
|
52e427117c | ||
|
|
312e26a5cf | ||
|
|
f757d5f09b | ||
|
|
a66adcbc88 | ||
|
|
f4f930e8bd | ||
|
|
5200940f2f | ||
|
|
63f8262a57 | ||
|
|
bb9d5e11f1 | ||
|
|
df76b7285c | ||
|
|
e105711678 | ||
|
|
b206858c67 | ||
|
|
bc1b803093 | ||
|
|
6e54e0f6e4 | ||
|
|
e0d2287973 | ||
|
|
7f26803dee | ||
|
|
22cbe23f85 | ||
|
|
8f0c442024 | ||
|
|
02b8e3f7c0 | ||
|
|
7846ff1666 | ||
|
|
3e1e20dbe2 | ||
|
|
eaf441c226 | ||
|
|
942b1d2591 | ||
|
|
710456f871 | ||
|
|
59df217a09 | ||
|
|
ffd7603b17 | ||
|
|
329616c029 | ||
|
|
8723a69a8f | ||
|
|
edddca4857 | ||
|
|
536123ec59 | ||
|
|
db699ed2c3 | ||
|
|
bf9c58b8ed | ||
|
|
8eeec3dc48 | ||
|
|
4a1dd5f519 | ||
|
|
5256edf0e5 | ||
|
|
e9385e6eb6 | ||
|
|
80f7e3092b | ||
|
|
ab06cf4788 | ||
|
|
c2300f7b2b | ||
|
|
ba2915ce4e | ||
|
|
c0b91dd107 | ||
|
|
439986e3fe | ||
|
|
e77ad244ad | ||
|
|
2e3c5e367e | ||
|
|
eb230a45f6 | ||
|
|
5aacf886e1 | ||
|
|
0cae86e2ad | ||
|
|
e7f0a005e2 | ||
|
|
b3c506c69e | ||
|
|
99f741fb3b | ||
|
|
52aa0a5b27 | ||
|
|
b7ac61cbea | ||
|
|
2896e7bd4b | ||
|
|
8a10f4b7a2 | ||
|
|
7619d0d7ff | ||
|
|
2175357e72 | ||
|
|
bd9f126973 | ||
|
|
4260a5b3df | ||
|
|
247fabaaf0 | ||
|
|
a991d327e6 | ||
|
|
c19712dccc | ||
|
|
7d67e851c9 | ||
|
|
7492ee5d2e | ||
|
|
7ea6080689 | ||
|
|
272dbf94e0 | ||
|
|
d96f7ae4ae | ||
|
|
20d4597fa0 | ||
|
|
c5947e2dd7 | ||
|
|
544bd7d4cc | ||
|
|
d1c1cb5f7c | ||
|
|
a1165183c2 | ||
|
|
07520fb26e | ||
|
|
46393d63af | ||
|
|
ccc067a1c6 | ||
|
|
0cd954749c | ||
|
|
916f60b59b | ||
|
|
115d17de01 | ||
|
|
8dfae523a3 | ||
|
|
0532135dc3 | ||
|
|
b28c6d6e4a | ||
|
|
f703b285bb | ||
|
|
749b9dd1bb | ||
|
|
42ff151ae4 | ||
|
|
5ec6f851c9 | ||
|
|
89be7adc80 | ||
|
|
39f9702db4 | ||
|
|
021c390091 | ||
|
|
cec1d4a28b | ||
|
|
38969dde2f | ||
|
|
3061ef9d4c | ||
|
|
e55b7fa70f | ||
|
|
79d04c2d24 | ||
|
|
d11be6fcf4 | ||
|
|
bed417dc62 | ||
|
|
7625ca439e | ||
|
|
6ff5733d7b | ||
|
|
a3117ef272 | ||
|
|
2fdbedfe95 | ||
|
|
5567484a8e | ||
|
|
d79c5bd1dc | ||
|
|
34d2db6d78 | ||
|
|
eceb9008cd | ||
|
|
731245773a | ||
|
|
d4a80ab3d0 | ||
|
|
ce709298cc | ||
|
|
6ab7a6678c | ||
|
|
f62283b595 | ||
|
|
e8058912b8 | ||
|
|
4f800fbd00 | ||
|
|
e367d456e1 | ||
|
|
3025b9b5e0 | ||
|
|
b0075842d1 | ||
|
|
0a10d6022f | ||
|
|
a634da2c0a | ||
|
|
94f0fc58cc | ||
|
|
bf76be5dfa | ||
|
|
a62aeb36d8 | ||
|
|
0d795fc651 | ||
|
|
7441af67a8 | ||
|
|
9077686998 | ||
|
|
d88f07fd31 | ||
|
|
805306bdf0 | ||
|
|
da53fdb50c | ||
|
|
549e5a85cb | ||
|
|
cd75c56ac4 | ||
|
|
82883d8187 | ||
|
|
74f49ec38f | ||
|
|
cb3411481d | ||
|
|
3aad0dff2e | ||
|
|
0510723ac1 | ||
|
|
294a120f14 | ||
|
|
e6313c89bc | ||
|
|
8362b8d226 | ||
|
|
7675472b41 | ||
|
|
c07f84911c | ||
|
|
6f18a50945 | ||
|
|
d5c9ce9125 | ||
|
|
3b4ac1c64d | ||
|
|
717b4ce4fa | ||
|
|
6efc6074cc | ||
|
|
76fa100c1d | ||
|
|
981171f42a | ||
|
|
33ef2ff5c9 | ||
|
|
380d0b9623 | ||
|
|
de27cb8a2f | ||
|
|
ac6c162a13 | ||
|
|
a8021e0d79 | ||
|
|
b52f696d49 | ||
|
|
983e37a0be | ||
|
|
f1e01a3cf6 | ||
|
|
858c3f653c | ||
|
|
4618588494 | ||
|
|
cd3c3fffde | ||
|
|
148b5ea376 | ||
|
|
6f9c197400 | ||
|
|
67ae85b840 | ||
|
|
0f6e8dd311 | ||
|
|
cb86d4d967 | ||
|
|
80fbc25442 | ||
|
|
c1f9fb6c3a | ||
|
|
a46dcd45d7 | ||
|
|
99ff1179cc | ||
|
|
4871dbaaa1 | ||
|
|
832dc259af | ||
|
|
78f4640736 | ||
|
|
0b7831c6df | ||
|
|
73a701f08c | ||
|
|
080405c022 | ||
|
|
58ae7f1cab | ||
|
|
59b1bd3d96 | ||
|
|
4d4979cc98 | ||
|
|
542c515bc1 | ||
|
|
3479e452de | ||
|
|
49ad25d001 | ||
|
|
13c8336c82 | ||
|
|
601186fd6a | ||
|
|
dfadfe37f6 | ||
|
|
b3372ebba2 | ||
|
|
01de453d25 | ||
|
|
64b6c0d0eb | ||
|
|
2f684e0255 | ||
|
|
3a77fcd005 | ||
|
|
06492d18a7 | ||
|
|
0297e974d4 | ||
|
|
354279bc1e | ||
|
|
e0278071cf | ||
|
|
a9bd1ced2e | ||
|
|
8cd397e56f | ||
|
|
7423fd9c98 | ||
|
|
cd75262ad1 | ||
|
|
70f91f8345 | ||
|
|
61a28c290b | ||
|
|
40c2674d49 | ||
|
|
b3d38bd4f1 | ||
|
|
7e199b0c7c | ||
|
|
6af30e8992 | ||
|
|
e7c86713c8 | ||
|
|
7cd480a1a9 | ||
|
|
3f249c2e93 | ||
|
|
36f5200abc | ||
|
|
89325f9995 | ||
|
|
83b3c3ab8f | ||
|
|
02277225d7 | ||
|
|
6f55c3e75a | ||
|
|
56131fd63a | ||
|
|
f65de3bbbb | ||
|
|
44d9551bd6 | ||
|
|
1aab29a958 | ||
|
|
0439d08689 | ||
|
|
618eb254c0 | ||
|
|
e2340363e3 | ||
|
|
a68125a5ee | ||
|
|
3d25938dd7 | ||
|
|
70994cb4b2 | ||
|
|
0d5ef132f3 | ||
|
|
5610aeb917 | ||
|
|
02f8991fb3 | ||
|
|
f53255570d | ||
|
|
543f3440dc | ||
|
|
1a8417951f | ||
|
|
2f68781ff9 | ||
|
|
d29e546678 | ||
|
|
a39943d57d | ||
|
|
c20ac116a8 | ||
|
|
c8f5ef8afb | ||
|
|
1ebef323de | ||
|
|
3b18745bcd | ||
|
|
236579a930 | ||
|
|
9b49b2694d | ||
|
|
62336b60b2 | ||
|
|
917b6d4521 | ||
|
|
fdec003973 | ||
|
|
55b4854cd4 | ||
|
|
6aca18193a | ||
|
|
745b2f0668 | ||
|
|
2b207359f9 | ||
|
|
6121c098c8 | ||
|
|
c15a91dbcc | ||
|
|
f46c58deaa | ||
|
|
c9b7e9f9aa | ||
|
|
6a8c99eef1 | ||
|
|
7025e07e8a | ||
|
|
2ba12008c8 | ||
|
|
ac2bbf16f6 | ||
|
|
d77ebd60cf | ||
|
|
997c7ebbcf | ||
|
|
afe5425163 | ||
|
|
32eadc0ea3 | ||
|
|
e75b244cae | ||
|
|
bb448905ac | ||
|
|
6928ce9cd3 | ||
|
|
b7394ad02e | ||
|
|
eca39b1a51 | ||
|
|
f66e63c690 | ||
|
|
42c2fc61b8 | ||
|
|
24303a5365 | ||
|
|
0ecae8a844 | ||
|
|
9e45f2da9f | ||
|
|
d676886dee | ||
|
|
2d0a0b5a62 | ||
|
|
6fe32b3b49 | ||
|
|
525145f2a3 | ||
|
|
2b8038d700 | ||
|
|
2454c0baae | ||
|
|
0189c5b990 | ||
|
|
c70285dcfc | ||
|
|
f5a392e189 | ||
|
|
cd729f054c | ||
|
|
5f551fa67a | ||
|
|
1e57376cc7 | ||
|
|
4771398e1e | ||
|
|
ee49dfa505 | ||
|
|
20d1551216 | ||
|
|
a3593a5124 | ||
|
|
c7646976fb | ||
|
|
8a10cc982c | ||
|
|
74e546e145 | ||
|
|
5586f7c517 | ||
|
|
fbeeaa4c1e | ||
|
|
48738bbae9 | ||
|
|
7f74948e91 | ||
|
|
a31bb79b78 | ||
|
|
821fcd5be4 | ||
|
|
0c75229250 | ||
|
|
5f67a600fc | ||
|
|
4669c320f6 | ||
|
|
545868da38 | ||
|
|
e154f3edb7 | ||
|
|
393c54fdc2 | ||
|
|
02981cec57 | ||
|
|
6e499c8213 | ||
|
|
9ca1ced6a2 | ||
|
|
6470222a06 | ||
|
|
eedf8b845c | ||
|
|
01c94596a4 | ||
|
|
978d7c0fca | ||
|
|
3bd53b4f61 | ||
|
|
8d9c325000 | ||
|
|
dfe8ae4fd1 | ||
|
|
069d67b24b | ||
|
|
0c926b84bc | ||
|
|
11bdd68d73 | ||
|
|
1beeaf3d4f | ||
|
|
8cc850de97 | ||
|
|
0931794f10 | ||
|
|
3b12883a1b | ||
|
|
e18faf085f | ||
|
|
a98edd42d1 | ||
|
|
c1aa49ef3a | ||
|
|
49a860bc9e | ||
|
|
1b94a30c9f | ||
|
|
5a52fc3657 | ||
|
|
df7680aa73 | ||
|
|
f42a16643c | ||
|
|
96e5dc3fc6 | ||
|
|
6c0eca0eca | ||
|
|
fefff70645 | ||
|
|
18fa18f612 | ||
|
|
b2311e2ea5 | ||
|
|
ee42f09b8d | ||
|
|
e7f5f4a6af | ||
|
|
4d07acd384 | ||
|
|
2c06bb46ea | ||
|
|
3c3bfff0cf | ||
|
|
a86f6d0e64 | ||
|
|
4d54bfa6b4 | ||
|
|
28d1dab18a | ||
|
|
f3d19a860a | ||
|
|
5732e34f50 | ||
|
|
ca94a61acf | ||
|
|
a875c61b5f | ||
|
|
5ec70c9e0d | ||
|
|
4b0373408d | ||
|
|
7f8c4eff39 | ||
|
|
00f152910b | ||
|
|
95fdeb03c3 | ||
|
|
66e9ef9cf6 | ||
|
|
6b3221f1da | ||
|
|
25ad7bcf5e | ||
|
|
9a04a6bdb1 | ||
|
|
1b9fb906e2 | ||
|
|
e23d7ca51b | ||
|
|
92773c2e1b | ||
|
|
776889cfbb | ||
|
|
67163e14e6 | ||
|
|
45f68840ed | ||
|
|
325ae5e977 | ||
|
|
14919c65d9 | ||
|
|
8888e88dc4 | ||
|
|
0533664f90 | ||
|
|
64b824f457 | ||
|
|
b6592d799f | ||
|
|
c89711a863 | ||
|
|
91a1292b12 | ||
|
|
b2d469cb84 | ||
|
|
4f41da34c6 | ||
|
|
f136f2dcaf | ||
|
|
e6df54537a | ||
|
|
e62278859e | ||
|
|
51b91bce6d | ||
|
|
d96a23d4f2 | ||
|
|
98e049b336 | ||
|
|
3c297f5d1d | ||
|
|
d64d196409 | ||
|
|
b1638e79c0 | ||
|
|
13753757d4 | ||
|
|
739e341218 | ||
|
|
fda282604d | ||
|
|
2cd7fa68d6 | ||
|
|
d78a0c87b8 | ||
|
|
88d4abeaf8 | ||
|
|
1c0abbfce6 | ||
|
|
1492e12ca2 | ||
|
|
2b9a39e2eb | ||
|
|
301ae447b4 | ||
|
|
3d47010cbd | ||
|
|
dd0ff999e4 | ||
|
|
05e5c93e91 | ||
|
|
1bd97730ce | ||
|
|
458378be66 | ||
|
|
c01101dbd0 | ||
|
|
f7364111f2 | ||
|
|
f3b84b8670 | ||
|
|
ec11a31d9d | ||
|
|
2271469d1b | ||
|
|
7fe92d87c2 | ||
|
|
6046b8fb79 | ||
|
|
a65239a8af | ||
|
|
746cd5f49c | ||
|
|
75c315ad8a | ||
|
|
c1926c6e25 | ||
|
|
3f8ba353b7 | ||
|
|
39a2152a46 | ||
|
|
ddd967534b | ||
|
|
4d52fe0490 | ||
|
|
264ffa80ce | ||
|
|
258a9c636a | ||
|
|
8015d1827c | ||
|
|
ae10bc6601 | ||
|
|
51c27afcd2 | ||
|
|
e09d4f2cf2 | ||
|
|
7e87f56699 | ||
|
|
ca9150a731 | ||
|
|
5250d819d0 | ||
|
|
d93413a4ae | ||
|
|
bb7f7eff51 | ||
|
|
838e8c7b35 | ||
|
|
bb48a16466 | ||
|
|
a02ff01d84 | ||
|
|
66d27d6ac5 | ||
|
|
5ba82ef0fc | ||
|
|
053b522aff | ||
|
|
4521f80e5a | ||
|
|
f24efc17c1 | ||
|
|
f32d3849e5 | ||
|
|
f2fb064ea6 | ||
|
|
ce5093f91f | ||
|
|
75121588c4 | ||
|
|
1ff0f478d4 | ||
|
|
6c68082359 | ||
|
|
a752d220cc | ||
|
|
ee1bbd5994 | ||
|
|
91368e5656 | ||
|
|
c4c554b420 | ||
|
|
52ec8bf049 | ||
|
|
5c40e02ee6 | ||
|
|
d2a89c5856 | ||
|
|
9ec3f1b89d | ||
|
|
3ab81c764d | ||
|
|
c072ce8f0c | ||
|
|
e44dbd0e77 | ||
|
|
ec12022550 | ||
|
|
e0f670499c | ||
|
|
177cc87985 | ||
|
|
3e387f35e9 | ||
|
|
7037723993 | ||
|
|
b1098d6287 | ||
|
|
be222a16ce | ||
|
|
17f9a3eba6 | ||
|
|
0ee77c0e7d | ||
|
|
b92fa45da7 | ||
|
|
e64c2fc110 | ||
|
|
49a6508888 | ||
|
|
859678536f | ||
|
|
9a5f788807 | ||
|
|
84b3b1d29c | ||
|
|
80eb18a425 | ||
|
|
3e1ab53abd | ||
|
|
18c119b4d5 | ||
|
|
e67a65c0db | ||
|
|
4c878c4963 | ||
|
|
e8fbe0f36c | ||
|
|
243b7e25f8 | ||
|
|
f1a4a08c7f | ||
|
|
c0fa36b9a1 | ||
|
|
835b2d7ced | ||
|
|
13c2381ba7 | ||
|
|
fbc8e899dd | ||
|
|
5ee8c8ce91 | ||
|
|
971793d6a1 | ||
|
|
9d7a905fb1 | ||
|
|
731f002175 | ||
|
|
7e6f3bfd83 | ||
|
|
3e14739b29 | ||
|
|
d7fb6b2892 | ||
|
|
7527f441ae | ||
|
|
5228ee1d91 | ||
|
|
297a98e065 | ||
|
|
727d8afd94 | ||
|
|
c292fba3df | ||
|
|
9954ff55f5 | ||
|
|
fefd84d431 | ||
|
|
b4a7d21b9e | ||
|
|
d03e051611 | ||
|
|
e8c141d775 | ||
|
|
5b45e29533 | ||
|
|
024d094459 | ||
|
|
df977577e2 | ||
|
|
b63b94bc81 | ||
|
|
7e514f5d34 | ||
|
|
cb2de2e5c4 | ||
|
|
f2fedbc3e6 | ||
|
|
8ef686fd21 | ||
|
|
4c96e9a17d | ||
|
|
939bc00b2b | ||
|
|
0b06d3412e | ||
|
|
94f6f60105 | ||
|
|
4bd6bc9683 | ||
|
|
3c59621425 | ||
|
|
a37e2ab26a | ||
|
|
d099febf7b | ||
|
|
b9f82332c8 | ||
|
|
c02c4c6d6a | ||
|
|
17476ec137 | ||
|
|
ee51a68c6f | ||
|
|
0120ce5d7c | ||
|
|
42c6e640fc | ||
|
|
bc571316b9 | ||
|
|
3cc1af9618 | ||
|
|
6957bf504b | ||
|
|
d47dd70141 | ||
|
|
86eb2360db | ||
|
|
c55e350cb2 | ||
|
|
b0fe032b8d | ||
|
|
aa25870fb8 | ||
|
|
a8118ea8f4 | ||
|
|
1a344c1441 | ||
|
|
86a1641ac1 | ||
|
|
10129fa568 | ||
|
|
935a8d36da | ||
|
|
2516a3af8a | ||
|
|
120a265fc3 | ||
|
|
33aebeb727 | ||
|
|
7e06cfb471 | ||
|
|
f2bcff69a9 | ||
|
|
39b7d175b9 | ||
|
|
b9cebe8d87 | ||
|
|
6814cfbcd7 | ||
|
|
2884696024 | ||
|
|
6930046bc6 | ||
|
|
174cbfe3b9 | ||
|
|
611c7633cf | ||
|
|
822d4269c4 | ||
|
|
8fd16efc33 | ||
|
|
ef082d855c | ||
|
|
a5c4739804 | ||
|
|
d1f1a88ffd | ||
|
|
c05f6b7bf3 | ||
|
|
4b5fa26cd6 | ||
|
|
0162d18343 | ||
|
|
b6415818f6 | ||
|
|
e16efbf58b | ||
|
|
46804d0faf | ||
|
|
a81567e2d6 | ||
|
|
217670b54a | ||
|
|
f2e19c0387 | ||
|
|
9799970042 | ||
|
|
ca75d0d765 | ||
|
|
0824e49000 | ||
|
|
c3a98db0ea | ||
|
|
f27685717b | ||
|
|
55034bfa6f | ||
|
|
6f8b420d0d | ||
|
|
2ed7e14a99 | ||
|
|
ee3bcef8ab | ||
|
|
adbcb97515 | ||
|
|
c667723958 | ||
|
|
d94634398e | ||
|
|
f348e58508 | ||
|
|
60f16970ac | ||
|
|
39c5eafafc | ||
|
|
b7f6c223d8 | ||
|
|
bf9a65338b | ||
|
|
5b3ae5eff9 | ||
|
|
f80a8d306b | ||
|
|
9ed9060940 | ||
|
|
5453e60099 | ||
|
|
3de61b69ad | ||
|
|
322a4ed05d | ||
|
|
8f3b4afcf7 | ||
|
|
ebdc6b94fc | ||
|
|
a7218d2e59 | ||
|
|
6d93beac8e | ||
|
|
1fb1309e77 | ||
|
|
5916f40b7a | ||
|
|
5226714bbd | ||
|
|
dabf486a9f | ||
|
|
c78f4407ea | ||
|
|
fae4127ddc | ||
|
|
9cc1497e9e | ||
|
|
cdd64d52eb | ||
|
|
4d319c12f8 | ||
|
|
8fc3e4ab12 | ||
|
|
ed7d68d6a7 | ||
|
|
59820519ce | ||
|
|
767c807a40 | ||
|
|
d25adc1b10 | ||
|
|
35f0067fe5 | ||
|
|
f1b01dd086 | ||
|
|
3df08d64e2 | ||
|
|
f56cc43331 | ||
|
|
b4b37daaf6 | ||
|
|
1f187d24c8 | ||
|
|
5b806a467b | ||
|
|
20d14d5a10 | ||
|
|
043b2df345 | ||
|
|
9ec7feb9ab | ||
|
|
57cf6db4e0 | ||
|
|
61b677c073 | ||
|
|
264e42a4c5 | ||
|
|
251fd660f9 | ||
|
|
6459f53263 | ||
|
|
55c8d93862 | ||
|
|
c6f83f8c14 | ||
|
|
c9eaca0e56 | ||
|
|
6267c17c6b | ||
|
|
616113d384 | ||
|
|
ac738aff10 | ||
|
|
7627bf80b9 | ||
|
|
172abb2710 | ||
|
|
a643c6ef1e | ||
|
|
64bfb0961e | ||
|
|
68d822f50a | ||
|
|
56e3bab02a | ||
|
|
9dd5ab4ebd | ||
|
|
b1ef86de75 | ||
|
|
b4a0d7a5b7 | ||
|
|
e6a93a799a | ||
|
|
4e175f9cd6 | ||
|
|
62e3fe1414 | ||
|
|
eeb7285528 | ||
|
|
0340b62b7c | ||
|
|
5488f60260 | ||
|
|
be7ef860d5 | ||
|
|
9aba700d8c | ||
|
|
7972acf5bf | ||
|
|
430c001d58 | ||
|
|
943777e5d0 | ||
|
|
c086c3b03b | ||
|
|
e517eceb24 | ||
|
|
7fb57a4064 | ||
|
|
888bca13c0 | ||
|
|
8b39e0631d | ||
|
|
d0d0148a58 | ||
|
|
a73b62c5bf | ||
|
|
bee0afd301 | ||
|
|
8f37940f4c | ||
|
|
0fa8d8cb51 | ||
|
|
1f589d0d5d | ||
|
|
ad36745a7c | ||
|
|
99b9860ea5 | ||
|
|
dc5f82cce2 | ||
|
|
dc3050537b | ||
|
|
5acd0dd2d1 | ||
|
|
0d933a1901 | ||
|
|
9f21865caf | ||
|
|
2ba81d3fef | ||
|
|
bcc1c2e658 | ||
|
|
5fa8972ae6 | ||
|
|
96363a0ce3 | ||
|
|
817fa9d9be | ||
|
|
89334bb459 | ||
|
|
0ae2d99599 | ||
|
|
e1199a02ee | ||
|
|
9408a61eb1 | ||
|
|
78d7e1bdfe | ||
|
|
dd44a0aaea | ||
|
|
b3144dd19a | ||
|
|
2722e96fac | ||
|
|
488de0014e | ||
|
|
9c2e0ebd4c | ||
|
|
28cc96cfd0 | ||
|
|
4ab3b15efd | ||
|
|
ff363e3893 | ||
|
|
cd2c10b6dc | ||
|
|
563e981902 | ||
|
|
c3e20d5d12 | ||
|
|
2802486671 | ||
|
|
1507d03c21 | ||
|
|
fbbf193345 | ||
|
|
78e51e6b11 | ||
|
|
be2bbec526 | ||
|
|
a366096ef4 | ||
|
|
c72222f718 | ||
|
|
fba0ec93bf | ||
|
|
86f767e1aa | ||
|
|
7e54192713 | ||
|
|
e76a73e276 | ||
|
|
ccf0490624 | ||
|
|
fe2721e04e | ||
|
|
fdd1a9afef | ||
|
|
abf7aed880 | ||
|
|
d986c7cdc0 | ||
|
|
9d5e994c01 | ||
|
|
6f16fc77b8 | ||
|
|
651dfb796c | ||
|
|
4f2fc17a8f | ||
|
|
7bc019547f | ||
|
|
f8c2629a3e | ||
|
|
b5b4bff2fc | ||
|
|
7054b92a14 | ||
|
|
5856f9a45f | ||
|
|
cec10060c6 | ||
|
|
74a479ab41 | ||
|
|
e51ab09bb1 | ||
|
|
0cd98bc353 | ||
|
|
158f9b0dc7 | ||
|
|
95fe6eaf86 | ||
|
|
40b4859b16 | ||
|
|
e4832f0d08 | ||
|
|
5d5400a9ac | ||
|
|
f439cad46c | ||
|
|
9fe2e8e31a | ||
|
|
92d3fc3d8c | ||
|
|
5d89599799 | ||
|
|
2eb5b5eb67 | ||
|
|
45549a8173 | ||
|
|
d7ebf2edc1 | ||
|
|
a9aed2e557 | ||
|
|
d691a0cf24 | ||
|
|
cbaa959521 | ||
|
|
2f128113b6 | ||
|
|
70251a8b2e | ||
|
|
e332f4e12b | ||
|
|
9a140ff93f | ||
|
|
97ab5dd1b5 | ||
|
|
075b4e92a9 | ||
|
|
f22dcfe03c | ||
|
|
124086419e | ||
|
|
0712db0d29 | ||
|
|
895f7edd12 | ||
|
|
a3c5c0c23a | ||
|
|
f7a3a6c17b | ||
|
|
98bec2580e | ||
|
|
5ca2d469a8 | ||
|
|
b413405876 | ||
|
|
330ff93e3e | ||
|
|
fe08104d18 | ||
|
|
e518605d69 | ||
|
|
9a35085ac3 | ||
|
|
b0cf41de08 | ||
|
|
00c3dc73f3 | ||
|
|
a73cc93d21 | ||
|
|
5a10299074 | ||
|
|
77d243f87f | ||
|
|
fb4f6406c9 | ||
|
|
3133b9b010 | ||
|
|
12723167fc | ||
|
|
2cc22778b5 | ||
|
|
790d3f12a6 | ||
|
|
beb1ab81e0 | ||
|
|
e5126b4c65 | ||
|
|
a2a4df5d06 | ||
|
|
ac0bd9714b | ||
|
|
60226d9195 | ||
|
|
64455b9852 | ||
|
|
96f6cdf677 | ||
|
|
c188491289 | ||
|
|
e9e4d566a5 | ||
|
|
85bedca236 | ||
|
|
d80191df3d | ||
|
|
9137e92c09 | ||
|
|
721dae3892 | ||
|
|
1cdacf69be | ||
|
|
b5b002aa4b | ||
|
|
78f5b513c0 | ||
|
|
0032fcaa66 | ||
|
|
0fba0923c8 | ||
|
|
e0169f6696 | ||
|
|
28217f10cb | ||
|
|
fb28f4bcd0 | ||
|
|
8852256ab6 | ||
|
|
95de453677 | ||
|
|
5ef40e15c4 | ||
|
|
31f223bff5 | ||
|
|
9fce2b1d8e | ||
|
|
a6ceb337b2 | ||
|
|
f4e22cb44c | ||
|
|
ab9750f8b2 | ||
|
|
fe8e0b0e0a | ||
|
|
c2565cf3b7 | ||
|
|
af82971bf5 | ||
|
|
271b52158e | ||
|
|
26c404adee | ||
|
|
f06af54165 | ||
|
|
2a77dfbcd2 | ||
|
|
738fcb6563 | ||
|
|
3d4754d4ad | ||
|
|
b9ea1d1be4 | ||
|
|
b1b0484dae | ||
|
|
20b79784bf | ||
|
|
4baa3358df | ||
|
|
8fe7f8b8d8 | ||
|
|
6996a0db2b | ||
|
|
b89a899c82 | ||
|
|
bbbbb660b3 | ||
|
|
6ba29219e5 | ||
|
|
dd97bdcc2c | ||
|
|
b63e0f08bf | ||
|
|
c5ae9d45ad | ||
|
|
e906a0da8c | ||
|
|
2edfb0aaac | ||
|
|
dc116858a9 | ||
|
|
1a938f8711 | ||
|
|
fc88cd3cb1 | ||
|
|
55205e631b | ||
|
|
a36fa76d21 | ||
|
|
b8d512f5e1 | ||
|
|
d4263b59c6 | ||
|
|
e5e1507dff | ||
|
|
2edf63c5fd | ||
|
|
5ec4b3441e | ||
|
|
dd1757b3c3 | ||
|
|
dda26545e5 | ||
|
|
410ef8ce96 | ||
|
|
ce7cb9cf64 | ||
|
|
31a16375ab | ||
|
|
ec7b47da22 | ||
|
|
0124020ba4 | ||
|
|
28f71d18bd | ||
|
|
fe226c1c8d | ||
|
|
18e20de4d6 | ||
|
|
956d345e17 | ||
|
|
ddfb958647 | ||
|
|
145d0ef37d | ||
|
|
019e3956f7 | ||
|
|
a72daff4ac | ||
|
|
58ce9cd37f | ||
|
|
687bdaff8f | ||
|
|
2143a66ad6 | ||
|
|
74892f1562 | ||
|
|
4a59ac011f | ||
|
|
e0fd2e8f27 | ||
|
|
ba76506773 | ||
|
|
d224827544 | ||
|
|
8d35b5bd11 | ||
|
|
9df28c25d7 | ||
|
|
5f9b2a91fd | ||
|
|
46a46f5e49 | ||
|
|
4bdc495d01 | ||
|
|
e60d5e6aeb | ||
|
|
7c3387755d | ||
|
|
6f04dad428 | ||
|
|
6ed4720df3 | ||
|
|
ac7b454039 | ||
|
|
0af39de346 | ||
|
|
d484979fe8 | ||
|
|
6e87e5c05f | ||
|
|
7633c8e76e | ||
|
|
c78e89c3c1 | ||
|
|
1852aaf332 | ||
|
|
8b4c8f63c0 | ||
|
|
d7b64c18c2 | ||
|
|
09668c972e | ||
|
|
68a0d10443 | ||
|
|
0708e7f8f6 | ||
|
|
1235e989d4 | ||
|
|
3a6808e4d8 | ||
|
|
dbfb034548 | ||
|
|
94d01e9e5a | ||
|
|
5e48b49b7e | ||
|
|
3b0785cae0 | ||
|
|
bd3b46d624 | ||
|
|
1cbe996831 | ||
|
|
18865c44c8 | ||
|
|
ead6ca73e5 | ||
|
|
deb3f6d9c4 | ||
|
|
b1b98c5256 | ||
|
|
4dc2227f23 | ||
|
|
a76f9e11fb | ||
|
|
abeb91a5e4 | ||
|
|
6d5e7cbe08 | ||
|
|
c468c26ad6 | ||
|
|
a0e940c5a9 | ||
|
|
2f1de22cae | ||
|
|
4631282709 | ||
|
|
306ac5243a | ||
|
|
956fe42a6c | ||
|
|
1824bdfe7e | ||
|
|
5f53284cbd | ||
|
|
7a84b71eb2 | ||
|
|
85382cd6c2 | ||
|
|
02a99f1e51 | ||
|
|
fe405df704 | ||
|
|
ac5ee90c9b | ||
|
|
fb6b34e155 | ||
|
|
caa8932c9a | ||
|
|
75611f3bca | ||
|
|
f0f14d8a22 | ||
|
|
98ad6cd23b | ||
|
|
bd80d1cd76 | ||
|
|
5a4670ec2f | ||
|
|
6fd039925a | ||
|
|
cd602ab5e3 | ||
|
|
f59ead54d3 | ||
|
|
4030f1e40d | ||
|
|
b7ac7452f7 | ||
|
|
5dd6867408 | ||
|
|
9d410df287 | ||
|
|
fe8dc36074 | ||
|
|
0cef3fbf27 | ||
|
|
b5d9b18da4 | ||
|
|
dc0ea197cd | ||
|
|
5bf17fc5ae | ||
|
|
33ca5943fa | ||
|
|
edc6591041 | ||
|
|
113ec33743 | ||
|
|
8c297832f6 | ||
|
|
e767b2ff94 | ||
|
|
a1ff408c13 | ||
|
|
440184e83c | ||
|
|
8ee6cad7ea | ||
|
|
edb17b76f0 | ||
|
|
31dc5f335d | ||
|
|
eb68e4c627 | ||
|
|
98e97920ae | ||
|
|
533723cd8b | ||
|
|
9e69afbbd6 | ||
|
|
2dea76dfa1 | ||
|
|
8a8bafb199 | ||
|
|
5a21d8c24d | ||
|
|
5111b4799c | ||
|
|
528bbe0116 | ||
|
|
3030ab8664 | ||
|
|
2698ff1a04 | ||
|
|
084dd1c8dd | ||
|
|
a8392889de | ||
|
|
3bf5edc2b3 | ||
|
|
97be0ff22a | ||
|
|
b43c8c018b | ||
|
|
38a5a4b97b | ||
|
|
73d70b6953 | ||
|
|
6b06733192 | ||
|
|
359146f60b | ||
|
|
0931c6a7e1 | ||
|
|
f2049c5910 | ||
|
|
de76827dd8 | ||
|
|
0cae3ac5a1 | ||
|
|
4fc378d3e2 | ||
|
|
e3e11d233c | ||
|
|
fcfd5c7419 | ||
|
|
be8c498aea | ||
|
|
5528b9ba09 | ||
|
|
c60877b6f2 | ||
|
|
07901946d0 | ||
|
|
705ea18b2a | ||
|
|
3277cc3675 | ||
|
|
c09b7bed34 | ||
|
|
83e633534d | ||
|
|
8a2c299653 | ||
|
|
74dc2ed1f9 | ||
|
|
dc0d6a9b4a | ||
|
|
3f264097a7 | ||
|
|
e0c7b17bd5 | ||
|
|
d43b027c25 | ||
|
|
85963cafe7 | ||
|
|
d4deeb4edd | ||
|
|
c72bfe3685 | ||
|
|
90137f2263 | ||
|
|
d8474cfafa | ||
|
|
493a756aaa | ||
|
|
95d30ba4ec | ||
|
|
dbcb3e6192 | ||
|
|
4228642b53 | ||
|
|
acba87ae46 | ||
|
|
533f17b3b0 | ||
|
|
77de71d79d | ||
|
|
caadb7fa27 | ||
|
|
1dd862f83d | ||
|
|
70bb4930f6 | ||
|
|
852eb5c524 | ||
|
|
3cfc45c4e8 | ||
|
|
db97c2a5b1 | ||
|
|
70993256b9 | ||
|
|
a439c3be3c | ||
|
|
0a060982e3 | ||
|
|
7ffcc176cd | ||
|
|
4a9650df80 | ||
|
|
f1c6f09f98 | ||
|
|
f039c0636e | ||
|
|
a620e1490c | ||
|
|
d682361cfc | ||
|
|
d3f0a14867 | ||
|
|
83393f299a | ||
|
|
bf1285567e | ||
|
|
e315726001 | ||
|
|
2f3e172162 | ||
|
|
d6cf9bd8ae | ||
|
|
5710a35388 | ||
|
|
1156d00538 | ||
|
|
5707354a18 | ||
|
|
155cc4573c | ||
|
|
3288592d30 | ||
|
|
886b683739 | ||
|
|
95cffca5f1 | ||
|
|
85cb592a7e | ||
|
|
13b9deb5ef | ||
|
|
c307c692a0 | ||
|
|
008e98d980 | ||
|
|
b11f597521 | ||
|
|
944c523a49 | ||
|
|
3c365259cc | ||
|
|
98274d4b17 | ||
|
|
12a1cb9e97 | ||
|
|
d273750849 | ||
|
|
75c54c6738 | ||
|
|
ffd72fbb4d | ||
|
|
71dc3d4826 | ||
|
|
b7757d71bf | ||
|
|
55338e731b | ||
|
|
097aa3fa16 | ||
|
|
935d6a7cf5 | ||
|
|
c69d1c7fb8 | ||
|
|
b5152c0c48 | ||
|
|
ed02df113f | ||
|
|
2afdcf54ab | ||
|
|
764fbe7fac | ||
|
|
0c9160ec8b | ||
|
|
33bed487ac | ||
|
|
3e36382b58 | ||
|
|
7ec656db09 | ||
|
|
cf61779b08 | ||
|
|
71600a4f37 | ||
|
|
14320f2155 | ||
|
|
1923368353 | ||
|
|
752bd78de5 | ||
|
|
c4b17855e5 | ||
|
|
a1543f79cb | ||
|
|
d4798ccaa5 | ||
|
|
c2c4ed1fe5 | ||
|
|
614188c82b | ||
|
|
53e98c114a | ||
|
|
73c8246204 | ||
|
|
58d98f8454 | ||
|
|
7605396e84 | ||
|
|
cec339552e | ||
|
|
fc003db139 | ||
|
|
caf434aef2 | ||
|
|
5261873f39 | ||
|
|
421b58f68e | ||
|
|
850dbd62c6 | ||
|
|
2af45da0a8 | ||
|
|
685e8bac22 | ||
|
|
47002f970d | ||
|
|
f6fd395485 | ||
|
|
4f426dafef | ||
|
|
7b6f2863a9 | ||
|
|
834a9bc84d | ||
|
|
7710a1fdb0 | ||
|
|
4abdc29d9e | ||
|
|
a4295d1e93 | ||
|
|
c9ff6be881 | ||
|
|
40a8892cb7 | ||
|
|
933b77e429 | ||
|
|
ccc4386285 | ||
|
|
4364ba46e2 | ||
|
|
d7917a6a9a | ||
|
|
81e30e75c4 | ||
|
|
7a94343dec | ||
|
|
9a77e6b3cc | ||
|
|
a1727cc047 | ||
|
|
5b012b6509 | ||
|
|
c23ffa2ce5 | ||
|
|
ff68383732 | ||
|
|
bce2b2adb6 | ||
|
|
fa8c9a8418 | ||
|
|
f6bb6037f3 | ||
|
|
7fac7c8713 | ||
|
|
bdaef0b0dc | ||
|
|
134cb68396 | ||
|
|
a299533508 | ||
|
|
d4bcbc3771 | ||
|
|
d8264fada7 | ||
|
|
1f636bf7a9 |
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"project_id" : "sourcemod",
|
||||||
|
"conduit_uri" : "https://phabricator.alliedmods.net/",
|
||||||
|
"history.immutable" : false
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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 [[email protected]](mailto:[email protected]) 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.
|
||||||
@@ -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
|
||||||
@@ -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.
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
# Binaries
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
*.exe
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Files generated by Visual Studio
|
||||||
|
*.aps
|
||||||
|
*.ipch
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
CrazyDebug*/
|
||||||
|
Debug*/
|
||||||
|
Release*/
|
||||||
|
LIB-Release/
|
||||||
|
LIB-Debug/
|
||||||
|
|
||||||
|
# Files generated by Mac OS X Finder
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Files generated by Windows Explorer
|
||||||
|
[Dd]esktop.ini
|
||||||
|
[Tt]humbs.db
|
||||||
|
|
||||||
|
# AMBuild build directories
|
||||||
|
build/
|
||||||
|
obj-*/
|
||||||
|
*~
|
||||||
|
*.rej
|
||||||
|
*.orig
|
||||||
|
*.smx
|
||||||
|
*.swp
|
||||||
|
*.gdb_history
|
||||||
@@ -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
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Binaries
|
|
||||||
\.dll$
|
|
||||||
\.exe$
|
|
||||||
\.so$
|
|
||||||
|
|
||||||
# Files generated by Visual Studio
|
|
||||||
\.aps$
|
|
||||||
\.ncb$
|
|
||||||
\.suo$
|
|
||||||
\.user$
|
|
||||||
|
|
||||||
# Build directories
|
|
||||||
/CrazyDebug.*
|
|
||||||
/Debug.*
|
|
||||||
/Release.*
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
54539fa4e51f98d7841c853c1370dff6ccd3cdf2 sourcemod-1.0.0
|
|
||||||
e6ef5ecdf8d75740ca2685a709bf321f8873bc3b sourcemod-1.1.0
|
|
||||||
e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1
|
|
||||||
b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2
|
|
||||||
3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0
|
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
git:
|
||||||
|
depth: 3
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
language: cpp
|
||||||
|
os: linux
|
||||||
|
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:
|
||||||
|
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
|
||||||
|
script:
|
||||||
|
- mkdir build && cd build
|
||||||
|
- PATH="~/.local/bin:$PATH"
|
||||||
|
- eval "${MATRIX_EVAL}"
|
||||||
|
- python ../configure.py --enable-optimize --sdks=episode1,css,tf2,l4d2,csgo,dota
|
||||||
|
- ambuild
|
||||||
+671
@@ -0,0 +1,671 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os, sys
|
||||||
|
|
||||||
|
class SDK(object):
|
||||||
|
def __init__(self, sdk, ext, aDef, name, platform, dir):
|
||||||
|
self.folder = 'hl2sdk-' + dir
|
||||||
|
self.envvar = sdk
|
||||||
|
self.ext = ext
|
||||||
|
self.code = aDef
|
||||||
|
self.define = name
|
||||||
|
self.platform = platform
|
||||||
|
self.name = dir
|
||||||
|
self.path = None # Actual path
|
||||||
|
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']
|
||||||
|
WinLinux = ['windows', 'linux']
|
||||||
|
WinLinuxMac = ['windows', 'linux', 'mac']
|
||||||
|
CSGO = {
|
||||||
|
'windows': ['x86'],
|
||||||
|
'linux': ['x86', 'x64'],
|
||||||
|
'mac': ['x64']
|
||||||
|
}
|
||||||
|
|
||||||
|
PossibleSDKs = {
|
||||||
|
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
|
||||||
|
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
|
||||||
|
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
|
||||||
|
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
|
||||||
|
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
|
||||||
|
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
|
||||||
|
'tf2': SDK('HL2SDKTF2', '2.tf2', '11', 'TF2', WinLinuxMac, 'tf2'),
|
||||||
|
'l4d': SDK('HL2SDKL4D', '2.l4d', '12', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
|
||||||
|
'nucleardawn': SDK('HL2SDKND', '2.nd', '13', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
|
||||||
|
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '15', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
|
||||||
|
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
|
||||||
|
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'),
|
||||||
|
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
|
||||||
|
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
|
||||||
|
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'),
|
||||||
|
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
|
||||||
|
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
|
||||||
|
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
|
||||||
|
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '14', '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):
|
||||||
|
if env in os.environ:
|
||||||
|
path = os.environ[env]
|
||||||
|
if os.path.isdir(path):
|
||||||
|
return path
|
||||||
|
return None
|
||||||
|
|
||||||
|
head = os.getcwd()
|
||||||
|
oldhead = None
|
||||||
|
while head != None and head != oldhead:
|
||||||
|
path = os.path.join(head, folder)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
return path
|
||||||
|
oldhead = head
|
||||||
|
head, tail = os.path.split(head)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def Normalize(path):
|
||||||
|
return os.path.abspath(os.path.normpath(path))
|
||||||
|
|
||||||
|
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):
|
||||||
|
def __init__(self):
|
||||||
|
self.sdks = {}
|
||||||
|
self.binaries = []
|
||||||
|
self.extensions = []
|
||||||
|
self.generated_headers = None
|
||||||
|
self.mms_root = None
|
||||||
|
self.mysql_root = {}
|
||||||
|
self.spcomp = None
|
||||||
|
self.spcomp_bins = None
|
||||||
|
self.smx_files = {}
|
||||||
|
self.versionlib = None
|
||||||
|
self.archs = builder.target.arch.replace('x86_64', 'x64').split(',')
|
||||||
|
|
||||||
|
def use_auto_versioning(self):
|
||||||
|
if builder.backend != 'amb2':
|
||||||
|
return False
|
||||||
|
return not getattr(builder.options, 'disable_auto_versioning', False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tag(self):
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
return 'Debug'
|
||||||
|
return 'Release'
|
||||||
|
|
||||||
|
def detectProductVersion(self):
|
||||||
|
builder.AddConfigureFile('product.version')
|
||||||
|
|
||||||
|
# For OS X dylib versioning
|
||||||
|
import re
|
||||||
|
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
|
||||||
|
productContents = fp.read()
|
||||||
|
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
|
||||||
|
if m == None:
|
||||||
|
self.productVersion = '1.0.0'
|
||||||
|
else:
|
||||||
|
major, minor, release = m.groups()
|
||||||
|
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
|
||||||
|
|
||||||
|
def detectSDKs(self):
|
||||||
|
sdk_list = builder.options.sdks.split(',')
|
||||||
|
use_all = sdk_list[0] == 'all'
|
||||||
|
use_present = sdk_list[0] == 'present'
|
||||||
|
|
||||||
|
for sdk_name in PossibleSDKs:
|
||||||
|
sdk = PossibleSDKs[sdk_name]
|
||||||
|
if sdk.shouldBuild(builder.target, self.archs):
|
||||||
|
if builder.options.hl2sdk_root:
|
||||||
|
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
|
||||||
|
else:
|
||||||
|
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
|
||||||
|
if sdk_path is None or not os.path.isdir(sdk_path):
|
||||||
|
if use_all or sdk_name in sdk_list:
|
||||||
|
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
|
||||||
|
continue
|
||||||
|
if use_all or use_present or sdk_name in sdk_list:
|
||||||
|
sdk.path = Normalize(sdk_path)
|
||||||
|
self.sdks[sdk_name] = sdk
|
||||||
|
|
||||||
|
if len(self.sdks) < 1 and len(sdk_list):
|
||||||
|
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:
|
||||||
|
self.mms_root = builder.options.mms_path
|
||||||
|
else:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
|
||||||
|
if not self.mms_root:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
|
||||||
|
if not self.mms_root:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
|
||||||
|
|
||||||
|
if not self.mms_root or not os.path.isdir(self.mms_root):
|
||||||
|
raise Exception('Could not find a source copy of Metamod:Source')
|
||||||
|
self.mms_root = Normalize(self.mms_root)
|
||||||
|
|
||||||
|
if builder.options.hasMySql:
|
||||||
|
if builder.options.mysql_path:
|
||||||
|
self.mysql_root['x86'] = builder.options.mysql_path
|
||||||
|
else:
|
||||||
|
for i in range(10):
|
||||||
|
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
|
||||||
|
if self.mysql_root['x86']:
|
||||||
|
break
|
||||||
|
if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
|
||||||
|
raise Exception('Could not find a path to MySQL!')
|
||||||
|
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):
|
||||||
|
builder.AddConfigureFile('pushbuild.txt')
|
||||||
|
|
||||||
|
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'):
|
||||||
|
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 += [
|
||||||
|
'stricmp=strcasecmp',
|
||||||
|
'_stricmp=strcasecmp',
|
||||||
|
'_snprintf=snprintf',
|
||||||
|
'_vsnprintf=vsnprintf',
|
||||||
|
'HAVE_STDINT_H',
|
||||||
|
'GNUC',
|
||||||
|
]
|
||||||
|
cxx.cflags += [
|
||||||
|
'-pipe',
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-Wall',
|
||||||
|
'-Werror',
|
||||||
|
'-Wno-unused',
|
||||||
|
'-Wno-switch',
|
||||||
|
'-Wno-array-bounds',
|
||||||
|
'-msse',
|
||||||
|
'-fvisibility=hidden',
|
||||||
|
]
|
||||||
|
cxx.cxxflags += [
|
||||||
|
'-std=c++11',
|
||||||
|
'-fno-exceptions',
|
||||||
|
'-fno-threadsafe-statics',
|
||||||
|
'-Wno-non-virtual-dtor',
|
||||||
|
'-Wno-overloaded-virtual',
|
||||||
|
'-fvisibility-inlines-hidden',
|
||||||
|
]
|
||||||
|
|
||||||
|
have_gcc = cxx.family == 'gcc'
|
||||||
|
have_clang = cxx.family == 'clang'
|
||||||
|
if cxx.version >= 'clang-3.9':
|
||||||
|
cxx.cxxflags += ['-Wno-expansion-to-defined']
|
||||||
|
if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
|
||||||
|
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']
|
||||||
|
if have_clang or (cxx.version >= 'gcc-4.7'):
|
||||||
|
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||||
|
if cxx.version >= 'gcc-4.8':
|
||||||
|
cxx.cflags += ['-Wno-unused-result']
|
||||||
|
if cxx.version >= 'gcc-9.0':
|
||||||
|
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
|
||||||
|
if have_clang:
|
||||||
|
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||||
|
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
||||||
|
cxx.cxxflags += ['-Wno-deprecated-register']
|
||||||
|
else:
|
||||||
|
cxx.cxxflags += ['-Wno-deprecated']
|
||||||
|
cxx.cflags += ['-Wno-sometimes-uninitialized']
|
||||||
|
|
||||||
|
if have_gcc:
|
||||||
|
cxx.cflags += ['-mfpmath=sse']
|
||||||
|
cxx.cflags += ['-Wno-maybe-uninitialized']
|
||||||
|
|
||||||
|
if builder.options.opt == '1':
|
||||||
|
cxx.cflags += ['-O3']
|
||||||
|
|
||||||
|
def configure_msvc(self, cxx):
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
cxx.cflags += ['/MTd']
|
||||||
|
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
||||||
|
else:
|
||||||
|
cxx.cflags += ['/MT']
|
||||||
|
cxx.defines += [
|
||||||
|
'_CRT_SECURE_NO_DEPRECATE',
|
||||||
|
'_CRT_SECURE_NO_WARNINGS',
|
||||||
|
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||||
|
'_ITERATOR_DEBUG_LEVEL=0',
|
||||||
|
]
|
||||||
|
cxx.cflags += [
|
||||||
|
'/W3',
|
||||||
|
]
|
||||||
|
cxx.cxxflags += [
|
||||||
|
'/EHsc',
|
||||||
|
'/GR-',
|
||||||
|
'/TP',
|
||||||
|
]
|
||||||
|
cxx.linkflags += [
|
||||||
|
'kernel32.lib',
|
||||||
|
'user32.lib',
|
||||||
|
'gdi32.lib',
|
||||||
|
'winspool.lib',
|
||||||
|
'comdlg32.lib',
|
||||||
|
'advapi32.lib',
|
||||||
|
'shell32.lib',
|
||||||
|
'ole32.lib',
|
||||||
|
'oleaut32.lib',
|
||||||
|
'uuid.lib',
|
||||||
|
'odbc32.lib',
|
||||||
|
'odbccp32.lib',
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.options.opt == '1':
|
||||||
|
cxx.cflags += ['/Ox', '/Zo']
|
||||||
|
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
||||||
|
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
cxx.cflags += ['/Od', '/RTC1']
|
||||||
|
|
||||||
|
# This needs to be after our optimization flags which could otherwise disable it.
|
||||||
|
# Don't omit the frame pointer.
|
||||||
|
cxx.cflags += ['/Oy-']
|
||||||
|
|
||||||
|
def configure_linux(self, cxx):
|
||||||
|
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
|
||||||
|
cxx.linkflags += ['-lm']
|
||||||
|
if cxx.family == 'gcc':
|
||||||
|
cxx.linkflags += ['-static-libgcc']
|
||||||
|
elif cxx.family == 'clang':
|
||||||
|
cxx.linkflags += ['-lgcc_eh']
|
||||||
|
|
||||||
|
def configure_mac(self, cxx):
|
||||||
|
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
|
||||||
|
cxx.cflags += ['-mmacosx-version-min=10.5']
|
||||||
|
cxx.linkflags += [
|
||||||
|
'-mmacosx-version-min=10.5',
|
||||||
|
'-lstdc++',
|
||||||
|
'-stdlib=libstdc++',
|
||||||
|
]
|
||||||
|
cxx.cxxflags += ['-stdlib=libstdc++']
|
||||||
|
|
||||||
|
def configure_windows(self, cxx):
|
||||||
|
cxx.defines += ['WIN32', '_WINDOWS']
|
||||||
|
|
||||||
|
def AddVersioning(self, binary, arch):
|
||||||
|
if builder.target.platform == 'windows':
|
||||||
|
binary.sources += ['version.rc']
|
||||||
|
binary.compiler.rcdefines += [
|
||||||
|
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
||||||
|
'RC_COMPILE',
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
if binary.type == 'library':
|
||||||
|
binary.compiler.postlink += [
|
||||||
|
'-compatibility_version', '1.0.0',
|
||||||
|
'-current_version', self.productVersion
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
binary.compiler.linkflags += [self.versionlib[arch]]
|
||||||
|
binary.compiler.sourcedeps += SM.generated_headers
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def LibraryBuilder(self, compiler, name, arch):
|
||||||
|
binary = compiler.Library(name)
|
||||||
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
self.AddVersioning(binary, arch)
|
||||||
|
if binary.compiler.like('msvc'):
|
||||||
|
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def ProgramBuilder(self, compiler, name, arch):
|
||||||
|
binary = compiler.Program(name)
|
||||||
|
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):
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(context.currentSourcePath),
|
||||||
|
os.path.join(context.currentSourcePath, 'sdk'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'extensions'),
|
||||||
|
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
|
]
|
||||||
|
return compiler
|
||||||
|
|
||||||
|
def ExtLibrary(self, context, name, arch):
|
||||||
|
binary = self.Library(context, name, arch)
|
||||||
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def ConfigureForHL2(self, binary, sdk, arch):
|
||||||
|
compiler = binary.compiler
|
||||||
|
|
||||||
|
SetArchFlags(compiler, arch, builder.target.platform)
|
||||||
|
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(self.mms_root, 'core'),
|
||||||
|
os.path.join(self.mms_root, 'core', 'sourcehook'),
|
||||||
|
]
|
||||||
|
|
||||||
|
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
|
||||||
|
compiler.defines += defines
|
||||||
|
|
||||||
|
paths = [
|
||||||
|
['public'],
|
||||||
|
['public', 'engine'],
|
||||||
|
['public', 'mathlib'],
|
||||||
|
['public', 'vstdlib'],
|
||||||
|
['public', 'tier0'],
|
||||||
|
['public', 'tier1']
|
||||||
|
]
|
||||||
|
if sdk.name == 'episode1' or sdk.name == 'darkm':
|
||||||
|
paths.append(['public', 'dlls'])
|
||||||
|
paths.append(['game_shared'])
|
||||||
|
else:
|
||||||
|
paths.append(['public', 'game', 'server'])
|
||||||
|
paths.append(['public', 'toolframework'])
|
||||||
|
paths.append(['game', 'shared'])
|
||||||
|
paths.append(['common'])
|
||||||
|
|
||||||
|
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
|
||||||
|
|
||||||
|
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
|
||||||
|
# The 2013 SDK already has these in public/tier0/basetypes.h
|
||||||
|
compiler.defines.remove('stricmp=strcasecmp')
|
||||||
|
compiler.defines.remove('_stricmp=strcasecmp')
|
||||||
|
compiler.defines.remove('_snprintf=snprintf')
|
||||||
|
compiler.defines.remove('_vsnprintf=vsnprintf')
|
||||||
|
|
||||||
|
if compiler.like('msvc'):
|
||||||
|
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
|
||||||
|
if compiler.version >= 1900:
|
||||||
|
compiler.linkflags += ['legacy_stdio_definitions.lib']
|
||||||
|
else:
|
||||||
|
compiler.defines += ['COMPILER_GCC']
|
||||||
|
|
||||||
|
if arch == 'x64':
|
||||||
|
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
|
||||||
|
|
||||||
|
# For everything after Swarm, this needs to be defined for entity networking
|
||||||
|
# to work properly with sendprop value changes.
|
||||||
|
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
|
||||||
|
compiler.defines += ['NETWORK_VARS_ENABLED']
|
||||||
|
|
||||||
|
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2']:
|
||||||
|
if builder.target.platform in ['linux', 'mac']:
|
||||||
|
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo' and builder.target.platform == 'linux':
|
||||||
|
compiler.linkflags += ['-lstdc++']
|
||||||
|
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
||||||
|
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
if sdk.name == 'episode1':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'linux_sdk')
|
||||||
|
elif sdk.name in ['sdk2013', 'bms']:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
|
||||||
|
elif arch == 'x64':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
|
||||||
|
else:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
if sdk.name in ['sdk2013', 'bms']:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
|
||||||
|
elif arch == 'x64':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'osx64')
|
||||||
|
else:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
|
||||||
|
|
||||||
|
if builder.target.platform in ['linux', 'mac']:
|
||||||
|
if sdk.name in ['sdk2013', 'bms'] or arch == 'x64':
|
||||||
|
compiler.postlink += [
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
compiler.postlink += [
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
|
||||||
|
]
|
||||||
|
|
||||||
|
if sdk.name in ['blade', 'insurgency', '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'))]
|
||||||
|
|
||||||
|
dynamic_libs = []
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']:
|
||||||
|
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
|
||||||
|
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']
|
||||||
|
else:
|
||||||
|
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
compiler.linkflags.append('-liconv')
|
||||||
|
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
|
||||||
|
elif builder.target.platform == 'windows':
|
||||||
|
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||||
|
if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']:
|
||||||
|
libs.append('interfaces')
|
||||||
|
for lib in libs:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
||||||
|
compiler.linkflags.append(compiler.Dep(lib_path))
|
||||||
|
|
||||||
|
for library in dynamic_libs:
|
||||||
|
source_path = os.path.join(lib_folder, library)
|
||||||
|
output_path = os.path.join(binary.localFolder, library)
|
||||||
|
|
||||||
|
def make_linker(source_path, output_path):
|
||||||
|
def link(context, binary):
|
||||||
|
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
|
||||||
|
return output
|
||||||
|
return link
|
||||||
|
|
||||||
|
linker = make_linker(source_path, output_path)
|
||||||
|
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
|
||||||
|
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def HL2Library(self, context, name, sdk, arch):
|
||||||
|
binary = self.Library(context, name, arch)
|
||||||
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
|
return self.ConfigureForHL2(binary, sdk, arch)
|
||||||
|
|
||||||
|
def HL2Project(self, context, name):
|
||||||
|
project = context.cxx.LibraryProject(name)
|
||||||
|
self.ConfigureForExtension(context, project.compiler)
|
||||||
|
return project
|
||||||
|
|
||||||
|
def HL2Config(self, project, name, sdk, arch):
|
||||||
|
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
|
||||||
|
AppendArchSuffix(binary, name, arch)
|
||||||
|
self.AddVersioning(binary, arch)
|
||||||
|
return self.ConfigureForHL2(binary, sdk, arch)
|
||||||
|
|
||||||
|
SM = SMConfig()
|
||||||
|
SM.detectProductVersion()
|
||||||
|
SM.detectSDKs()
|
||||||
|
SM.configure()
|
||||||
|
|
||||||
|
if SM.use_auto_versioning():
|
||||||
|
SM.generated_headers = builder.Build(
|
||||||
|
'tools/buildbot/Versioning',
|
||||||
|
{ 'SM': SM }
|
||||||
|
)
|
||||||
|
SM.versionlib = builder.Build(
|
||||||
|
'versionlib/AMBuilder',
|
||||||
|
{ '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 = [
|
||||||
|
'loader/AMBuilder',
|
||||||
|
'core/AMBuilder',
|
||||||
|
'core/logic/AMBuilder',
|
||||||
|
'extensions/bintools/AMBuilder',
|
||||||
|
'extensions/clientprefs/AMBuilder',
|
||||||
|
'extensions/curl/AMBuilder',
|
||||||
|
'extensions/cstrike/AMBuilder',
|
||||||
|
'extensions/geoip/AMBuilder',
|
||||||
|
'extensions/mysql/AMBuilder',
|
||||||
|
'extensions/regex/AMBuilder',
|
||||||
|
'extensions/sdkhooks/AMBuilder',
|
||||||
|
'extensions/sdktools/AMBuilder',
|
||||||
|
'extensions/sqlite/AMBuilder',
|
||||||
|
'extensions/tf2/AMBuilder',
|
||||||
|
'extensions/topmenus/AMBuilder',
|
||||||
|
'extensions/updater/AMBuilder',
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.backend == 'amb2':
|
||||||
|
BuildScripts += [
|
||||||
|
'plugins/AMBuilder',
|
||||||
|
'tools/buildbot/PackageScript',
|
||||||
|
]
|
||||||
|
|
||||||
|
builder.Build(BuildScripts, { 'SM': SM })
|
||||||
|
|
||||||
|
if builder.options.breakpad_dump:
|
||||||
|
builder.Build('tools/buildbot/BreakpadSymbols', { 'SM': SM })
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
CONFIGURE YOUR IDENTITY FOR MERCURIAL!
|
|
||||||
IF YOU ARE A DEVELOPER WITH PUSH ACCESS, DO IT NOW KPLZTHX.
|
|
||||||
|
|
||||||
http://wiki.alliedmods.net/Mercurial_Tutorial#Identity
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
SourceMod
|
||||||
|
=========
|
||||||
|
|
||||||
|
General
|
||||||
|
-------
|
||||||
|
- [SourceMod website](http://www.sourcemod.net): Source Engine scripting and server administration
|
||||||
|
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=52): Discussion forum including plugin/extension development
|
||||||
|
- [General documentation](https://wiki.alliedmods.net/Category:SourceMod_Documentation): Miscellaneous information about SourceMod
|
||||||
|
- [Stable builds](http://www.sourcemod.net/downloads.php?branch=stable): The latest stable SourceMod releases
|
||||||
|
- [Dev builds](http://www.sourcemod.net/downloads.php?branch=dev): Builds of recent development versions
|
||||||
|
|
||||||
|
Development
|
||||||
|
-----------
|
||||||
|
- [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)
|
||||||
|
- [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
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
|
|
||||||
@@ -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_
|
||||||
|
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
@@ -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_
|
||||||
|
|
||||||
+253
@@ -2,6 +2,259 @@ SourceMod Changelog
|
|||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.6 [2010-10-31]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.6_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Updated support for latest Left 4 Dead 1 (bug 4681).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Updated TF2 custom kill defines (bug 4682).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.5 [2010-10-17]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.5_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Updated support for CS:S, Garry's Mod, DoD:S, TF2, HL2DM.
|
||||||
|
- Added support for Firearms: Source (bug 4537).
|
||||||
|
- Added support for Fistful of Frags (bug 3883).
|
||||||
|
- Added support for Alien Swarm (bug 4530).
|
||||||
|
- Fixed living players hearing dead players if alltalk is disabled while deadtalk is on (bug 4533, thanks Zach Callear).
|
||||||
|
- Fixed timeleft not getting reset on Game_Commencing in CS:S (bug 4557).
|
||||||
|
- Fixed PlayerRunCmd being hooked when not used (bug 3990).
|
||||||
|
- Fixed errors and missing effects caused by missing sprites on L4D2 (bug 4512).
|
||||||
|
- Fixed 'sm plugins' public command skipping plugins in recommended listing (bug 4501).
|
||||||
|
- Fixed corruption with large database.cfg files (bug 4286).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Added TF2 object stocks (bug 4536).
|
||||||
|
- Added TF2_MakeBleed native to TF2 ext (bug 4542).
|
||||||
|
- Added support for logical entities in Synergy (bug 4534).
|
||||||
|
- Updated TF2 conditions enum and defines (bug 4526).
|
||||||
|
- Fixed potential crash with IMemUtils::FindPattern on Linux (bug 4554).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.4 [2010-07-18]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.4_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Support for latest TF update (bug 4506).
|
||||||
|
- Support for latest L4D2 update (bug 4509).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Added FindFlagChar native (bug 3776).
|
||||||
|
- Added GetConVarDefault native (bug 4502).
|
||||||
|
- Added forward for TF's GetHoliday function (bug 4462).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.3 [2010-06-23]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.3_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Added support for CS:S on Orange Box
|
||||||
|
- Added gamedata for Resistance and Liberation (bug 4418).
|
||||||
|
- Updated gamedata for SourceForts, Empires, Obsidian Conflict, Zombie Master.
|
||||||
|
- Fixed memory corruption and leaks with some voice functionality (bug 4415).
|
||||||
|
- Fixed UI bug in sm_motd (bug 4460).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Added new player condition (TFCond_CritCola, bug 4447).
|
||||||
|
- Fixed clientprefs deleting cookies twice in rare cases (bug 4412).
|
||||||
|
- Fixed OnClientConnected forward not firing for bots (bug 4443).
|
||||||
|
- Fixed sm_dump_datamaps crash (bug 4424).
|
||||||
|
- Fixed switch case comparisons failing with large numbers (bug 4457).
|
||||||
|
- Fixed rare crash in output hooks (bug 4422).
|
||||||
|
- Fixed bug with dynamically sized arrays being sliced (bug 4428).
|
||||||
|
- Fixed SendConVarValue() on TF2, DOD:S, L4D, and L4D2 (bug 4273).
|
||||||
|
- Fixed TF2 natives not being marked optional (bug 4389).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.2 [2010-05-02]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.2_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Support for recent TF, DoD, and L4D2 updates (bug 4356, bug 4361, bug 4371, bug 4374, bug 4375).
|
||||||
|
- Fixed rare crash when replicating cvars to clients (bug 4315).
|
||||||
|
- Lots of extra game support for Insurgency, ZPS, CSProMod, PVKII, and FortressForever (thanks
|
||||||
|
Nicholas "psychonic" hastings).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Added TF functions for stunning, conditions, regeneration, and power play (bug 4166, bug 4331).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.1 [2010-02-09]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.1_Release_Notes
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Added extended support for CSProMod (bug 4255).
|
||||||
|
- Fixed client disconnect crash on many third party games (bug 4231).
|
||||||
|
- Improved support for Battlegrounds 2 (bug 4146).
|
||||||
|
- Improved support for Insurgency (bug 4180).
|
||||||
|
- Improved support for Garry's Mod (bug 4230, bug 4268).
|
||||||
|
- Improved support for Synergy (bug 4235).
|
||||||
|
- Updated Day of Defeat support for 20010123 update (bug 4262).
|
||||||
|
- Fixed Webternet extension not loading on Windows 2000 (bug 4234).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Fixed compiler complaints when using |any| tag on array arguments (bug 4274).
|
||||||
|
- Fixed GetClientCookieTime not being exported (bug 4237).
|
||||||
|
- Fixed potential crash in entity handling code (bug 4249).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.3.0 [2010-01-15]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.3.0_Release_Notes
|
||||||
|
|
||||||
|
Major Features:
|
||||||
|
* Left 4 Dead 2 support
|
||||||
|
* Non-networked entity support
|
||||||
|
|
||||||
|
User Changes:
|
||||||
|
|
||||||
|
- Added Left 4 Dead 2 support (bug 4075).
|
||||||
|
- Added much richer voting progress feedback (bug 1997).
|
||||||
|
- Improved support for various third-party games (Nicholas "psychonic" Hastings).
|
||||||
|
- Added @spec target (bug 2718).
|
||||||
|
- Added sm_resetcvar command (bug 3636).
|
||||||
|
- Added "motd" chat trigger (bug 2694).
|
||||||
|
- Updated GeoIP to OCT-2009.
|
||||||
|
- Fixed rare map vote error (bug 3905).
|
||||||
|
- Fixed small leak in the nominations plugin (bug 4104).
|
||||||
|
- Fixed last client being excluded from some command effects (bug 3984).
|
||||||
|
- Fixed crashes in plugin [|un|re]loading (bug 4034, bug 4038, bug 4044, bug 4153).
|
||||||
|
- Special target "@me" is now filtered for certain statuses properly (bug 4000).
|
||||||
|
- Improved non-admin to admin chat (bug 3844).
|
||||||
|
- Removed "auto.*" extension folders (bug 3949).
|
||||||
|
|
||||||
|
Developer Changes:
|
||||||
|
|
||||||
|
- Added non-networked entity support (bug 2459).
|
||||||
|
- Added improved random number generator (bug 3831).
|
||||||
|
- Added GetClientCookieTime native (bug 3736).
|
||||||
|
- Added AskPluginLoad2 callback (bug 3716).
|
||||||
|
- Added PlayerRunCmd callback (bug 3289).
|
||||||
|
- Added PointOutsideWorld native (bug 3906).
|
||||||
|
- Added API for "blanket" command hooks (bug 4015).
|
||||||
|
- Added ability to test for SourceMod features (bug 4021).
|
||||||
|
- Added ability to change broadcast status on hooked events (bug 3886).
|
||||||
|
- OnClientCommand no longer receives unconnected clients (bug 3732).
|
||||||
|
- Fixed various bugs in client listening API (bug 3818).
|
||||||
|
- Fixed crash in BanClient (bug 3912).
|
||||||
|
- Fixed various crashes in self-removing callbacks (bug 4059).
|
||||||
|
- Fixed rare HUD text crash on TF (bug 4016).
|
||||||
|
- Fixed OnConfigsExecuted not running on EP1 games with large configs (bug 3828).
|
||||||
|
- Fixed entity output hooks not working (bug 3988).
|
||||||
|
- Gamedata folder matches are now case-insensitive (bug 3913).
|
||||||
|
- Blocked plugins from hooking "sm" command (bug 4013).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.2.4 [2009-10-03]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.2.4_Release_Notes
|
||||||
|
|
||||||
|
- Updated for L4D changes (bugs 4032, 4033, 4035).
|
||||||
|
- Updated GeoLite Country database for GeoIP extension.
|
||||||
|
- Fixed crash when block-loading more than eight plugins (bug 4034).
|
||||||
|
- Fixed rare crash in hudtext code on TF (bug 4016).
|
||||||
|
- Fixed crash when reloading a blocked plugin failed (bug 4038).
|
||||||
|
- Fixed Huntsman not firing critical callback on TF (bug 3927).
|
||||||
|
- Registering the "sm" command no longer has any effect (bug 4013).
|
||||||
|
- Fixed translation bug in extension API (bug 4010).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.2.3 [2009-08-28]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.2.3_Release_Notes
|
||||||
|
|
||||||
|
- Fix extension filename lookup. (bug 3975).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.2.2 [2009-08-28]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.2.2_Release_Notes
|
||||||
|
|
||||||
|
- Removed auto folders. (bug 3949).
|
||||||
|
- Added PointOutsideWorld native to sdktools. (bug 3906).
|
||||||
|
- Added "motd" chat trigger to basetriggers. (bug 2694).
|
||||||
|
- Added manual extension reloading command to root console menu. (bug 3934)
|
||||||
|
- Fixed 'list' type custom menu entries overwriting admin restrictions. (bug 3783).
|
||||||
|
- Added sm_resetcvar command to basecommands. (bug 3636).
|
||||||
|
- Updated gamedata for DOD:S. (bug 3948).
|
||||||
|
- Updated gamedata for TF2. (bug 3948).
|
||||||
|
- Added new .ep2v build config for valve OB based games. (bug 3948).
|
||||||
|
- Fixed incorrect escaping in clientprefs SQLite queries. (bug 3904)
|
||||||
|
- Updated gamedata for Synergy. (bug 3315).
|
||||||
|
- Upgraded to pcre-7.9 (bug 3923).
|
||||||
|
- Switched Insurgency chat printing to SayText. (bug 3738).
|
||||||
|
- Updated gamedata for Insurgency. (bug 3511).
|
||||||
|
- Updated gamedata for ZM. (bug 3746).
|
||||||
|
- Updated gamedata for Empires. (bug 3500).
|
||||||
|
- Updated gamedata for ZPS. (bug 3877).
|
||||||
|
- Updated gamedata for AoC. (bug 3891).
|
||||||
|
- Fixed RemovePlayerDisguise signature for TF2. (bug 3892).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
SourceMod 1.2.1 [2009-05-31]
|
||||||
|
|
||||||
|
URL: http://wiki.alliedmods.net/SourceMod_1.2.1_Release_Notes
|
||||||
|
|
||||||
|
- Updated SDKTools for latest Team Fortress update.
|
||||||
|
- Added L4D handling to GuessSDKVersion() (bug 3842).
|
||||||
|
- Updated Zombie Panic Source offsets (bug 3632).
|
||||||
|
- Fixed crash when clientprefs saw disconnect from 64th client (bug 3821).
|
||||||
|
- Fixed Plugin_Handled acting like a Stop in usermsg hooks (bug 3685).
|
||||||
|
- Fixed early tv_enable causing crashes (bug 3766).
|
||||||
|
- Fixed unhook event crash (bug 3814).
|
||||||
|
- Fixed compiler reading uninitialized strings while processing varargs (bug 3811).
|
||||||
|
- Fixed compiler choosing whether to emit stradjust.pri on dynamic arrays based on uninitialized memory (bug 3810).
|
||||||
|
- Fixed Windows L4D CreateFakeClient signature (bug 3792).
|
||||||
|
- Fixed sm_slap for EP1 games (bug 3768).
|
||||||
|
- Fixed casting problems in TextParsers breaking TrimString for non-ASCII characters (bug 3800).
|
||||||
|
- Fixed OnClientConnect rejectmsg handling, improved doc (bug 3690).
|
||||||
|
- Fixed clientprefs not loading cookies for clients on late load (bug 3735).
|
||||||
|
- Fixed GetCommandFlags on original engine games (bug 3759).
|
||||||
|
- Fixed compiler asserting when returning a string literal (bug 3836).
|
||||||
|
- Fixed compiler erroring when tagging functions for string return (bug 3837).
|
||||||
|
- Fixed compiler not handling constant chained relational operators correctly (bug 3838).
|
||||||
|
- Fixed revote bug and inflexibilities in RedrawClientVoteMenu (bug 3834).
|
||||||
|
- Fixed auto update URL being set too late (bug 3699).
|
||||||
|
- Disabled nextmap in Synergy and Dystopia (bug 3687, bug 3741).
|
||||||
|
- Removed unnecessary SSE optimizations from msvc9 project files (bug 3756).
|
||||||
|
- Removed short-lived tag system (bug 3751).
|
||||||
|
- Removed the alive check from sm_rename. (bug 3698).
|
||||||
|
- Switched FortressForever to Valve menus (bug 3819).
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
||||||
SourceMod 1.2.0 [2009-03-05]
|
SourceMod 1.2.0 [2009-03-05]
|
||||||
|
|
||||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.0_Release_Notes
|
URL: http://wiki.alliedmods.net/SourceMod_1.2.0_Release_Notes
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"banreasons"
|
||||||
|
{
|
||||||
|
"Abusive" "Abusive"
|
||||||
|
"Racism" "Racism"
|
||||||
|
"General cheating/exploits" "General cheating/exploits"
|
||||||
|
"Wallhack" "Wallhack"
|
||||||
|
"Aimbot" "Aimbot"
|
||||||
|
"Speedhacking" "Speedhacking"
|
||||||
|
"Mic spamming" "Mic spamming"
|
||||||
|
"Admin disrespect" "Admin disrespect"
|
||||||
|
"Camping" "Camping"
|
||||||
|
"Team killing" "Team killing"
|
||||||
|
"Unacceptable Spray" "Unacceptable Spray"
|
||||||
|
"Breaking Server Rules" "Breaking Server Rules"
|
||||||
|
"Other" "Other"
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
||||||
//any more plugins from being loaded.
|
//any more plugins from being loaded.
|
||||||
sm plugins unload_all
|
sm plugins unload_all
|
||||||
|
sm plugins load_unlock
|
||||||
sm plugins load basebans.smx
|
sm plugins load basebans.smx
|
||||||
sm plugins load basecommands.smx
|
sm plugins load basecommands.smx
|
||||||
sm plugins load admin-flatfile.smx
|
sm plugins load admin-flatfile.smx
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -80,21 +84,21 @@ sm_reserve_type 0
|
|||||||
sm_reserved_slots 0
|
sm_reserved_slots 0
|
||||||
|
|
||||||
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
||||||
// slot count). Valid values are 0 (visible) or 1 (hidden).
|
// slot count). Valid values are 0 (Visible) or 1 (Hidden).
|
||||||
// --
|
// --
|
||||||
// Requires: reservedslots.smx
|
// Requires: reservedslots.smx
|
||||||
// Default: 0
|
// Default: 0
|
||||||
sm_hide_slots 0
|
sm_hide_slots 0
|
||||||
|
|
||||||
// Specifies whether or not non-admins can send messages to admins using
|
// Specifies whether or not non-admins can send messages to admins using
|
||||||
// say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
|
// say_team @<message>. Valid values are 0 (Disabled) or 1 (Enabled)
|
||||||
// --
|
// --
|
||||||
// Requires: basechat.smx
|
// Requires: basechat.smx
|
||||||
// Default: 1
|
// Default: 1
|
||||||
sm_chat_mode 1
|
sm_chat_mode 1
|
||||||
|
|
||||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
// Specifies whether or not "timeleft" will 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
|
||||||
// Default: 0
|
// Default: 0
|
||||||
@@ -105,5 +109,30 @@ 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
|
||||||
|
// "hint" box (near the bottom of the screen in most games).
|
||||||
|
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||||
|
// --
|
||||||
|
// Default: 0
|
||||||
|
sm_vote_progress_hintbox 0
|
||||||
|
|
||||||
|
// Specifies whether or not to display vote progress to clients in the
|
||||||
|
// chat area. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||||
|
// --
|
||||||
|
// Default: 0
|
||||||
|
sm_vote_progress_chat 0
|
||||||
|
|
||||||
|
// Specifies whether or not to display vote progress in the server console.
|
||||||
|
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||||
|
// --
|
||||||
|
// Default: 0
|
||||||
|
sm_vote_progress_console 0
|
||||||
|
|
||||||
|
// Specifies whether or not to display vote progress to clients in the
|
||||||
|
// client console. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||||
|
// --
|
||||||
|
// Default: 0
|
||||||
|
sm_vote_progress_client_console 0
|
||||||
|
|||||||
+42
-3
@@ -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"
|
||||||
|
|
||||||
@@ -107,4 +107,43 @@
|
|||||||
* Currently this will log details about the gamedata updating process.
|
* Currently this will log details about the gamedata updating process.
|
||||||
*/
|
*/
|
||||||
"DebugSpew" "no"
|
"DebugSpew" "no"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to yes, SourceMod will validate steamid auth strings with the Steam backend before giving out admin access.
|
||||||
|
* This can prevent malicious users from impersonating admins with stolen Steam apptickets.
|
||||||
|
* If Steam is down, admins will not be authenticated until Steam comes back up.
|
||||||
|
* This option increases the security of your server, but is still experimental.
|
||||||
|
*/
|
||||||
|
"SteamAuthstringValidation" "yes"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
|
||||||
|
* It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
|
||||||
|
* allow anyone to delete files on the server, gain full rcon control, etc.
|
||||||
|
*
|
||||||
|
* "yes" - Block malware or illegal plugins from loading (default)
|
||||||
|
* "no" - Warn about malware or illegal plugins loading
|
||||||
|
*/
|
||||||
|
"BlockBadPlugins" "yes"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a plugin takes too long to execute, hanging or freezing the game server in the process,
|
||||||
|
* SourceMod will attempt to terminate that plugin after the specified timeout length has
|
||||||
|
* passed. You can disable this feature by setting the value to "0".
|
||||||
|
*/
|
||||||
|
"SlowScriptTimeout" "8"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
"driver_default" "mysql"
|
"driver_default" "mysql"
|
||||||
|
|
||||||
|
// When specifying "host", you may use an IP address, a hostname, or a socket file path
|
||||||
|
|
||||||
"default"
|
"default"
|
||||||
{
|
{
|
||||||
"driver" "default"
|
"driver" "default"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* Each sub-section of "Plugins" should have a title which specifies a plugin filename.
|
|
||||||
* Filenames have a wildcard of *. Appending .smx is not required.
|
|
||||||
* If the filename has no explicit path, it will be patched to any sub-path in the plugins folder.
|
|
||||||
*
|
|
||||||
* Available properties for plugins are:
|
|
||||||
* "pause" - Whether or not the plugin should load paused - "yes" or "no" (default)
|
|
||||||
* "lifetime" - Lifetime of the plugin. Options:
|
|
||||||
* "mapsync" - Plugins should be reloaded on mapchange if changed (default)
|
|
||||||
* "global" - Plugin will never be unloaded or updated
|
|
||||||
* "blockload" - Plugin will always be blocked from loading. Implicit (automatic) loads
|
|
||||||
* produce no error, but explicit (manual) loads will show an error message.
|
|
||||||
* (Options are one of "yes" or "no")
|
|
||||||
*
|
|
||||||
* You can also have an "Options" section declaring options to pass onto the JIT:
|
|
||||||
* "profile" - Bit flags for profiling level. Add flags together to reach a value.
|
|
||||||
* WARNING: Profiler is _ALPHA_ software! Use it at your own risk for
|
|
||||||
* development cycles only (not production setups).
|
|
||||||
* See the wiki article "SourceMod Profiler" for more information.
|
|
||||||
* 1 - Profile natives
|
|
||||||
* 2 - Profile callbacks
|
|
||||||
* 4 - Profile internal plugin function calls
|
|
||||||
*/
|
|
||||||
|
|
||||||
"Plugins"
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
{
|
|
||||||
"pause" "no"
|
|
||||||
"lifetime" "mapsync"
|
|
||||||
|
|
||||||
"Options"
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# vim: set ts=2 sw=2 tw=99 noet:
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
from ambuild2 import run, util
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
import ambuild
|
||||||
|
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
|
||||||
|
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
|
||||||
|
except:
|
||||||
|
sys.stderr.write('AMBuild must be installed to build this project.\n')
|
||||||
|
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def make_objdir_name(p):
|
||||||
|
return 'obj-' + util.Platform() + '-' + p.target_arch
|
||||||
|
|
||||||
|
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')
|
||||||
|
parser.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
|
||||||
|
help='Path to MySQL 5')
|
||||||
|
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')
|
||||||
|
parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
||||||
|
help='Enable debugging symbols')
|
||||||
|
parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||||
|
help='Enable optimization')
|
||||||
|
parser.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
||||||
|
help='Disable building MySQL extension')
|
||||||
|
parser.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
||||||
|
help='Build against specified SDKs; valid args are "all", "present", or '
|
||||||
|
'comma-delimited list of engine names (default: %default)')
|
||||||
|
parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||||
|
default=False, help='Dump and upload breakpad symbols')
|
||||||
|
parser.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
||||||
|
default=False, help='Disable the auto versioning script')
|
||||||
|
parser.Configure()
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os
|
||||||
|
|
||||||
|
project = SM.HL2Project(builder, 'sourcemod')
|
||||||
|
project.sources += [
|
||||||
|
'MenuStyle_Valve.cpp',
|
||||||
|
'logic_bridge.cpp',
|
||||||
|
'smn_entities.cpp',
|
||||||
|
'sm_stringutil.cpp',
|
||||||
|
'MenuVoting.cpp',
|
||||||
|
'smn_events.cpp',
|
||||||
|
'frame_hooks.cpp',
|
||||||
|
'smn_nextmap.cpp',
|
||||||
|
'sourcemm_api.cpp',
|
||||||
|
'ChatTriggers.cpp',
|
||||||
|
'smn_player.cpp',
|
||||||
|
'sourcemod.cpp',
|
||||||
|
'concmd_cleaner.cpp',
|
||||||
|
'HalfLife2.cpp',
|
||||||
|
'NextMap.cpp',
|
||||||
|
'ConCmdManager.cpp',
|
||||||
|
'ConVarManager.cpp',
|
||||||
|
'PlayerManager.cpp',
|
||||||
|
'TimerSys.cpp',
|
||||||
|
'CoreConfig.cpp',
|
||||||
|
'Logger.cpp',
|
||||||
|
'smn_halflife.cpp',
|
||||||
|
'smn_console.cpp',
|
||||||
|
'UserMessages.cpp',
|
||||||
|
'MenuManager.cpp',
|
||||||
|
'smn_hudtext.cpp',
|
||||||
|
'smn_usermsgs.cpp',
|
||||||
|
'MenuStyle_Base.cpp',
|
||||||
|
'smn_keyvalues.cpp',
|
||||||
|
'smn_vector.cpp',
|
||||||
|
'EventManager.cpp',
|
||||||
|
'MenuStyle_Radio.cpp',
|
||||||
|
'sm_autonatives.cpp',
|
||||||
|
'ConsoleDetours.cpp',
|
||||||
|
'vprof_tool.cpp',
|
||||||
|
'smn_commandline.cpp',
|
||||||
|
'GameHooks.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
|
for sdk_name in SM.sdks:
|
||||||
|
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 = SM.HL2Config(project, binary_name, sdk, arch)
|
||||||
|
compiler = binary.compiler
|
||||||
|
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
builder.sourcePath
|
||||||
|
]
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||||
|
]
|
||||||
|
|
||||||
|
if compiler.like('msvc'):
|
||||||
|
compiler.defines += ['_ALLOW_KEYWORD_MACROS']
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
compiler.postlink += ['-lpthread', '-lrt']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
if arch == 'x86':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||||
|
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')
|
||||||
|
elif arch == 'x64':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
|
||||||
|
elif builder.target.platform == 'windows':
|
||||||
|
msvc_ver = compiler.version
|
||||||
|
vs_year = ''
|
||||||
|
if msvc_ver == 1800:
|
||||||
|
vs_year = '2013'
|
||||||
|
elif 1900 <= msvc_ver < 2000:
|
||||||
|
vs_year = '2015'
|
||||||
|
else:
|
||||||
|
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||||
|
|
||||||
|
if 'DEBUG' in compiler.defines:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
|
else:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
|
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
binary.sources += ['smn_protobuf.cpp']
|
||||||
|
else:
|
||||||
|
binary.sources += ['smn_bitbuffer.cpp']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
binary.sources += [
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||||
|
]
|
||||||
|
|
||||||
|
SM.binaries += builder.Add(project)
|
||||||
|
|
||||||
@@ -1,259 +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(size_t) + size);
|
|
||||||
size_t pos = m_curptr - m_pBase;
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = size;
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
*addr = m_curptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_curptr += size;
|
|
||||||
m_size += sizeof(size_t) + size;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackCell(cell_t cell)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(size_t) + sizeof(cell_t));
|
|
||||||
|
|
||||||
*(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(size_t) + sizeof(cell_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackFloat(float val)
|
|
||||||
{
|
|
||||||
CheckSize(sizeof(size_t) + sizeof(float));
|
|
||||||
|
|
||||||
*(size_t *)m_curptr = sizeof(float);
|
|
||||||
m_curptr += sizeof(size_t);
|
|
||||||
|
|
||||||
*(float *)m_curptr = val;
|
|
||||||
m_curptr += sizeof(float);
|
|
||||||
|
|
||||||
m_size += sizeof(size_t) + sizeof(float);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDataPack::PackString(const char *string)
|
|
||||||
{
|
|
||||||
size_t len = strlen(string);
|
|
||||||
size_t maxsize = sizeof(size_t) + len + 1;
|
|
||||||
CheckSize(maxsize);
|
|
||||||
|
|
||||||
// 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(size_t) + sizeof(cell_t)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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(size_t) + sizeof(float)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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(size_t)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -81,11 +81,17 @@ inline int CellRecipientFilter::GetRecipientCount() const
|
|||||||
|
|
||||||
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
if ((slot < 0) || (slot >= GetRecipientCount()))
|
if ((slot < 0) || (slot >= GetRecipientCount()))
|
||||||
{
|
{
|
||||||
return -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
return static_cast<int>(m_Players[slot]);
|
else
|
||||||
|
{
|
||||||
|
ret = static_cast<int>(m_Players[slot]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
||||||
|
|||||||
+222
-176
@@ -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.
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
* 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
|
||||||
@@ -34,66 +34,71 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "Translator.h"
|
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
|
#include "sourcemod.h"
|
||||||
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
|
#include "provider.h"
|
||||||
* can technically be compiled against any MM:S version after 1.4.2.
|
#include <bridge/include/ILogger.h>
|
||||||
*/
|
#include <amtl/am-string.h>
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
|
||||||
#else
|
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#if SH_IMPL_VERSION >= 5
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#elif SH_IMPL_VERSION == 4
|
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#elif SH_IMPL_VERSION == 3
|
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
|
||||||
#endif //SH_IMPL_VERSION
|
|
||||||
#endif //SE_ORANGEBOX
|
|
||||||
|
|
||||||
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_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
|
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;
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
m_bIsINS = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatTriggers::~ChatTriggers()
|
ChatTriggers::~ChatTriggers()
|
||||||
{
|
{
|
||||||
delete [] m_PubTrigger;
|
delete [] m_ArgSBackup;
|
||||||
m_PubTrigger = NULL;
|
m_ArgSBackup = NULL;
|
||||||
delete [] m_PrivTrigger;
|
|
||||||
m_PrivTrigger = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
void ChatTriggers::SetChatTrigger(ChatTriggerType type, const char *value)
|
||||||
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,
|
||||||
|
const char *value,
|
||||||
ConfigSource source,
|
ConfigSource source,
|
||||||
char *error,
|
char *error,
|
||||||
size_t maxlength)
|
size_t maxlength)
|
||||||
{
|
{
|
||||||
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)
|
||||||
@@ -107,204 +112,238 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
|||||||
|
|
||||||
void ChatTriggers::OnSourceModAllInitialized()
|
void ChatTriggers::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
|
m_pShouldFloodBlock = forwardsys->CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
|
||||||
m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
|
m_pDidFloodBlock = forwardsys->CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
|
||||||
|
m_pOnClientSayCmd = forwardsys->CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||||
|
m_pOnClientSayCmd_Post = forwardsys->CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModAllInitialized_Post()
|
void ChatTriggers::OnSourceModAllInitialized_Post()
|
||||||
{
|
{
|
||||||
g_pCorePhrases->AddPhraseFile("antiflood.phrases");
|
logicore.AddCorePhraseFile("antiflood.phrases");
|
||||||
}
|
}
|
||||||
|
|
||||||
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_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
};
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, 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_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
|
||||||
|
if (m_bIsINS) {
|
||||||
|
if (ConCommand *say2 = FindCommand("say2")) {
|
||||||
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
|
||||||
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||||
|
if (ConCommand *say_squad = FindCommand("say_squad")) {
|
||||||
|
hooks_.append(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
|
||||||
|
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModShutdown()
|
void ChatTriggers::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
if (m_pSayTeamCmd)
|
hooks_.clear();
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
}
|
|
||||||
if (m_pSayCmd)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Forwards.ReleaseForward(m_pShouldFloodBlock);
|
forwardsys->ReleaseForward(m_pShouldFloodBlock);
|
||||||
g_Forwards.ReleaseForward(m_pDidFloodBlock);
|
forwardsys->ReleaseForward(m_pDidFloodBlock);
|
||||||
|
forwardsys->ReleaseForward(m_pOnClientSayCmd);
|
||||||
|
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
bool ChatTriggers::OnSayCommand_Pre(int client, const ICommandArgs *command)
|
||||||
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
|
||||||
{
|
{
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Pre()
|
|
||||||
{
|
|
||||||
CCommand command;
|
|
||||||
#endif
|
|
||||||
int client;
|
|
||||||
CPlayer *pPlayer;
|
|
||||||
|
|
||||||
client = g_ConCmds.GetCommandClient();
|
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
m_bWasFloodedMessage = false;
|
m_bWasFloodedMessage = false;
|
||||||
|
m_bPluginIgnored = true;
|
||||||
|
|
||||||
|
const char *args = command->ArgS();
|
||||||
|
|
||||||
|
if (!args)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Save these off for post hook as the command data returned from the engine in older engine versions
|
||||||
|
* can be NULL, despite the data still being there and valid. */
|
||||||
|
m_Arg0Backup = command->Arg(0);
|
||||||
|
size_t len = strlen(args);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
if (m_bIsINS)
|
||||||
|
{
|
||||||
|
if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
|
||||||
|
{
|
||||||
|
args += 4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The first pair of quotes are stripped from client say commands, but not console ones.
|
||||||
|
* We do not want the forwards to differ from what is displayed.
|
||||||
|
* So only strip the first pair of quotes from client say commands. */
|
||||||
|
bool is_quoted = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
!m_bIsINS &&
|
||||||
|
#endif
|
||||||
|
client != 0 && args[0] == '"' && args[len-1] == '"')
|
||||||
|
{
|
||||||
|
/* The server normally won't display empty say commands, but in this case it does.
|
||||||
|
* I don't think it's desired so let's block it. */
|
||||||
|
if (len <= 2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
args++;
|
||||||
|
len--;
|
||||||
|
is_quoted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some? engines strip the last quote when printing the string to chat.
|
||||||
|
* This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
|
||||||
|
* but losing the last quote in the OnClientSayCommand_Post ("message) forward.
|
||||||
|
* To compensate this, we copy the args into our own buffer where the engine won't mess with
|
||||||
|
* and strip the quotes. */
|
||||||
|
delete [] m_ArgSBackup;
|
||||||
|
m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
|
||||||
|
memcpy(m_ArgSBackup, args, len+1);
|
||||||
|
|
||||||
|
/* Strip the quotes from the argument */
|
||||||
|
if (is_quoted)
|
||||||
|
{
|
||||||
|
if (m_ArgSBackup[len-1] == '"')
|
||||||
|
{
|
||||||
|
m_ArgSBackup[--len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The server console cannot do this */
|
/* The server console cannot do this */
|
||||||
if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
|
if (client == 0)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
|
||||||
/* We guarantee the client is connected */
|
/* We guarantee the client is connected */
|
||||||
if (!pPlayer->IsConnected())
|
if (!pPlayer || !pPlayer->IsConnected())
|
||||||
{
|
return false;
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *args = command.ArgS();
|
|
||||||
|
|
||||||
if (!args)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we need to block this message from being sent */
|
/* Check if we need to block this message from being sent */
|
||||||
if (ClientIsFlooding(client))
|
if (ClientIsFlooding(client))
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
|
|
||||||
if (!CoreTranslate(
|
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
|
||||||
buffer,
|
ke::SafeSprintf(buffer, sizeof(buffer), "You are flooding the server!");
|
||||||
sizeof(buffer),
|
|
||||||
"%T",
|
|
||||||
2,
|
|
||||||
NULL,
|
|
||||||
"Flooding the server",
|
|
||||||
&client))
|
|
||||||
{
|
|
||||||
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* :TODO: we should probably kick people who spam too much. */
|
/* :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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle quoted string sets */
|
|
||||||
bool is_quoted = false;
|
|
||||||
if (args[0] == '"')
|
|
||||||
{
|
|
||||||
args++;
|
|
||||||
is_quoted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_trigger = false;
|
bool is_trigger = false;
|
||||||
bool is_silent = false;
|
bool is_silent = false;
|
||||||
|
|
||||||
/* Check for either trigger */
|
// Prefer the silent trigger in case of clashes.
|
||||||
if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
|
if (strchr(m_PrivTrigger.chars(), m_ArgSBackup[0])) {
|
||||||
{
|
|
||||||
is_trigger = true;
|
|
||||||
args = &args[m_PubTriggerSize];
|
|
||||||
}
|
|
||||||
else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0)
|
|
||||||
{
|
|
||||||
is_trigger = true;
|
is_trigger = true;
|
||||||
is_silent = true;
|
is_silent = true;
|
||||||
args = &args[m_PrivTriggerSize];
|
} else if (strchr(m_PubTrigger.chars(), m_ArgSBackup[0])) {
|
||||||
|
is_trigger = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_trigger)
|
if (is_trigger) {
|
||||||
{
|
// Bump the args past the chat trigger - we only support single-character triggers now.
|
||||||
RETURN_META(MRES_IGNORED);
|
args = &m_ArgSBackup[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if this is actually a command!
|
* Test if this is actually a command!
|
||||||
*/
|
*/
|
||||||
if (!PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
|
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args))
|
||||||
{
|
{
|
||||||
CPlayer *pPlayer;
|
m_bIsChatTrigger = true;
|
||||||
if (is_silent
|
|
||||||
&& g_bSupressSilentFails
|
/**
|
||||||
&& client != 0
|
* We'll execute it in post.
|
||||||
&& (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
|
*/
|
||||||
&& pPlayer->GetAdminId() != INVALID_ADMIN_ID)
|
m_bWillProcessInPost = true;
|
||||||
{
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bIsChatTrigger = true;
|
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
|
||||||
|
return true;
|
||||||
|
|
||||||
/**
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
* We'll execute it in post.
|
return true;
|
||||||
*/
|
|
||||||
m_bWillProcessInPost = true;
|
|
||||||
m_bTriggerWasSilent = is_silent;
|
|
||||||
|
|
||||||
/* If we're silent, block */
|
|
||||||
if (is_silent)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, let the command continue */
|
/* Otherwise, let the command continue */
|
||||||
RETURN_META(MRES_IGNORED);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
bool ChatTriggers::OnSayCommand_Post(int client, const ICommandArgs *command)
|
||||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
|
||||||
#else
|
|
||||||
void ChatTriggers::OnSayCommand_Post()
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
m_bIsChatTrigger = false;
|
|
||||||
m_bWasFloodedMessage = false;
|
|
||||||
if (m_bWillProcessInPost)
|
if (m_bWillProcessInPost)
|
||||||
{
|
{
|
||||||
/* Reset this for re-entrancy */
|
/* Reset this for re-entrancy */
|
||||||
m_bWillProcessInPost = false;
|
m_bWillProcessInPost = false;
|
||||||
|
|
||||||
/* Execute the cached command */
|
/* Execute the cached command */
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
||||||
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
||||||
SetReplyTo(old);
|
SetReplyTo(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_bPluginIgnored && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
|
||||||
|
{
|
||||||
|
m_pOnClientSayCmd_Post->PushCell(client);
|
||||||
|
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
|
||||||
|
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
|
||||||
|
m_pOnClientSayCmd_Post->Execute(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bIsChatTrigger = false;
|
||||||
|
m_bWasFloodedMessage = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
|
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
||||||
{
|
{
|
||||||
/* Extract a command. This is kind of sloppy. */
|
/* Extract a command. This is kind of sloppy. */
|
||||||
char cmd_buf[64];
|
char cmd_buf[64];
|
||||||
size_t cmd_len = 0;
|
size_t cmd_len = 0;
|
||||||
const char *inptr = args;
|
const char *inptr = args;
|
||||||
while (*inptr != '\0'
|
while (*inptr != '\0'
|
||||||
&& !textparsers->IsWhitespace(inptr)
|
&& !textparsers->IsWhitespace(inptr)
|
||||||
&& *inptr != '"'
|
&& *inptr != '"'
|
||||||
&& cmd_len < sizeof(cmd_buf) - 1)
|
&& cmd_len < sizeof(cmd_buf) - 1)
|
||||||
{
|
{
|
||||||
@@ -327,50 +366,57 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, prepend. Don't worry about the buffers. This will
|
/* Now, prepend. Don't worry about the buffers. This will
|
||||||
* work because the sizes are limited from earlier.
|
* work because the sizes are limited from earlier.
|
||||||
*/
|
*/
|
||||||
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))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepended = true;
|
prepended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if we need to do extra string manipulation */
|
/* See if we need to do extra string manipulation */
|
||||||
if (is_quoted || prepended)
|
if (prepended)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* 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);
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we need to strip a quote */
|
|
||||||
if (is_quoted)
|
|
||||||
{
|
|
||||||
if (m_ToExecute[len-1] == '"')
|
|
||||||
{
|
|
||||||
m_ToExecute[--len] = '\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell_t ChatTriggers::CallOnClientSayCommand(int client)
|
||||||
|
{
|
||||||
|
cell_t res = Pl_Continue;
|
||||||
|
if (m_pOnClientSayCmd->GetFunctionCount() != 0)
|
||||||
|
{
|
||||||
|
m_pOnClientSayCmd->PushCell(client);
|
||||||
|
m_pOnClientSayCmd->PushString(m_Arg0Backup);
|
||||||
|
m_pOnClientSayCmd->PushString(m_ArgSBackup);
|
||||||
|
m_pOnClientSayCmd->Execute(&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bPluginIgnored = (res >= Pl_Stop);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
||||||
{
|
{
|
||||||
unsigned int old = m_ReplyTo;
|
unsigned int old = m_ReplyTo;
|
||||||
|
|||||||
+27
-20
@@ -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.
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
* 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
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -48,42 +50,47 @@ public: //SMGlobalClass
|
|||||||
void OnSourceModAllInitialized_Post();
|
void OnSourceModAllInitialized_Post();
|
||||||
void OnSourceModGameInitialized();
|
void OnSourceModGameInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||||
const char *value,
|
const char *value,
|
||||||
ConfigSource source,
|
ConfigSource source,
|
||||||
char *error,
|
char *error,
|
||||||
size_t maxlength);
|
size_t maxlength);
|
||||||
private: //ConCommand
|
private: //ConCommand
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
bool OnSayCommand_Pre(int client, const ICommandArgs *args);
|
||||||
void OnSayCommand_Pre(const CCommand &command);
|
bool OnSayCommand_Post(int client, const ICommandArgs *args);
|
||||||
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:
|
||||||
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
|
enum ChatTriggerType {
|
||||||
|
ChatTrigger_Public,
|
||||||
|
ChatTrigger_Private,
|
||||||
|
};
|
||||||
|
void SetChatTrigger(ChatTriggerType type, const char *value);
|
||||||
|
bool PreProcessTrigger(edict_t *pEdict, const char *args);
|
||||||
bool ClientIsFlooding(int client);
|
bool ClientIsFlooding(int client);
|
||||||
|
cell_t CallOnClientSayCommand(int client);
|
||||||
private:
|
private:
|
||||||
ConCommand *m_pSayCmd;
|
ke::Vector<ke::RefPtr<CommandHook>> hooks_;
|
||||||
ConCommand *m_pSayTeamCmd;
|
ke::AString m_PubTrigger;
|
||||||
char *m_PubTrigger;
|
ke::AString m_PrivTrigger;
|
||||||
size_t m_PubTriggerSize;
|
|
||||||
char *m_PrivTrigger;
|
|
||||||
size_t m_PrivTriggerSize;
|
|
||||||
bool m_bWillProcessInPost;
|
bool m_bWillProcessInPost;
|
||||||
bool m_bTriggerWasSilent;
|
|
||||||
bool m_bIsChatTrigger;
|
bool m_bIsChatTrigger;
|
||||||
bool m_bWasFloodedMessage;
|
bool m_bWasFloodedMessage;
|
||||||
|
bool m_bPluginIgnored;
|
||||||
unsigned int m_ReplyTo;
|
unsigned int m_ReplyTo;
|
||||||
char m_ToExecute[300];
|
char m_ToExecute[300];
|
||||||
|
const char *m_Arg0Backup;
|
||||||
|
char *m_ArgSBackup;
|
||||||
IForward *m_pShouldFloodBlock;
|
IForward *m_pShouldFloodBlock;
|
||||||
IForward *m_pDidFloodBlock;
|
IForward *m_pDidFloodBlock;
|
||||||
|
IForward *m_pOnClientSayCmd;
|
||||||
|
IForward *m_pOnClientSayCmd_Post;
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
bool m_bIsINS;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ChatTriggers g_ChatTriggers;
|
extern ChatTriggers g_ChatTriggers;
|
||||||
|
|||||||
+257
-617
File diff suppressed because it is too large
Load Diff
+68
-51
@@ -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,75 +34,93 @@
|
|||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "ForwardSys.h"
|
#include <IForwardSys.h>
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include <IAdminSystem.h>
|
#include <IAdminSystem.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
|
#include "GameHooks.h"
|
||||||
|
#include <am-autoptr.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
#include <am-utility.h>
|
||||||
|
#include <am-inlinelist.h>
|
||||||
|
#include <am-linkedlist.h>
|
||||||
|
#include <am-refcounting.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
enum CmdType
|
struct CmdHook;
|
||||||
|
struct ConCmdInfo;
|
||||||
|
|
||||||
|
struct CommandGroup : public ke::Refcounted<CommandGroup>
|
||||||
{
|
{
|
||||||
Cmd_Server,
|
ke::LinkedList<CmdHook *> hooks;
|
||||||
Cmd_Console,
|
|
||||||
Cmd_Admin,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AdminCmdInfo
|
struct AdminCmdInfo
|
||||||
{
|
{
|
||||||
AdminCmdInfo()
|
AdminCmdInfo(const ke::RefPtr<CommandGroup> &group, FlagBits flags)
|
||||||
|
: group(group),
|
||||||
|
flags(flags),
|
||||||
|
eflags(0)
|
||||||
{
|
{
|
||||||
cmdGrpId = -1;
|
|
||||||
flags = 0;
|
|
||||||
eflags = 0;
|
|
||||||
}
|
}
|
||||||
int cmdGrpId; /* index into cmdgroup string table */
|
ke::RefPtr<CommandGroup> group;
|
||||||
FlagBits flags; /* default flags */
|
FlagBits flags; /* default flags */
|
||||||
FlagBits eflags; /* effective flags */
|
FlagBits eflags; /* effective flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdHook
|
struct CmdHook : public ke::InlineListNode<CmdHook>
|
||||||
{
|
{
|
||||||
CmdHook()
|
enum Type {
|
||||||
|
Server,
|
||||||
|
Client
|
||||||
|
};
|
||||||
|
|
||||||
|
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
|
||||||
|
: type(type),
|
||||||
|
info(cmd),
|
||||||
|
pf(fun),
|
||||||
|
helptext(description)
|
||||||
{
|
{
|
||||||
pf = NULL;
|
|
||||||
pAdmin = NULL;
|
|
||||||
}
|
}
|
||||||
IPluginFunction *pf; /* function hook */
|
|
||||||
String helptext; /* help text */
|
Type type;
|
||||||
AdminCmdInfo *pAdmin; /* admin requirements, if any */
|
ConCmdInfo *info;
|
||||||
|
IPluginFunction *pf; /* function hook */
|
||||||
|
ke::AString helptext; /* help text */
|
||||||
|
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef ke::InlineList<CmdHook> CmdHookList;
|
||||||
|
|
||||||
struct ConCmdInfo
|
struct ConCmdInfo
|
||||||
{
|
{
|
||||||
ConCmdInfo()
|
ConCmdInfo()
|
||||||
{
|
{
|
||||||
|
pPlugin = nullptr;
|
||||||
sourceMod = false;
|
sourceMod = false;
|
||||||
pCmd = NULL;
|
pCmd = nullptr;
|
||||||
|
eflags = 0;
|
||||||
}
|
}
|
||||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
||||||
ConCommand *pCmd; /**< Pointer to the command itself */
|
ConCommand *pCmd; /**< Pointer to the command itself */
|
||||||
List<CmdHook *> srvhooks; /**< Hooks as a server command */
|
CmdHookList hooks; /**< Hook list */
|
||||||
List<CmdHook *> conhooks; /**< Hooks as a console command */
|
FlagBits eflags; /**< Effective admin flags */
|
||||||
AdminCmdInfo admin; /**< Admin info, if any */
|
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
|
||||||
bool is_admin_set; /**< Whether or not admin info is set */
|
IPlugin *pPlugin; /**< Owning plugin handle. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef List<ConCmdInfo *> ConCmdList;
|
||||||
|
|
||||||
class ConCmdManager :
|
class ConCmdManager :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IRootConsoleCommand,
|
public IRootConsoleCommand,
|
||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IConCommandTracker
|
public IConCommandTracker
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
friend void CommandCallback(DISPATCH_ARGS);
|
||||||
friend void CommandCallback(const CCommand &command);
|
|
||||||
#else
|
|
||||||
friend void CommandCallback();
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
ConCmdManager();
|
ConCmdManager();
|
||||||
~ConCmdManager();
|
~ConCmdManager();
|
||||||
@@ -112,50 +130,49 @@ 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 AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
|
||||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *group,
|
const char *group,
|
||||||
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);
|
||||||
bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
|
|
||||||
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);
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist);
|
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
|
||||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||||
|
|
||||||
|
// Case insensitive
|
||||||
|
ConCmdList::iterator FindInList(const char *name);
|
||||||
|
|
||||||
|
// Case sensitive
|
||||||
|
ConCmdInfo *FindInTrie(const char *name);
|
||||||
public:
|
public:
|
||||||
inline int GetCommandClient()
|
|
||||||
{
|
|
||||||
return m_CmdClient;
|
|
||||||
}
|
|
||||||
inline const List<ConCmdInfo *> & GetCommandList()
|
inline const List<ConCmdInfo *> & GetCommandList()
|
||||||
{
|
{
|
||||||
return m_CmdList;
|
return m_CmdList;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Trie *m_pCmds; /* command lookup */
|
typedef StringHashMap<ke::RefPtr<CommandGroup> > GroupMap;
|
||||||
Trie *m_pCmdGrps; /* command group lookup */
|
|
||||||
List<ConCmdInfo *> m_CmdList; /* command list */
|
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
|
||||||
int m_CmdClient; /* current client */
|
GroupMap m_CmdGrps; /* command group map */
|
||||||
BaseStringTable m_Strings; /* string table */
|
ConCmdList m_CmdList; /* command list */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConCmdManager g_ConCmds;
|
extern ConCmdManager g_ConCmds;
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
class ConCommandBaseIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline ConCommandBaseIterator() : iter(icvar)
|
||||||
|
{
|
||||||
|
iter.SetFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsValid()
|
||||||
|
{
|
||||||
|
return iter.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Next()
|
||||||
|
{
|
||||||
|
iter.Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ConCommandBase *Get()
|
||||||
|
{
|
||||||
|
return iter.Get();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ICvar::Iterator iter;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class ConCommandBaseIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline ConCommandBaseIterator()
|
||||||
|
{
|
||||||
|
iter = icvar->GetCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsValid()
|
||||||
|
{
|
||||||
|
return iter != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Next()
|
||||||
|
{
|
||||||
|
iter = const_cast<ConCommandBase *>(iter->GetNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ConCommandBase *Get()
|
||||||
|
{
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ConCommandBase *iter;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ */
|
||||||
|
|
||||||
+153
-165
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2009 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -25,42 +25,59 @@
|
|||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include <sm_namehashset.h>
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "sourcemod.h"
|
||||||
|
#include "provider.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
ConVarManager g_ConVarManager;
|
ConVarManager g_ConVarManager;
|
||||||
|
|
||||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
|
||||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
|
||||||
#else
|
|
||||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
|
||||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
||||||
typedef List<const ConVar *> ConVarList;
|
typedef List<const ConVar *> ConVarList;
|
||||||
KTrie<ConVarInfo *> convar_cache;
|
NameHashSet<ConVarInfo *> convar_cache;
|
||||||
|
|
||||||
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
class ConVarReentrancyGuard
|
||||||
|
{
|
||||||
|
ConVar *cvar;
|
||||||
|
ConVarReentrancyGuard *up;
|
||||||
|
public:
|
||||||
|
static ConVarReentrancyGuard *chain;
|
||||||
|
|
||||||
|
ConVarReentrancyGuard(ConVar *cvar)
|
||||||
|
: cvar(cvar), up(chain)
|
||||||
|
{
|
||||||
|
chain = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ConVarReentrancyGuard()
|
||||||
|
{
|
||||||
|
assert(chain == this);
|
||||||
|
chain = up;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsCvarInChain(ConVar *cvar)
|
||||||
|
{
|
||||||
|
ConVarReentrancyGuard *guard = chain;
|
||||||
|
while (guard != NULL)
|
||||||
|
{
|
||||||
|
if (guard->cvar == cvar)
|
||||||
|
return true;
|
||||||
|
guard = guard->up;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
|
||||||
|
|
||||||
|
ConVarManager::ConVarManager() : m_ConVarType(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,26 +95,17 @@ void ConVarManager::OnSourceModStartup(bool late)
|
|||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||||
|
|
||||||
/* Create the 'ConVar' handle type */
|
/* Create the 'ConVar' handle type */
|
||||||
m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
m_ConVarType = handlesys->CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnSourceModAllInitialized()
|
void ConVarManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
/**
|
g_Players.AddClientListener(this);
|
||||||
* 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_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsDLLQueryHooked = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
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()
|
||||||
@@ -112,10 +120,10 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
|
|
||||||
iter = m_ConVars.erase(iter);
|
iter = m_ConVars.erase(iter);
|
||||||
|
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
handlesys->FreeHandle(pInfo->handle, &sec);
|
||||||
if (pInfo->pChangeForward != NULL)
|
if (pInfo->pChangeForward != NULL)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pInfo->pChangeForward);
|
forwardsys->ReleaseForward(pInfo->pChangeForward);
|
||||||
}
|
}
|
||||||
if (pInfo->sourceMod)
|
if (pInfo->sourceMod)
|
||||||
{
|
{
|
||||||
@@ -143,77 +151,23 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
}
|
}
|
||||||
convar_cache.clear();
|
convar_cache.clear();
|
||||||
|
|
||||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
g_Players.RemoveClientListener(this);
|
||||||
/* Unhook things */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsDLLQueryHooked = false;
|
|
||||||
}
|
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsVSPQueryHooked = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
|
||||||
|
|
||||||
/* Remove the 'convars' option from the 'sm' console command */
|
/* Remove the 'convars' option from the 'sm' console command */
|
||||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
rootmenu->RemoveRootConsoleCommand("cvars", this);
|
||||||
|
|
||||||
|
scripts->RemovePluginsListener(this);
|
||||||
|
|
||||||
/* Remove the 'ConVar' handle type */
|
/* Remove the 'ConVar' handle type */
|
||||||
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
|
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
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
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
|
||||||
m_bIsVSPQueryHooked = true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
||||||
{
|
{
|
||||||
ConVarInfo **pLookup = convar_cache.retrieve(name);
|
return convar_cache.retrieve(name, pVar);
|
||||||
if (pLookup != NULL)
|
|
||||||
{
|
|
||||||
*pVar = *pLookup;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name)
|
||||||
{
|
{
|
||||||
/* 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;
|
||||||
@@ -229,7 +183,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
|||||||
convar_cache.remove(name);
|
convar_cache.remove(name);
|
||||||
|
|
||||||
/* Now make sure no plugins are referring to this pointer */
|
/* Now make sure no plugins are referring to this pointer */
|
||||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
IPluginIterator *pl_iter = scripts->GetPluginIterator();
|
||||||
while (pl_iter->MorePlugins())
|
while (pl_iter->MorePlugins())
|
||||||
{
|
{
|
||||||
IPlugin *pl = pl_iter->GetPlugin();
|
IPlugin *pl = pl_iter->GetPlugin();
|
||||||
@@ -245,19 +199,51 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
handlesys->FreeHandle(pInfo->handle, &sec);
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
ConVarList *pConVarList;
|
ConVarList *pConVarList;
|
||||||
|
List<ConVarQuery>::iterator iter;
|
||||||
|
|
||||||
/* If plugin has a convar list, free its memory */
|
/* If plugin has a convar list, free its memory */
|
||||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
||||||
{
|
{
|
||||||
delete pConVarList;
|
delete pConVarList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IPluginRuntime * pRuntime = plugin->GetRuntime();
|
||||||
|
|
||||||
|
/* Remove convar queries for this plugin that haven't returned results yet */
|
||||||
|
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||||
|
{
|
||||||
|
ConVarQuery &query = (*iter);
|
||||||
|
if (query.pCallback->GetParentRuntime() == pRuntime)
|
||||||
|
{
|
||||||
|
iter = m_ConVarQueries.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConVarManager::OnClientDisconnected(int client)
|
||||||
|
{
|
||||||
|
/* Remove convar queries for this client that haven't returned results yet */
|
||||||
|
for (List<ConVarQuery>::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||||
|
{
|
||||||
|
ConVarQuery &query = (*iter);
|
||||||
|
if (query.client == client)
|
||||||
|
{
|
||||||
|
iter = m_ConVarQueries.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||||
@@ -270,20 +256,27 @@ 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;
|
||||||
|
|
||||||
/* Get plugin index that was passed */
|
/* Get plugin index that was passed */
|
||||||
const char *arg = command.Arg(2);
|
const char *arg = command->Arg(2);
|
||||||
|
if (argcount >= 4 && strcmp(arg, "reset") == 0)
|
||||||
|
{
|
||||||
|
wantReset = true;
|
||||||
|
arg = command->Arg(3);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get plugin object */
|
/* Get plugin object */
|
||||||
CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
|
IPlugin *plugin = scripts->FindPluginByConsoleArg(arg);
|
||||||
|
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
{
|
{
|
||||||
g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
|
UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,25 +290,38 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
if (!wantReset)
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
{
|
||||||
|
UTIL_ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
||||||
/* Iterate convar list and display each one */
|
UTIL_ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate convar list and display/reset each one */
|
||||||
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
||||||
{
|
{
|
||||||
const ConVar *pConVar = (*iter);
|
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
if (!wantReset)
|
||||||
|
{
|
||||||
|
UTIL_ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
||||||
|
} else {
|
||||||
|
pConVar->Revert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantReset)
|
||||||
|
{
|
||||||
|
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 convars <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)
|
||||||
@@ -347,7 +353,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
pInfo->pVar = pConVar;
|
pInfo->pVar = pConVar;
|
||||||
|
|
||||||
/* If we don't, then create a new handle from the convar */
|
/* If we don't, then create a new handle from the convar */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -378,7 +384,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
|
|
||||||
/* Create a handle from the new convar */
|
/* Create a handle from the new convar */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -407,7 +413,13 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
ConVarInfo *pInfo;
|
ConVarInfo *pInfo;
|
||||||
Handle_t hndl;
|
Handle_t hndl;
|
||||||
|
|
||||||
/* Search for convar */
|
/* Check convar cache to find out if we already have a handle */
|
||||||
|
if (convar_cache_lookup(name, &pInfo))
|
||||||
|
{
|
||||||
|
return pInfo->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Couldn't find it in cache, so search for it */
|
||||||
pConVar = icvar->FindVar(name);
|
pConVar = icvar->FindVar(name);
|
||||||
|
|
||||||
/* If it doesn't exist, then return an invalid handle */
|
/* If it doesn't exist, then return an invalid handle */
|
||||||
@@ -416,12 +428,6 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point, the convar exists. So, find out if we already have a handle */
|
|
||||||
if (convar_cache_lookup(name, &pInfo))
|
|
||||||
{
|
|
||||||
return pInfo->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
/* Create and initialize ConVarInfo structure */
|
||||||
pInfo = new ConVarInfo();
|
pInfo = new ConVarInfo();
|
||||||
pInfo->sourceMod = false;
|
pInfo->sourceMod = false;
|
||||||
@@ -429,7 +435,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
pInfo->pVar = pConVar;
|
pInfo->pVar = pConVar;
|
||||||
|
|
||||||
/* If we don't have a handle, then create a new one */
|
/* If we don't have a handle, then create a new one */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -487,7 +493,7 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
|
|||||||
/* If forward does not exist, create it */
|
/* If forward does not exist, create it */
|
||||||
if (!pForward)
|
if (!pForward)
|
||||||
{
|
{
|
||||||
pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
||||||
pInfo->pChangeForward = pForward;
|
pInfo->pChangeForward = pForward;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,10 +529,11 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the forward now has 0 functions in it... */
|
/* If the forward now has 0 functions in it... */
|
||||||
if (pForward->GetFunctionCount() == 0)
|
if (pForward->GetFunctionCount() == 0 &&
|
||||||
|
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
|
||||||
{
|
{
|
||||||
/* Free this forward */
|
/* Free this forward */
|
||||||
g_Forwards.ReleaseForward(pForward);
|
forwardsys->ReleaseForward(pForward);
|
||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,26 +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
|
if (pCallback != NULL)
|
||||||
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
|
|
||||||
if (m_bIsDLLQueryHooked)
|
|
||||||
{
|
{
|
||||||
cookie = engine->StartQueryCvarValue(pPlayer, name);
|
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||||
|
m_ConVarQueries.push_back(query);
|
||||||
}
|
}
|
||||||
else if (m_bIsVSPQueryHooked)
|
|
||||||
{
|
|
||||||
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return InvalidQueryCvarCookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConVarQuery query = {cookie, pCallback, hndl};
|
|
||||||
m_ConVarQueries.push_back(query);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
@@ -565,7 +559,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
|
|||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
const char *orig = pConVar->GetName();
|
const char *orig = pConVar->GetName();
|
||||||
|
|
||||||
IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||||
|
|
||||||
/* Check plugin for an existing convar list */
|
/* Check plugin for an existing convar list */
|
||||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
||||||
@@ -596,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)
|
||||||
@@ -620,20 +610,14 @@ 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)
|
||||||
{
|
{
|
||||||
|
ConVarReentrancyGuard guard(pConVar);
|
||||||
|
|
||||||
/* Now call forwards in plugins that have hooked this */
|
/* Now call forwards in plugins that have hooked this */
|
||||||
pForward->PushCell(pInfo->handle);
|
pForward->PushCell(pInfo->handle);
|
||||||
pForward->PushString(oldValue);
|
pForward->PushString(oldValue);
|
||||||
@@ -644,11 +628,15 @@ 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
|
||||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie,
|
||||||
|
int client,
|
||||||
|
EQueryCvarValueStatus result,
|
||||||
|
const char *cvarName,
|
||||||
|
const char *cvarValue)
|
||||||
{
|
{
|
||||||
IPluginFunction *pCallback = NULL;
|
IPluginFunction *pCallback = NULL;
|
||||||
cell_t value = 0;
|
cell_t value = 0;
|
||||||
@@ -670,7 +658,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
|||||||
cell_t ret;
|
cell_t ret;
|
||||||
|
|
||||||
pCallback->PushCell(cookie);
|
pCallback->PushCell(cookie);
|
||||||
pCallback->PushCell(IndexOfEdict(pPlayer));
|
pCallback->PushCell(client);
|
||||||
pCallback->PushCell(result);
|
pCallback->PushCell(result);
|
||||||
pCallback->PushString(cvarName);
|
pCallback->PushString(cvarName);
|
||||||
|
|
||||||
@@ -696,7 +684,7 @@ HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
|||||||
ConVarInfo *pInfo;
|
ConVarInfo *pInfo;
|
||||||
HandleError error;
|
HandleError error;
|
||||||
|
|
||||||
if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
|
if ((error = handlesys->ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-29
@@ -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.
|
||||||
@@ -39,13 +39,11 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
|
#include <IPlayerHelpers.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
#if SOURCE_ENGINE == SE_DARKMESSIAH
|
#include <sm_stringhashmap.h>
|
||||||
class EQueryCvarValueStatus;
|
|
||||||
typedef int QueryCvarCookie_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
@@ -65,6 +63,15 @@ struct ConVarInfo
|
|||||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
||||||
ConVar *pVar; /**< The actual convar */
|
ConVar *pVar; /**< The actual convar */
|
||||||
List<IConVarChangeListener *> changeListeners;
|
List<IConVarChangeListener *> changeListeners;
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const ConVarInfo *info)
|
||||||
|
{
|
||||||
|
return strcmp(name, info->pVar->GetName()) == 0;
|
||||||
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,6 +82,7 @@ struct ConVarQuery
|
|||||||
QueryCvarCookie_t cookie; /**< Cookie that identifies query */
|
QueryCvarCookie_t cookie; /**< Cookie that identifies query */
|
||||||
IPluginFunction *pCallback; /**< Function that will be called when query is finished */
|
IPluginFunction *pCallback; /**< Function that will be called when query is finished */
|
||||||
cell_t value; /**< Optional value passed to query function */
|
cell_t value; /**< Optional value passed to query function */
|
||||||
|
cell_t client; /**< Only used for cleaning up on client disconnection */
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConVarManager :
|
class ConVarManager :
|
||||||
@@ -82,7 +90,8 @@ class ConVarManager :
|
|||||||
public IHandleTypeDispatch,
|
public IHandleTypeDispatch,
|
||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IRootConsoleCommand,
|
public IRootConsoleCommand,
|
||||||
public IConCommandTracker
|
public IConCommandTracker,
|
||||||
|
public IClientListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConVarManager();
|
ConVarManager();
|
||||||
@@ -91,16 +100,17 @@ 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
|
||||||
|
void OnClientDisconnected(int client);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a convar and return a handle to it.
|
* Create a convar and return a handle to it.
|
||||||
@@ -136,34 +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_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;
|
||||||
|
|||||||
@@ -0,0 +1,409 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On SourceHook v4.3 or lower, there are no DVP hooks. Very sad, right?
|
||||||
|
* Only do this on newer versions. For the older code, we'll do an incredibly
|
||||||
|
* hacky detour.
|
||||||
|
*
|
||||||
|
* The idea of the "non-hacky" (yeah... no) code is that every unique
|
||||||
|
* ConCommand vtable gets its own DVP hook. We watch for unloading and
|
||||||
|
* loading commands to remove stale hooks from SH.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sourcemod.h"
|
||||||
|
#include "sourcemm_api.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "compat_wrappers.h"
|
||||||
|
#include "ConsoleDetours.h"
|
||||||
|
#include <IGameConfigs.h>
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
#include "ConCmdManager.h"
|
||||||
|
#include "HalfLife2.h"
|
||||||
|
#include "ConCommandBaseIterator.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "command_args.h"
|
||||||
|
#include "provider.h"
|
||||||
|
#include <am-utility.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
|
#if defined PLATFORM_POSIX
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include <sys/mman.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
|
#else
|
||||||
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class GenericCommandHooker : public IConCommandLinkListener
|
||||||
|
{
|
||||||
|
struct HackInfo
|
||||||
|
{
|
||||||
|
void **vtable;
|
||||||
|
int hook;
|
||||||
|
unsigned int refcount;
|
||||||
|
};
|
||||||
|
CVector<HackInfo> vtables;
|
||||||
|
bool enabled;
|
||||||
|
SourceHook::MemFuncInfo dispatch;
|
||||||
|
|
||||||
|
inline void **GetVirtualTable(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<void***>(reinterpret_cast<char*>(pBase) +
|
||||||
|
dispatch.thisptroffs +
|
||||||
|
dispatch.vtbloffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool FindVtable(void **ptr, size_t& index)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < vtables.size(); i++)
|
||||||
|
{
|
||||||
|
if (vtables[i].vtable == ptr)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeHookable(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
if (!pBase->IsCommand())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConCommand *cmd = (ConCommand*)pBase;
|
||||||
|
void **vtable = GetVirtualTable(cmd);
|
||||||
|
|
||||||
|
size_t index;
|
||||||
|
if (!FindVtable(vtable, index))
|
||||||
|
{
|
||||||
|
HackInfo hack;
|
||||||
|
hack.vtable = vtable;
|
||||||
|
hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false);
|
||||||
|
hack.refcount = 1;
|
||||||
|
vtables.push_back(hack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vtables[index].refcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void Dispatch(const CCommand& args)
|
||||||
|
#else
|
||||||
|
void Dispatch()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
, args
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if (res >= Pl_Handled)
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReparseCommandList()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < vtables.size(); i++)
|
||||||
|
vtables[i].refcount = 0;
|
||||||
|
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||||
|
MakeHookable(iter.Get());
|
||||||
|
CVector<HackInfo>::iterator iter = vtables.begin();
|
||||||
|
while (iter != vtables.end())
|
||||||
|
{
|
||||||
|
if ((*iter).refcount)
|
||||||
|
{
|
||||||
|
iter++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Damn it. This event happens AFTER the plugin has unloaded!
|
||||||
|
* There's two options. Remove the hook now and hope SH's memory
|
||||||
|
* protection will prevent a crash. Otherwise, we can wait until
|
||||||
|
* the server shuts down and more likely crash then.
|
||||||
|
*
|
||||||
|
* This situation only arises if:
|
||||||
|
* 1) Someone has used AddCommandFilter()
|
||||||
|
* 2) ... on a Dark Messiah server (mm:s new api)
|
||||||
|
* 3) ... and another MM:S plugin that uses ConCommands has unloaded.
|
||||||
|
*
|
||||||
|
* Even though the impact is really small, we'll wait until the
|
||||||
|
* server shuts down, so normal operation isn't interrupted.
|
||||||
|
*
|
||||||
|
* See bug 4018.
|
||||||
|
*/
|
||||||
|
iter = vtables.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnhookCommand(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
if (!pBase->IsCommand())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConCommand *cmd = (ConCommand*)pBase;
|
||||||
|
void **vtable = GetVirtualTable(cmd);
|
||||||
|
|
||||||
|
size_t index;
|
||||||
|
if (!FindVtable(vtable, index))
|
||||||
|
{
|
||||||
|
logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(vtables[index].refcount > 0);
|
||||||
|
vtables[index].refcount--;
|
||||||
|
if (vtables[index].refcount == 0)
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK_ID(vtables[index].hook);
|
||||||
|
vtables.erase(vtables.iterAt(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
GenericCommandHooker() : enabled(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Enable()
|
||||||
|
{
|
||||||
|
SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch);
|
||||||
|
|
||||||
|
if (dispatch.thisptroffs < 0)
|
||||||
|
{
|
||||||
|
logger->LogError("Command filter could not determine ConCommand layout");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||||
|
MakeHookable(iter.Get());
|
||||||
|
|
||||||
|
if (!vtables.size())
|
||||||
|
{
|
||||||
|
logger->LogError("Command filter could not find any cvars!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disable()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < vtables.size(); i++)
|
||||||
|
SH_REMOVE_HOOK_ID(vtables[i].hook);
|
||||||
|
vtables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
MakeHookable(pBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
if (pBase == NULL)
|
||||||
|
ReparseCommandList();
|
||||||
|
else
|
||||||
|
UnhookCommand(pBase);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BEGIN THE ACTUALLY GENERIC CODE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FEATURECAP_COMMANDLISTENER "command listener"
|
||||||
|
|
||||||
|
static GenericCommandHooker s_GenericHooker;
|
||||||
|
ConsoleDetours g_ConsoleDetours;
|
||||||
|
|
||||||
|
ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleDetours::OnSourceModAllInitialized()
|
||||||
|
{
|
||||||
|
m_pForward = forwardsys->CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
|
||||||
|
Param_String, Param_Cell);
|
||||||
|
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleDetours::OnSourceModShutdown()
|
||||||
|
{
|
||||||
|
for (StringHashMap<IChangeableForward *>::iterator iter = m_Listeners.iter();
|
||||||
|
!iter.empty();
|
||||||
|
iter.next())
|
||||||
|
{
|
||||||
|
forwardsys->ReleaseForward(iter->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
forwardsys->ReleaseForward(m_pForward);
|
||||||
|
s_GenericHooker.Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureStatus ConsoleDetours::GetFeatureStatus(FeatureType type, const char *name)
|
||||||
|
{
|
||||||
|
return GetStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureStatus ConsoleDetours::GetStatus()
|
||||||
|
{
|
||||||
|
if (status == FeatureStatus_Unknown)
|
||||||
|
{
|
||||||
|
status = s_GenericHooker.Enable() ? FeatureStatus_Available : FeatureStatus_Unavailable;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
|
||||||
|
{
|
||||||
|
if (GetStatus() != FeatureStatus_Available)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
m_pForward->AddFunction(fun);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||||
|
{
|
||||||
|
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
||||||
|
Param_String, Param_Cell);
|
||||||
|
m_Listeners.insert(str.get(), forward);
|
||||||
|
}
|
||||||
|
forward->AddFunction(fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
||||||
|
{
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
return m_pForward->RemoveFunction(fun);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||||
|
return false;
|
||||||
|
return forward->RemoveFunction(fun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t ConsoleDetours::InternalDispatch(int client, const ICommandArgs *args)
|
||||||
|
{
|
||||||
|
char name[255];
|
||||||
|
const char *realname = args->Arg(0);
|
||||||
|
size_t len = strlen(realname);
|
||||||
|
|
||||||
|
// Disallow command strings that are too long, for now.
|
||||||
|
if (len >= sizeof(name) - 1)
|
||||||
|
return Pl_Continue;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (realname[i] >= 'A' && realname[i] <= 'Z')
|
||||||
|
name[i] = tolower(realname[i]);
|
||||||
|
else
|
||||||
|
name[i] = realname[i];
|
||||||
|
}
|
||||||
|
name[len] = '\0';
|
||||||
|
|
||||||
|
cell_t result = Pl_Continue;
|
||||||
|
m_pForward->PushCell(client);
|
||||||
|
m_pForward->PushString(name);
|
||||||
|
m_pForward->PushCell(args->ArgC() - 1);
|
||||||
|
m_pForward->Execute(&result, NULL);
|
||||||
|
|
||||||
|
/* Don't let plugins block this. */
|
||||||
|
if (strcmp(name, "sm") == 0)
|
||||||
|
result = Pl_Continue;
|
||||||
|
|
||||||
|
if (result >= Pl_Handled)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(name, &forward))
|
||||||
|
return result;
|
||||||
|
if (forward->GetFunctionCount() == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
cell_t result2 = Pl_Continue;
|
||||||
|
forward->PushCell(client);
|
||||||
|
forward->PushString(name);
|
||||||
|
forward->PushCell(args->ArgC() - 1);
|
||||||
|
forward->Execute(&result2, NULL);
|
||||||
|
|
||||||
|
if (result2 > result)
|
||||||
|
result = result2;
|
||||||
|
|
||||||
|
/* "sm" should not have flown through the above. */
|
||||||
|
assert(strcmp(name, "sm") != 0 || result == Pl_Continue);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
cell_t ConsoleDetours::Dispatch(ConCommand *pBase, const CCommand& args)
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
|
||||||
|
{
|
||||||
|
CCommand args;
|
||||||
|
#endif
|
||||||
|
EngineArgs cargs(args);
|
||||||
|
cell_t res;
|
||||||
|
{
|
||||||
|
AutoEnterCommand autoEnterCommand(&cargs);
|
||||||
|
res = g_ConsoleDetours.InternalDispatch(sCoreProviderImpl.CommandClient(), &cargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2009 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -28,61 +28,55 @@
|
|||||||
*
|
*
|
||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_SERVERCOMMANDS_H_
|
#include "sm_globals.h"
|
||||||
#define _INCLUDE_SOURCEMOD_SERVERCOMMANDS_H_
|
|
||||||
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include <IRootConsoleMenu.h>
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include <sh_list.h>
|
#include <IForwardSys.h>
|
||||||
#include <sh_string.h>
|
#include <sm_stringhashmap.h>
|
||||||
#include <compat_wrappers.h>
|
|
||||||
#include "sm_trie.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
namespace SourceMod {
|
||||||
using namespace SourceHook;
|
class ICommandArgs;
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
struct ConsoleEntry
|
class ConsoleDetours :
|
||||||
{
|
|
||||||
String command;
|
|
||||||
String description;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RootConsoleMenu :
|
|
||||||
public IConCommandBaseAccessor,
|
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IRootConsoleCommand,
|
public IFeatureProvider
|
||||||
public IRootConsole
|
|
||||||
{
|
{
|
||||||
|
friend class PlayerManager;
|
||||||
|
friend class GenericCommandHooker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RootConsoleMenu();
|
ConsoleDetours();
|
||||||
~RootConsoleMenu();
|
|
||||||
public:
|
|
||||||
const char *GetInterfaceName();
|
|
||||||
unsigned int GetInterfaceVersion();
|
|
||||||
public: //IConCommandBaseAccessor
|
|
||||||
bool RegisterConCommandBase(ConCommandBase *pCommand);
|
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModStartup(bool late);
|
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
public: //IRootConsoleCommand
|
public: //IFeatureProvider
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||||
public: //IRootConsole
|
|
||||||
bool AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler);
|
|
||||||
bool RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler);
|
|
||||||
void ConsolePrint(const char *fmt, ...);
|
|
||||||
void DrawGenericOption(const char *cmd, const char *text);
|
|
||||||
public:
|
public:
|
||||||
void GotRootCmd(const CCommand &cmd);
|
bool AddListener(IPluginFunction *fun, const char *command);
|
||||||
|
bool RemoveListener(IPluginFunction *fun, const char *command);
|
||||||
private:
|
private:
|
||||||
bool m_CfgExecDone;
|
cell_t InternalDispatch(int client, const SourceMod::ICommandArgs *args);
|
||||||
Trie *m_pCommands;
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
List<ConsoleEntry *> m_Menu;
|
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
|
||||||
|
#else
|
||||||
|
static cell_t Dispatch(ConCommand *pBase);
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
FeatureStatus GetStatus();
|
||||||
|
bool IsEnabled()
|
||||||
|
{
|
||||||
|
return status == FeatureStatus_Available;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
FeatureStatus status;
|
||||||
|
IChangeableForward *m_pForward;
|
||||||
|
StringHashMap<IChangeableForward *> m_Listeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern RootConsoleMenu g_RootMenu;
|
extern ConsoleDetours g_ConsoleDetours;
|
||||||
|
|
||||||
|
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_SERVERCOMMANDS_H_
|
|
||||||
+126
-81
@@ -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,14 +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_version.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "compat_wrappers.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");
|
||||||
@@ -64,12 +70,8 @@ void CheckAndFinalizeConfigs();
|
|||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if 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
|
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
|
||||||
void Hook_ExecDispatchPre()
|
|
||||||
#else
|
#else
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
|
||||||
void Hook_ExecDispatchPre()
|
void Hook_ExecDispatchPre()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@@ -103,23 +105,19 @@ void CheckAndFinalizeConfigs()
|
|||||||
{
|
{
|
||||||
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
|
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
g_PendingInternalPush = true;
|
g_PendingInternalPush = true;
|
||||||
#else
|
|
||||||
SM_InternalCmdTrigger();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
||||||
g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
||||||
g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreConfig::CoreConfig() : m_Strings(512)
|
CoreConfig::CoreConfig()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,15 +127,15 @@ CoreConfig::~CoreConfig()
|
|||||||
|
|
||||||
void CoreConfig::OnSourceModShutdown()
|
void CoreConfig::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
rootmenu->RemoveRootConsoleCommand("config", this);
|
||||||
g_Forwards.ReleaseForward(g_pOnServerCfg);
|
forwardsys->ReleaseForward(g_pOnServerCfg);
|
||||||
g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
|
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
|
||||||
g_Forwards.ReleaseForward(g_pOnAutoConfigsBuffered);
|
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
|
||||||
|
|
||||||
if (g_pExecPtr != NULL)
|
if (g_pExecPtr != NULL)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
|
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
|
||||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
|
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
|
||||||
g_pExecPtr = NULL;
|
g_pExecPtr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,8 +160,8 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
|||||||
g_pExecPtr = FindCommand("exec");
|
g_pExecPtr = FindCommand("exec");
|
||||||
if (g_pExecPtr != NULL)
|
if (g_pExecPtr != NULL)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
|
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
|
||||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
|
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -179,31 +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("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;
|
||||||
|
} else if (argcount >= 3) {
|
||||||
|
const char *option = command->Arg(2);
|
||||||
|
|
||||||
|
const char *value = GetCoreConfigValue(option);
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
{
|
||||||
|
UTIL_ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
||||||
|
} else {
|
||||||
|
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()
|
||||||
@@ -214,25 +226,38 @@ void CoreConfig::Initialize()
|
|||||||
/* Try to get command line value of core config convar */
|
/* Try to get command line value of core config convar */
|
||||||
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
||||||
|
|
||||||
/* If sm_corecfgfile not specified on command line, use default value */
|
/* If sm_corecfgfile is on the command line, use that
|
||||||
if (!corecfg)
|
* If sm_corecfgfile isn't there, check sm_basepath on the command line and build the path off that
|
||||||
|
* If sm_basepath isn't there, just use the default path for the cfg
|
||||||
|
*/
|
||||||
|
if (corecfg)
|
||||||
{
|
{
|
||||||
corecfg = sm_corecfgfile.GetDefault();
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *basepath = icvar->GetCommandLineValue("sm_basepath");
|
||||||
|
|
||||||
/* Format path to config file */
|
/* Format path to config file */
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
if (basepath)
|
||||||
|
{
|
||||||
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset cached key values */
|
/* Reset cached key values */
|
||||||
m_KeyValues.clear();
|
m_KeyValues.clear();
|
||||||
m_Strings.Reset();
|
|
||||||
|
|
||||||
/* Parse config file */
|
/* Parse config file */
|
||||||
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
||||||
{
|
{
|
||||||
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
||||||
const char *error = textparsers->GetSMCErrorString(err);
|
const char *error = textparsers->GetSMCErrorString(err);
|
||||||
g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
|
logger->LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +269,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
|||||||
if (err == ConfigResult_Reject)
|
if (err == ConfigResult_Reject)
|
||||||
{
|
{
|
||||||
/* This is a fatal error */
|
/* This is a fatal error */
|
||||||
g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
|
logger->LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SMCResult_Continue;
|
return SMCResult_Continue;
|
||||||
@@ -252,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;
|
||||||
@@ -260,24 +285,23 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_KeyValues.replace(option, m_Strings.AddString(value));
|
ke::AString vstr(value);
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
int *pKey = m_KeyValues.retrieve(key);
|
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key);
|
||||||
if (pKey == NULL)
|
if (!r.found())
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
return r->value.chars();
|
||||||
return m_Strings.GetString(*pKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SM_AreConfigsExecuted()
|
bool SM_AreConfigsExecuted()
|
||||||
@@ -294,7 +318,7 @@ inline bool IsPathSepChar(char c)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||||
{
|
{
|
||||||
bool will_create = false;
|
bool will_create = false;
|
||||||
|
|
||||||
@@ -312,12 +336,12 @@ bool SM_ExecuteConfig(CPlugin *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
|
||||||
@@ -338,14 +362,12 @@ bool SM_ExecuteConfig(CPlugin *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);
|
||||||
}
|
}
|
||||||
@@ -357,13 +379,13 @@ bool SM_ExecuteConfig(CPlugin *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());
|
||||||
@@ -371,7 +393,7 @@ bool SM_ExecuteConfig(CPlugin *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;
|
||||||
@@ -381,7 +403,7 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
FILE *fp = fopen(file, "wt");
|
FILE *fp = fopen(file, "wt");
|
||||||
if (fp)
|
if (fp)
|
||||||
{
|
{
|
||||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
|
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SOURCEMOD_VERSION);
|
||||||
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
||||||
fprintf(fp, "\n\n");
|
fprintf(fp, "\n\n");
|
||||||
|
|
||||||
@@ -390,8 +412,11 @@ bool SM_ExecuteConfig(CPlugin *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;
|
||||||
}
|
}
|
||||||
@@ -400,7 +425,7 @@ bool SM_ExecuteConfig(CPlugin *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 */
|
||||||
@@ -438,13 +463,18 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
can_create = false;
|
can_create = false;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||||
|
return 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,10 +498,10 @@ void SM_DoSingleExecFwds(IPluginContext *ctx)
|
|||||||
|
|
||||||
void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
||||||
{
|
{
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
IPluginIterator *iter = scripts->GetPluginIterator();
|
||||||
while (iter->MorePlugins())
|
while (iter->MorePlugins())
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
IPlugin *plugin = iter->GetPlugin();
|
||||||
if (plugin->GetSerial() == serial)
|
if (plugin->GetSerial() == serial)
|
||||||
{
|
{
|
||||||
SM_DoSingleExecFwds(plugin->GetBaseContext());
|
SM_DoSingleExecFwds(plugin->GetBaseContext());
|
||||||
@@ -484,7 +514,7 @@ void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
|||||||
|
|
||||||
void SM_ExecuteForPlugin(IPluginContext *ctx)
|
void SM_ExecuteForPlugin(IPluginContext *ctx)
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
|
SMPlugin *plugin = scripts->FindPluginByContext(ctx->GetContext());
|
||||||
|
|
||||||
unsigned int num = plugin->GetConfigCount();
|
unsigned int num = plugin->GetConfigCount();
|
||||||
if (!num)
|
if (!num)
|
||||||
@@ -499,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,19 +543,17 @@ void SM_ExecuteAllConfigs()
|
|||||||
|
|
||||||
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
|
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
|
||||||
|
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
AutoPluginList plugins(scripts);
|
||||||
while (iter->MorePlugins())
|
for (size_t i = 0; i < plugins->size(); i++)
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
SMPlugin *plugin = plugins->at(i);
|
||||||
unsigned int num = plugin->GetConfigCount();
|
unsigned int num = plugin->GetConfigCount();
|
||||||
bool can_create = true;
|
bool can_create = true;
|
||||||
for (unsigned int i=0; i<num; i++)
|
for (unsigned int i=0; i<num; i++)
|
||||||
{
|
{
|
||||||
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
||||||
}
|
}
|
||||||
iter->NextPlugin();
|
|
||||||
}
|
}
|
||||||
iter->Release();
|
|
||||||
|
|
||||||
g_bGotServerStart = true;
|
g_bGotServerStart = true;
|
||||||
CheckAndFinalizeConfigs();
|
CheckAndFinalizeConfigs();
|
||||||
@@ -548,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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+5
-6
@@ -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.
|
||||||
@@ -35,8 +35,8 @@
|
|||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include <ITextParsers.h>
|
#include <ITextParsers.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include <am-string.h>
|
||||||
#include "sm_memtable.h"
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -68,8 +68,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
||||||
private:
|
private:
|
||||||
BaseStringTable m_Strings;
|
StringHashMap<ke::AString> m_KeyValues;
|
||||||
KTrie<int> m_KeyValues;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool SM_AreConfigsExecuted();
|
extern bool SM_AreConfigsExecuted();
|
||||||
|
|||||||
@@ -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;
|
|
||||||
+75
-42
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2010 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,10 +30,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EventManager.h"
|
#include "EventManager.h"
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include <bridge/include/IScriptManager.h>
|
||||||
|
|
||||||
EventManager g_EventManager;
|
EventManager g_EventManager;
|
||||||
|
|
||||||
@@ -42,16 +43,26 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
|
|||||||
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
||||||
typedef List<EventHook *> EventHookList;
|
typedef List<EventHook *> EventHookList;
|
||||||
|
|
||||||
|
class EventForwardFilter : public IForwardFilter
|
||||||
|
{
|
||||||
|
EventInfo *pEventInfo;
|
||||||
|
public:
|
||||||
|
EventForwardFilter(EventInfo *pEventInfo) : pEventInfo(pEventInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
|
||||||
|
{
|
||||||
|
params[2].val = pEventInfo->bDontBroadcast ? 1 : 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
EventManager::EventManager() : m_EventType(0)
|
EventManager::EventManager() : m_EventType(0)
|
||||||
{
|
{
|
||||||
/* Create an event lookup trie */
|
|
||||||
m_EventHooks = sm_trie_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventManager::~EventManager()
|
EventManager::~EventManager()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_EventHooks);
|
|
||||||
|
|
||||||
/* Free memory used by EventInfo structs if any */
|
/* Free memory used by EventInfo structs if any */
|
||||||
CStack<EventInfo *>::iterator iter;
|
CStack<EventInfo *>::iterator iter;
|
||||||
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
|
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
|
||||||
@@ -65,8 +76,8 @@ EventManager::~EventManager()
|
|||||||
void EventManager::OnSourceModAllInitialized()
|
void EventManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
/* Add a hook for IGameEventManager2::FireEvent() */
|
/* Add a hook for IGameEventManager2::FireEvent() */
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
||||||
|
|
||||||
HandleAccess sec;
|
HandleAccess sec;
|
||||||
|
|
||||||
@@ -76,17 +87,17 @@ void EventManager::OnSourceModAllInitialized()
|
|||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||||
|
|
||||||
/* Create the 'GameEvent' handle type */
|
/* Create the 'GameEvent' handle type */
|
||||||
m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
m_EventType = handlesys->CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::OnSourceModShutdown()
|
void EventManager::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
/* Remove hook for IGameEventManager2::FireEvent() */
|
/* Remove hook for IGameEventManager2::FireEvent() */
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
||||||
|
|
||||||
/* Remove the 'GameEvent' handle type */
|
/* Remove the 'GameEvent' handle type */
|
||||||
g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
|
handlesys->RemoveType(m_EventType, g_pCoreIdent);
|
||||||
|
|
||||||
/* Remove ourselves as listener for events */
|
/* Remove ourselves as listener for events */
|
||||||
gameevents->RemoveListener(this);
|
gameevents->RemoveListener(this);
|
||||||
@@ -124,12 +135,12 @@ void EventManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
{
|
{
|
||||||
if (pHook->pPreHook)
|
if (pHook->pPreHook)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pHook->pPreHook);
|
forwardsys->ReleaseForward(pHook->pPreHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHook->pPostHook)
|
if (pHook->pPostHook)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pHook->pPostHook);
|
forwardsys->ReleaseForward(pHook->pPostHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pHook;
|
delete pHook;
|
||||||
@@ -147,6 +158,13 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
|||||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
int EventManager::GetEventDebugID()
|
||||||
|
{
|
||||||
|
return EVENT_DEBUG_ID_INIT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
||||||
{
|
{
|
||||||
EventHook *pHook;
|
EventHook *pHook;
|
||||||
@@ -163,10 +181,10 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If a hook structure does not exist... */
|
/* If a hook structure does not exist... */
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
if (!m_EventHooks.retrieve(name, &pHook))
|
||||||
{
|
{
|
||||||
EventHookList *pHookList;
|
EventHookList *pHookList;
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
|
||||||
|
|
||||||
/* Check plugin for an existing EventHook list */
|
/* Check plugin for an existing EventHook list */
|
||||||
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
|
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
|
||||||
@@ -181,12 +199,12 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
if (mode == EventHookMode_Pre)
|
if (mode == EventHookMode_Pre)
|
||||||
{
|
{
|
||||||
/* Create forward for a pre hook */
|
/* Create forward for a pre hook */
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
|
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
|
||||||
/* Add to forward list */
|
/* Add to forward list */
|
||||||
pHook->pPreHook->AddFunction(pFunction);
|
pHook->pPreHook->AddFunction(pFunction);
|
||||||
} else {
|
} else {
|
||||||
/* Create forward for a post hook */
|
/* Create forward for a post hook */
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
||||||
/* Should we copy data from a pre hook to the post hook? */
|
/* Should we copy data from a pre hook to the post hook? */
|
||||||
pHook->postCopy = (mode == EventHookMode_Post);
|
pHook->postCopy = (mode == EventHookMode_Post);
|
||||||
/* Add to forward list */
|
/* Add to forward list */
|
||||||
@@ -194,14 +212,14 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cache the name for post hooks */
|
/* Cache the name for post hooks */
|
||||||
pHook->name = sm_strdup(name);
|
pHook->name = name;
|
||||||
|
|
||||||
/* Increase reference count */
|
/* Increase reference count */
|
||||||
pHook->refCount++;
|
pHook->refCount++;
|
||||||
|
|
||||||
/* Add hook structure to hook lists */
|
/* Add hook structure to hook lists */
|
||||||
pHookList->push_back(pHook);
|
pHookList->push_back(pHook);
|
||||||
sm_trie_insert(m_EventHooks, name, pHook);
|
m_EventHooks.insert(name, pHook);
|
||||||
|
|
||||||
return EventHookErr_Okay;
|
return EventHookErr_Okay;
|
||||||
}
|
}
|
||||||
@@ -213,7 +231,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
/* Create pre hook forward if necessary */
|
/* Create pre hook forward if necessary */
|
||||||
if (!pHook->pPreHook)
|
if (!pHook->pPreHook)
|
||||||
{
|
{
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
|
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add plugin function to forward list */
|
/* Add plugin function to forward list */
|
||||||
@@ -222,7 +240,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
/* Create post hook forward if necessary */
|
/* Create post hook forward if necessary */
|
||||||
if (!pHook->pPostHook)
|
if (!pHook->pPostHook)
|
||||||
{
|
{
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If postCopy is false, then we may want to set it to true */
|
/* If postCopy is false, then we may want to set it to true */
|
||||||
@@ -247,7 +265,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
IChangeableForward **pEventForward;
|
IChangeableForward **pEventForward;
|
||||||
|
|
||||||
/* If hook does not exist at all */
|
/* If hook does not exist at all */
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
if (!m_EventHooks.retrieve(name, &pHook))
|
||||||
{
|
{
|
||||||
return EventHookErr_NotActive;
|
return EventHookErr_NotActive;
|
||||||
}
|
}
|
||||||
@@ -269,7 +287,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
/* If forward's list contains 0 functions now, free it */
|
/* If forward's list contains 0 functions now, free it */
|
||||||
if ((*pEventForward)->GetFunctionCount() == 0)
|
if ((*pEventForward)->GetFunctionCount() == 0)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(*pEventForward);
|
forwardsys->ReleaseForward(*pEventForward);
|
||||||
*pEventForward = NULL;
|
*pEventForward = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +297,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
/* If reference count is now 0, free hook structure */
|
/* If reference count is now 0, free hook structure */
|
||||||
|
|
||||||
EventHookList *pHookList;
|
EventHookList *pHookList;
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
|
||||||
|
|
||||||
/* Get plugin's event hook list */
|
/* Get plugin's event hook list */
|
||||||
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
|
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
|
||||||
@@ -297,10 +315,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
pHookList->remove(pHook);
|
pHookList->remove(pHook);
|
||||||
|
|
||||||
/* Delete entry in trie */
|
/* Delete entry in trie */
|
||||||
sm_trie_delete(m_EventHooks, name);
|
m_EventHooks.remove(name);
|
||||||
|
|
||||||
/* Free the cached name */
|
|
||||||
delete pHook->name;
|
|
||||||
|
|
||||||
/* And finally free structure memory */
|
/* And finally free structure memory */
|
||||||
delete pHook;
|
delete pHook;
|
||||||
@@ -327,6 +342,7 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
|
|||||||
|
|
||||||
pInfo->pEvent = pEvent;
|
pInfo->pEvent = pEvent;
|
||||||
pInfo->pOwner = pContext->GetIdentity();
|
pInfo->pOwner = pContext->GetIdentity();
|
||||||
|
pInfo->bDontBroadcast = false;
|
||||||
|
|
||||||
return pInfo;
|
return pInfo;
|
||||||
}
|
}
|
||||||
@@ -346,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 */
|
||||||
@@ -365,6 +388,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
IChangeableForward *pForward;
|
IChangeableForward *pForward;
|
||||||
const char *name;
|
const char *name;
|
||||||
cell_t res = Pl_Continue;
|
cell_t res = Pl_Continue;
|
||||||
|
bool broadcast = bDontBroadcast;
|
||||||
|
|
||||||
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
||||||
if (!pEvent)
|
if (!pEvent)
|
||||||
@@ -374,7 +398,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
|
|
||||||
name = pEvent->GetName();
|
name = pEvent->GetName();
|
||||||
|
|
||||||
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
|
if (m_EventHooks.retrieve(name, &pHook))
|
||||||
{
|
{
|
||||||
/* Push the event onto the event stack. The reference count is increased to make sure
|
/* Push the event onto the event stack. The reference count is increased to make sure
|
||||||
* the structure is not garbage collected in between now and the post hook.
|
* the structure is not garbage collected in between now and the post hook.
|
||||||
@@ -388,14 +412,20 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
{
|
{
|
||||||
EventInfo info(pEvent, NULL);
|
EventInfo info(pEvent, NULL);
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||||
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
Handle_t hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
|
info.bDontBroadcast = bDontBroadcast;
|
||||||
|
|
||||||
|
EventForwardFilter filter(&info);
|
||||||
|
|
||||||
pForward->PushCell(hndl);
|
pForward->PushCell(hndl);
|
||||||
pForward->PushString(name);
|
pForward->PushString(name);
|
||||||
pForward->PushCell(bDontBroadcast);
|
pForward->PushCell(bDontBroadcast);
|
||||||
pForward->Execute(&res, NULL);
|
pForward->Execute(&res, &filter);
|
||||||
|
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
broadcast = info.bDontBroadcast;
|
||||||
|
|
||||||
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHook->postCopy)
|
if (pHook->postCopy)
|
||||||
@@ -403,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);
|
||||||
@@ -414,6 +444,9 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
m_EventStack.push(NULL);
|
m_EventStack.push(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (broadcast != bDontBroadcast)
|
||||||
|
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,16 +474,17 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
{
|
{
|
||||||
if (pHook->postCopy)
|
if (pHook->postCopy)
|
||||||
{
|
{
|
||||||
|
info.bDontBroadcast = bDontBroadcast;
|
||||||
info.pEvent = m_EventCopies.front();
|
info.pEvent = m_EventCopies.front();
|
||||||
info.pOwner = NULL;
|
info.pOwner = NULL;
|
||||||
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
pForward->PushCell(hndl);
|
pForward->PushCell(hndl);
|
||||||
} else {
|
} else {
|
||||||
pForward->PushCell(BAD_HANDLE);
|
pForward->PushCell(BAD_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pForward->PushString(pHook->name);
|
pForward->PushString(pHook->name.chars());
|
||||||
pForward->PushCell(bDontBroadcast);
|
pForward->PushCell(bDontBroadcast);
|
||||||
pForward->Execute(NULL);
|
pForward->Execute(NULL);
|
||||||
|
|
||||||
@@ -458,7 +492,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
{
|
{
|
||||||
/* Free handle */
|
/* Free handle */
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
|
|
||||||
/* Free event structure */
|
/* Free event structure */
|
||||||
gameevents->FreeEvent(info.pEvent);
|
gameevents->FreeEvent(info.pEvent);
|
||||||
@@ -471,8 +505,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
{
|
{
|
||||||
assert(pHook->pPostHook == NULL);
|
assert(pHook->pPostHook == NULL);
|
||||||
assert(pHook->pPreHook == NULL);
|
assert(pHook->pPreHook == NULL);
|
||||||
sm_trie_delete(m_EventHooks, pHook->name);
|
m_EventHooks.remove(pHook->name.chars());
|
||||||
delete pHook->name;
|
|
||||||
delete pHook;
|
delete pHook;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-5
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2010 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,13 +34,15 @@
|
|||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_namehashset.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
|
|
||||||
|
class IClient;
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
struct EventInfo
|
struct EventInfo
|
||||||
@@ -53,6 +55,7 @@ struct EventInfo
|
|||||||
}
|
}
|
||||||
IGameEvent *pEvent;
|
IGameEvent *pEvent;
|
||||||
IdentityToken_t *pOwner;
|
IdentityToken_t *pOwner;
|
||||||
|
bool bDontBroadcast;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventHook
|
struct EventHook
|
||||||
@@ -68,7 +71,16 @@ struct EventHook
|
|||||||
IChangeableForward *pPostHook;
|
IChangeableForward *pPostHook;
|
||||||
bool postCopy;
|
bool postCopy;
|
||||||
unsigned int refCount;
|
unsigned int refCount;
|
||||||
char *name;
|
ke::AString name;
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const EventHook *hook)
|
||||||
|
{
|
||||||
|
return strcmp(name, hook->name.chars()) == 0;
|
||||||
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EventHookMode
|
enum EventHookMode
|
||||||
@@ -104,6 +116,9 @@ public: // IPluginsListener
|
|||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public: // IGameEventListener2
|
public: // IGameEventListener2
|
||||||
void FireGameEvent(IGameEvent *pEvent);
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
|
int GetEventDebugID();
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Get the 'GameEvent' handle type ID.
|
* Get the 'GameEvent' handle type ID.
|
||||||
@@ -117,13 +132,14 @@ 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);
|
||||||
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
||||||
private:
|
private:
|
||||||
HandleType_t m_EventType;
|
HandleType_t m_EventType;
|
||||||
Trie *m_EventHooks;
|
NameHashSet<EventHook *> m_EventHooks;
|
||||||
CStack<EventInfo *> m_FreeEvents;
|
CStack<EventInfo *> m_FreeEvents;
|
||||||
CStack<EventHook *> m_EventStack;
|
CStack<EventHook *> m_EventStack;
|
||||||
CStack<IGameEvent *> m_EventCopies;
|
CStack<IGameEvent *> m_EventCopies;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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_
|
||||||
+888
-108
File diff suppressed because it is too large
Load Diff
+163
-20
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-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
|
||||||
@@ -35,16 +35,24 @@
|
|||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_tinyhash.h>
|
#include <sh_tinyhash.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include <am-utility.h>
|
||||||
#include "sm_trie.h"
|
#include <am-hashset.h>
|
||||||
|
#include <am-hashmap.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
#include <sm_namehashset.h>
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sm_queue.h"
|
#include "sm_queue.h"
|
||||||
#include <IGameHelpers.h>
|
#include <IGameHelpers.h>
|
||||||
#include <KeyValues.h>
|
#include <KeyValues.h>
|
||||||
#include <server_class.h>
|
#include <server_class.h>
|
||||||
#include <datamap.h>
|
#include <datamap.h>
|
||||||
|
#include <ihandleentity.h>
|
||||||
|
#include <tier0/icommandline.h>
|
||||||
|
#include <string_t.h>
|
||||||
|
|
||||||
class CCommand;
|
namespace SourceMod {
|
||||||
|
class ICommandArgs;
|
||||||
|
} // namespace SourceMod
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -52,18 +60,79 @@ 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
|
||||||
|
{
|
||||||
|
static inline bool matches(const char *name, const sm_sendprop_info_t &info)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return strcmp(name, info->sc->GetName()) == 0;
|
||||||
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTableInfo(ServerClass *sc)
|
||||||
|
: sc(sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ServerClass *sc;
|
ServerClass *sc;
|
||||||
KTrie<sm_sendprop_info_t> lookup;
|
NameHashSet<sm_sendprop_info_t, SendPropPolicy> lookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DataMapTrie
|
struct DataMapCachePolicy
|
||||||
{
|
{
|
||||||
DataMapTrie() : trie(NULL) {}
|
static inline bool matches(const char *name, const sm_datatable_info_t &info)
|
||||||
Trie *trie;
|
{
|
||||||
|
return strcmp(name, info.prop->fieldName) == 0;
|
||||||
|
}
|
||||||
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
|
||||||
|
|
||||||
struct DelayedFakeCliCmd
|
struct DelayedFakeCliCmd
|
||||||
{
|
{
|
||||||
String cmd;
|
String cmd;
|
||||||
@@ -73,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
|
||||||
@@ -86,26 +155,56 @@ struct DelayedKickInfo
|
|||||||
char buffer[384];
|
char buffer[384];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// copy from game/shared/entitylist_base.h
|
||||||
|
class CEntInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IHandleEntity *m_pEntity;
|
||||||
|
int m_SerialNumber;
|
||||||
|
CEntInfo *m_pPrev;
|
||||||
|
CEntInfo *m_pNext;
|
||||||
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
|
string_t m_iName;
|
||||||
|
string_t m_iClassName;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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();
|
||||||
public:
|
public:
|
||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
|
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);
|
||||||
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
||||||
ServerClass *FindServerClass(const char *classname);
|
ServerClass *FindServerClass(const char *classname);
|
||||||
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
||||||
|
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
|
||||||
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
||||||
bool TextMsg(int client, int dest, const char *msg);
|
bool TextMsg(int client, int dest, const char *msg);
|
||||||
bool HintTextMsg(int client, const char *msg);
|
bool HintTextMsg(int client, const char *msg);
|
||||||
|
bool HintTextMsg(cell_t *players, int count, const char *msg);
|
||||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||||
bool IsLANServer();
|
bool IsLANServer();
|
||||||
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||||
@@ -115,25 +214,47 @@ public: //IGameHelpers
|
|||||||
void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt);
|
void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt);
|
||||||
const char *GetCurrentMap();
|
const char *GetCurrentMap();
|
||||||
void ServerCommand(const char *buffer);
|
void ServerCommand(const char *buffer);
|
||||||
|
CBaseEntity *ReferenceToEntity(cell_t entRef);
|
||||||
|
cell_t EntityToReference(CBaseEntity *pEntity);
|
||||||
|
cell_t IndexToReference(int entIndex);
|
||||||
|
int ReferenceToIndex(cell_t entRef);
|
||||||
|
cell_t ReferenceToBCompatRef(cell_t entRef);
|
||||||
|
CEntInfo *LookupEntity(int entIndex);
|
||||||
|
cell_t EntityToBCompatRef(CBaseEntity *pEntity);
|
||||||
|
void *GetGlobalEntityList();
|
||||||
|
int GetSendPropOffset(SendProp *prop);
|
||||||
|
ICommandLine *GetValveCommandLine();
|
||||||
|
const char *GetEntityClassname(edict_t *pEdict);
|
||||||
|
const char *GetEntityClassname(CBaseEntity *pEntity);
|
||||||
|
bool IsMapValid(const char *map);
|
||||||
|
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
|
|
||||||
bool IsOriginalEngine();
|
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
|
void PushCommandStack(const ICommandArgs *cmd);
|
||||||
|
void PopCommandStack();
|
||||||
DataTableInfo *_FindServerClass(const char *classname);
|
DataTableInfo *_FindServerClass(const char *classname);
|
||||||
private:
|
private:
|
||||||
Trie *m_pClasses;
|
void InitLogicalEntData();
|
||||||
List<DataTableInfo *> m_Tables;
|
void InitCommandLine();
|
||||||
THash<datamap_t *, DataMapTrie> m_Maps;
|
private:
|
||||||
|
typedef ke::HashMap<datamap_t *, DataMapCache *, ke::PointerPolicy<datamap_t> > DataTableMap;
|
||||||
|
|
||||||
|
NameHashSet<DataTableInfo *> m_Classes;
|
||||||
|
DataTableMap m_Maps;
|
||||||
int m_MsgTextMsg;
|
int m_MsgTextMsg;
|
||||||
int m_HinTextMsg;
|
int m_HinTextMsg;
|
||||||
int m_SayTextMsg;
|
int m_SayTextMsg;
|
||||||
@@ -142,10 +263,32 @@ private:
|
|||||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||||
CStack<CachedCommandInfo> m_CommandStack;
|
CStack<CachedCommandInfo> m_CommandStack;
|
||||||
Queue<DelayedKickInfo> m_DelayedKicks;
|
Queue<DelayedKickInfo> m_DelayedKicks;
|
||||||
|
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;
|
||||||
|
|
||||||
edict_t *GetEntity(cell_t num, CBaseEntity **pData);
|
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_
|
||||||
|
|||||||
+29
-504
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,512 +34,37 @@
|
|||||||
#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 "sm_version.h"
|
#include "logic_bridge.h"
|
||||||
|
#include <sourcemod_version.h>
|
||||||
Logger g_Logger;
|
#include <bridge/include/IProviderCallbacks.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* :TODO: This should be creating the log folder if it doesn't exist
|
|
||||||
*/
|
|
||||||
|
|
||||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength)
|
|
||||||
{
|
|
||||||
if (strcasecmp(key, "Logging") == 0)
|
|
||||||
{
|
|
||||||
bool state;
|
|
||||||
|
|
||||||
if (strcasecmp(value, "on") == 0)
|
|
||||||
{
|
|
||||||
state = true;
|
|
||||||
} else if (strcasecmp(value, "off") == 0) {
|
|
||||||
state = false;
|
|
||||||
} else {
|
|
||||||
UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
|
||||||
return ConfigResult_Reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source == ConfigSource_Console)
|
|
||||||
{
|
|
||||||
state ? EnableLogging() : DisableLogging();
|
|
||||||
} else {
|
|
||||||
m_InitialState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
} else if (strcasecmp(key, "LogMode") == 0) {
|
|
||||||
if (strcasecmp(value, "daily") == 0)
|
|
||||||
{
|
|
||||||
m_Mode = LoggingMode_Daily;
|
|
||||||
} else if (strcasecmp(value, "map") == 0) {
|
|
||||||
m_Mode = LoggingMode_PerMap;
|
|
||||||
} else if (strcasecmp(value, "game") == 0) {
|
|
||||||
m_Mode = LoggingMode_Game;
|
|
||||||
} else {
|
|
||||||
UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
|
|
||||||
return ConfigResult_Reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Accept;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModStartup(bool late)
|
|
||||||
{
|
|
||||||
InitLogger(m_Mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModAllShutdown()
|
|
||||||
{
|
|
||||||
CloseLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::OnSourceModLevelChange(const char *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;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
g_SourceMod.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];
|
|
||||||
g_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, SVN_FULL_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;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
m_CurDay = curtime->tm_mday;
|
|
||||||
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
|
|
||||||
switch (m_Mode)
|
|
||||||
{
|
|
||||||
case LoggingMode_PerMap:
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
m_DelayedStart = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LoggingMode_Daily:
|
|
||||||
{
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_DailyPrintHdr = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* do nothing... */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::CloseLogger()
|
|
||||||
{
|
|
||||||
_CloseFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, msg);
|
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, msg);
|
|
||||||
LogToFileOnlyEx(fp, msg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[3072];
|
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
|
||||||
|
|
||||||
char date[32];
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
|
||||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[3072];
|
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
|
||||||
|
|
||||||
char date[32];
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
|
||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
|
||||||
fflush(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogMessage(const char *vafmt, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Mode == LoggingMode_Game)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
_PrintToGameLog(vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_DelayedStart)
|
|
||||||
{
|
|
||||||
m_DelayedStart = false;
|
|
||||||
_NewMapFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
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_CurDay != curtime->tm_mday)
|
|
||||||
{
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_NrmFileName.assign(_filename);
|
|
||||||
m_CurDay = 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, SVN_FULL_VERSION);
|
|
||||||
}
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
|
||||||
} else {
|
|
||||||
goto print_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
print_error:
|
|
||||||
char error[255];
|
|
||||||
g_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogError(const char *vafmt, ...)
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
GetAdjustedTime(&t);
|
|
||||||
tm *curtime = localtime(&t);
|
|
||||||
|
|
||||||
if (curtime->tm_mday != m_CurDay)
|
|
||||||
{
|
|
||||||
char _filename[256];
|
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
|
||||||
m_ErrFileName.assign(_filename);
|
|
||||||
m_CurDay = 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;
|
|
||||||
}
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char error[255];
|
|
||||||
g_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::MapChange(const char *mapname)
|
|
||||||
{
|
|
||||||
m_CurMapName.assign(mapname);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
char msg[3072];
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
|
|
||||||
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
|
|
||||||
|
|
||||||
msg[len++] = '\n';
|
|
||||||
msg[len] = '\0';
|
|
||||||
|
|
||||||
Engine_LogPrintWrapper(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()
|
|
||||||
{
|
|
||||||
if (m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_Active = true;
|
|
||||||
LogMessage("[SM] Logging enabled manually by user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::DisableLogging()
|
|
||||||
{
|
|
||||||
if (!m_Active)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LogMessage("[SM] Logging disabled manually by user.");
|
|
||||||
m_Active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::LogFatal(const char *msg, ...)
|
|
||||||
{
|
|
||||||
/* :TODO: make this print all pretty-like
|
|
||||||
* In fact, the pretty log printing function should be abstracted.
|
|
||||||
* It's already implemented twice which is bad.
|
|
||||||
*/
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
|
||||||
|
|
||||||
FILE *fp = fopen(path, "at");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
m_Active = true;
|
|
||||||
va_start(ap, msg);
|
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
m_Active = false;
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool g_in_game_log_hook = false;
|
bool g_in_game_log_hook = false;
|
||||||
|
|
||||||
|
static LoggerCore g_LoggerCore;
|
||||||
|
|
||||||
|
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
|
||||||
|
|
||||||
|
static void HookLogPrint(const char *message)
|
||||||
|
{
|
||||||
|
g_in_game_log_hook = true;
|
||||||
|
bool stopped = logicore.callbacks->OnLogPrint(message);
|
||||||
|
g_in_game_log_hook = false;
|
||||||
|
|
||||||
|
if (stopped)
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggerCore::OnSourceModStartup(bool late)
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggerCore::OnSourceModAllShutdown()
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||||
|
}
|
||||||
|
|
||||||
void Engine_LogPrintWrapper(const char *msg)
|
void Engine_LogPrintWrapper(const char *msg)
|
||||||
{
|
{
|
||||||
if (g_in_game_log_hook)
|
if (g_in_game_log_hook)
|
||||||
|
|||||||
+1
-60
@@ -38,72 +38,13 @@
|
|||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
enum LogType
|
class LoggerCore : public SMGlobalClass
|
||||||
{
|
{
|
||||||
LogType_Normal,
|
|
||||||
LogType_Error
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LoggingMode
|
|
||||||
{
|
|
||||||
LoggingMode_Daily,
|
|
||||||
LoggingMode_PerMap,
|
|
||||||
LoggingMode_Game
|
|
||||||
};
|
|
||||||
|
|
||||||
class Logger : public SMGlobalClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
|
||||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
|
||||||
m_InitialState(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
|
||||||
const char *value,
|
|
||||||
ConfigSource source,
|
|
||||||
char *error,
|
|
||||||
size_t maxlength);
|
|
||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllShutdown();
|
void OnSourceModAllShutdown();
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
|
||||||
public:
|
|
||||||
void InitLogger(LoggingMode mode);
|
|
||||||
void CloseLogger();
|
|
||||||
void EnableLogging();
|
|
||||||
void DisableLogging();
|
|
||||||
void LogMessage(const char *msg, ...);
|
|
||||||
void LogError(const char *msg, ...);
|
|
||||||
void LogFatal(const char *msg, ...);
|
|
||||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
|
||||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
|
||||||
/* This version does not print to console, and is thus thread-safe */
|
|
||||||
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
|
||||||
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
|
||||||
void MapChange(const char *mapname);
|
|
||||||
const char *GetLogFileName(LogType type) const;
|
|
||||||
LoggingMode GetLoggingMode() const;
|
|
||||||
private:
|
|
||||||
void _CloseFile();
|
|
||||||
void _NewMapFile();
|
|
||||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
|
||||||
private:
|
|
||||||
String m_NrmFileName;
|
|
||||||
String m_ErrFileName;
|
|
||||||
String m_CurMapName;
|
|
||||||
LoggingMode m_Mode;
|
|
||||||
int m_CurDay;
|
|
||||||
bool m_ErrMapStart;
|
|
||||||
bool m_Active;
|
|
||||||
bool m_DelayedStart;
|
|
||||||
bool m_DailyPrintHdr;
|
|
||||||
bool m_InitialState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Engine_LogPrintWrapper(const char *msg);
|
void Engine_LogPrintWrapper(const char *msg);
|
||||||
|
|
||||||
extern bool g_in_game_log_hook;
|
|
||||||
extern Logger g_Logger;
|
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||||
|
|||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
# (C)2004-2008 SourceMod Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
SMSDK = ..
|
|
||||||
SRCDS_BASE = ~/srcds
|
|
||||||
HL2SDK_ORIG = ../../hl2sdk
|
|
||||||
HL2SDK_OB = ../../hl2sdk-ob
|
|
||||||
HL2SDK_L4D = ../../hl2sdk-l4d
|
|
||||||
MMSOURCE17 = ../../mmsource-1.7
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
#####################################
|
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
|
||||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
|
||||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
|
||||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
|
||||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
|
||||||
frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp PhraseCollection.cpp NextMap.cpp \
|
|
||||||
NativeOwner.cpp
|
|
||||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
|
||||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
|
||||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
|
||||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
|
|
||||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
|
|
||||||
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
|
|
||||||
OBJECTS += ExtensionSys.cpp \
|
|
||||||
ForwardSys.cpp \
|
|
||||||
HandleSys.cpp \
|
|
||||||
LibrarySys.cpp \
|
|
||||||
PluginInfoDatabase.cpp \
|
|
||||||
PluginSys.cpp \
|
|
||||||
ShareSys.cpp \
|
|
||||||
NativeInvoker.cpp
|
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
|
||||||
|
|
||||||
##############################################
|
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
|
||||||
##############################################
|
|
||||||
|
|
||||||
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
|
|
||||||
ifeq "$(ENGINE)" "original"
|
|
||||||
HL2SDK = $(HL2SDK_ORIG)
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=1
|
|
||||||
METAMOD = $(MMSOURCE17)/core-legacy
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/dlls
|
|
||||||
SRCDS = $(SRCDS_BASE)
|
|
||||||
BINARY = sourcemod.1.ep1.so
|
|
||||||
override ENGSET = true
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "orangebox"
|
|
||||||
HL2SDK = $(HL2SDK_OB)
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=3
|
|
||||||
METAMOD = $(MMSOURCE17)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
SRCDS = $(SRCDS_BASE)/orangebox
|
|
||||||
BINARY = sourcemod.2.ep2.so
|
|
||||||
override ENGSET = true
|
|
||||||
endif
|
|
||||||
ifeq "$(ENGINE)" "left4dead"
|
|
||||||
HL2SDK = $(HL2SDK_L4D)
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/lib/linux
|
|
||||||
CFLAGS += -DSOURCE_ENGINE=4
|
|
||||||
METAMOD = $(MMSOURCE17)/core
|
|
||||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
|
||||||
SRCDS = $(SRCDS_BASE)/l4d
|
|
||||||
BINARY = sourcemod.2.l4d.so
|
|
||||||
override ENGSET = true
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_LEFT4DEAD=4
|
|
||||||
|
|
||||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
|
|
||||||
tier0_i486.so -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \
|
|
||||||
-I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
|
|
||||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
|
||||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
|
|
||||||
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
|
|
||||||
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
################################################
|
|
||||||
### 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)/systems
|
|
||||||
mkdir -p $(BIN_DIR)/thread
|
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
|
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
|
|
||||||
$(MAKE) -f Makefile sourcemod
|
|
||||||
|
|
||||||
check:
|
|
||||||
if [ "$(ENGSET)" = "false" ]; then \
|
|
||||||
echo "You must supply ENGINE=left4dead or ENGINE=orangebox or ENGINE=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)/systems/*.o
|
|
||||||
rm -rf $(BIN_DIR)/thread/*.o
|
|
||||||
rm -rf $(BIN_DIR)/$(BINARY)
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "MemoryUtils.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#ifdef PLATFORM_LINUX
|
|
||||||
#include <string.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MemoryUtils g_MemUtils;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
MemoryUtils::MemoryUtils()
|
|
||||||
{
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
|
||||||
|
|
||||||
SYSTEM_INFO info;
|
|
||||||
GetSystemInfo(&info);
|
|
||||||
|
|
||||||
m_PageSize = info.dwPageSize;
|
|
||||||
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
|
|
||||||
m_PageSize = sysconf(_SC_PAGE_SIZE);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void MemoryUtils::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
|
|
||||||
{
|
|
||||||
DynLibInfo lib;
|
|
||||||
bool found;
|
|
||||||
char *ptr, *end;
|
|
||||||
|
|
||||||
memset(&lib, 0, sizeof(DynLibInfo));
|
|
||||||
|
|
||||||
if (!GetLibraryInfo(libPtr, lib))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = reinterpret_cast<char *>(lib.baseAddress);
|
|
||||||
end = ptr + lib.memorySize;
|
|
||||||
|
|
||||||
while (ptr < end)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
for (register size_t i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
|
|
||||||
{
|
|
||||||
found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
|
||||||
{
|
|
||||||
unsigned long baseAddr;
|
|
||||||
|
|
||||||
if (libPtr == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
|
||||||
IMAGE_DOS_HEADER *dos;
|
|
||||||
IMAGE_NT_HEADERS *pe;
|
|
||||||
IMAGE_FILE_HEADER *file;
|
|
||||||
IMAGE_OPTIONAL_HEADER *opt;
|
|
||||||
|
|
||||||
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseAddr = reinterpret_cast<unsigned long>(info.AllocationBase);
|
|
||||||
|
|
||||||
/* All this is for our insane sanity checks :o */
|
|
||||||
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
|
|
||||||
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
|
|
||||||
file = &pe->FileHeader;
|
|
||||||
opt = &pe->OptionalHeader;
|
|
||||||
|
|
||||||
/* Check PE magic and signature */
|
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check architecture, which is 32-bit/x86 right now
|
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
|
||||||
*/
|
|
||||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For our purposes, this must be a dynamic library */
|
|
||||||
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, we can do this */
|
|
||||||
lib.memorySize = opt->SizeOfImage;
|
|
||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
|
|
||||||
Dl_info info;
|
|
||||||
Elf32_Ehdr *file;
|
|
||||||
Elf32_Phdr *phdr;
|
|
||||||
uint16_t phdrCount;
|
|
||||||
|
|
||||||
if (!dladdr(libPtr, &info))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.dli_fbase || !info.dli_fname)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is for our insane sanity checks :o */
|
|
||||||
baseAddr = reinterpret_cast<unsigned long>(info.dli_fbase);
|
|
||||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
|
||||||
|
|
||||||
/* Check ELF magic */
|
|
||||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check ELF version */
|
|
||||||
if (file->e_ident[EI_VERSION] != EV_CURRENT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
|
||||||
* Should change this for 64-bit if Valve gets their act together
|
|
||||||
*/
|
|
||||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For our purposes, this must be a dynamic library/shared object */
|
|
||||||
if (file->e_type != ET_DYN)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
phdrCount = file->e_phnum;
|
|
||||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
|
||||||
|
|
||||||
/* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */
|
|
||||||
for (uint16_t i = 0; i < phdrCount; i++)
|
|
||||||
{
|
|
||||||
Elf32_Phdr &hdr = phdr[i];
|
|
||||||
|
|
||||||
if (hdr.p_type == PT_LOAD)
|
|
||||||
{
|
|
||||||
lib.memorySize += hdr.p_memsz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
+50
-26
@@ -38,10 +38,8 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "Translator.h"
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
MenuManager g_Menus;
|
MenuManager g_Menus;
|
||||||
VoteMenuHandler s_VoteHandler;
|
VoteMenuHandler s_VoteHandler;
|
||||||
@@ -56,24 +54,24 @@ MenuManager::MenuManager()
|
|||||||
|
|
||||||
void MenuManager::OnSourceModAllInitialized()
|
void MenuManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
|
|
||||||
HandleAccess access;
|
HandleAccess access;
|
||||||
g_HandleSys.InitAccessDefaults(NULL, &access);
|
handlesys->InitAccessDefaults(NULL, &access);
|
||||||
|
|
||||||
/* Deny cloning to menus */
|
/* Deny cloning to menus */
|
||||||
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
||||||
m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
m_MenuType = handlesys->CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
/* Also deny deletion to styles */
|
/* Also deny deletion to styles */
|
||||||
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
||||||
m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
m_StyleType = handlesys->CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuManager::OnSourceModAllShutdown()
|
void MenuManager::OnSourceModAllShutdown()
|
||||||
{
|
{
|
||||||
g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
|
handlesys->RemoveType(m_MenuType, g_pCoreIdent);
|
||||||
g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
|
handlesys->RemoveType(m_StyleType, g_pCoreIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
|
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||||
@@ -112,7 +110,7 @@ Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
|
return handlesys->CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
||||||
@@ -122,7 +120,7 @@ Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
|
return handlesys->CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
||||||
@@ -132,7 +130,7 @@ HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
|||||||
sec.pIdentity = g_pCoreIdent;
|
sec.pIdentity = g_pCoreIdent;
|
||||||
sec.pOwner = NULL;
|
sec.pOwner = NULL;
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
|
return handlesys->ReadHandle(handle, m_MenuType, &sec, (void **)menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
||||||
@@ -142,7 +140,7 @@ HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
|||||||
sec.pIdentity = g_pCoreIdent;
|
sec.pIdentity = g_pCoreIdent;
|
||||||
sec.pOwner = g_pCoreIdent;
|
sec.pOwner = g_pCoreIdent;
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
|
return handlesys->ReadHandle(handle, m_StyleType, &sec, (void **)style);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
||||||
@@ -231,6 +229,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
unsigned int pgn = menu->GetPagination();
|
unsigned int pgn = menu->GetPagination();
|
||||||
unsigned int maxItems = style->GetMaxPageItems();
|
unsigned int maxItems = style->GetMaxPageItems();
|
||||||
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
|
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
|
||||||
|
bool novoteButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_NOVOTE) == MENUFLAG_BUTTON_NOVOTE;
|
||||||
|
|
||||||
if (pgn != MENU_NO_PAGINATION)
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
{
|
{
|
||||||
@@ -241,6 +240,11 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
maxItems--;
|
maxItems--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (novoteButton)
|
||||||
|
{
|
||||||
|
maxItems--;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is very not allowed! */
|
/* This is very not allowed! */
|
||||||
if (maxItems < 2)
|
if (maxItems < 2)
|
||||||
{
|
{
|
||||||
@@ -304,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);
|
||||||
@@ -394,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))
|
||||||
@@ -416,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))
|
||||||
@@ -436,6 +440,20 @@ skip_search:
|
|||||||
/* Draw the item according to the order */
|
/* Draw the item according to the order */
|
||||||
menu_slots_t *slots = md.slots;
|
menu_slots_t *slots = md.slots;
|
||||||
unsigned int position = 0; /* Keep track of the last position */
|
unsigned int position = 0; /* Keep track of the last position */
|
||||||
|
|
||||||
|
if (novoteButton)
|
||||||
|
{
|
||||||
|
char text[50];
|
||||||
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
|
||||||
|
{
|
||||||
|
ke::SafeStrcpy(text, sizeof(text), "No Vote");
|
||||||
|
}
|
||||||
|
ItemDrawInfo dr(text, 0);
|
||||||
|
position = panel->DrawItem(dr);
|
||||||
|
slots[position].type = ItemSel_Exit;
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
if (order == ItemOrder_Ascending)
|
if (order == ItemOrder_Ascending)
|
||||||
{
|
{
|
||||||
md.item_on_page = drawItems[0].position;
|
md.item_on_page = drawItems[0].position;
|
||||||
@@ -552,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;
|
||||||
}
|
}
|
||||||
@@ -586,9 +604,9 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (exitBackButton)
|
if (exitBackButton)
|
||||||
{
|
{
|
||||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Back");
|
ke::SafeStrcpy(text, sizeof(text), "Back");
|
||||||
}
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@@ -596,9 +614,9 @@ skip_search:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Previous");
|
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);
|
||||||
@@ -617,9 +635,9 @@ skip_search:
|
|||||||
/* NEXT */
|
/* NEXT */
|
||||||
if (displayNext || canDrawDisabled)
|
if (displayNext || canDrawDisabled)
|
||||||
{
|
{
|
||||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Next");
|
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);
|
||||||
@@ -648,9 +666,9 @@ skip_search:
|
|||||||
/* EXIT */
|
/* EXIT */
|
||||||
if (exitButton)
|
if (exitButton)
|
||||||
{
|
{
|
||||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
||||||
{
|
{
|
||||||
UTIL_Format(text, sizeof(text), "Exit");
|
ke::SafeStrcpy(text, sizeof(text), "Exit");
|
||||||
}
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
@@ -798,5 +816,11 @@ bool MenuManager::IsClientInVotePool(int client)
|
|||||||
|
|
||||||
bool MenuManager::RedrawClientVoteMenu(int client)
|
bool MenuManager::RedrawClientVoteMenu(int client)
|
||||||
{
|
{
|
||||||
return s_VoteHandler.RedrawToClient(client);
|
return RedrawClientVoteMenu2(client, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MenuManager::RedrawClientVoteMenu2(int client, bool revote)
|
||||||
|
{
|
||||||
|
return s_VoteHandler.RedrawToClient(client, revote);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,6 @@
|
|||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -91,6 +90,7 @@ public:
|
|||||||
unsigned int GetRemainingVoteDelay();
|
unsigned int GetRemainingVoteDelay();
|
||||||
bool IsClientInVotePool(int client);
|
bool IsClientInVotePool(int client);
|
||||||
bool RedrawClientVoteMenu(int client);
|
bool RedrawClientVoteMenu(int client);
|
||||||
|
bool RedrawClientVoteMenu2(int client, bool revote);
|
||||||
public: //IHandleTypeDispatch
|
public: //IHandleTypeDispatch
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
void OnHandleDestroy(HandleType_t type, void *object);
|
||||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||||
|
|||||||
+101
-48
@@ -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,11 +34,12 @@
|
|||||||
#include "MenuStyle_Base.h"
|
#include "MenuStyle_Base.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuManager.h"
|
#include "MenuManager.h"
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "CellRecipientFilter.h"
|
#include "CellRecipientFilter.h"
|
||||||
#if defined MENU_DEBUG
|
#if defined MENU_DEBUG
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "AutoHandleRooter.h"
|
||||||
|
|
||||||
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
|
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
|
||||||
{
|
{
|
||||||
@@ -322,15 +323,25 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
if (pCollideable)
|
if (pCollideable)
|
||||||
{
|
{
|
||||||
const Vector & pos = pCollideable->GetCollisionOrigin();
|
const Vector & pos = pCollideable->GetCollisionOrigin();
|
||||||
|
|
||||||
enginesound->EmitSound(filter,
|
enginesound->EmitSound(filter,
|
||||||
client,
|
client,
|
||||||
CHAN_AUTO,
|
CHAN_AUTO,
|
||||||
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
|
sound,
|
||||||
|
-1,
|
||||||
|
#endif
|
||||||
sound,
|
sound,
|
||||||
VOL_NORM,
|
VOL_NORM,
|
||||||
ATTN_NORM,
|
ATTN_NORM,
|
||||||
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
0,
|
0,
|
||||||
PITCH_NORM,
|
PITCH_NORM,
|
||||||
|
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
|
||||||
|
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
&pos);
|
&pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,6 +388,9 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
RemoveClientFromWatch(client);
|
RemoveClientFromWatch(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle_t hndl = menu ? menu->GetHandle() : BAD_HANDLE;
|
||||||
|
AutoHandleRooter ahr(hndl);
|
||||||
|
|
||||||
if (cancel)
|
if (cancel)
|
||||||
{
|
{
|
||||||
mh->OnMenuCancel(menu, client, reason);
|
mh->OnMenuCancel(menu, client, reason);
|
||||||
@@ -591,7 +605,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
|
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
|
||||||
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
|
m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
|
||||||
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
|
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
|
||||||
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
|
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
|
||||||
{
|
{
|
||||||
@@ -614,94 +628,135 @@ Handle_t CBaseMenu::GetHandle()
|
|||||||
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
||||||
{
|
{
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
&& m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CItem item;
|
CItem item(m_items.length());
|
||||||
|
|
||||||
item.infoString = m_Strings.AddString(info);
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
{
|
item.display = new ke::AString(draw.display);
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
item.style = draw.style;
|
||||||
|
|
||||||
m_items.push_back(item);
|
m_items.append(ke::Move(item));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
||||||
{
|
{
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
if (m_Pagination == (unsigned)MENU_NO_PAGINATION &&
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position >= m_items.size())
|
if (position >= m_items.length())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
CItem item;
|
CItem item(position);
|
||||||
item.infoString = m_Strings.AddString(info);
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
{
|
item.display = new ke::AString(draw.display);
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
item.style = draw.style;
|
||||||
|
|
||||||
CVector<CItem>::iterator iter = m_items.iterAt(position);
|
m_items.insert(position, ke::Move(item));
|
||||||
m_items.insert(iter, item);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::RemoveItem(unsigned int position)
|
bool CBaseMenu::RemoveItem(unsigned int position)
|
||||||
{
|
{
|
||||||
if (position >= m_items.size())
|
if (position >= m_items.length())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
m_items.erase(m_items.iterAt(position));
|
|
||||||
|
|
||||||
if (m_items.size() == 0)
|
|
||||||
{
|
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
m_items.remove(position);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBaseMenu::RemoveAllItems()
|
void CBaseMenu::RemoveAllItems()
|
||||||
{
|
{
|
||||||
m_items.clear();
|
m_items.clear();
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */, int client/* =0 */)
|
||||||
{
|
{
|
||||||
if (position >= m_items.size())
|
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_Strings.GetString(m_items[position].displayString);
|
draw->display = m_items[position].display->chars();
|
||||||
draw->style = m_items[position].style;
|
draw->style = m_items[position].style;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_Strings.GetString(m_items[position].infoString);
|
return m_items[position].info.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.size();
|
return m_items.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
||||||
@@ -734,12 +789,12 @@ IMenuStyle *CBaseMenu::GetDrawStyle()
|
|||||||
|
|
||||||
void CBaseMenu::SetDefaultTitle(const char *message)
|
void CBaseMenu::SetDefaultTitle(const char *message)
|
||||||
{
|
{
|
||||||
m_Title.assign(message);
|
m_Title = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CBaseMenu::GetDefaultTitle()
|
const char *CBaseMenu::GetDefaultTitle()
|
||||||
{
|
{
|
||||||
return m_Title.c_str();
|
return m_Title.chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBaseMenu::Cancel()
|
void CBaseMenu::Cancel()
|
||||||
@@ -806,7 +861,7 @@ void CBaseMenu::InternalDelete()
|
|||||||
|
|
||||||
m_hHandle = BAD_HANDLE;
|
m_hHandle = BAD_HANDLE;
|
||||||
m_bDeleting = true;
|
m_bDeleting = true;
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pHandler->OnMenuDestroy(this);
|
m_pHandler->OnMenuDestroy(this);
|
||||||
@@ -831,7 +886,5 @@ IMenuHandler *CBaseMenu::GetHandler()
|
|||||||
|
|
||||||
unsigned int CBaseMenu::GetBaseMemUsage()
|
unsigned int CBaseMenu::GetBaseMemUsage()
|
||||||
{
|
{
|
||||||
return m_Title.size()
|
return m_Title.length() + (m_items.length() * sizeof(CItem));
|
||||||
+ m_Strings.GetMemTable()->GetMemUsage()
|
|
||||||
+ (m_items.size() * sizeof(CItem));
|
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-14
@@ -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,29 +34,50 @@
|
|||||||
|
|
||||||
#include <IMenuManager.h>
|
#include <IMenuManager.h>
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <sh_string.h>
|
#include <am-autoptr.h>
|
||||||
#include <sh_vector.h>
|
#include <am-string.h>
|
||||||
#include "sm_memtable.h"
|
#include <am-vector.h>
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class CItem
|
class CItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CItem()
|
CItem(unsigned int index)
|
||||||
{
|
{
|
||||||
infoString = -1;
|
this->index = index;
|
||||||
displayString = -1;
|
|
||||||
style = 0;
|
style = 0;
|
||||||
access = 0;
|
access = 0;
|
||||||
}
|
}
|
||||||
|
CItem(CItem &&other)
|
||||||
|
: info(ke::Move(other.info)),
|
||||||
|
display(ke::Move(other.display))
|
||||||
|
{
|
||||||
|
index = other.index;
|
||||||
|
style = other.style;
|
||||||
|
access = other.access;
|
||||||
|
}
|
||||||
|
CItem & operator =(CItem &&other)
|
||||||
|
{
|
||||||
|
index = other.index;
|
||||||
|
info = ke::Move(other.info);
|
||||||
|
display = ke::Move(other.display);
|
||||||
|
style = other.style;
|
||||||
|
access = other.access;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int infoString;
|
unsigned int index;
|
||||||
int displayString;
|
ke::AString info;
|
||||||
|
ke::AutoPtr<ke::AString> display;
|
||||||
unsigned int style;
|
unsigned int style;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CItem(const CItem &other) = delete;
|
||||||
|
CItem &operator =(const CItem &other) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CBaseMenuPlayer
|
class CBaseMenuPlayer
|
||||||
@@ -121,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();
|
||||||
@@ -135,15 +156,18 @@ 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();
|
||||||
protected:
|
protected:
|
||||||
String m_Title;
|
ke::AString m_Title;
|
||||||
IMenuStyle *m_pStyle;
|
IMenuStyle *m_pStyle;
|
||||||
BaseStringTable m_Strings;
|
|
||||||
unsigned int m_Pagination;
|
unsigned int m_Pagination;
|
||||||
CVector<CItem> m_items;
|
ke::Vector<CItem> m_items;
|
||||||
bool m_bShouldDelete;
|
bool m_bShouldDelete;
|
||||||
bool m_bCancelling;
|
bool m_bCancelling;
|
||||||
IdentityToken_t *m_pOwner;
|
IdentityToken_t *m_pOwner;
|
||||||
@@ -152,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
|
||||||
|
|||||||
+76
-21
@@ -32,11 +32,20 @@
|
|||||||
#include "MenuStyle_Radio.h"
|
#include "MenuStyle_Radio.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
#include "GameConfigs.h"
|
#include <IGameConfigs.h>
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#if defined MENU_DEBUG
|
#if defined MENU_DEBUG
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const char *g_RadioNumTable[];
|
extern const char *g_RadioNumTable[];
|
||||||
CRadioStyle g_RadioMenuStyle;
|
CRadioStyle g_RadioMenuStyle;
|
||||||
@@ -44,6 +53,14 @@ int g_ShowMenuId = -1;
|
|||||||
bool g_bRadioInit = false;
|
bool g_bRadioInit = false;
|
||||||
unsigned int g_RadioMenuTimeout = 0;
|
unsigned int g_RadioMenuTimeout = 0;
|
||||||
|
|
||||||
|
// back, next, exit
|
||||||
|
#define MAX_PAGINATION_OPTIONS 3
|
||||||
|
|
||||||
|
#define MAX_MENUSLOT_KEYS 10
|
||||||
|
|
||||||
|
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
|
||||||
|
|
||||||
|
|
||||||
CRadioStyle::CRadioStyle()
|
CRadioStyle::CRadioStyle()
|
||||||
{
|
{
|
||||||
m_players = new CRadioMenuPlayer[256+1];
|
m_players = new CRadioMenuPlayer[256+1];
|
||||||
@@ -66,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')
|
||||||
{
|
{
|
||||||
@@ -89,7 +110,18 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
|||||||
g_RadioMenuTimeout = 0;
|
g_RadioMenuTimeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Menus.AddStyle(this);
|
const char *items = g_pGameConf->GetKeyValue("RadioMenuMaxPageItems");
|
||||||
|
if (items != NULL)
|
||||||
|
{
|
||||||
|
int value = atoi(items);
|
||||||
|
|
||||||
|
// Only override the mostly-safe default if it's a sane value
|
||||||
|
if (value > MAX_PAGINATION_OPTIONS && value <= MAX_MENUSLOT_KEYS)
|
||||||
|
{
|
||||||
|
s_RadioMaxPageItems = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_Menus.SetDefaultStyle(this);
|
g_Menus.SetDefaultStyle(this);
|
||||||
|
|
||||||
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
||||||
@@ -134,13 +166,22 @@ static unsigned int g_last_holdtime = 0;
|
|||||||
static unsigned int g_last_client_count = 0;
|
static unsigned int g_last_client_count = 0;
|
||||||
static int g_last_clients[256];
|
static int g_last_clients[256];
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
|
||||||
|
#else
|
||||||
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int count = pFilter->GetRecipientCount();
|
int count = pFilter->GetRecipientCount();
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||||
|
#else
|
||||||
bf_read br(bf->GetBasePointer(), 3);
|
bf_read br(bf->GetBasePointer(), 3);
|
||||||
|
|
||||||
br.ReadWord();
|
br.ReadWord();
|
||||||
int c = br.ReadChar();
|
int c = br.ReadChar();
|
||||||
|
#endif
|
||||||
|
|
||||||
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
||||||
|
|
||||||
@@ -188,7 +229,7 @@ IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwn
|
|||||||
|
|
||||||
unsigned int CRadioStyle::GetMaxPageItems()
|
unsigned int CRadioStyle::GetMaxPageItems()
|
||||||
{
|
{
|
||||||
return 10;
|
return s_RadioMaxPageItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CRadioStyle::GetStyleName()
|
const char *CRadioStyle::GetStyleName()
|
||||||
@@ -217,15 +258,6 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
|
|||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMenuPanel *CRadioStyle::MakeRadioDisplay(const char *str, int keys)
|
|
||||||
{
|
|
||||||
CRadioDisplay *pPanel = MakeRadioDisplay(NULL);
|
|
||||||
|
|
||||||
pPanel->DirectSet(str, keys);
|
|
||||||
|
|
||||||
return pPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
|
void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
|
||||||
{
|
{
|
||||||
m_FreeDisplays.push(display);
|
m_FreeDisplays.push(display);
|
||||||
@@ -292,11 +324,12 @@ void CRadioDisplay::Reset()
|
|||||||
keys = 0;
|
keys = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRadioDisplay::DirectSet(const char *str, int keymap)
|
bool CRadioDisplay::DirectSet(const char *str)
|
||||||
{
|
{
|
||||||
m_Title.clear();
|
m_Title.clear();
|
||||||
m_BufferText.assign(str);
|
m_BufferText.assign(str);
|
||||||
keys = keymap;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CRadioDisplay::GetCurrentKey()
|
unsigned int CRadioDisplay::GetCurrentKey()
|
||||||
@@ -306,7 +339,7 @@ unsigned int CRadioDisplay::GetCurrentKey()
|
|||||||
|
|
||||||
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
||||||
{
|
{
|
||||||
if (key < m_NextPos || m_NextPos > 10)
|
if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -342,7 +375,7 @@ void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
|||||||
|
|
||||||
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
||||||
{
|
{
|
||||||
if (m_NextPos > 10 || !CanDrawItem(item.style))
|
if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -417,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,
|
||||||
@@ -425,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;
|
||||||
@@ -435,7 +467,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|||||||
|
|
||||||
void CRadioMenuPlayer::Radio_Refresh()
|
void CRadioMenuPlayer::Radio_Refresh()
|
||||||
{
|
{
|
||||||
cell_t players[1] = {m_index};
|
cell_t players[1] = { (cell_t)m_index };
|
||||||
char *ptr = display_pkt;
|
char *ptr = display_pkt;
|
||||||
char save = 0;
|
char save = 0;
|
||||||
size_t len = display_len;
|
size_t len = display_len;
|
||||||
@@ -451,6 +483,14 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
// TODO: find what happens past 240 on CS:GO
|
||||||
|
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||||
|
msg->set_bits_valid_slots(display_keys);
|
||||||
|
msg->set_display_time(time);
|
||||||
|
msg->set_menu_string(ptr);
|
||||||
|
g_UserMsgs.EndMessage();
|
||||||
|
#else
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (len > 240)
|
if (len > 240)
|
||||||
@@ -458,7 +498,8 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
save = ptr[240];
|
save = ptr[240];
|
||||||
ptr[240] = '\0';
|
ptr[240] = '\0';
|
||||||
}
|
}
|
||||||
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
|
||||||
|
bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||||
buffer->WriteWord(display_keys);
|
buffer->WriteWord(display_keys);
|
||||||
buffer->WriteChar(time ? time : -1);
|
buffer->WriteChar(time ? time : -1);
|
||||||
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
||||||
@@ -475,6 +516,7 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
display_last_refresh = gpGlobals->curtime;
|
display_last_refresh = gpGlobals->curtime;
|
||||||
}
|
}
|
||||||
@@ -510,6 +552,7 @@ unsigned int CRadioDisplay::GetApproxMemUsage()
|
|||||||
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
||||||
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
||||||
{
|
{
|
||||||
|
m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
||||||
@@ -543,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,
|
||||||
@@ -550,6 +594,17 @@ bool CRadioMenu::DisplayAtItem(int client,
|
|||||||
time);
|
time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CRadioMenu::SetPagination(unsigned int itemsPerPage)
|
||||||
|
{
|
||||||
|
const unsigned int maxPerPage = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
|
||||||
|
if (itemsPerPage > maxPerPage)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CBaseMenu::SetPagination(itemsPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
void CRadioMenu::Cancel_Finally()
|
void CRadioMenu::Cancel_Finally()
|
||||||
{
|
{
|
||||||
g_RadioMenuStyle.CancelMenu(this);
|
g_RadioMenuStyle.CancelMenu(this);
|
||||||
|
|||||||
+14
-5
@@ -37,10 +37,12 @@
|
|||||||
#include "MenuStyle_Base.h"
|
#include "MenuStyle_Base.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <IUserMessages.h>
|
#include "UserMessages.h"
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
|
#include "logic/common_logic.h"
|
||||||
|
#include "AutoHandleRooter.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
@@ -65,7 +67,11 @@ private:
|
|||||||
class CRadioStyle :
|
class CRadioStyle :
|
||||||
public BaseMenuStyle,
|
public BaseMenuStyle,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IUserMessageListener
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
public IProtobufUserMessageListener
|
||||||
|
#else
|
||||||
|
public IBitBufUserMessageListener
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRadioStyle();
|
CRadioStyle();
|
||||||
@@ -84,7 +90,11 @@ public: //IMenuStyle
|
|||||||
unsigned int GetMaxPageItems();
|
unsigned int GetMaxPageItems();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
public: //IUserMessageListener
|
public: //IUserMessageListener
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
|
||||||
|
#else
|
||||||
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||||
|
#endif
|
||||||
void OnUserMessageSent(int msg_id);
|
void OnUserMessageSent(int msg_id);
|
||||||
public:
|
public:
|
||||||
bool IsSupported();
|
bool IsSupported();
|
||||||
@@ -93,7 +103,6 @@ public:
|
|||||||
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
|
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
|
||||||
void FreeRadioDisplay(CRadioDisplay *display);
|
void FreeRadioDisplay(CRadioDisplay *display);
|
||||||
CRadioMenuPlayer *GetRadioMenuPlayer(int client);
|
CRadioMenuPlayer *GetRadioMenuPlayer(int client);
|
||||||
IMenuPanel *MakeRadioDisplay(const char *str, int keys);
|
|
||||||
private:
|
private:
|
||||||
CRadioMenuPlayer *m_players;
|
CRadioMenuPlayer *m_players;
|
||||||
CStack<CRadioDisplay *> m_FreeDisplays;
|
CStack<CRadioDisplay *> m_FreeDisplays;
|
||||||
@@ -121,8 +130,7 @@ public: //IMenuPanel
|
|||||||
bool SetCurrentKey(unsigned int key);
|
bool SetCurrentKey(unsigned int key);
|
||||||
int GetAmountRemaining();
|
int GetAmountRemaining();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
public:
|
bool DirectSet(const char *str);
|
||||||
void DirectSet(const char *str, int keymap);
|
|
||||||
private:
|
private:
|
||||||
String m_BufferText;
|
String m_BufferText;
|
||||||
String m_Title;
|
String m_Title;
|
||||||
@@ -142,6 +150,7 @@ public:
|
|||||||
unsigned int time,
|
unsigned int time,
|
||||||
unsigned int start_item,
|
unsigned int start_item,
|
||||||
IMenuHandler *alt_handler/* =NULL */);
|
IMenuHandler *alt_handler/* =NULL */);
|
||||||
|
bool SetPagination(unsigned int itemsPerPage);
|
||||||
void Cancel_Finally();
|
void Cancel_Finally();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -32,7 +32,6 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "Translator.h"
|
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
|
|
||||||
@@ -67,14 +66,14 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
|
|||||||
void ValveMenuStyle::OnSourceModAllInitialized()
|
void ValveMenuStyle::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_Players.AddClientListener(this);
|
g_Players.AddClientListener(this);
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValveMenuStyle::OnSourceModShutdown()
|
void ValveMenuStyle::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_Players.RemoveClientListener(this);
|
g_Players.RemoveClientListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,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]);
|
||||||
@@ -379,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;
|
||||||
@@ -405,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;
|
||||||
|
|
||||||
@@ -75,6 +77,7 @@ public: //IMenuStyle
|
|||||||
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
||||||
unsigned int GetMaxPageItems();
|
unsigned int GetMaxPageItems();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
|
bool IsSupported() { return true; }
|
||||||
private:
|
private:
|
||||||
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
|
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
|
||||||
private:
|
private:
|
||||||
@@ -105,6 +108,7 @@ public:
|
|||||||
bool SetCurrentKey(unsigned int key);
|
bool SetCurrentKey(unsigned int key);
|
||||||
int GetAmountRemaining();
|
int GetAmountRemaining();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
|
bool DirectSet(const char *str) { return false; }
|
||||||
private:
|
private:
|
||||||
KeyValues *m_pKv;
|
KeyValues *m_pKv;
|
||||||
unsigned int m_NextPos;
|
unsigned int m_NextPos;
|
||||||
|
|||||||
+223
-12
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,9 +34,56 @@
|
|||||||
#include "MenuVoting.h"
|
#include "MenuVoting.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include <sourcemod.h>
|
||||||
|
#include <Logger.h>
|
||||||
|
#include <HalfLife2.h>
|
||||||
|
#include <mathlib.h>
|
||||||
|
#include <const.h>
|
||||||
|
#include <ITranslator.h>
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
float g_next_vote = 0.0f;
|
float g_next_vote = 0.0f;
|
||||||
|
|
||||||
|
#define VOTE_NOT_VOTING -2
|
||||||
|
#define VOTE_PENDING -1
|
||||||
|
|
||||||
|
ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
|
||||||
|
"0",
|
||||||
|
0,
|
||||||
|
"Show current vote progress in a hint box",
|
||||||
|
true,
|
||||||
|
0.0,
|
||||||
|
true,
|
||||||
|
1.0);
|
||||||
|
|
||||||
|
ConVar sm_vote_chat("sm_vote_progress_chat",
|
||||||
|
"0",
|
||||||
|
0,
|
||||||
|
"Show current vote progress as chat messages",
|
||||||
|
true,
|
||||||
|
0.0,
|
||||||
|
true,
|
||||||
|
1.0);
|
||||||
|
|
||||||
|
ConVar sm_vote_console("sm_vote_progress_console",
|
||||||
|
"0",
|
||||||
|
0,
|
||||||
|
"Show current vote progress as console messages",
|
||||||
|
true,
|
||||||
|
0.0,
|
||||||
|
true,
|
||||||
|
1.0);
|
||||||
|
|
||||||
|
ConVar sm_vote_client_console("sm_vote_progress_client_console",
|
||||||
|
"0",
|
||||||
|
0,
|
||||||
|
"Show current vote progress as console messages to clients",
|
||||||
|
true,
|
||||||
|
0.0,
|
||||||
|
true,
|
||||||
|
1.0);
|
||||||
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
|
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
|
||||||
#else
|
#else
|
||||||
@@ -117,7 +164,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
|||||||
* newly connected client is not allowed to vote.
|
* newly connected client is not allowed to vote.
|
||||||
*/
|
*/
|
||||||
int item;
|
int item;
|
||||||
if ((item = m_ClientVotes[client]) >= -1)
|
if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
|
||||||
{
|
{
|
||||||
if (item >= 0)
|
if (item >= 0)
|
||||||
{
|
{
|
||||||
@@ -125,7 +172,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
|||||||
assert(m_Votes[item] > 0);
|
assert(m_Votes[item] > 0);
|
||||||
m_Votes[item]--;
|
m_Votes[item]--;
|
||||||
}
|
}
|
||||||
m_ClientVotes[client] = -2;
|
m_ClientVotes[client] = VOTE_NOT_VOTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,13 +236,13 @@ bool VoteMenuHandler::IsClientInVotePool(int client)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (m_ClientVotes[client] > -2);
|
return (m_ClientVotes[client] > VOTE_NOT_VOTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||||
{
|
{
|
||||||
if (!IsClientInVotePool(client)
|
if (!IsClientInVotePool(client)
|
||||||
|| m_ClientVotes[client] == -1)
|
|| m_ClientVotes[client] == VOTE_PENDING)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -205,7 +252,7 @@ bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoteMenuHandler::RedrawToClient(int client)
|
bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
|
||||||
{
|
{
|
||||||
unsigned int time_limit;
|
unsigned int time_limit;
|
||||||
|
|
||||||
@@ -214,6 +261,20 @@ bool VoteMenuHandler::RedrawToClient(int client)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ClientVotes[client] >= 0)
|
||||||
|
{
|
||||||
|
if ((m_VoteFlags & VOTEFLAG_NO_REVOTES) == VOTEFLAG_NO_REVOTES || !revotes)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert((unsigned)m_ClientVotes[client] < m_Items);
|
||||||
|
assert(m_Votes[m_ClientVotes[client]] > 0);
|
||||||
|
m_Votes[m_ClientVotes[client]]--;
|
||||||
|
m_ClientVotes[client] = VOTE_PENDING;
|
||||||
|
m_Revoting[client] = true;
|
||||||
|
m_NumVotes--;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_nMenuTime == MENU_TIME_FOREVER)
|
if (m_nMenuTime == MENU_TIME_FOREVER)
|
||||||
{
|
{
|
||||||
time_limit = m_nMenuTime;
|
time_limit = m_nMenuTime;
|
||||||
@@ -247,7 +308,8 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
|||||||
/* Mark all clients as not voting */
|
/* Mark all clients as not voting */
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||||
{
|
{
|
||||||
m_ClientVotes[i] = -2;
|
m_ClientVotes[i] = VOTE_NOT_VOTING;
|
||||||
|
m_Revoting[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Items = menu->GetItemCount();
|
m_Items = menu->GetItemCount();
|
||||||
@@ -291,6 +353,8 @@ void VoteMenuHandler::StartVoting()
|
|||||||
|
|
||||||
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
||||||
|
|
||||||
|
m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
|
||||||
/* By now we know how many clients were set.
|
/* By now we know how many clients were set.
|
||||||
* If there are none, we should end IMMEDIATELY.
|
* If there are none, we should end IMMEDIATELY.
|
||||||
*/
|
*/
|
||||||
@@ -298,6 +362,8 @@ void VoteMenuHandler::StartVoting()
|
|||||||
{
|
{
|
||||||
EndVoting();
|
EndVoting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_TotalClients = m_Clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoteMenuHandler::DecrementPlayerCount()
|
void VoteMenuHandler::DecrementPlayerCount()
|
||||||
@@ -334,6 +400,11 @@ void VoteMenuHandler::EndVoting()
|
|||||||
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_displayTimer)
|
||||||
|
{
|
||||||
|
g_Timers.KillTimer(m_displayTimer);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_bCancelled)
|
if (m_bCancelled)
|
||||||
{
|
{
|
||||||
/* If we were cancelled, don't bother tabulating anything.
|
/* If we were cancelled, don't bother tabulating anything.
|
||||||
@@ -380,7 +451,7 @@ void VoteMenuHandler::EndVoting()
|
|||||||
/* Build the client list */
|
/* Build the client list */
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||||
{
|
{
|
||||||
if (m_ClientVotes[i] >= -1)
|
if (m_ClientVotes[i] >= VOTE_PENDING)
|
||||||
{
|
{
|
||||||
client_vote[vote.num_clients].client = i;
|
client_vote[vote.num_clients].client = i;
|
||||||
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
||||||
@@ -424,7 +495,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
|
|||||||
|
|
||||||
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
||||||
{
|
{
|
||||||
m_ClientVotes[client] = -1;
|
m_ClientVotes[client] = VOTE_PENDING;
|
||||||
m_pHandler->OnMenuDisplay(menu, client, display);
|
m_pHandler->OnMenuDisplay(menu, client, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,9 +514,62 @@ 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())
|
||||||
|
{
|
||||||
|
static char buffer[1024];
|
||||||
|
ItemDrawInfo dr;
|
||||||
|
menu->GetItemInfo(item, &dr, client);
|
||||||
|
|
||||||
|
if (sm_vote_console.GetBool())
|
||||||
|
{
|
||||||
|
int target = SOURCEMOD_SERVER_LANGUAGE;
|
||||||
|
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
|
||||||
|
&target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||||
|
Engine_LogPrintWrapper(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
|
||||||
|
{
|
||||||
|
int maxclients = g_Players.GetMaxClients();
|
||||||
|
for (int i=1; i<=maxclients; i++)
|
||||||
|
{
|
||||||
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
|
||||||
|
assert(pPlayer);
|
||||||
|
|
||||||
|
if (pPlayer->IsInGame() && !pPlayer->IsFakeClient())
|
||||||
|
{
|
||||||
|
if (m_Revoting[client])
|
||||||
|
{
|
||||||
|
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote",
|
||||||
|
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
|
||||||
|
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm_vote_chat.GetBool())
|
||||||
|
{
|
||||||
|
g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm_vote_client_console.GetBool())
|
||||||
|
{
|
||||||
|
ClientConsolePrint(pPlayer->GetEdict(), buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildVoteLeaders();
|
||||||
|
DrawHintProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pHandler->OnMenuSelect(menu, client, item);
|
m_pHandler->OnMenuSelect(menu, client, item);
|
||||||
@@ -468,6 +592,9 @@ void VoteMenuHandler::InternalReset()
|
|||||||
m_NumVotes = 0;
|
m_NumVotes = 0;
|
||||||
m_bCancelled = false;
|
m_bCancelled = false;
|
||||||
m_pHandler = NULL;
|
m_pHandler = NULL;
|
||||||
|
m_leaderList[0] = '\0';
|
||||||
|
m_displayTimer = NULL;
|
||||||
|
m_TotalClients = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoteMenuHandler::CancelVoting()
|
void VoteMenuHandler::CancelVoting()
|
||||||
@@ -489,3 +616,87 @@ bool VoteMenuHandler::IsCancelling()
|
|||||||
{
|
{
|
||||||
return m_bCancelled;
|
return m_bCancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoteMenuHandler::DrawHintProgress()
|
||||||
|
{
|
||||||
|
if (!sm_vote_hintbox.GetBool())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char buffer[1024];
|
||||||
|
|
||||||
|
float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
|
||||||
|
if (timeRemaining < 0)
|
||||||
|
{
|
||||||
|
timeRemaining = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iTimeRemaining = RoundFloatToInt(timeRemaining);
|
||||||
|
|
||||||
|
int maxclients = g_Players.GetMaxClients();
|
||||||
|
for (int i=1; i<=maxclients; i++)
|
||||||
|
{
|
||||||
|
if (g_Players.GetPlayerByIndex(i)->IsInGame())
|
||||||
|
{
|
||||||
|
logicore.CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count",
|
||||||
|
&i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
|
||||||
|
g_HL2.HintTextMsg(i, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoteMenuHandler::BuildVoteLeaders()
|
||||||
|
{
|
||||||
|
if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu_vote_result_t vote;
|
||||||
|
menu_vote_result_t::menu_item_vote_t item_vote[256];
|
||||||
|
|
||||||
|
memset(&vote, 0, sizeof(vote));
|
||||||
|
|
||||||
|
/* Build the item list */
|
||||||
|
for (unsigned int i=0; i<m_Items; i++)
|
||||||
|
{
|
||||||
|
if (m_Votes[i] > 0)
|
||||||
|
{
|
||||||
|
item_vote[vote.num_items].count = m_Votes[i];
|
||||||
|
item_vote[vote.num_items].item = i;
|
||||||
|
vote.num_votes += m_Votes[i];
|
||||||
|
vote.num_items++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vote.item_list = item_vote;
|
||||||
|
assert(vote.num_votes);
|
||||||
|
|
||||||
|
/* Sort the item list descending */
|
||||||
|
qsort(item_vote,
|
||||||
|
vote.num_items,
|
||||||
|
sizeof(menu_vote_result_t::menu_item_vote_t),
|
||||||
|
SortVoteItems);
|
||||||
|
|
||||||
|
/* Take the top 3 (if applicable) and draw them */
|
||||||
|
int len = 0;
|
||||||
|
for (unsigned int i=0; i<vote.num_items && i<3; i++)
|
||||||
|
{
|
||||||
|
int curItem = vote.item_list[i].item;
|
||||||
|
ItemDrawInfo dr;
|
||||||
|
m_pCurMenu->GetItemInfo(curItem, &dr);
|
||||||
|
len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
|
||||||
|
{
|
||||||
|
DrawHintProgress();
|
||||||
|
|
||||||
|
return Pl_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
|
||||||
|
{
|
||||||
|
m_displayTimer = NULL;
|
||||||
|
}
|
||||||
|
|||||||
+14
-2
@@ -36,6 +36,7 @@
|
|||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
|
#include <TimerSys.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -43,7 +44,8 @@ using namespace SourceMod;
|
|||||||
class VoteMenuHandler :
|
class VoteMenuHandler :
|
||||||
public IMenuHandler,
|
public IMenuHandler,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IClientListener
|
public IClientListener,
|
||||||
|
public ITimedEvent
|
||||||
{
|
{
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
@@ -61,6 +63,9 @@ public: //IMenuHandler
|
|||||||
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
||||||
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
||||||
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
|
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
|
||||||
|
public: //ITimedEvent
|
||||||
|
ResultType OnTimer(ITimer *pTimer, void *pData);
|
||||||
|
void OnTimerEnd(ITimer *pTimer, void *pData);
|
||||||
public:
|
public:
|
||||||
bool StartVote(IBaseMenu *menu,
|
bool StartVote(IBaseMenu *menu,
|
||||||
unsigned int num_clients,
|
unsigned int num_clients,
|
||||||
@@ -74,7 +79,7 @@ public:
|
|||||||
unsigned int GetRemainingVoteDelay();
|
unsigned int GetRemainingVoteDelay();
|
||||||
bool IsClientInVotePool(int client);
|
bool IsClientInVotePool(int client);
|
||||||
bool GetClientVoteChoice(int client, unsigned int *pItem);
|
bool GetClientVoteChoice(int client, unsigned int *pItem);
|
||||||
bool RedrawToClient(int client);
|
bool RedrawToClient(int client, bool revote);
|
||||||
private:
|
private:
|
||||||
void Reset(IMenuHandler *mh);
|
void Reset(IMenuHandler *mh);
|
||||||
void DecrementPlayerCount();
|
void DecrementPlayerCount();
|
||||||
@@ -85,9 +90,12 @@ private:
|
|||||||
unsigned int time,
|
unsigned int time,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
void StartVoting();
|
void StartVoting();
|
||||||
|
void DrawHintProgress();
|
||||||
|
void BuildVoteLeaders();
|
||||||
private:
|
private:
|
||||||
IMenuHandler *m_pHandler;
|
IMenuHandler *m_pHandler;
|
||||||
unsigned int m_Clients;
|
unsigned int m_Clients;
|
||||||
|
unsigned int m_TotalClients;
|
||||||
unsigned int m_Items;
|
unsigned int m_Items;
|
||||||
CVector<unsigned int> m_Votes;
|
CVector<unsigned int> m_Votes;
|
||||||
IBaseMenu *m_pCurMenu;
|
IBaseMenu *m_pCurMenu;
|
||||||
@@ -99,6 +107,10 @@ private:
|
|||||||
float m_fStartTime;
|
float m_fStartTime;
|
||||||
unsigned int m_nMenuTime;
|
unsigned int m_nMenuTime;
|
||||||
int m_ClientVotes[256+1];
|
int m_ClientVotes[256+1];
|
||||||
|
bool m_Revoting[256+1];
|
||||||
|
char m_leaderList[1024];
|
||||||
|
ITimer *m_displayTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
||||||
|
|
||||||
|
|||||||
@@ -1,379 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourcePawn
|
|
||||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "NativeInvoker.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
|
|
||||||
NativeInterface g_NInvoke;
|
|
||||||
|
|
||||||
NativeInvoker::NativeInvoker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeInvoker::~NativeInvoker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *NativeInterface::GetInterfaceName()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_NINVOKE_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NativeInterface::GetInterfaceVersion()
|
|
||||||
{
|
|
||||||
return SMINTERFACE_NINVOKE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeInterface::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_ShareSys.AddInterface(NULL, &g_NInvoke);
|
|
||||||
}
|
|
||||||
|
|
||||||
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
|
|
||||||
{
|
|
||||||
return g_pSourcePawn2->CreateEmptyRuntime(name, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
INativeInvoker *NativeInterface::CreateInvoker()
|
|
||||||
{
|
|
||||||
return new NativeInvoker();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
|
|
||||||
{
|
|
||||||
NativeEntry *entry;
|
|
||||||
|
|
||||||
entry = g_ShareSys.FindNative(name);
|
|
||||||
if (entry == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
native = NULL;
|
|
||||||
if (entry->replacement.owner != NULL)
|
|
||||||
{
|
|
||||||
native = entry->replacement.func;
|
|
||||||
}
|
|
||||||
else if (entry->owner != NULL)
|
|
||||||
{
|
|
||||||
native = entry->func;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (native == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->pContext = pContext;
|
|
||||||
|
|
||||||
m_curparam = 0;
|
|
||||||
m_errorstate = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t NativeInvoker::PushCell(cell_t cell)
|
|
||||||
{
|
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
|
||||||
{
|
|
||||||
return SetError(SP_ERROR_PARAMS_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_info[m_curparam].marked = false;
|
|
||||||
m_params[m_curparam] = cell;
|
|
||||||
m_curparam++;
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
|
|
||||||
{
|
|
||||||
return PushArray(cell, 1, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushFloat(float number)
|
|
||||||
{
|
|
||||||
cell_t val = *(cell_t *)&number;
|
|
||||||
|
|
||||||
return PushCell(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushFloatByRef(float *number, int flags)
|
|
||||||
{
|
|
||||||
return PushCellByRef((cell_t *)number, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
|
|
||||||
{
|
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
|
||||||
{
|
|
||||||
return SetError(SP_ERROR_PARAMS_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParamInfo *info = &m_info[m_curparam];
|
|
||||||
|
|
||||||
info->flags = inarray ? copyback : 0;
|
|
||||||
info->marked = true;
|
|
||||||
info->size = cells;
|
|
||||||
info->str.is_sz = false;
|
|
||||||
info->orig_addr = inarray;
|
|
||||||
|
|
||||||
m_curparam++;
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushString(const char *string)
|
|
||||||
{
|
|
||||||
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
|
|
||||||
{
|
|
||||||
return _PushString(buffer, sz_flags, cp_flags, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
|
|
||||||
{
|
|
||||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
|
||||||
{
|
|
||||||
return SetError(SP_ERROR_PARAMS_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParamInfo *info = &m_info[m_curparam];
|
|
||||||
|
|
||||||
info->marked = true;
|
|
||||||
info->orig_addr = (cell_t *)string;
|
|
||||||
info->flags = cp_flags;
|
|
||||||
info->size = len;
|
|
||||||
info->str.sz_flags = sz_flags;
|
|
||||||
info->str.is_sz = true;
|
|
||||||
|
|
||||||
m_curparam++;
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeInvoker::Cancel()
|
|
||||||
{
|
|
||||||
if (pContext == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_errorstate = SP_ERROR_NONE;
|
|
||||||
m_curparam = 0;
|
|
||||||
pContext = NULL;
|
|
||||||
native = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::SetError(int err)
|
|
||||||
{
|
|
||||||
m_errorstate = err;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NativeInvoker::Invoke(cell_t *result)
|
|
||||||
{
|
|
||||||
int err = SP_ERROR_NONE;
|
|
||||||
|
|
||||||
if (pContext == NULL)
|
|
||||||
{
|
|
||||||
return SP_ERROR_INVALID_NATIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_errorstate != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
err = m_errorstate;
|
|
||||||
Cancel();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_t tresult;
|
|
||||||
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
result = &tresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is for re-entrancy!
|
|
||||||
IPluginContext *ctx = pContext;
|
|
||||||
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
|
|
||||||
cell_t *temp_params = &_temp_params[1];
|
|
||||||
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
|
||||||
unsigned int numparams = m_curparam;
|
|
||||||
unsigned int i;
|
|
||||||
bool docopies = true;
|
|
||||||
|
|
||||||
if (numparams)
|
|
||||||
{
|
|
||||||
//Save the info locally, then reset it for re-entrant calls.
|
|
||||||
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
|
|
||||||
}
|
|
||||||
m_curparam = 0;
|
|
||||||
pContext = NULL;
|
|
||||||
|
|
||||||
/* Initialize 0th parameter */
|
|
||||||
_temp_params[0] = numparams;
|
|
||||||
|
|
||||||
/* Browse the parameters and build arrays */
|
|
||||||
for (i = 0; i < numparams; i++)
|
|
||||||
{
|
|
||||||
/* Is this marked as an array? */
|
|
||||||
if (temp_info[i].marked)
|
|
||||||
{
|
|
||||||
if (!temp_info[i].str.is_sz)
|
|
||||||
{
|
|
||||||
/* Allocate a normal/generic array */
|
|
||||||
if ((err = ctx->HeapAlloc(temp_info[i].size,
|
|
||||||
&temp_info[i].local_addr,
|
|
||||||
&temp_info[i].phys_addr))
|
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (temp_info[i].orig_addr)
|
|
||||||
{
|
|
||||||
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Calculate cells required for the string */
|
|
||||||
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
|
||||||
|
|
||||||
/* Allocate the buffer */
|
|
||||||
if ((err = ctx->HeapAlloc(cells,
|
|
||||||
&temp_info[i].local_addr,
|
|
||||||
&temp_info[i].phys_addr))
|
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Copy original string if necessary */
|
|
||||||
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
|
|
||||||
{
|
|
||||||
/* Cut off UTF-8 properly */
|
|
||||||
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
|
||||||
{
|
|
||||||
if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
|
|
||||||
temp_info[i].size,
|
|
||||||
(const char *)temp_info[i].orig_addr,
|
|
||||||
NULL))
|
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Copy a binary blob */
|
|
||||||
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
|
|
||||||
{
|
|
||||||
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
|
|
||||||
}
|
|
||||||
/* Copy ASCII characters */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((err = ctx->StringToLocal(temp_info[i].local_addr,
|
|
||||||
temp_info[i].size,
|
|
||||||
(const char *)temp_info[i].orig_addr))
|
|
||||||
!= SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} /* End array/string calculation */
|
|
||||||
/* Update the pushed parameter with the byref local address */
|
|
||||||
temp_params[i] = temp_info[i].local_addr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Just copy the value normally */
|
|
||||||
temp_params[i] = m_params[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the call if we can */
|
|
||||||
if (err == SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
*result = native(ctx, _temp_params);
|
|
||||||
if (ctx->GetLastNativeError() != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
docopies = false;
|
|
||||||
ctx->ClearLastNativeError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
docopies = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* i should be equal to the last valid parameter + 1 */
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
if (!temp_info[i].marked)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
|
|
||||||
{
|
|
||||||
if (temp_info[i].orig_addr)
|
|
||||||
{
|
|
||||||
if (temp_info[i].str.is_sz)
|
|
||||||
{
|
|
||||||
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (temp_info[i].size == 1)
|
|
||||||
{
|
|
||||||
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(temp_info[i].orig_addr,
|
|
||||||
temp_info[i].phys_addr,
|
|
||||||
temp_info[i].size * sizeof(cell_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
|
||||||
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include <INativeInvoker.h>
|
|
||||||
|
|
||||||
struct ParamInfo
|
|
||||||
{
|
|
||||||
int flags; /* Copy-back flags */
|
|
||||||
bool marked; /* Whether this is marked as being used */
|
|
||||||
cell_t local_addr; /* Local address to free */
|
|
||||||
cell_t *phys_addr; /* Physical address of our copy */
|
|
||||||
cell_t *orig_addr; /* Original address to copy back to */
|
|
||||||
ucell_t size; /* Size of array in bytes */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool is_sz; /* is a string */
|
|
||||||
int sz_flags; /* has sz flags */
|
|
||||||
} str;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NativeInvoker : public INativeInvoker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NativeInvoker();
|
|
||||||
~NativeInvoker();
|
|
||||||
public: /* ICallable */
|
|
||||||
int PushCell(cell_t cell);
|
|
||||||
int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
|
|
||||||
int PushFloat(float number);
|
|
||||||
int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
|
|
||||||
int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
|
|
||||||
int PushString(const char *string);
|
|
||||||
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
|
|
||||||
void Cancel();
|
|
||||||
public: /* INativeInvoker */
|
|
||||||
bool Start(IPluginContext *pContext, const char *name);
|
|
||||||
int Invoke(cell_t *result);
|
|
||||||
private:
|
|
||||||
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
|
||||||
int SetError(int err);
|
|
||||||
private:
|
|
||||||
IPluginContext *pContext;
|
|
||||||
SPVM_NATIVE_FUNC native;
|
|
||||||
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
|
||||||
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
|
||||||
unsigned int m_curparam;
|
|
||||||
int m_errorstate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NativeInterface :
|
|
||||||
public INativeInterface,
|
|
||||||
public SMGlobalClass
|
|
||||||
{
|
|
||||||
public: /* SMGlobalClass */
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
public: /* SMInterface */
|
|
||||||
unsigned int GetInterfaceVersion();
|
|
||||||
const char *GetInterfaceName();
|
|
||||||
public: /* INativeInvoker */
|
|
||||||
IPluginRuntime *CreateRuntime(const char *name, size_t bytes);
|
|
||||||
INativeInvoker *CreateInvoker();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern NativeInterface g_NInvoke;
|
|
||||||
|
|
||||||
#endif /* _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ */
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
#include "NativeOwner.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
|
|
||||||
CNativeOwner::CNativeOwner() : m_nMarkSerial(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::SetMarkSerial(unsigned int serial)
|
|
||||||
{
|
|
||||||
m_nMarkSerial = serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CNativeOwner::GetMarkSerial()
|
|
||||||
{
|
|
||||||
return m_nMarkSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::AddDependent(CPlugin *pPlugin)
|
|
||||||
{
|
|
||||||
m_Dependents.push_back(pPlugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::AddWeakRef(const WeakNative & ref)
|
|
||||||
{
|
|
||||||
m_WeakRefs.push_back(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
|
|
||||||
{
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
|
|
||||||
{
|
|
||||||
if ((pEntry = g_ShareSys.AddNativeToCache(this, &natives[i])) == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Natives.push_back(pEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::PropogateMarkSerial(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)
|
|
||||||
{
|
|
||||||
sp_native_t *native;
|
|
||||||
IPluginContext *pContext;
|
|
||||||
|
|
||||||
pContext = ref.pl->GetBaseContext();
|
|
||||||
if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
/* If there is no reference, the native must be unbound */
|
|
||||||
if (ref.entry == NULL)
|
|
||||||
{
|
|
||||||
native->status = SP_NATIVE_UNBOUND;
|
|
||||||
native->pfn = NULL;
|
|
||||||
}
|
|
||||||
/* If we've cached a reference, it's a core native we can
|
|
||||||
* rebind back to its original (this was a replacement).
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
native->pfn = ref.entry->func;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::DropEverything()
|
|
||||||
{
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
List<WeakNative>::iterator iter;
|
|
||||||
List<NativeEntry *>::iterator ntv_iter;
|
|
||||||
|
|
||||||
/* Unbind and remove all weak references to us */
|
|
||||||
iter = m_WeakRefs.begin();
|
|
||||||
while (iter != m_WeakRefs.end())
|
|
||||||
{
|
|
||||||
UnbindWeakRef((*iter));
|
|
||||||
iter = m_WeakRefs.erase(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmark our replacement natives */
|
|
||||||
ntv_iter = m_ReplacedNatives.begin();
|
|
||||||
while (ntv_iter != m_ReplacedNatives.end())
|
|
||||||
{
|
|
||||||
pEntry = (*ntv_iter);
|
|
||||||
pEntry->replacement.func = NULL;
|
|
||||||
pEntry->replacement.owner = NULL;
|
|
||||||
ntv_iter = m_ReplacedNatives.erase(ntv_iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Strip all of our natives from the cache */
|
|
||||||
ntv_iter = m_Natives.begin();
|
|
||||||
while (ntv_iter != m_Natives.end())
|
|
||||||
{
|
|
||||||
g_ShareSys.ClearNativeFromCache(this, (*ntv_iter)->name);
|
|
||||||
ntv_iter = m_Natives.erase(ntv_iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin)
|
|
||||||
{
|
|
||||||
List<WeakNative>::iterator iter;
|
|
||||||
|
|
||||||
iter = m_WeakRefs.begin();
|
|
||||||
while (iter != m_WeakRefs.end())
|
|
||||||
{
|
|
||||||
WeakNative & ref = (*iter);
|
|
||||||
|
|
||||||
if (ref.pl == pPlugin)
|
|
||||||
{
|
|
||||||
iter = m_WeakRefs.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::DropRefsTo(CPlugin *pPlugin)
|
|
||||||
{
|
|
||||||
m_Dependents.remove(pPlugin);
|
|
||||||
DropWeakRefsTo(pPlugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNativeOwner::AddReplacedNative(NativeEntry *pEntry)
|
|
||||||
{
|
|
||||||
m_ReplacedNatives.push_back(pEntry);
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
|
|
||||||
|
|
||||||
#include <sp_vm_types.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
|
|
||||||
class CPlugin;
|
|
||||||
struct NativeEntry;
|
|
||||||
|
|
||||||
struct WeakNative
|
|
||||||
{
|
|
||||||
WeakNative(CPlugin *plugin, uint32_t index) :
|
|
||||||
pl(plugin), idx(index), entry(NULL)
|
|
||||||
{
|
|
||||||
pl = plugin;
|
|
||||||
idx = index;
|
|
||||||
}
|
|
||||||
WeakNative(CPlugin *plugin, uint32_t index, NativeEntry *pEntry) :
|
|
||||||
pl(plugin), idx(index), entry(pEntry)
|
|
||||||
{
|
|
||||||
pl = plugin;
|
|
||||||
idx = index;
|
|
||||||
}
|
|
||||||
CPlugin *pl;
|
|
||||||
uint32_t idx;
|
|
||||||
NativeEntry *entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class CNativeOwner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CNativeOwner();
|
|
||||||
public:
|
|
||||||
virtual void DropEverything();
|
|
||||||
public:
|
|
||||||
void AddNatives(const sp_nativeinfo_t *info);
|
|
||||||
public:
|
|
||||||
void SetMarkSerial(unsigned int serial);
|
|
||||||
unsigned int GetMarkSerial();
|
|
||||||
void PropogateMarkSerial(unsigned int serial);
|
|
||||||
public:
|
|
||||||
void AddDependent(CPlugin *pPlugin);
|
|
||||||
void AddWeakRef(const WeakNative & ref);
|
|
||||||
void DropRefsTo(CPlugin *pPlugin);
|
|
||||||
void AddReplacedNative(NativeEntry *pEntry);
|
|
||||||
private:
|
|
||||||
void DropWeakRefsTo(CPlugin *pPlugin);
|
|
||||||
void UnbindWeakRef(const WeakNative & ref);
|
|
||||||
protected:
|
|
||||||
List<CPlugin *> m_Dependents;
|
|
||||||
unsigned int m_nMarkSerial;
|
|
||||||
List<WeakNative> m_WeakRefs;
|
|
||||||
List<NativeEntry *> m_Natives;
|
|
||||||
List<NativeEntry *> m_ReplacedNatives;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
|
|
||||||
+32
-27
@@ -31,10 +31,14 @@
|
|||||||
|
|
||||||
#include "NextMap.h"
|
#include "NextMap.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "HalfLife2.h"
|
||||||
#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 "compat_wrappers.h"
|
||||||
|
#include <time.h>
|
||||||
|
#include <bridge/include/ILogger.h>
|
||||||
|
|
||||||
NextMapManager g_NextMap;
|
NextMapManager g_NextMap;
|
||||||
|
|
||||||
@@ -46,16 +50,14 @@ SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, co
|
|||||||
|
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if 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
|
|
||||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
|
||||||
#else
|
#else
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
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;
|
||||||
|
|
||||||
@@ -64,13 +66,13 @@ void NextMapManager::OnSourceModAllInitialized_Post()
|
|||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
#else
|
#else
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
|
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConCommand *pCmd = FindCommand("changelevel");
|
ConCommand *pCmd = FindCommand("changelevel");
|
||||||
if (pCmd != NULL)
|
if (pCmd != NULL)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false);
|
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false);
|
||||||
changeLevelCmd = pCmd;
|
changeLevelCmd = pCmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,12 +82,12 @@ void NextMapManager::OnSourceModShutdown()
|
|||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
#else
|
#else
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
|
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (changeLevelCmd != NULL)
|
if (changeLevelCmd != NULL)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, changeLevelCmd, CmdChangeLevelCallback, false);
|
SH_REMOVE_HOOK(ConCommand, Dispatch, changeLevelCmd, SH_STATIC(CmdChangeLevelCallback), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceHook::List<MapChangeData *>::iterator iter;
|
SourceHook::List<MapChangeData *>::iterator iter;
|
||||||
@@ -105,7 +107,7 @@ const char *NextMapManager::GetNextMap()
|
|||||||
|
|
||||||
bool NextMapManager::SetNextMap(const char *map)
|
bool NextMapManager::SetNextMap(const char *map)
|
||||||
{
|
{
|
||||||
if (!engine->IsMapValid(map))
|
if (!g_HL2.IsMapValid(map))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -123,21 +125,21 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
|||||||
{
|
{
|
||||||
if (g_forcedChange)
|
if (g_forcedChange)
|
||||||
{
|
{
|
||||||
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
|
logger->LogMessage("[SM] Changed map to \"%s\"", map);
|
||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *newmap = sm_nextmap.GetString();
|
const char *newmap = sm_nextmap.GetString();
|
||||||
|
|
||||||
if (newmap[0] == 0 || !engine->IsMapValid(newmap))
|
if (newmap[0] == 0 || !g_HL2.IsMapValid(newmap))
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_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));
|
||||||
@@ -160,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), 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), mapName);
|
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
|
||||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), 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;
|
||||||
@@ -216,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ struct MapChangeData
|
|||||||
startTime = 0;
|
startTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char m_mapName[32];
|
char m_mapName[PLATFORM_MAX_PATH];
|
||||||
char m_changeReason[100];
|
char m_changeReason[100];
|
||||||
time_t startTime;
|
time_t startTime;
|
||||||
};
|
};
|
||||||
|
|||||||
+1151
-218
File diff suppressed because it is too large
Load Diff
+90
-25
@@ -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,13 +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-deque.h>
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.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
|
||||||
@@ -56,7 +63,7 @@ union serial_t
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t index;
|
uint32_t index : 8;
|
||||||
uint32_t serial : 24;
|
uint32_t serial : 24;
|
||||||
} bits;
|
} bits;
|
||||||
};
|
};
|
||||||
@@ -69,68 +76,98 @@ public:
|
|||||||
public:
|
public:
|
||||||
const char *GetName();
|
const char *GetName();
|
||||||
const char *GetIPAddress();
|
const char *GetIPAddress();
|
||||||
const char *GetAuthString();
|
const char *GetAuthString(bool validated = true);
|
||||||
|
unsigned int GetSteamAccountID(bool validated = true);
|
||||||
|
const CSteamID &GetSteamId(bool validated = true);
|
||||||
|
uint64_t GetSteamId64(bool validated = true) { return GetSteamId(validated).ConvertToUint64(); }
|
||||||
|
const char *GetSteam2Id(bool validated = true);
|
||||||
|
const char *GetSteam3Id(bool validated = true);
|
||||||
edict_t *GetEdict();
|
edict_t *GetEdict();
|
||||||
bool IsInGame();
|
bool IsInGame();
|
||||||
bool WasCountedAsInGame();
|
bool WasCountedAsInGame();
|
||||||
bool IsConnected();
|
bool IsConnected();
|
||||||
bool IsAuthorized();
|
bool IsAuthorized();
|
||||||
bool IsFakeClient();
|
bool IsFakeClient();
|
||||||
|
bool IsSourceTV() const;
|
||||||
|
bool IsReplay() const;
|
||||||
void SetAdminId(AdminId id, bool temporary);
|
void SetAdminId(AdminId id, bool temporary);
|
||||||
AdminId GetAdminId();
|
AdminId GetAdminId();
|
||||||
void Kick(const char *str);
|
void Kick(const char *str);
|
||||||
|
bool IsInKickQueue();
|
||||||
IPlayerInfo *GetPlayerInfo();
|
IPlayerInfo *GetPlayerInfo();
|
||||||
unsigned int GetLanguageId();
|
unsigned int GetLanguageId();
|
||||||
|
void SetLanguageId(unsigned int id);
|
||||||
int GetUserId();
|
int GetUserId();
|
||||||
bool RunAdminCacheChecks();
|
bool RunAdminCacheChecks();
|
||||||
void NotifyPostAdminChecks();
|
void NotifyPostAdminChecks();
|
||||||
unsigned int GetSerial();
|
unsigned int GetSerial();
|
||||||
|
int GetIndex() const;
|
||||||
|
void PrintToConsole(const char *pMsg);
|
||||||
|
void ClearAdmin();
|
||||||
public:
|
public:
|
||||||
void DoBasicAdminChecks();
|
void DoBasicAdminChecks();
|
||||||
bool IsInKickQueue();
|
|
||||||
void MarkAsBeingKicked();
|
void MarkAsBeingKicked();
|
||||||
int GetLifeState();
|
int GetLifeState();
|
||||||
|
|
||||||
|
// 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();
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
void SetName(const char *name);
|
void SetName(const char *name);
|
||||||
void DumpAdmin(bool deleting);
|
void DumpAdmin(bool deleting);
|
||||||
void Authorize(const char *auth);
|
void UpdateAuthIds();
|
||||||
|
void Authorize();
|
||||||
void Authorize_Post();
|
void Authorize_Post();
|
||||||
void DoPostConnectAuthorization();
|
void DoPostConnectAuthorization();
|
||||||
|
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;
|
||||||
String m_AuthID;
|
ke::AString m_AuthID;
|
||||||
AdminId m_Admin;
|
ke::AString m_Steam2Id;
|
||||||
bool m_TempAdmin;
|
ke::AString m_Steam3Id;
|
||||||
edict_t *m_pEdict;
|
AdminId m_Admin = INVALID_ADMIN_ID;
|
||||||
IPlayerInfo *m_Info;
|
bool m_TempAdmin = false;
|
||||||
|
edict_t *m_pEdict = nullptr;
|
||||||
|
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 = false;
|
||||||
|
bool m_bIsReplay = false;
|
||||||
serial_t m_Serial;
|
serial_t m_Serial;
|
||||||
|
CSteamID m_SteamId;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
|
||||||
|
#endif
|
||||||
|
ke::Deque<ke::AString> m_PrintfBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerManager :
|
class PlayerManager :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IPlayerManager,
|
public IPlayerManager,
|
||||||
public IConVarChangeListener
|
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();
|
||||||
@@ -139,8 +176,6 @@ public: //SMGlobalClass
|
|||||||
public:
|
public:
|
||||||
CPlayer *GetPlayerByIndex(int client) const;
|
CPlayer *GetPlayerByIndex(int client) const;
|
||||||
void RunAuthChecks();
|
void RunAuthChecks();
|
||||||
void ClearAdminId(AdminId id);
|
|
||||||
void ClearAllAdmins();
|
|
||||||
public:
|
public:
|
||||||
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);
|
||||||
@@ -149,11 +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);
|
||||||
|
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);
|
||||||
@@ -161,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);
|
||||||
@@ -169,8 +212,10 @@ public: //IPlayerManager
|
|||||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
void ProcessCommandTarget(cmd_target_info_t *info);
|
||||||
int GetClientFromSerial(unsigned int serial);
|
int GetClientFromSerial(unsigned int serial);
|
||||||
public: // IConVarChangeListener
|
void ClearAdminId(AdminId id);
|
||||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
void RecheckAnyAdmins();
|
||||||
|
public: // IGameEventListener2
|
||||||
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
public:
|
public:
|
||||||
inline int MaxClients()
|
inline int MaxClients()
|
||||||
{
|
{
|
||||||
@@ -187,20 +232,29 @@ public:
|
|||||||
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
||||||
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
||||||
const char *GetPassInfoVar();
|
const char *GetPassInfoVar();
|
||||||
void RecheckAnyAdmins();
|
|
||||||
unsigned int GetReplyTo();
|
unsigned int GetReplyTo();
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
unsigned int SetReplyTo(unsigned int reply);
|
||||||
void MaxPlayersChanged(int newvalue = -1);
|
void MaxPlayersChanged(int newvalue = -1);
|
||||||
|
inline bool InClientCommandKeyValuesHook()
|
||||||
|
{
|
||||||
|
return m_bInCCKVHook;
|
||||||
|
}
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
bool HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
void InvalidatePlayer(CPlayer *pPlayer);
|
void InvalidatePlayer(CPlayer *pPlayer);
|
||||||
private:
|
private:
|
||||||
List<IClientListener *> m_hooks;
|
List<IClientListener *> m_hooks;
|
||||||
IForward *m_clconnect;
|
IForward *m_clconnect;
|
||||||
|
IForward *m_clconnect_post;
|
||||||
IForward *m_cldisconnect;
|
IForward *m_cldisconnect;
|
||||||
IForward *m_cldisconnect_post;
|
IForward *m_cldisconnect_post;
|
||||||
IForward *m_clputinserver;
|
IForward *m_clputinserver;
|
||||||
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;
|
||||||
@@ -209,12 +263,23 @@ private:
|
|||||||
int *m_UserIdLookUp;
|
int *m_UserIdLookUp;
|
||||||
int m_maxClients;
|
int m_maxClients;
|
||||||
int m_PlayerCount;
|
int m_PlayerCount;
|
||||||
bool m_FirstPass;
|
int m_PlayersSinceActive;
|
||||||
|
bool m_bServerActivated;
|
||||||
unsigned int *m_AuthQueue;
|
unsigned int *m_AuthQueue;
|
||||||
String m_PassInfoVar;
|
String m_PassInfoVar;
|
||||||
bool m_QueryLang;
|
bool m_QueryLang;
|
||||||
|
bool m_bAuthstringValidation; // are we validating admins with steam before authorizing?
|
||||||
bool m_bIsListenServer;
|
bool m_bIsListenServer;
|
||||||
int m_ListenClient;
|
int m_ListenClient;
|
||||||
|
bool m_bIsSourceTVActive;
|
||||||
|
bool m_bIsReplayActive;
|
||||||
|
int m_SourceTVUserId;
|
||||||
|
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_ORANGEBOX
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
|||||||
@@ -1,349 +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 <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "PluginInfoDatabase.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
|
|
||||||
void PluginSettings::Init()
|
|
||||||
{
|
|
||||||
name = -1;
|
|
||||||
pause_val = false;
|
|
||||||
type_val = PluginType_MapUpdated;
|
|
||||||
optarray = -1;
|
|
||||||
opts_num = 0;
|
|
||||||
opts_size = 0;
|
|
||||||
blockload_val = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* :TODO: write the logger, make these errors log instead of being static
|
|
||||||
* NOTE: once we do that, we will have to change some code to ignore sections
|
|
||||||
*/
|
|
||||||
|
|
||||||
CPluginInfoDatabase::CPluginInfoDatabase()
|
|
||||||
{
|
|
||||||
m_strtab = NULL;
|
|
||||||
m_infodb_count = 0;
|
|
||||||
m_infodb_size = 0;
|
|
||||||
m_infodb = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPluginInfoDatabase::~CPluginInfoDatabase()
|
|
||||||
{
|
|
||||||
delete m_strtab;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPluginInfoDatabase::ReadSMC_ParseStart()
|
|
||||||
{
|
|
||||||
/* Create or reset our string table */
|
|
||||||
if (m_strtab)
|
|
||||||
{
|
|
||||||
m_strtab->Reset();
|
|
||||||
} else {
|
|
||||||
m_strtab = new BaseStringTable(1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set our internal states to the beginning */
|
|
||||||
in_plugins = false;
|
|
||||||
cur_plugin = -1;
|
|
||||||
in_options = false;
|
|
||||||
m_infodb_size = 0;
|
|
||||||
m_infodb_count = 0;
|
|
||||||
m_infodb = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
char buffer[512];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
m_errmsg = m_strtab->AddString(buffer);
|
|
||||||
|
|
||||||
return SMCResult_HaltFail;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CPluginInfoDatabase::GetSettingsNum()
|
|
||||||
{
|
|
||||||
return m_infodb_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
|
|
||||||
{
|
|
||||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
|
||||||
int *table = (int *)memtab->GetAddress(m_infodb);
|
|
||||||
|
|
||||||
if (!table || index >= m_infodb_count)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
|
|
||||||
|
|
||||||
const char *name = m_strtab->GetString(plugin->name);
|
|
||||||
|
|
||||||
if (!name)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_PluginSys.TestAliasMatch(name, filename))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
|
|
||||||
{
|
|
||||||
PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
|
|
||||||
if (!table)
|
|
||||||
{
|
|
||||||
*key = NULL;
|
|
||||||
*val = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_num >= settings->opts_num)
|
|
||||||
{
|
|
||||||
*key = NULL;
|
|
||||||
*val = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*key = m_strtab->GetString(table[opt_num].key);
|
|
||||||
*val = m_strtab->GetString(table[opt_num].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CPluginInfoDatabase::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
if (cur_plugin != -1)
|
|
||||||
{
|
|
||||||
PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
|
|
||||||
if (!in_options)
|
|
||||||
{
|
|
||||||
if (strcmp(key, "pause") == 0)
|
|
||||||
{
|
|
||||||
if (strcasecmp(value, "yes") == 0)
|
|
||||||
{
|
|
||||||
plugin->pause_val = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugin->pause_val = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(key, "lifetime") == 0)
|
|
||||||
{
|
|
||||||
if (strcasecmp(value, "private") == 0)
|
|
||||||
{
|
|
||||||
plugin->type_val = PluginType_Private;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(value, "mapsync") == 0)
|
|
||||||
{
|
|
||||||
plugin->type_val = PluginType_MapUpdated;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(value, "maponly") == 0)
|
|
||||||
{
|
|
||||||
plugin->type_val = PluginType_MapOnly;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(value, "global") == 0)
|
|
||||||
{
|
|
||||||
plugin->type_val = PluginType_Global;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(key, "blockload") == 0)
|
|
||||||
{
|
|
||||||
plugin->blockload_val = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return MakeError("Unknown property key: \"%s\"", key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Cache every option, valid or not */
|
|
||||||
int keyidx = m_strtab->AddString(key);
|
|
||||||
int validx = m_strtab->AddString(value);
|
|
||||||
PluginOpts *table;
|
|
||||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
|
||||||
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
|
|
||||||
if (plugin->opts_num + 1 > plugin->opts_size)
|
|
||||||
{
|
|
||||||
unsigned int oldsize = plugin->opts_size;
|
|
||||||
if (oldsize == 0)
|
|
||||||
{
|
|
||||||
//right now we don't have many
|
|
||||||
plugin->opts_size = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugin->opts_size *= 2;
|
|
||||||
}
|
|
||||||
int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
|
|
||||||
/* in case it resized */
|
|
||||||
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
|
|
||||||
if (plugin->optarray != -1)
|
|
||||||
{
|
|
||||||
void *oldtable = memtab->GetAddress(plugin->optarray);
|
|
||||||
memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
|
|
||||||
}
|
|
||||||
plugin->optarray = newidx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
|
|
||||||
}
|
|
||||||
PluginOpts *opt = &table[plugin->opts_num++];
|
|
||||||
opt->key = keyidx;
|
|
||||||
opt->val = validx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in_plugins)
|
|
||||||
{
|
|
||||||
return MakeError("Unknown property key: \"%s\"", key);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Ignore anything we don't know about! */
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
|
|
||||||
{
|
|
||||||
if (in_plugins)
|
|
||||||
{
|
|
||||||
if (cur_plugin != -1)
|
|
||||||
{
|
|
||||||
if (in_options)
|
|
||||||
{
|
|
||||||
in_options = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If the plugin is ending, add it to the table */
|
|
||||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
|
||||||
int *table;
|
|
||||||
if (m_infodb_count + 1 > m_infodb_size)
|
|
||||||
{
|
|
||||||
unsigned int oldsize = m_infodb_size;
|
|
||||||
if (!m_infodb_size)
|
|
||||||
{
|
|
||||||
m_infodb_size = 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_infodb_size *= 2;
|
|
||||||
}
|
|
||||||
int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
|
|
||||||
if (m_infodb != -1)
|
|
||||||
{
|
|
||||||
void *oldtable = (int *)memtab->GetAddress(m_infodb);
|
|
||||||
memcpy(table, oldtable, oldsize * sizeof(int));
|
|
||||||
}
|
|
||||||
m_infodb = newidx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table = (int *)memtab->GetAddress(m_infodb);
|
|
||||||
}
|
|
||||||
/* Assign to table and scrap the current plugin */
|
|
||||||
table[m_infodb_count++] = cur_plugin;
|
|
||||||
cur_plugin = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
in_plugins = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMCResult CPluginInfoDatabase::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
|
||||||
{
|
|
||||||
if (!in_plugins)
|
|
||||||
{
|
|
||||||
/* If we're not in the main Plugins section, and we don't get it for the name, error out */
|
|
||||||
if (strcmp(name, "Plugins") != 0)
|
|
||||||
{
|
|
||||||
return MakeError("Unknown root section: \"%s\"", name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Otherwise set our states */
|
|
||||||
in_plugins = true;
|
|
||||||
cur_plugin = -1;
|
|
||||||
in_options = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cur_plugin == -1)
|
|
||||||
{
|
|
||||||
/* If we get a plugin node and we don't have a current plugin, create a new one */
|
|
||||||
PluginSettings *plugin;
|
|
||||||
int i_name = m_strtab->AddString(name);
|
|
||||||
cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
|
|
||||||
plugin->Init();
|
|
||||||
plugin->name = i_name;
|
|
||||||
in_options = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!in_options && strcmp(name, "Options") == 0)
|
|
||||||
{
|
|
||||||
in_options = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return MakeError("Unknown plugin sub-section: \"%s\"", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SMCResult_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file parses plugin_settings.cfg and stores the information in cached memory.
|
|
||||||
* It provides simplistic abstraction to retrieving the info.
|
|
||||||
* :TODO: currently untested
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "ITextParsers.h"
|
|
||||||
#include "IPluginSys.h"
|
|
||||||
#include "sm_globals.h"
|
|
||||||
|
|
||||||
struct PluginOpts
|
|
||||||
{
|
|
||||||
int key;
|
|
||||||
int val;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PluginSettings
|
|
||||||
{
|
|
||||||
void Init();
|
|
||||||
int name;
|
|
||||||
bool pause_val;
|
|
||||||
PluginType type_val;
|
|
||||||
int optarray;
|
|
||||||
size_t opts_num;
|
|
||||||
size_t opts_size;
|
|
||||||
bool blockload_val;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPluginInfoDatabase : public ITextListener_SMC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPluginInfoDatabase();
|
|
||||||
~CPluginInfoDatabase();
|
|
||||||
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);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Returns the number of plugin settings available.
|
|
||||||
*/
|
|
||||||
unsigned int GetSettingsNum();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an index, returns the plugin settings block if the filename matches.
|
|
||||||
* Otherwise, returns NULL.
|
|
||||||
*/
|
|
||||||
PluginSettings *GetSettingsIfMatch(unsigned int index, const char *filename);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a plugin settings struct and an index,
|
|
||||||
* returns the given JIT key/value option pair at that index.
|
|
||||||
* If the input is invalid, key and val will be set to NULL.
|
|
||||||
*/
|
|
||||||
void GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val);
|
|
||||||
private:
|
|
||||||
SMCResult MakeError(const char *fmt, ...);
|
|
||||||
private:
|
|
||||||
BaseStringTable *m_strtab;
|
|
||||||
int m_errmsg;
|
|
||||||
bool in_plugins;
|
|
||||||
bool in_options;
|
|
||||||
int m_infodb;
|
|
||||||
size_t m_infodb_count;
|
|
||||||
size_t m_infodb_size;
|
|
||||||
int cur_plugin;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
|
||||||
-2706
File diff suppressed because it is too large
Load Diff
@@ -1,464 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <IPluginSys.h>
|
|
||||||
#include <IHandleSys.h>
|
|
||||||
#include <IForwardSys.h>
|
|
||||||
#include <sh_list.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include <sh_string.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "PluginInfoDatabase.h"
|
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include <IRootConsoleMenu.h>
|
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
|
||||||
#include "convar_sm_l4d.h"
|
|
||||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
|
||||||
#include "convar_sm_ob.h"
|
|
||||||
#else
|
|
||||||
#include "convar_sm.h"
|
|
||||||
#endif
|
|
||||||
#include "ITranslator.h"
|
|
||||||
#include "NativeOwner.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
|
|
||||||
class CPlayer;
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTES:
|
|
||||||
*
|
|
||||||
* UPDATE 2008-03-11: These comments are horribly out of date. They paint a good overall
|
|
||||||
* picture of how PluginSys works, but things like dependencies and fake natives have
|
|
||||||
* complicated things quite a bit.
|
|
||||||
*
|
|
||||||
* Currently this system needs a lot of work but it's good skeletally. Plugin creation
|
|
||||||
* is done without actually compiling anything. This is done by Load functions in the
|
|
||||||
* manager. This will need a rewrite when we add context switching.
|
|
||||||
*
|
|
||||||
* The plugin object itself has a few things to note. The most important is that it stores
|
|
||||||
* a table of function objects. The manager marshals allocation and freeing of these objects.
|
|
||||||
* The plugin object can be in erroneous states, they are:
|
|
||||||
* Plugin_Error --> Some error occurred any time during or after compilation.
|
|
||||||
* This error can be cleared since the plugin itself is valid.
|
|
||||||
* However, the state itself being set prevents any runtime action.
|
|
||||||
* Plugin_BadLoad --> The plugin failed to load entirely and nothing can be done to save it.
|
|
||||||
*
|
|
||||||
* If a plugin fails to load externally, it is never added to the internal tracker. However,
|
|
||||||
* plugins that failed to load from the internal loading mechanism are always tracked. This
|
|
||||||
* allows users to see which automatically loaded plugins failed, and makes the interface a bit
|
|
||||||
* more flexible.
|
|
||||||
*
|
|
||||||
* Once a plugin is compiled, it sets its own state to Plugin_Created. This state is still invalid
|
|
||||||
* for execution. SourceMod is a two pass system, and even though the second pass is not implemented
|
|
||||||
* yet, it is structured so Plugin_Created must be switched to Plugin_Running in the second pass. When
|
|
||||||
* implemented, a Created plugin will be switched to Error in the second pass if it not loadable.
|
|
||||||
*
|
|
||||||
* The two pass loading mechanism is described below. Modules/natives are not implemented yet.
|
|
||||||
* PASS ONE: All loadable plugins are found and have the following steps performed:
|
|
||||||
* 1. Loading and compilation is attempted.
|
|
||||||
* 2. If successful, all natives from Core are added.
|
|
||||||
* 3. OnPluginLoad() is called.
|
|
||||||
* 4. If failed, any user natives are scrapped and the process halts here.
|
|
||||||
* 5. If successful, the plugin is ready for Pass 2.
|
|
||||||
* INTERMEDIATE:
|
|
||||||
* 1. All forced modules are loaded.
|
|
||||||
* PASS TWO: All loaded plugins are found and have these steps performed:
|
|
||||||
* 1. Any modules referenced in the plugin that are not already loaded, are loaded.
|
|
||||||
* 2. If any module fails to load and the plugin requires it, load fails and jump to step 6.
|
|
||||||
* 3. If any natives are unresolved, check if they are found in the user-natives pool.
|
|
||||||
* 4. If yes, load succeeds. If not, natives are passed through a native acceptance filter.
|
|
||||||
* 5. If the filter fails, the plugin is marked as failed.
|
|
||||||
* 6. If the plugin has failed to load at this point, any dynamic natives it has added are scrapped.
|
|
||||||
* Furthermore, any plugin that referenced these natives must now have pass 2 re-ran.
|
|
||||||
* PASS THREE (not a real pass):
|
|
||||||
* 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum LoadRes
|
|
||||||
{
|
|
||||||
LoadRes_Successful,
|
|
||||||
LoadRes_AlreadyLoaded,
|
|
||||||
LoadRes_Failure,
|
|
||||||
LoadRes_NeverLoad
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AutoConfig
|
|
||||||
{
|
|
||||||
String autocfg;
|
|
||||||
String folder;
|
|
||||||
bool create;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPlugin;
|
|
||||||
|
|
||||||
class CPlugin :
|
|
||||||
public IPlugin,
|
|
||||||
public CNativeOwner
|
|
||||||
{
|
|
||||||
friend class CPluginManager;
|
|
||||||
friend class CFunction;
|
|
||||||
public:
|
|
||||||
CPlugin(const char *file);
|
|
||||||
~CPlugin();
|
|
||||||
public:
|
|
||||||
PluginType GetType();
|
|
||||||
SourcePawn::IPluginContext *GetBaseContext();
|
|
||||||
sp_context_t *GetContext();
|
|
||||||
void *GetPluginStructure();
|
|
||||||
const char *GetFilename();
|
|
||||||
bool IsDebugging();
|
|
||||||
PluginStatus GetStatus();
|
|
||||||
const sm_plugininfo_t *GetPublicInfo();
|
|
||||||
bool SetPauseState(bool paused);
|
|
||||||
unsigned int GetSerial();
|
|
||||||
IdentityToken_t *GetIdentity();
|
|
||||||
unsigned int CalcMemUsage();
|
|
||||||
bool SetProperty(const char *prop, void *ptr);
|
|
||||||
bool GetProperty(const char *prop, void **ptr, bool remove=false);
|
|
||||||
void DropEverything();
|
|
||||||
SourcePawn::IPluginRuntime *GetRuntime();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a plugin object with default values.
|
|
||||||
* If an error buffer is specified, and an error occurs, the error will be copied to the buffer
|
|
||||||
* and NULL will be returned.
|
|
||||||
* If an error buffer is not specified, the error will be copied to an internal buffer and
|
|
||||||
* a valid (but error-stated) CPlugin will be returned.
|
|
||||||
*/
|
|
||||||
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an error state on the plugin
|
|
||||||
*/
|
|
||||||
void SetErrorState(PluginStatus status, const char *error_fmt, ...);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the plugin's identity information
|
|
||||||
*/
|
|
||||||
void InitIdentity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the OnPluginLoad function, and sets any failed states if necessary.
|
|
||||||
* NOTE: Valid pre-states are: Plugin_Created
|
|
||||||
* NOTE: If validated, plugin state is changed to Plugin_Loaded
|
|
||||||
*
|
|
||||||
* If the error buffer is NULL, the error message is cached locally.
|
|
||||||
*/
|
|
||||||
bool Call_AskPluginLoad(char *error, size_t maxlength);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the OnPluginStart function.
|
|
||||||
* NOTE: Valid pre-states are: Plugin_Created
|
|
||||||
* NOTE: Post-state will be Plugin_Running
|
|
||||||
*/
|
|
||||||
void Call_OnPluginStart();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the OnPluginEnd function.
|
|
||||||
*/
|
|
||||||
void Call_OnPluginEnd();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the OnAllPluginsLoaded function.
|
|
||||||
*/
|
|
||||||
void Call_OnAllPluginsLoaded();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a plugin is usable.
|
|
||||||
*/
|
|
||||||
bool IsRunnable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get languages info.
|
|
||||||
*/
|
|
||||||
IPhraseCollection *GetPhrases();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Returns the modification time during last plugin load.
|
|
||||||
*/
|
|
||||||
time_t GetTimeStamp();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current modification time of the plugin file.
|
|
||||||
*/
|
|
||||||
time_t GetFileTimeStamp();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the plugin was running, but is now invalid.
|
|
||||||
*/
|
|
||||||
bool WasRunning();
|
|
||||||
|
|
||||||
Handle_t GetMyHandle();
|
|
||||||
|
|
||||||
bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
|
|
||||||
void AddConfig(bool autoCreate, const char *cfg, const char *folder);
|
|
||||||
unsigned int GetConfigCount();
|
|
||||||
AutoConfig *GetConfig(unsigned int i);
|
|
||||||
inline void AddLibrary(const char *name)
|
|
||||||
{
|
|
||||||
m_Libraries.push_back(name);
|
|
||||||
}
|
|
||||||
void LibraryActions(bool dropping);
|
|
||||||
void SyncMaxClients(int max_clients);
|
|
||||||
protected:
|
|
||||||
bool UpdateInfo();
|
|
||||||
void SetTimeStamp(time_t t);
|
|
||||||
void DependencyDropped(CPlugin *pOwner);
|
|
||||||
private:
|
|
||||||
PluginType m_type;
|
|
||||||
char m_filename[PLATFORM_MAX_PATH];
|
|
||||||
PluginStatus m_status;
|
|
||||||
unsigned int m_serial;
|
|
||||||
sm_plugininfo_t m_info;
|
|
||||||
char m_errormsg[256];
|
|
||||||
time_t m_LastAccess;
|
|
||||||
IdentityToken_t *m_ident;
|
|
||||||
Handle_t m_handle;
|
|
||||||
bool m_WasRunning;
|
|
||||||
IPhraseCollection *m_pPhrases;
|
|
||||||
List<String> m_RequiredLibs;
|
|
||||||
List<String> m_Libraries;
|
|
||||||
Trie *m_pProps;
|
|
||||||
bool m_FakeNativesMissing;
|
|
||||||
bool m_LibraryMissing;
|
|
||||||
CVector<AutoConfig *> m_configs;
|
|
||||||
bool m_bGotAllLoaded;
|
|
||||||
int m_FileVersion;
|
|
||||||
char m_DateTime[256];
|
|
||||||
IPluginRuntime *m_pRuntime;
|
|
||||||
IPluginContext *m_pContext;
|
|
||||||
sp_pubvar_t *m_MaxClientsVar;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPluginManager :
|
|
||||||
public IPluginManager,
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IHandleTypeDispatch,
|
|
||||||
public IRootConsoleCommand
|
|
||||||
{
|
|
||||||
friend class CPlugin;
|
|
||||||
public:
|
|
||||||
CPluginManager();
|
|
||||||
~CPluginManager();
|
|
||||||
public:
|
|
||||||
/* Implements iterator class */
|
|
||||||
class CPluginIterator : public IPluginIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPluginIterator(List<CPlugin *> *mylist);
|
|
||||||
virtual ~CPluginIterator();
|
|
||||||
virtual bool MorePlugins();
|
|
||||||
virtual IPlugin *GetPlugin();
|
|
||||||
virtual void NextPlugin();
|
|
||||||
void Release();
|
|
||||||
public:
|
|
||||||
void Reset();
|
|
||||||
private:
|
|
||||||
List<CPlugin *> *mylist;
|
|
||||||
List<CPlugin *>::iterator current;
|
|
||||||
};
|
|
||||||
friend class CPluginManager::CPluginIterator;
|
|
||||||
public: //IPluginManager
|
|
||||||
IPlugin *LoadPlugin(const char *path,
|
|
||||||
bool debug,
|
|
||||||
PluginType type,
|
|
||||||
char error[],
|
|
||||||
size_t maxlength,
|
|
||||||
bool *wasloaded);
|
|
||||||
bool UnloadPlugin(IPlugin *plugin);
|
|
||||||
IPlugin *FindPluginByContext(const sp_context_t *ctx);
|
|
||||||
unsigned int GetPluginCount();
|
|
||||||
IPluginIterator *GetPluginIterator();
|
|
||||||
void AddPluginsListener(IPluginsListener *listener);
|
|
||||||
void RemovePluginsListener(IPluginsListener *listener);
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
void OnSourceModMaxPlayersChanged(int newvalue);
|
|
||||||
public: //IHandleTypeDispatch
|
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
|
||||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
|
||||||
public: //IRootConsoleCommand
|
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Loads all plugins not yet loaded
|
|
||||||
*/
|
|
||||||
void LoadAll_FirstPass(const char *config, const char *basedir);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the second loading pass for all plugins
|
|
||||||
*/
|
|
||||||
void LoadAll_SecondPass();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests a plugin file mask against a local folder.
|
|
||||||
* The alias is searched backwards from localdir - i.e., given this input:
|
|
||||||
* csdm/ban csdm/ban
|
|
||||||
* ban csdm/ban
|
|
||||||
* csdm/ban optional/csdm/ban
|
|
||||||
* All of these will return true for an alias match.
|
|
||||||
* Wildcards are allowed in the filename.
|
|
||||||
*/
|
|
||||||
bool TestAliasMatch(const char *alias, const char *localdir);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether anything loaded will be a late load.
|
|
||||||
*/
|
|
||||||
bool IsLateLoadTime() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a Handle to an IPlugin if possible.
|
|
||||||
*/
|
|
||||||
IPlugin *PluginFromHandle(Handle_t handle, HandleError *err);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a plugin based on its index. (starts on index 1)
|
|
||||||
*/
|
|
||||||
CPlugin *GetPluginByOrder(int num);
|
|
||||||
|
|
||||||
int GetOrderOfPlugin(IPlugin *pl);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal version of FindPluginByContext()
|
|
||||||
*/
|
|
||||||
CPlugin *GetPluginByCtx(const sp_context_t *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets status text for a status code
|
|
||||||
*/
|
|
||||||
const char *GetStatusText(PluginStatus status);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reload or update plugins on level shutdown.
|
|
||||||
*/
|
|
||||||
void ReloadOrUnloadPlugins();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add public functions from all running or paused
|
|
||||||
* plugins to the specified forward if the names match.
|
|
||||||
*/
|
|
||||||
void AddFunctionsToForward(const char *name, IChangeableForward *pForward);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates through plugins to call OnAllPluginsLoaded.
|
|
||||||
*/
|
|
||||||
void AllPluginsLoaded();
|
|
||||||
|
|
||||||
CPlugin *GetPluginFromIdentity(IdentityToken_t *pToken);
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop);
|
|
||||||
|
|
||||||
bool LibraryExists(const char *lib);
|
|
||||||
|
|
||||||
bool ReloadPlugin(CPlugin *pl);
|
|
||||||
|
|
||||||
void UnloadAll();
|
|
||||||
|
|
||||||
CPlugin *FindPluginByConsoleArg(const char *arg);
|
|
||||||
|
|
||||||
void SyncMaxClients(int max_clients);
|
|
||||||
|
|
||||||
void ListPluginsToClient(CPlayer *player, const CCommand &args);
|
|
||||||
private:
|
|
||||||
LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength);
|
|
||||||
|
|
||||||
void LoadAutoPlugin(const char *plugin);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively loads all plugins in the given directory.
|
|
||||||
*/
|
|
||||||
void LoadPluginsFromDir(const char *basedir, const char *localdir);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a plugin object. This is wrapped by LoadPlugin functions.
|
|
||||||
*/
|
|
||||||
void AddPlugin(CPlugin *pPlugin);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the second loading pass on a plugin.
|
|
||||||
*/
|
|
||||||
bool RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs an extension pass on a plugin.
|
|
||||||
*/
|
|
||||||
bool LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages required natives.
|
|
||||||
*/
|
|
||||||
bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength);
|
|
||||||
|
|
||||||
void _SetPauseState(CPlugin *pPlugin, bool pause);
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Caching internal objects
|
|
||||||
*/
|
|
||||||
void ReleaseIterator(CPluginIterator *iter);
|
|
||||||
public:
|
|
||||||
inline IdentityToken_t *GetIdentity()
|
|
||||||
{
|
|
||||||
return m_MyIdent;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void TryRefreshDependencies(CPlugin *pOther);
|
|
||||||
private:
|
|
||||||
List<IPluginsListener *> m_listeners;
|
|
||||||
List<CPlugin *> m_plugins;
|
|
||||||
CStack<CPluginManager::CPluginIterator *> m_iters;
|
|
||||||
CPluginInfoDatabase m_PluginInfo;
|
|
||||||
Trie *m_LoadLookup;
|
|
||||||
bool m_AllPluginsLoaded;
|
|
||||||
IdentityToken_t *m_MyIdent;
|
|
||||||
|
|
||||||
/* Dynamic native stuff */
|
|
||||||
List<FakeNative *> m_Natives;
|
|
||||||
|
|
||||||
bool m_LoadingLocked;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CPluginManager g_PluginSys;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
|
||||||
@@ -1,487 +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 "Profiler.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#if defined PLATFORM_POSIX
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ProfileEngine g_Profiler;
|
|
||||||
IProfiler *sm_profiler = &g_Profiler;
|
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
double WINDOWS_PERFORMANCE_FREQUENCY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class EmptyProfiler : public IProfiler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void OnNativeEnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void OnFunctionBegin(IPluginContext *pContext, const char *name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void OnFunctionEnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
int OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void OnCallbackEnd(int serial)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
} s_EmptyProfiler;
|
|
||||||
|
|
||||||
inline void InitProfPoint(prof_point_t &pt)
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
QueryPerformanceCounter(&pt.value);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
gettimeofday(&pt.value, NULL);
|
|
||||||
#endif
|
|
||||||
pt.is_set = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileEngine::ProfileEngine()
|
|
||||||
{
|
|
||||||
m_serial = 0;
|
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
LARGE_INTEGER pf;
|
|
||||||
|
|
||||||
if (QueryPerformanceFrequency(&pf))
|
|
||||||
{
|
|
||||||
WINDOWS_PERFORMANCE_FREQUENCY = 1.0 / (double)(pf.QuadPart);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WINDOWS_PERFORMANCE_FREQUENCY = -1.0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (IsEnabled())
|
|
||||||
{
|
|
||||||
InitProfPoint(m_ProfStart);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sm_profiler = &s_EmptyProfiler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProfileEngine::IsEnabled()
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
return (WINDOWS_PERFORMANCE_FREQUENCY > 0.0);
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double DiffProfPoints(const prof_point_t &start, const prof_point_t &end)
|
|
||||||
{
|
|
||||||
double seconds;
|
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
LONGLONG diff;
|
|
||||||
|
|
||||||
diff = end.value.QuadPart - start.value.QuadPart;
|
|
||||||
seconds = diff * WINDOWS_PERFORMANCE_FREQUENCY;
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
seconds = (double)(end.value.tv_sec - start.value.tv_sec);
|
|
||||||
|
|
||||||
if (start.value.tv_usec > end.value.tv_usec)
|
|
||||||
{
|
|
||||||
seconds -= 1.0;
|
|
||||||
seconds += (double)(1000000 - (start.value.tv_usec - end.value.tv_usec)) / 1000000.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seconds += (double)(end.value.tv_usec - start.value.tv_usec) / 1000000.0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double CalcAtomTime(const prof_atom_t &atom)
|
|
||||||
{
|
|
||||||
if (!atom.end.is_set)
|
|
||||||
{
|
|
||||||
return atom.base_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
return atom.base_time + DiffProfPoints(atom.start, atom.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnNativeBegin(IPluginContext *pContext, sp_native_t *native)
|
|
||||||
{
|
|
||||||
PushProfileStack(pContext, SP_PROF_NATIVES, native->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnNativeEnd()
|
|
||||||
{
|
|
||||||
assert(!m_AtomStack.empty());
|
|
||||||
assert(m_AtomStack.front().atom_type == SP_PROF_NATIVES);
|
|
||||||
|
|
||||||
PopProfileStack(&m_Natives);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnFunctionBegin(IPluginContext *pContext, const char *name)
|
|
||||||
{
|
|
||||||
PushProfileStack(pContext, SP_PROF_FUNCTIONS, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnFunctionEnd()
|
|
||||||
{
|
|
||||||
assert(!m_AtomStack.empty());
|
|
||||||
assert(m_AtomStack.front().atom_type == SP_PROF_FUNCTIONS);
|
|
||||||
|
|
||||||
PopProfileStack(&m_Functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ProfileEngine::OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc)
|
|
||||||
{
|
|
||||||
PushProfileStack(pContext, SP_PROF_CALLBACKS, pubfunc->name);
|
|
||||||
|
|
||||||
return m_serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnCallbackEnd(int serial)
|
|
||||||
{
|
|
||||||
assert(!m_AtomStack.empty());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Account for the situation where the JIT discards the
|
|
||||||
* stack because there was an RTE of sorts.
|
|
||||||
*/
|
|
||||||
if (m_AtomStack.front().atom_type != SP_PROF_CALLBACKS
|
|
||||||
&& m_AtomStack.front().atom_serial != serial)
|
|
||||||
{
|
|
||||||
prof_atom_t atom;
|
|
||||||
double total_time;
|
|
||||||
|
|
||||||
/* There was an error, and we need to discard things. */
|
|
||||||
total_time = 0.0;
|
|
||||||
while (!m_AtomStack.empty()
|
|
||||||
&& m_AtomStack.front().atom_type != SP_PROF_CALLBACKS
|
|
||||||
&& m_AtomStack.front().atom_serial != serial)
|
|
||||||
{
|
|
||||||
total_time += CalcAtomTime(m_AtomStack.front());
|
|
||||||
m_AtomStack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Now we can end and discard ourselves, without saving the data.
|
|
||||||
* Since this data is all erroneous anyway, we don't care if it's
|
|
||||||
* not totally accurate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(!m_AtomStack.empty());
|
|
||||||
atom = m_AtomStack.front();
|
|
||||||
m_AtomStack.pop();
|
|
||||||
|
|
||||||
/* Note: We don't need to resume ourselves because end is set by Pause(). */
|
|
||||||
total_time += CalcAtomTime(atom);
|
|
||||||
|
|
||||||
ResumeParent(total_time);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PopProfileStack(&m_Callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::PushProfileStack(IPluginContext *ctx, int type, const char *name)
|
|
||||||
{
|
|
||||||
prof_atom_t atom;
|
|
||||||
|
|
||||||
PauseParent();
|
|
||||||
|
|
||||||
atom.atom_type = type;
|
|
||||||
atom.base_time = 0.0;
|
|
||||||
atom.ctx = ctx->GetContext();
|
|
||||||
atom.name = name;
|
|
||||||
atom.end.is_set = false;
|
|
||||||
|
|
||||||
if (type == SP_PROF_CALLBACKS)
|
|
||||||
{
|
|
||||||
atom.atom_serial = ++m_serial;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
atom.atom_serial = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_AtomStack.push(atom);
|
|
||||||
|
|
||||||
/* Note: We do this after because the stack could grow and skew results */
|
|
||||||
InitProfPoint(m_AtomStack.front().start);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::PopProfileStack(ProfileReport *reporter)
|
|
||||||
{
|
|
||||||
double total_time;
|
|
||||||
|
|
||||||
prof_atom_t &atom = m_AtomStack.front();
|
|
||||||
|
|
||||||
/* We're okay to cache our used time. */
|
|
||||||
InitProfPoint(atom.end);
|
|
||||||
total_time = CalcAtomTime(atom);
|
|
||||||
|
|
||||||
/* Now it's time to save this! This may do a lot of computations which
|
|
||||||
* is why we've cached the time beforehand.
|
|
||||||
*/
|
|
||||||
reporter->SaveAtom(atom);
|
|
||||||
m_AtomStack.pop();
|
|
||||||
|
|
||||||
/* Finally, tell our parent how much time we used. */
|
|
||||||
ResumeParent(total_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::PauseParent()
|
|
||||||
{
|
|
||||||
if (m_AtomStack.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitProfPoint(m_AtomStack.front().end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::ResumeParent(double addTime)
|
|
||||||
{
|
|
||||||
if (m_AtomStack.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
prof_atom_t &atom = m_AtomStack.front();
|
|
||||||
|
|
||||||
/* Move its "paused time" to its base (known) time,
|
|
||||||
* then reset the start/end. Note that since CalcAtomTime()
|
|
||||||
* reads the base time, we SHOULD NOT use += to add.
|
|
||||||
*/
|
|
||||||
atom.base_time = CalcAtomTime(atom);
|
|
||||||
atom.base_time += addTime;
|
|
||||||
InitProfPoint(atom.start);
|
|
||||||
atom.end.is_set = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::Clear()
|
|
||||||
{
|
|
||||||
m_Natives.Clear();
|
|
||||||
m_Callbacks.Clear();
|
|
||||||
m_Functions.Clear();
|
|
||||||
InitProfPoint(m_ProfStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnSourceModAllInitialized()
|
|
||||||
{
|
|
||||||
g_RootMenu.AddRootConsoleCommand("profiler", "Profiler commands", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
g_RootMenu.RemoveRootConsoleCommand("profiler", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
|
||||||
{
|
|
||||||
if (command.ArgC() >= 3)
|
|
||||||
{
|
|
||||||
if (strcmp(command.Arg(2), "flush") == 0)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char path[256];
|
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
|
||||||
|
|
||||||
if ((fp = fopen(path, "wt")) == NULL)
|
|
||||||
{
|
|
||||||
g_RootMenu.ConsolePrint("Failed, could not open file for writing: %s", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateReport(fp);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("Profiler report generated as: %s\n", path);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("Profiler commands:");
|
|
||||||
g_RootMenu.DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProfileEngine::GenerateReport(FILE *fp)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
double total_time;
|
|
||||||
prof_point_t end_time;
|
|
||||||
|
|
||||||
InitProfPoint(end_time);
|
|
||||||
total_time = DiffProfPoints(m_ProfStart, end_time);
|
|
||||||
|
|
||||||
t = time(NULL);
|
|
||||||
|
|
||||||
fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
|
|
||||||
fprintf(fp, "<profile time=\"%d\" uptime=\"%f\">\n", (int)t, total_time);
|
|
||||||
WriteReport(fp, &m_Natives, "natives");
|
|
||||||
WriteReport(fp, &m_Callbacks, "callbacks");
|
|
||||||
WriteReport(fp, &m_Functions, "functions");
|
|
||||||
fprintf(fp, "</profile>\n");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *name)
|
|
||||||
{
|
|
||||||
size_t i, num;
|
|
||||||
prof_atom_report_t *ar;
|
|
||||||
char new_name[512];
|
|
||||||
|
|
||||||
fprintf(fp, " <report name=\"%s\">\n", name);
|
|
||||||
|
|
||||||
num = report->GetNumReports();
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
ar = report->GetReport(i);
|
|
||||||
|
|
||||||
strncopy(new_name, ar->atom_name, sizeof(new_name));
|
|
||||||
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "<");
|
|
||||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">");
|
|
||||||
|
|
||||||
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
|
|
||||||
new_name,
|
|
||||||
ar->num_calls,
|
|
||||||
ar->min_time,
|
|
||||||
ar->max_time,
|
|
||||||
ar->total_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, " </report>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileReport::~ProfileReport()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_Reports.size(); i++)
|
|
||||||
{
|
|
||||||
delete m_Reports[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileReport::Clear()
|
|
||||||
{
|
|
||||||
m_ReportLookup.clear();
|
|
||||||
for (size_t i = 0; i < m_Reports.size(); i++)
|
|
||||||
{
|
|
||||||
delete m_Reports[i];
|
|
||||||
}
|
|
||||||
m_Reports.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ProfileReport::GetNumReports()
|
|
||||||
{
|
|
||||||
return m_Reports.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
prof_atom_report_t *ProfileReport::GetReport(size_t i)
|
|
||||||
{
|
|
||||||
return m_Reports[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileReport::SaveAtom(const prof_atom_t &atom)
|
|
||||||
{
|
|
||||||
double atom_time;
|
|
||||||
char full_name[256];
|
|
||||||
prof_atom_report_t **pReport, *report;
|
|
||||||
|
|
||||||
if (atom.atom_type == SP_PROF_NATIVES)
|
|
||||||
{
|
|
||||||
strncopy(full_name, atom.name, sizeof(full_name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CPlugin *pl;
|
|
||||||
const char *file;
|
|
||||||
|
|
||||||
file = "unknown";
|
|
||||||
if ((pl = g_PluginSys.GetPluginByCtx(atom.ctx)) != NULL)
|
|
||||||
{
|
|
||||||
file = pl->GetFilename();
|
|
||||||
}
|
|
||||||
|
|
||||||
UTIL_Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
atom_time = CalcAtomTime(atom);
|
|
||||||
|
|
||||||
if ((pReport = m_ReportLookup.retrieve(full_name)) == NULL)
|
|
||||||
{
|
|
||||||
report = new prof_atom_report_t;
|
|
||||||
|
|
||||||
strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
|
||||||
report->max_time = atom_time;
|
|
||||||
report->min_time = atom_time;
|
|
||||||
report->num_calls = 1;
|
|
||||||
report->total_time = atom_time;
|
|
||||||
|
|
||||||
m_ReportLookup.insert(full_name, report);
|
|
||||||
m_Reports.push_back(report);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
report = *pReport;
|
|
||||||
|
|
||||||
if (atom_time > report->max_time)
|
|
||||||
{
|
|
||||||
report->max_time = atom_time;
|
|
||||||
}
|
|
||||||
if (atom_time < report->min_time)
|
|
||||||
{
|
|
||||||
report->min_time = atom_time;
|
|
||||||
}
|
|
||||||
report->num_calls++;
|
|
||||||
report->total_time += atom_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-131
@@ -1,131 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
|
||||||
#define _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
|
||||||
|
|
||||||
#include <sp_vm_api.h>
|
|
||||||
#include <sm_platform.h>
|
|
||||||
#include <sm_trie_tpl.h>
|
|
||||||
#include <sh_vector.h>
|
|
||||||
#include <sh_stack.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "sm_srvcmds.h"
|
|
||||||
|
|
||||||
using namespace SourcePawn;
|
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
struct prof_point_t
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
LARGE_INTEGER value;
|
|
||||||
#elif defined PLATFORM_POSIX
|
|
||||||
struct timeval value;
|
|
||||||
#endif
|
|
||||||
bool is_set;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prof_atom_t
|
|
||||||
{
|
|
||||||
int atom_type; /* Type of object we're profiling */
|
|
||||||
int atom_serial; /* Serial number, if appropriate */
|
|
||||||
sp_context_t *ctx; /* Plugin context. */
|
|
||||||
const char *name; /* Name of the function */
|
|
||||||
prof_point_t start; /* Start time */
|
|
||||||
prof_point_t end; /* End time */
|
|
||||||
double base_time; /* Known time from children or pausing. */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prof_atom_report_t
|
|
||||||
{
|
|
||||||
char atom_name[256]; /* Full name to shove to logs */
|
|
||||||
double total_time; /* Total time spent executing, in s */
|
|
||||||
unsigned int num_calls; /* Number of invocations */
|
|
||||||
double min_time; /* Min time spent in one call, in s */
|
|
||||||
double max_time; /* Max time spent in one call, in s */
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProfileReport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~ProfileReport();
|
|
||||||
public:
|
|
||||||
void SaveAtom(const prof_atom_t &atom);
|
|
||||||
size_t GetNumReports();
|
|
||||||
prof_atom_report_t *GetReport(size_t i);
|
|
||||||
void Clear();
|
|
||||||
private:
|
|
||||||
KTrie<prof_atom_report_t *> m_ReportLookup;
|
|
||||||
CVector<prof_atom_report_t *> m_Reports;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProfileEngine :
|
|
||||||
public SMGlobalClass,
|
|
||||||
public IRootConsoleCommand,
|
|
||||||
public IProfiler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProfileEngine();
|
|
||||||
public:
|
|
||||||
bool IsEnabled();
|
|
||||||
bool GenerateReport(FILE *fp);
|
|
||||||
void Clear();
|
|
||||||
public: //SMGlobalClass
|
|
||||||
void OnSourceModAllInitialized();
|
|
||||||
void OnSourceModShutdown();
|
|
||||||
public: //IRootConsoleCommand
|
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
|
||||||
public: //IProfiler
|
|
||||||
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
|
|
||||||
void OnNativeEnd() ;
|
|
||||||
void OnFunctionBegin(IPluginContext *pContext, const char *name);
|
|
||||||
void OnFunctionEnd();
|
|
||||||
int OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc);
|
|
||||||
void OnCallbackEnd(int serial);
|
|
||||||
private:
|
|
||||||
void PushProfileStack(IPluginContext *ctx, int type, const char *name);
|
|
||||||
void PopProfileStack(ProfileReport *reporter);
|
|
||||||
void PauseParent();
|
|
||||||
void ResumeParent(double addTime);
|
|
||||||
void WriteReport(FILE *fp, ProfileReport *report, const char *name);
|
|
||||||
private:
|
|
||||||
CStack<prof_atom_t> m_AtomStack;
|
|
||||||
ProfileReport m_Callbacks;
|
|
||||||
ProfileReport m_Functions;
|
|
||||||
ProfileReport m_Natives;
|
|
||||||
int m_serial;
|
|
||||||
prof_point_t m_ProfStart;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ProfileEngine g_Profiler;
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
|
||||||
@@ -1,529 +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 "ShareSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "ExtensionSys.h"
|
|
||||||
#include "LibrarySys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
ShareSystem g_ShareSys;
|
|
||||||
static unsigned int g_mark_serial = 0;
|
|
||||||
|
|
||||||
ShareSystem::ShareSystem()
|
|
||||||
{
|
|
||||||
m_IdentRoot.ident = 0;
|
|
||||||
m_TypeRoot = 0;
|
|
||||||
m_IfaceType = 0;
|
|
||||||
m_CoreType = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentityToken_t *ShareSystem::CreateCoreIdentity()
|
|
||||||
{
|
|
||||||
if (!m_CoreType)
|
|
||||||
{
|
|
||||||
m_CoreType = CreateIdentType("CORE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateIdentity(m_CoreType, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::Initialize()
|
|
||||||
{
|
|
||||||
TypeAccess sec;
|
|
||||||
|
|
||||||
g_HandleSys.InitAccessDefaults(&sec, NULL);
|
|
||||||
sec.ident = GetIdentRoot();
|
|
||||||
|
|
||||||
m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
|
|
||||||
m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
|
|
||||||
|
|
||||||
/* Initialize our static identity handle */
|
|
||||||
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
|
|
||||||
|
|
||||||
/* Add the Handle System and others... they are too innocent and pure to do it themselves */
|
|
||||||
AddInterface(NULL, &g_HandleSys);
|
|
||||||
AddInterface(NULL, &g_LibSys);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::OnSourceModShutdown()
|
|
||||||
{
|
|
||||||
if (m_CoreType)
|
|
||||||
{
|
|
||||||
g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
|
|
||||||
}
|
|
||||||
|
|
||||||
g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
|
|
||||||
g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentityType_t ShareSystem::FindIdentType(const char *name)
|
|
||||||
{
|
|
||||||
HandleType_t type;
|
|
||||||
|
|
||||||
if (g_HandleSys.FindHandleType(name, &type))
|
|
||||||
{
|
|
||||||
if (g_HandleSys.TypeCheck(type, m_TypeRoot))
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentityType_t ShareSystem::CreateIdentType(const char *name)
|
|
||||||
{
|
|
||||||
if (!m_TypeRoot)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
|
|
||||||
{
|
|
||||||
/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr)
|
|
||||||
{
|
|
||||||
if (!m_TypeRoot)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* :TODO: Cache? */
|
|
||||||
IdentityToken_t *pToken = new IdentityToken_t;
|
|
||||||
|
|
||||||
HandleSecurity sec;
|
|
||||||
sec.pOwner = sec.pIdentity = GetIdentRoot();
|
|
||||||
|
|
||||||
pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true);
|
|
||||||
pToken->ptr = ptr;
|
|
||||||
pToken->type = type;
|
|
||||||
|
|
||||||
return pToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
|
|
||||||
{
|
|
||||||
if (!iface)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IfaceInfo info;
|
|
||||||
|
|
||||||
info.owner = myself;
|
|
||||||
info.iface = iface;
|
|
||||||
|
|
||||||
m_Interfaces.push_back(info);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShareSystem::RequestInterface(const char *iface_name,
|
|
||||||
unsigned int iface_vers,
|
|
||||||
IExtension *myself,
|
|
||||||
SMInterface **pIface)
|
|
||||||
{
|
|
||||||
/* See if the interface exists */
|
|
||||||
List<IfaceInfo>::iterator iter;
|
|
||||||
SMInterface *iface;
|
|
||||||
IExtension *iface_owner;
|
|
||||||
bool found = false;
|
|
||||||
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
|
|
||||||
{
|
|
||||||
IfaceInfo &info = (*iter);
|
|
||||||
iface = info.iface;
|
|
||||||
if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
|
|
||||||
{
|
|
||||||
if (iface->GetInterfaceVersion() == iface_vers
|
|
||||||
|| iface->IsVersionCompatible(iface_vers))
|
|
||||||
{
|
|
||||||
iface_owner = info.owner;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a dependency node */
|
|
||||||
if (iface_owner)
|
|
||||||
{
|
|
||||||
IfaceInfo info;
|
|
||||||
info.iface = iface;
|
|
||||||
info.owner = iface_owner;
|
|
||||||
g_Extensions.BindDependency(myself, &info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pIface)
|
|
||||||
{
|
|
||||||
*pIface = iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
|
|
||||||
{
|
|
||||||
CNativeOwner *pOwner;
|
|
||||||
|
|
||||||
pOwner = g_Extensions.GetNativeOwner(myself);
|
|
||||||
|
|
||||||
pOwner->AddNatives(natives);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
|
|
||||||
{
|
|
||||||
HandleSecurity sec;
|
|
||||||
|
|
||||||
sec.pOwner = GetIdentRoot();
|
|
||||||
sec.pIdentity = GetIdentRoot();
|
|
||||||
|
|
||||||
g_HandleSys.FreeHandle(identity->ident, &sec);
|
|
||||||
delete identity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::DestroyIdentType(IdentityType_t type)
|
|
||||||
{
|
|
||||||
g_HandleSys.RemoveType(type, GetIdentRoot());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::RemoveInterfaces(IExtension *pExtension)
|
|
||||||
{
|
|
||||||
List<IfaceInfo>::iterator iter = m_Interfaces.begin();
|
|
||||||
|
|
||||||
while (iter != m_Interfaces.end())
|
|
||||||
{
|
|
||||||
if ((*iter).owner == pExtension)
|
|
||||||
{
|
|
||||||
iter = m_Interfaces.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload)
|
|
||||||
{
|
|
||||||
g_Extensions.AddDependency(myself, filename, require, autoload);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
|
|
||||||
{
|
|
||||||
g_Extensions.AddLibrary(myself, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
CNativeOwner *pOwner;
|
|
||||||
|
|
||||||
pOwner = g_Extensions.GetNativeOwner(myself);
|
|
||||||
|
|
||||||
for (i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
|
|
||||||
{
|
|
||||||
if ((pEntry = FindNative(natives[i].name)) == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry->owner != g_pCoreNatives)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry->replacement.owner != NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now it's safe to add the override */
|
|
||||||
pEntry->replacement.func = natives[i].func;
|
|
||||||
pEntry->replacement.owner = pOwner;
|
|
||||||
pOwner->AddReplacedNative(pEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeEntry *ShareSystem::FindNative(const char *name)
|
|
||||||
{
|
|
||||||
NativeEntry **ppEntry;
|
|
||||||
|
|
||||||
if ((ppEntry = m_NtvCache.retrieve(name)) == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *ppEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
|
|
||||||
{
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
sp_native_t *native;
|
|
||||||
uint32_t i, native_count;
|
|
||||||
IPluginContext *pContext;
|
|
||||||
|
|
||||||
pContext = pPlugin->GetBaseContext();
|
|
||||||
|
|
||||||
/* Generate a new serial ID, mark our dependencies with it. */
|
|
||||||
g_mark_serial++;
|
|
||||||
pPlugin->PropogateMarkSerial(g_mark_serial);
|
|
||||||
|
|
||||||
native_count = pContext->GetNativesNum();
|
|
||||||
for (i = 0; i < native_count; i++)
|
|
||||||
{
|
|
||||||
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're bound, check if there is a replacement available.
|
|
||||||
* If not, this native is totally finalized.
|
|
||||||
*/
|
|
||||||
if (native->status == SP_NATIVE_BOUND)
|
|
||||||
{
|
|
||||||
pEntry = (NativeEntry *)native->user;
|
|
||||||
assert(pEntry != NULL);
|
|
||||||
if (pEntry->replacement.owner == NULL
|
|
||||||
|| (pEntry->replacement.owner != NULL
|
|
||||||
&& pEntry->replacement.func == native->pfn))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Otherwise, the native must be in our cache. */
|
|
||||||
else if ((pEntry = FindNative(native->name)) == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bCoreOnly && pEntry->owner != g_pCoreNatives)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BindNativeToPlugin(pPlugin, native, i, pEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
sp_native_t *native;
|
|
||||||
IPluginContext *pContext;
|
|
||||||
|
|
||||||
pContext = pPlugin->GetBaseContext();
|
|
||||||
|
|
||||||
if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (native->status == SP_NATIVE_BOUND)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BindNativeToPlugin(pPlugin, native, i, pEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
|
|
||||||
sp_native_t *native,
|
|
||||||
uint32_t index,
|
|
||||||
NativeEntry *pEntry)
|
|
||||||
{
|
|
||||||
/* Mark as bound... we do the rest next. */
|
|
||||||
native->status = SP_NATIVE_BOUND;
|
|
||||||
native->user = pEntry;
|
|
||||||
|
|
||||||
/* See if a replacement is available. */
|
|
||||||
if (pEntry->replacement.owner != NULL)
|
|
||||||
{
|
|
||||||
/* Perform a replacement bind. */
|
|
||||||
native->pfn = pEntry->replacement.func;
|
|
||||||
pEntry->replacement.owner->AddWeakRef(WeakNative(pPlugin, index, pEntry));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Perform a normal bind. */
|
|
||||||
native->pfn = pEntry->func;
|
|
||||||
|
|
||||||
/* We don't bother with dependency crap if the owner is Core. */
|
|
||||||
if (pEntry->owner != g_pCoreNatives)
|
|
||||||
{
|
|
||||||
/* The native is optional, this is a special case */
|
|
||||||
if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
|
|
||||||
{
|
|
||||||
/* Only add if there is a valid owner. */
|
|
||||||
if (pEntry->owner != NULL)
|
|
||||||
{
|
|
||||||
pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
native->status = SP_NATIVE_UNBOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Otherwise, we're a strong dependent and not a weak one */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* See if this has already been marked as a dependent.
|
|
||||||
* If it has, it means this relationship has already occurred,
|
|
||||||
* and there is no reason to do it again.
|
|
||||||
*/
|
|
||||||
if (pEntry->owner != pPlugin
|
|
||||||
&& pEntry->owner->GetMarkSerial() != g_mark_serial)
|
|
||||||
{
|
|
||||||
/* This has not been marked as a dependency yet */
|
|
||||||
//pPlugin->AddDependency(pEntry->owner);
|
|
||||||
pEntry->owner->AddDependent(pPlugin);
|
|
||||||
pEntry->owner->SetMarkSerial(g_mark_serial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
|
|
||||||
{
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
|
|
||||||
if ((pEntry = FindNative(ntv->name)) == NULL)
|
|
||||||
{
|
|
||||||
pEntry = new NativeEntry;
|
|
||||||
|
|
||||||
pEntry->owner = pOwner;
|
|
||||||
pEntry->name = ntv->name;
|
|
||||||
pEntry->func = ntv->func;
|
|
||||||
pEntry->replacement.func = NULL;
|
|
||||||
pEntry->replacement.owner = NULL;
|
|
||||||
pEntry->fake = NULL;
|
|
||||||
|
|
||||||
m_NtvCache.insert(ntv->name, pEntry);
|
|
||||||
|
|
||||||
return pEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry->owner != NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEntry->owner = pOwner;
|
|
||||||
pEntry->func = ntv->func;
|
|
||||||
pEntry->name = ntv->name;
|
|
||||||
|
|
||||||
return pEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
|
|
||||||
{
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
|
|
||||||
if ((pEntry = FindNative(name)) == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry->owner != pOwner)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry->fake != NULL)
|
|
||||||
{
|
|
||||||
g_pSourcePawn2->DestroyFakeNative(pEntry->func);
|
|
||||||
delete pEntry->fake;
|
|
||||||
pEntry->fake = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEntry->func = NULL;
|
|
||||||
pEntry->name = NULL;
|
|
||||||
pEntry->owner = NULL;
|
|
||||||
pEntry->replacement.func = NULL;
|
|
||||||
pEntry->replacement.owner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
|
|
||||||
{
|
|
||||||
FakeNative *pFake;
|
|
||||||
NativeEntry *pEntry;
|
|
||||||
SPVM_NATIVE_FUNC gate;
|
|
||||||
|
|
||||||
if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pFake = new FakeNative;
|
|
||||||
|
|
||||||
if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
|
|
||||||
{
|
|
||||||
delete pFake;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry == NULL)
|
|
||||||
{
|
|
||||||
pEntry = new NativeEntry;
|
|
||||||
m_NtvCache.insert(name, pEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
pFake->call = pFunc;
|
|
||||||
pFake->ctx = pFunc->GetParentContext();
|
|
||||||
strncopy(pFake->name, name, sizeof(pFake->name));
|
|
||||||
|
|
||||||
pEntry->fake = pFake;
|
|
||||||
pEntry->func = gate;
|
|
||||||
pEntry->name = pFake->name;
|
|
||||||
pEntry->owner = g_PluginSys.GetPluginByCtx(pFake->ctx->GetContext());
|
|
||||||
pEntry->replacement.func = NULL;
|
|
||||||
pEntry->replacement.owner = NULL;
|
|
||||||
|
|
||||||
return pEntry;
|
|
||||||
}
|
|
||||||
+6
-6
@@ -31,10 +31,10 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
#define TIMER_MIN_ACCURACY 0.1
|
#define TIMER_MIN_ACCURACY 0.1
|
||||||
|
|
||||||
@@ -180,9 +180,9 @@ TimerSystem::~TimerSystem()
|
|||||||
|
|
||||||
void TimerSystem::OnSourceModAllInitialized()
|
void TimerSystem::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
m_pOnGameFrame = forwardsys->CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
||||||
m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
|
m_pOnMapTimeLeftChanged = forwardsys->CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerSystem::OnSourceModGameInitialized()
|
void TimerSystem::OnSourceModGameInitialized()
|
||||||
@@ -198,8 +198,8 @@ void TimerSystem::OnSourceModGameInitialized()
|
|||||||
void TimerSystem::OnSourceModShutdown()
|
void TimerSystem::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
SetMapTimer(NULL);
|
SetMapTimer(NULL);
|
||||||
g_Forwards.ReleaseForward(m_pOnGameFrame);
|
forwardsys->ReleaseForward(m_pOnGameFrame);
|
||||||
g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
|
forwardsys->ReleaseForward(m_pOnMapTimeLeftChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerSystem::OnSourceModLevelEnd()
|
void TimerSystem::OnSourceModLevelEnd()
|
||||||
|
|||||||
+2
-2
@@ -32,11 +32,11 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <ITimerSystem.h>
|
#include <ITimerSystem.h>
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include "sm_globals.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -78,11 +78,11 @@ public: //ITimerSystem
|
|||||||
float GetTickedTime();
|
float GetTickedTime();
|
||||||
void NotifyOfGameStart(float offset /* = 0.0f */);
|
void NotifyOfGameStart(float offset /* = 0.0f */);
|
||||||
bool GetMapTimeLeft(float *pTime);
|
bool GetMapTimeLeft(float *pTime);
|
||||||
|
IMapTimer *GetMapTimer();
|
||||||
public:
|
public:
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
void RemoveMapChangeTimers();
|
void RemoveMapChangeTimers();
|
||||||
void GameFrame(bool simulating);
|
void GameFrame(bool simulating);
|
||||||
IMapTimer *GetMapTimer();
|
|
||||||
private:
|
private:
|
||||||
List<ITimer *> m_SingleTimers;
|
List<ITimer *> m_SingleTimers;
|
||||||
List<ITimer *> m_LoopTimers;
|
List<ITimer *> m_LoopTimers;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+340
-67
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2010 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -31,19 +31,34 @@
|
|||||||
|
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
#include <cstrike15_usermessage_helpers.h>
|
||||||
|
#endif
|
||||||
|
#include <amtl/am-string.h>
|
||||||
|
|
||||||
UserMessages g_UserMsgs;
|
UserMessages g_UserMsgs;
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
||||||
|
#else
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
|
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
|
||||||
#else
|
#else
|
||||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||||
#endif
|
#endif
|
||||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
||||||
|
#endif // ==SE_CSGO
|
||||||
|
|
||||||
UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
UserMessages::UserMessages()
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
|
: m_InterceptBuffer(m_pBase, 2500)
|
||||||
{
|
{
|
||||||
m_Names = sm_trie_create();
|
#else
|
||||||
|
: m_InterceptBuffer(NULL)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
m_HookCount = 0;
|
m_HookCount = 0;
|
||||||
m_InExec = false;
|
m_InExec = false;
|
||||||
m_InHook = false;
|
m_InHook = false;
|
||||||
@@ -53,8 +68,6 @@ UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
|||||||
|
|
||||||
UserMessages::~UserMessages()
|
UserMessages::~UserMessages()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_Names);
|
|
||||||
|
|
||||||
CStack<ListenerInfo *>::iterator iter;
|
CStack<ListenerInfo *>::iterator iter;
|
||||||
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
||||||
{
|
{
|
||||||
@@ -65,32 +78,43 @@ UserMessages::~UserMessages()
|
|||||||
|
|
||||||
void UserMessages::OnSourceModStartup(bool late)
|
void UserMessages::OnSourceModStartup(bool late)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
/* -1 means SourceMM was unable to get the user message list */
|
/* -1 means SourceMM was unable to get the user message list */
|
||||||
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllInitialized()
|
void UserMessages::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllShutdown()
|
void UserMessages::OnSourceModAllShutdown()
|
||||||
{
|
{
|
||||||
if (m_HookCount)
|
if (m_HookCount)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
m_HookCount = 0;
|
m_HookCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UserMessages::GetMessageIndex(const char *msg)
|
int UserMessages::GetMessageIndex(const char *msg)
|
||||||
{
|
{
|
||||||
int msgid;
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
// Can split this per engine and/or game later
|
||||||
|
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||||
|
#else
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
|
int msgid;
|
||||||
|
if (!m_Names.retrieve(msg, &msgid))
|
||||||
{
|
{
|
||||||
if (m_FallbackSearch)
|
if (m_FallbackSearch)
|
||||||
{
|
{
|
||||||
@@ -102,7 +126,7 @@ int UserMessages::GetMessageIndex(const char *msg)
|
|||||||
{
|
{
|
||||||
if (strcmp(msgbuf, msg) == 0)
|
if (strcmp(msgbuf, msg) == 0)
|
||||||
{
|
{
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
m_Names.insert(msg, msgid);
|
||||||
return msgid;
|
return msgid;
|
||||||
}
|
}
|
||||||
msgid++;
|
msgid++;
|
||||||
@@ -112,16 +136,25 @@ int UserMessages::GetMessageIndex(const char *msg)
|
|||||||
msgid = g_SMAPI->FindUserMessage(msg);
|
msgid = g_SMAPI->FindUserMessage(msg);
|
||||||
|
|
||||||
if (msgid != INVALID_MESSAGE_ID)
|
if (msgid != INVALID_MESSAGE_ID)
|
||||||
{
|
m_Names.insert(msg, msgid);
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return msgid;
|
return msgid;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
||||||
{
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||||
|
#endif
|
||||||
|
if (!pszName)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ke::SafeStrcpy(buffer, maxlength, pszName);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
if (m_FallbackSearch)
|
if (m_FallbackSearch)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
@@ -132,15 +165,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
bf_write *buffer;
|
bf_write *buffer;
|
||||||
|
|
||||||
if (m_InExec || m_InHook)
|
if (m_InExec || m_InHook)
|
||||||
@@ -168,13 +205,13 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
|||||||
|
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
{
|
{
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||||
#else
|
#else
|
||||||
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||||
#else
|
#else
|
||||||
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||||
@@ -182,6 +219,75 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
#endif // USE_PROTOBUF_USERMESSAGES
|
||||||
|
}
|
||||||
|
|
||||||
|
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||||
|
{
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
protobuf::Message *buffer;
|
||||||
|
|
||||||
|
if (m_InExec || m_InHook)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (msg_id < 0 || msg_id >= 255)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CurId = msg_id;
|
||||||
|
m_CellRecFilter.Initialize(players, playersNum);
|
||||||
|
|
||||||
|
m_CurFlags = flags;
|
||||||
|
if (m_CurFlags & USERMSG_INITMSG)
|
||||||
|
{
|
||||||
|
m_CellRecFilter.SetToInit(true);
|
||||||
|
}
|
||||||
|
if (m_CurFlags & USERMSG_RELIABLE)
|
||||||
|
{
|
||||||
|
m_CellRecFilter.SetToReliable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_InExec = true;
|
||||||
|
|
||||||
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
|
{
|
||||||
|
// direct message creation, return buffer "from engine". keep track
|
||||||
|
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
|
||||||
|
buffer = m_FakeEngineBuffer;
|
||||||
|
} else {
|
||||||
|
char messageName[32];
|
||||||
|
if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
|
||||||
|
{
|
||||||
|
m_InExec = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
|
||||||
|
switch (m_FakeMetaRes)
|
||||||
|
{
|
||||||
|
case MRES_IGNORED:
|
||||||
|
case MRES_HANDLED:
|
||||||
|
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
|
||||||
|
buffer = m_FakeEngineBuffer;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MRES_OVERRIDE:
|
||||||
|
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
|
||||||
|
// fallthrough
|
||||||
|
case MRES_SUPERCEDE:
|
||||||
|
buffer = msg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
#endif // USE_PROTOBUF_USERMESSAGES
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::EndMessage()
|
bool UserMessages::EndMessage()
|
||||||
@@ -191,12 +297,37 @@ bool UserMessages::EndMessage()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
|
{
|
||||||
|
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||||
|
delete m_FakeEngineBuffer;
|
||||||
|
m_FakeEngineBuffer = NULL;
|
||||||
|
} else {
|
||||||
|
OnMessageEnd_Pre();
|
||||||
|
|
||||||
|
switch (m_FakeMetaRes)
|
||||||
|
{
|
||||||
|
case MRES_IGNORED:
|
||||||
|
case MRES_HANDLED:
|
||||||
|
case MRES_OVERRIDE:
|
||||||
|
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||||
|
delete m_FakeEngineBuffer;
|
||||||
|
m_FakeEngineBuffer = NULL;
|
||||||
|
break;
|
||||||
|
//case MRES_SUPERCEDE:
|
||||||
|
}
|
||||||
|
|
||||||
|
OnMessageEnd_Post();
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
{
|
{
|
||||||
ENGINE_CALL(MessageEnd)();
|
ENGINE_CALL(MessageEnd)();
|
||||||
} else {
|
} else {
|
||||||
engine->MessageEnd();
|
engine->MessageEnd();
|
||||||
}
|
}
|
||||||
|
#endif // SE_CSGO
|
||||||
|
|
||||||
m_InExec = false;
|
m_InExec = false;
|
||||||
m_CurFlags = 0;
|
m_CurFlags = 0;
|
||||||
@@ -205,31 +336,60 @@ bool UserMessages::EndMessage()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserMessageType UserMessages::GetUserMessageType() const
|
||||||
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return UM_Protobuf;
|
||||||
|
#else
|
||||||
|
return UM_BitBuf;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool UserMessages::HookUserMessage2(int msg_id,
|
bool UserMessages::HookUserMessage2(int msg_id,
|
||||||
IUserMessageListener *pListener,
|
IUserMessageListener *pListener,
|
||||||
bool intercept)
|
bool intercept)
|
||||||
{
|
{
|
||||||
return InternalHook(msg_id, pListener, intercept, true);
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||||
|
#else
|
||||||
|
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::UnhookUserMessage2(int msg_id,
|
bool UserMessages::UnhookUserMessage2(int msg_id,
|
||||||
IUserMessageListener *pListener,
|
IUserMessageListener *pListener,
|
||||||
bool intercept)
|
bool intercept)
|
||||||
{
|
{
|
||||||
return InternalUnhook(msg_id, pListener, intercept, true);
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||||
|
#else
|
||||||
|
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||||
{
|
{
|
||||||
return InternalHook(msg_id, pListener, intercept, false);
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#else
|
||||||
|
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||||
{
|
{
|
||||||
return InternalUnhook(msg_id, pListener, intercept, false);
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#else
|
||||||
|
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||||
|
#else
|
||||||
|
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (msg_id < 0 || msg_id >= 255)
|
if (msg_id < 0 || msg_id >= 255)
|
||||||
{
|
{
|
||||||
@@ -252,10 +412,15 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
|||||||
|
|
||||||
if (!m_HookCount++)
|
if (!m_HookCount++)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intercept)
|
if (intercept)
|
||||||
@@ -268,7 +433,20 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||||
|
#else
|
||||||
|
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
MsgList *pList;
|
MsgList *pList;
|
||||||
MsgIter iter;
|
MsgIter iter;
|
||||||
@@ -309,14 +487,73 @@ void UserMessages::_DecRefCounter()
|
|||||||
{
|
{
|
||||||
if (--m_HookCount == 0)
|
if (--m_HookCount == 0)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
|
#endif
|
||||||
|
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||||
|
{
|
||||||
|
int size = msg.ByteSize();
|
||||||
|
uint8 *data = (uint8 *)stackalloc(size);
|
||||||
|
msg.SerializePartialToArray(data, size);
|
||||||
|
m_InterceptBuffer->ParsePartialFromArray(data, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OnMessageEnd_Pre();
|
||||||
|
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||||
|
{
|
||||||
|
OnMessageEnd_Post();
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
#define UM_RETURN_META_VALUE(res, val) \
|
||||||
|
m_FakeMetaRes = res; \
|
||||||
|
return val;
|
||||||
|
|
||||||
|
#define UM_RETURN_META(res) \
|
||||||
|
m_FakeMetaRes = res; \
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
#define UM_RETURN_META_VALUE(res, val) \
|
||||||
|
RETURN_META_VALUE(res, val)
|
||||||
|
|
||||||
|
#define UM_RETURN_META(res) \
|
||||||
|
RETURN_META(res)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
#else
|
#else
|
||||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
||||||
@@ -329,7 +566,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
|||||||
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
||||||
{
|
{
|
||||||
m_InHook = false;
|
m_InHook = false;
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurId = msg_type;
|
m_CurId = msg_type;
|
||||||
@@ -339,14 +576,24 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
|||||||
|
|
||||||
if (!is_intercept_empty)
|
if (!is_intercept_empty)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
if (m_InterceptBuffer)
|
||||||
|
delete m_InterceptBuffer;
|
||||||
|
m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
|
||||||
|
|
||||||
|
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
|
||||||
|
#else
|
||||||
m_InterceptBuffer.Reset();
|
m_InterceptBuffer.Reset();
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||||
#else
|
#else
|
||||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
||||||
@@ -354,19 +601,26 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
|
|||||||
{
|
{
|
||||||
if (!m_InHook)
|
if (!m_InHook)
|
||||||
{
|
{
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||||
|
m_OrigBuffer = m_InterceptBuffer;
|
||||||
|
else
|
||||||
|
m_OrigBuffer = m_FakeEngineBuffer;
|
||||||
|
#else
|
||||||
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
|
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
|
||||||
|
#endif
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserMessages::OnMessageEnd_Post()
|
void UserMessages::OnMessageEnd_Post()
|
||||||
{
|
{
|
||||||
if (!m_InHook)
|
if (!m_InHook)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
UM_RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgList *pList;
|
MsgList *pList;
|
||||||
@@ -434,7 +688,7 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
{
|
{
|
||||||
if (!m_InHook)
|
if (!m_InHook)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
UM_RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgList *pList;
|
MsgList *pList;
|
||||||
@@ -450,7 +704,11 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
pInfo->IsHooked = true;
|
pInfo->IsHooked = true;
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
|
||||||
|
#else
|
||||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
||||||
|
#endif
|
||||||
|
|
||||||
intercepted = true;
|
intercepted = true;
|
||||||
|
|
||||||
@@ -496,16 +754,13 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled)
|
if (!handled && intercepted)
|
||||||
{
|
|
||||||
goto supercede;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intercepted)
|
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||||
|
#else
|
||||||
bf_write *engine_bfw;
|
bf_write *engine_bfw;
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
|
||||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
|
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
|
||||||
#else
|
#else
|
||||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
|
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
|
||||||
@@ -513,29 +768,47 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
pList = &m_msgHooks[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
pInfo->IsHooked = true;
|
int size = m_OrigBuffer->ByteSize();
|
||||||
pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
|
uint8 *data = (uint8 *)stackalloc(size);
|
||||||
|
m_OrigBuffer->SerializePartialToArray(data, size);
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
|
||||||
|
pTempMsg->ParsePartialFromArray(data, size);
|
||||||
|
#else
|
||||||
|
bf_write *pTempMsg = m_OrigBuffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pList = &m_msgHooks[m_CurId];
|
||||||
|
for (iter=pList->begin(); iter!=pList->end(); )
|
||||||
{
|
{
|
||||||
iter = pList->erase(iter);
|
pInfo = (*iter);
|
||||||
m_FreeListeners.push(pInfo);
|
pInfo->IsHooked = true;
|
||||||
_DecRefCounter();
|
pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter);
|
||||||
continue;
|
|
||||||
|
if (pInfo->KillMe)
|
||||||
|
{
|
||||||
|
iter = pList->erase(iter);
|
||||||
|
m_FreeListeners.push(pInfo);
|
||||||
|
_DecRefCounter();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->IsHooked = false;
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
pInfo->IsHooked = false;
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
iter++;
|
delete pTempMsg;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||||
supercede:
|
supercede:
|
||||||
m_BlockEndPost = true;
|
m_BlockEndPost = true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
UM_RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-11
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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-2010 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,20 +32,41 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <IUserMessages.h>
|
#include <IUserMessages.h>
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_stringhashmap.h>
|
||||||
|
#include "sm_stringutil.h"
|
||||||
#include "CellRecipientFilter.h"
|
#include "CellRecipientFilter.h"
|
||||||
|
#include "sm_globals.h"
|
||||||
|
#include <sh_list.h>
|
||||||
|
#include <sh_stack.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
#define USE_PROTOBUF_USERMESSAGES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <netmessages.pb.h>
|
||||||
|
|
||||||
|
using namespace google;
|
||||||
|
#else
|
||||||
|
#include <bitbuf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INVALID_MESSAGE_ID -1
|
#define INVALID_MESSAGE_ID -1
|
||||||
|
|
||||||
struct ListenerInfo
|
struct ListenerInfo
|
||||||
{
|
{
|
||||||
IUserMessageListener *Callback;
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
IProtobufUserMessageListener *Callback;
|
||||||
|
#else
|
||||||
|
IBitBufUserMessageListener *Callback;
|
||||||
|
#endif
|
||||||
bool IsHooked;
|
bool IsHooked;
|
||||||
bool KillMe;
|
bool KillMe;
|
||||||
bool IsNew;
|
bool IsNew;
|
||||||
@@ -70,7 +91,8 @@ public: //IUserMessages
|
|||||||
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
||||||
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||||
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||||
bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||||
|
google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||||
bool EndMessage();
|
bool EndMessage();
|
||||||
bool HookUserMessage2(int msg_id,
|
bool HookUserMessage2(int msg_id,
|
||||||
IUserMessageListener *pListener,
|
IUserMessageListener *pListener,
|
||||||
@@ -78,8 +100,17 @@ public: //IUserMessages
|
|||||||
bool UnhookUserMessage2(int msg_id,
|
bool UnhookUserMessage2(int msg_id,
|
||||||
IUserMessageListener *pListener,
|
IUserMessageListener *pListener,
|
||||||
bool intercept=false);
|
bool intercept=false);
|
||||||
|
UserMessageType GetUserMessageType() const;
|
||||||
public:
|
public:
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||||
|
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
|
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
|
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||||
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||||
#else
|
#else
|
||||||
@@ -89,24 +120,41 @@ public:
|
|||||||
void OnMessageEnd_Pre();
|
void OnMessageEnd_Pre();
|
||||||
void OnMessageEnd_Post();
|
void OnMessageEnd_Post();
|
||||||
private:
|
private:
|
||||||
bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
const protobuf::Message *GetMessagePrototype(int msg_type);
|
||||||
|
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||||
|
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||||
|
#else
|
||||||
|
bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||||
|
bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||||
|
#endif
|
||||||
void _DecRefCounter();
|
void _DecRefCounter();
|
||||||
private:
|
private:
|
||||||
List<ListenerInfo *> m_msgHooks[255];
|
List<ListenerInfo *> m_msgHooks[255];
|
||||||
List<ListenerInfo *> m_msgIntercepts[255];
|
List<ListenerInfo *> m_msgIntercepts[255];
|
||||||
CStack<ListenerInfo *> m_FreeListeners;
|
CStack<ListenerInfo *> m_FreeListeners;
|
||||||
unsigned char m_pBase[2500];
|
|
||||||
IRecipientFilter *m_CurRecFilter;
|
IRecipientFilter *m_CurRecFilter;
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
|
unsigned char m_pBase[2500];
|
||||||
bf_write m_InterceptBuffer;
|
bf_write m_InterceptBuffer;
|
||||||
bf_write *m_OrigBuffer;
|
bf_write *m_OrigBuffer;
|
||||||
bf_read m_ReadBuffer;
|
bf_read m_ReadBuffer;
|
||||||
|
#else
|
||||||
|
// The engine used to provide this. Now we track it.
|
||||||
|
protobuf::Message *m_OrigBuffer;
|
||||||
|
protobuf::Message *m_FakeEngineBuffer;
|
||||||
|
META_RES m_FakeMetaRes;
|
||||||
|
|
||||||
|
protobuf::Message *m_InterceptBuffer;
|
||||||
|
#endif
|
||||||
size_t m_HookCount;
|
size_t m_HookCount;
|
||||||
bool m_InHook;
|
bool m_InHook;
|
||||||
bool m_BlockEndPost;
|
bool m_BlockEndPost;
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
bool m_FallbackSearch;
|
bool m_FallbackSearch;
|
||||||
|
|
||||||
Trie *m_Names;
|
StringHashMap<int> m_Names;
|
||||||
|
#endif
|
||||||
CellRecipientFilter m_CellRecFilter;
|
CellRecipientFilter m_CellRecFilter;
|
||||||
bool m_InExec;
|
bool m_InExec;
|
||||||
int m_CurFlags;
|
int m_CurFlags;
|
||||||
|
|||||||
@@ -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_
|
||||||
+81
-68
@@ -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,9 +32,17 @@
|
|||||||
#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 *);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
@@ -51,64 +55,73 @@ struct ConCommandInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
List<ConCommandInfo *> tracked_bases;
|
List<ConCommandInfo *> tracked_bases;
|
||||||
|
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name);
|
ConCommandBase *FindConCommandBase(const char *name);
|
||||||
|
|
||||||
class ConCommandCleaner : public SMGlobalClass
|
class ConCommandCleaner : public SMGlobalClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
||||||
void OnSourceModAllInitialized()
|
void OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
|
||||||
|
SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#else
|
||||||
|
SH_ADD_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnSourceModShutdown()
|
void OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
}
|
SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
|
||||||
|
SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#else
|
||||||
|
SH_REMOVE_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
void LinkConCommandBase(ConCommandBase *pBase, bool unknown)
|
||||||
|
#else
|
||||||
|
void LinkConCommandBase(ConCommandBase *pBase)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||||
|
while (listener)
|
||||||
|
{
|
||||||
|
listener->OnLinkConCommand(pBase);
|
||||||
|
listener = listener->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnlinkConCommandBase(ConCommandBase *pBase)
|
void UnlinkConCommandBase(ConCommandBase *pBase)
|
||||||
{
|
{
|
||||||
ConCommandInfo *pInfo;
|
ConCommandInfo *pInfo;
|
||||||
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
||||||
|
|
||||||
if (pBase)
|
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||||
|
while (listener)
|
||||||
{
|
{
|
||||||
while (iter != tracked_bases.end())
|
listener->OnUnlinkConCommand(pBase);
|
||||||
{
|
listener = listener->next;
|
||||||
if ((*iter)->pBase == pBase)
|
|
||||||
{
|
|
||||||
pInfo = (*iter);
|
|
||||||
iter = tracked_bases.erase(iter);
|
|
||||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
|
|
||||||
delete pInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (iter != tracked_bases.end())
|
||||||
|
{
|
||||||
|
if ((*iter)->pBase == pBase)
|
||||||
|
{
|
||||||
|
pInfo = (*iter);
|
||||||
|
iter = tracked_bases.erase(iter);
|
||||||
|
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName());
|
||||||
|
delete pInfo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
||||||
@@ -117,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);
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -35,11 +35,33 @@
|
|||||||
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);
|
||||||
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
||||||
|
|
||||||
|
class IConCommandLinkListener
|
||||||
|
{
|
||||||
|
friend class ConCommandCleaner;
|
||||||
|
|
||||||
|
static IConCommandLinkListener *head;
|
||||||
|
IConCommandLinkListener *next;
|
||||||
|
public:
|
||||||
|
IConCommandLinkListener()
|
||||||
|
{
|
||||||
|
next = head;
|
||||||
|
head = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -1,712 +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 _LINUX
|
|
||||||
#define FORCEINLINE_CVAR inline
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Forward declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar;
|
|
||||||
class CCommand;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
struct characterset_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helper method for console development
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined( _X360 ) && !defined( _RETAIL )
|
|
||||||
void ConVar_PublishToVXConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
|
||||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Interface version
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ICommandCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
|
||||||
friend void ConVar_PublishToVXConsole();
|
|
||||||
|
|
||||||
// FIXME: Remove when ConVar changes are done
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
// Remove flag
|
|
||||||
virtual void RemoveFlags( int flags );
|
|
||||||
// Get flags
|
|
||||||
virtual int GetFlags( void ) const;
|
|
||||||
|
|
||||||
// Return name of cvar
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
|
|
||||||
// Return help text for cvar
|
|
||||||
virtual const char *GetHelpText( void ) const;
|
|
||||||
|
|
||||||
// Deal with next pointer
|
|
||||||
const ConCommandBase *GetNext( void ) const;
|
|
||||||
ConCommandBase *GetNext( void );
|
|
||||||
|
|
||||||
inline void SetNext(ConCommandBase *pBase)
|
|
||||||
{
|
|
||||||
m_pNext = pBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Returns the DLL identifier
|
|
||||||
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Create( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize/shutdown
|
|
||||||
virtual void Init();
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// Internal copy routine ( uses new operator from correct module )
|
|
||||||
char *CopyString( const char *from );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Next ConVar in chain
|
|
||||||
// Prior to register, it points to the next convar in the DLL.
|
|
||||||
// Once registered, though, m_pNext is reset to point to the next
|
|
||||||
// convar in the global list
|
|
||||||
ConCommandBase *m_pNext;
|
|
||||||
|
|
||||||
// Has the cvar been added to the global list?
|
|
||||||
bool m_bRegistered;
|
|
||||||
|
|
||||||
// Static data
|
|
||||||
const char *m_pszName;
|
|
||||||
const char *m_pszHelpString;
|
|
||||||
|
|
||||||
// ConVar flags
|
|
||||||
int m_nFlags;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// ConVars add themselves to this list for the executable.
|
|
||||||
// Then ConVar_Register runs through all the console variables
|
|
||||||
// and registers them into a global list stored in vstdlib.dll
|
|
||||||
static ConCommandBase *s_pConCommandBases;
|
|
||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
|
||||||
public:
|
|
||||||
inline void SetFlags(int flags)
|
|
||||||
{
|
|
||||||
m_nFlags = flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Command tokenizer
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class CCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCommand();
|
|
||||||
CCommand( int nArgC, const char **ppArgV );
|
|
||||||
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
int ArgC() const;
|
|
||||||
const char **ArgV() const;
|
|
||||||
const char *ArgS() const; // All args that occur after the 0th arg, in string form
|
|
||||||
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
|
|
||||||
const char *operator[]( int nIndex ) const; // Gets at arguments
|
|
||||||
const char *Arg( int nIndex ) const; // Gets at arguments
|
|
||||||
|
|
||||||
// Helper functions to parse arguments to commands.
|
|
||||||
const char* FindArg( const char *pName ) const;
|
|
||||||
int FindArgInt( const char *pName, int nDefaultVal ) const;
|
|
||||||
|
|
||||||
static int MaxCommandLength();
|
|
||||||
static characterset_t* DefaultBreakSet();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
COMMAND_MAX_ARGC = 64,
|
|
||||||
COMMAND_MAX_LENGTH = 512,
|
|
||||||
};
|
|
||||||
|
|
||||||
int m_nArgc;
|
|
||||||
int m_nArgv0Size;
|
|
||||||
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
|
|
||||||
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int CCommand::MaxCommandLength()
|
|
||||||
{
|
|
||||||
return COMMAND_MAX_LENGTH - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int CCommand::ArgC() const
|
|
||||||
{
|
|
||||||
return m_nArgc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char **CCommand::ArgV() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? (const char**)m_ppArgv : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::ArgS() const
|
|
||||||
{
|
|
||||||
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::GetCommandString() const
|
|
||||||
{
|
|
||||||
return m_nArgc ? m_pArgSBuffer : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::Arg( int nIndex ) const
|
|
||||||
{
|
|
||||||
// FIXME: Many command handlers appear to not be particularly careful
|
|
||||||
// about checking for valid argc range. For now, we're going to
|
|
||||||
// do the extra check and return an empty string if it's out of range
|
|
||||||
if ( nIndex < 0 || nIndex >= m_nArgc )
|
|
||||||
return "";
|
|
||||||
return m_ppArgv[nIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *CCommand::operator[]( int nIndex ) const
|
|
||||||
{
|
|
||||||
return Arg( nIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The console invoked command
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, FnCommandCallback_t callback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
|
||||||
ConCommand( const char *pName, ICommandCallback *pCallback,
|
|
||||||
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommand( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
|
|
||||||
|
|
||||||
virtual bool CanAutoComplete( void );
|
|
||||||
|
|
||||||
// Invoke the function
|
|
||||||
virtual void Dispatch( const CCommand &command );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// NOTE: To maintain backward compat, we have to be very careful:
|
|
||||||
// All public virtual methods must appear in the same order always
|
|
||||||
// since engine code will be calling into this code, which *does not match*
|
|
||||||
// in the mod code; it's using slightly different, but compatible versions
|
|
||||||
// of this class. Also: Be very careful about adding new fields to this class.
|
|
||||||
// Those fields will not exist in the version of this class that is instanced
|
|
||||||
// in mod code.
|
|
||||||
|
|
||||||
// Call this function when executing the command
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
|
||||||
FnCommandCallback_t m_fnCommandCallback;
|
|
||||||
ICommandCallback *m_pCommandCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
|
||||||
ICommandCompletionCallback *m_pCommandCompletionCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool m_bHasCompletionCallback : 1;
|
|
||||||
bool m_bUsingNewCommandCallback : 1;
|
|
||||||
bool m_bUsingCommandCallbackInterface : 1;
|
|
||||||
public:
|
|
||||||
inline FnCommandCallback_t GetCallback() const
|
|
||||||
{
|
|
||||||
return m_fnCommandCallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: A console variable
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar : public ConCommandBase, public IConVar
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVarRef;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef ConCommandBase BaseClass;
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
|
|
||||||
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, FnChangeCallback_t callback );
|
|
||||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
|
||||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
|
||||||
FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
virtual ~ConVar( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
virtual int GetFlags( void ) const;
|
|
||||||
virtual const char *GetName( void ) const;
|
|
||||||
virtual const char* GetHelpText( void ) const;
|
|
||||||
virtual bool IsRegistered( void ) const;
|
|
||||||
|
|
||||||
// Install a change callback (there shouldn't already be one....)
|
|
||||||
void InstallChangeCallback( FnChangeCallback_t callback );
|
|
||||||
|
|
||||||
// Retrieve value
|
|
||||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
|
||||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
|
||||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
|
||||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
|
||||||
|
|
||||||
// Used internally by OneTimeInit to initialize.
|
|
||||||
virtual void Init();
|
|
||||||
|
|
||||||
virtual const char *GetBaseName( void ) const;
|
|
||||||
virtual int GetSplitScreenPlayerSlot ( void ) const;
|
|
||||||
|
|
||||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
|
||||||
// from alloc/free across dll/exe boundaries.
|
|
||||||
|
|
||||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
|
||||||
virtual void SetValue( const char *value );
|
|
||||||
virtual void SetValue( float value );
|
|
||||||
virtual void SetValue( int value );
|
|
||||||
|
|
||||||
// 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 );
|
|
||||||
|
|
||||||
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 _LINUX
|
|
||||||
#define FORCEINLINE_CVAR inline
|
|
||||||
#else
|
|
||||||
#error "implement me"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Forward declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConVar;
|
|
||||||
class CCommand;
|
|
||||||
class ConCommand;
|
|
||||||
class ConCommandBase;
|
|
||||||
struct characterset_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Any executable that wants to use ConVars need to implement one of
|
|
||||||
// these to hook up access to console variables.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class IConCommandBaseAccessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Flags is a combination of FCVAR flags in cvar.h.
|
|
||||||
// hOut is filled in with a handle to the variable.
|
|
||||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helper method for console development
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#if defined( _X360 ) && !defined( _RETAIL )
|
|
||||||
void ConVar_PublishToVXConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Called when a ConCommand needs to execute
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
|
||||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
|
||||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Interface version
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ICommandCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommandCompletionCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Purpose: The base console invoked command/cvar interface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class ConCommandBase
|
|
||||||
{
|
|
||||||
friend class CCvar;
|
|
||||||
friend class ConVar;
|
|
||||||
friend class ConCommand;
|
|
||||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
|
||||||
friend void ConVar_PublishToVXConsole();
|
|
||||||
|
|
||||||
// FIXME: Remove when ConVar changes are done
|
|
||||||
friend class CDefaultCvar;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConCommandBase( void );
|
|
||||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
|
||||||
int flags = 0 );
|
|
||||||
|
|
||||||
virtual ~ConCommandBase( void );
|
|
||||||
|
|
||||||
virtual bool IsCommand( void ) const;
|
|
||||||
|
|
||||||
// Check flag
|
|
||||||
virtual bool IsFlagSet( int flag ) const;
|
|
||||||
// Set flag
|
|
||||||
virtual void AddFlags( int flags );
|
|
||||||
|
|
||||||
// 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
|
|
||||||
@@ -30,14 +30,14 @@
|
|||||||
*/
|
*/
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "Database.h"
|
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "MenuStyle_Radio.h"
|
#include "MenuStyle_Radio.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "CoreConfig.h"
|
#include "CoreConfig.h"
|
||||||
#include <sm_queue.h>
|
#include <sm_queue.h>
|
||||||
#include "ThreadSupport.h"
|
#include <IThreader.h>
|
||||||
|
#include "sourcemod.h"
|
||||||
|
|
||||||
static IMutex *frame_mutex;
|
static IMutex *frame_mutex;
|
||||||
static Queue<FrameAction> *frame_queue;
|
static Queue<FrameAction> *frame_queue;
|
||||||
@@ -95,7 +95,6 @@ void RunFrameHooks(bool simulating)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Frame based hooks */
|
/* Frame based hooks */
|
||||||
g_DBMan.RunFrame();
|
|
||||||
g_HL2.ProcessFakeCliCmdQueue();
|
g_HL2.ProcessFakeCliCmdQueue();
|
||||||
g_HL2.ProcessDelayedKicks();
|
g_HL2.ProcessDelayedKicks();
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ADTFactory.h"
|
#include "ADTFactory.h"
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
|
|
||||||
ADTFactory g_AdtFactory;
|
ADTFactory g_AdtFactory;
|
||||||
@@ -57,32 +56,30 @@ IBasicTrie *ADTFactory::CreateBasicTrie()
|
|||||||
|
|
||||||
BaseTrie::BaseTrie()
|
BaseTrie::BaseTrie()
|
||||||
{
|
{
|
||||||
m_pTrie = sm_trie_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseTrie::~BaseTrie()
|
BaseTrie::~BaseTrie()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_pTrie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Insert(const char *key, void *value)
|
bool BaseTrie::Insert(const char *key, void *value)
|
||||||
{
|
{
|
||||||
return sm_trie_insert(m_pTrie, key, value);
|
return map_.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Retrieve(const char *key, void **value)
|
bool BaseTrie::Retrieve(const char *key, void **value)
|
||||||
{
|
{
|
||||||
return sm_trie_retrieve(m_pTrie, key, value);
|
return map_.retrieve(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Delete(const char *key)
|
bool BaseTrie::Delete(const char *key)
|
||||||
{
|
{
|
||||||
return sm_trie_delete(m_pTrie, key);
|
return map_.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTrie::Clear()
|
void BaseTrie::Clear()
|
||||||
{
|
{
|
||||||
sm_trie_clear(m_pTrie);
|
map_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTrie::Destroy()
|
void BaseTrie::Destroy()
|
||||||
@@ -92,5 +89,5 @@ void BaseTrie::Destroy()
|
|||||||
|
|
||||||
bool BaseTrie::Replace(const char *key, void *value)
|
bool BaseTrie::Replace(const char *key, void *value)
|
||||||
{
|
{
|
||||||
return sm_trie_replace(m_pTrie, key, value);
|
return map_.replace(key, value);
|
||||||
}
|
}
|
||||||
@@ -1,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,8 +33,8 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
||||||
|
|
||||||
#include <IADTFactory.h>
|
#include <IADTFactory.h>
|
||||||
#include "sm_globals.h"
|
#include "common_logic.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
virtual void Clear();
|
virtual void Clear();
|
||||||
virtual void Destroy();
|
virtual void Destroy();
|
||||||
private:
|
private:
|
||||||
Trie *m_pTrie;
|
StringHashMap<void *> map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADTFactory :
|
class ADTFactory :
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os
|
||||||
|
|
||||||
|
for arch in SM.archs:
|
||||||
|
binary = SM.Library(builder, 'sourcemod.logic', arch)
|
||||||
|
binary.compiler.cxxincludes += [
|
||||||
|
builder.sourcePath,
|
||||||
|
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||||
|
os.path.join(builder.sourcePath, 'public'),
|
||||||
|
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(SM.mms_root, 'core', 'sourcehook')
|
||||||
|
]
|
||||||
|
binary.compiler.defines += [
|
||||||
|
'SM_DEFAULT_THREADER',
|
||||||
|
'SM_LOGIC'
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.target.platform == 'linux':
|
||||||
|
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||||
|
elif builder.target.platform == 'mac':
|
||||||
|
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||||
|
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||||
|
|
||||||
|
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||||
|
binary.compiler.cxxflags += ['-fno-rtti']
|
||||||
|
elif binary.compiler.family == 'msvc':
|
||||||
|
binary.compiler.cxxflags += ['/GR-']
|
||||||
|
|
||||||
|
binary.sources += [
|
||||||
|
'common_logic.cpp',
|
||||||
|
'smn_adt_array.cpp',
|
||||||
|
'smn_sorting.cpp',
|
||||||
|
'smn_maplists.cpp',
|
||||||
|
'ADTFactory.cpp',
|
||||||
|
'smn_adt_stack.cpp',
|
||||||
|
'thread/ThreadWorker.cpp',
|
||||||
|
'thread/BaseWorker.cpp',
|
||||||
|
'ThreadSupport.cpp',
|
||||||
|
'smn_float.cpp',
|
||||||
|
'TextParsers.cpp',
|
||||||
|
'smn_textparse.cpp',
|
||||||
|
'smn_adt_trie.cpp',
|
||||||
|
'smn_functions.cpp',
|
||||||
|
'smn_timers.cpp',
|
||||||
|
'smn_players.cpp',
|
||||||
|
'MemoryUtils.cpp',
|
||||||
|
'smn_admin.cpp',
|
||||||
|
'smn_banning.cpp',
|
||||||
|
'smn_filesystem.cpp',
|
||||||
|
'stringutil.cpp',
|
||||||
|
'Translator.cpp',
|
||||||
|
'PhraseCollection.cpp',
|
||||||
|
'smn_lang.cpp',
|
||||||
|
'smn_string.cpp',
|
||||||
|
'smn_handles.cpp',
|
||||||
|
'smn_datapacks.cpp',
|
||||||
|
'smn_gameconfigs.cpp',
|
||||||
|
'smn_fakenatives.cpp',
|
||||||
|
'GameConfigs.cpp',
|
||||||
|
'sm_crc32.cpp',
|
||||||
|
'smn_profiler.cpp',
|
||||||
|
'ShareSys.cpp',
|
||||||
|
'PluginSys.cpp',
|
||||||
|
'HandleSys.cpp',
|
||||||
|
'NativeOwner.cpp',
|
||||||
|
'ExtensionSys.cpp',
|
||||||
|
'DebugReporter.cpp',
|
||||||
|
'Database.cpp',
|
||||||
|
'smn_database.cpp',
|
||||||
|
'ForwardSys.cpp',
|
||||||
|
'AdminCache.cpp',
|
||||||
|
'sm_trie.cpp',
|
||||||
|
'smn_console.cpp',
|
||||||
|
'ProfileTools.cpp',
|
||||||
|
'Logger.cpp',
|
||||||
|
'smn_core.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 arch == 'x64':
|
||||||
|
binary.sources += ['PseudoAddrManager.cpp']
|
||||||
|
|
||||||
|
if builder.target.platform == 'windows':
|
||||||
|
binary.sources += ['thread/WinThreads.cpp']
|
||||||
|
else:
|
||||||
|
binary.sources += ['thread/PosixThreads.cpp']
|
||||||
|
|
||||||
|
SM.binaries += [builder.Add(binary)]
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,208 +1,231 @@
|
|||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
* Free Software Foundation.
|
* Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* details.
|
* details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
*
|
*
|
||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
|
|
||||||
#include "sm_memtable.h"
|
#include "common_logic.h"
|
||||||
#include <sm_trie.h>
|
#include <IAdminSystem.h>
|
||||||
#include <sh_list.h>
|
#include "sm_memtable.h"
|
||||||
#include <sh_string.h>
|
#include <sm_trie.h>
|
||||||
#include <IAdminSystem.h>
|
#include <sh_list.h>
|
||||||
#include "sm_globals.h"
|
#include <sh_string.h>
|
||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
using namespace SourceHook;
|
#include <sm_namehashset.h>
|
||||||
|
|
||||||
#define GRP_MAGIC_SET 0xDEADFADE
|
using namespace SourceHook;
|
||||||
#define GRP_MAGIC_UNSET 0xFACEFACE
|
|
||||||
#define USR_MAGIC_SET 0xDEADFACE
|
#define GRP_MAGIC_SET 0xDEADFADE
|
||||||
#define USR_MAGIC_UNSET 0xFADEDEAD
|
#define GRP_MAGIC_UNSET 0xFACEFACE
|
||||||
|
#define USR_MAGIC_SET 0xDEADFACE
|
||||||
struct AdminGroup
|
#define USR_MAGIC_UNSET 0xFADEDEAD
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation (ugh) */
|
typedef StringHashMap<OverrideRule> OverrideMap;
|
||||||
unsigned int immunity_level; /* Immunity level */
|
|
||||||
/* Immune from target table (-1 = nonexistent)
|
struct AdminGroup
|
||||||
* [0] = number of entries
|
{
|
||||||
* [1...N] = immune targets
|
uint32_t magic; /* Magic flag, for memory validation (ugh) */
|
||||||
*/
|
unsigned int immunity_level; /* Immunity level */
|
||||||
int immune_table;
|
/* Immune from target table (-1 = nonexistent)
|
||||||
Trie *pCmdTable; /* Command override table (can be NULL) */
|
* [0] = number of entries
|
||||||
Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
|
* [1...N] = immune targets
|
||||||
int next_grp; /* Next group in the chain */
|
*/
|
||||||
int prev_grp; /* Previous group in the chain */
|
int immune_table;
|
||||||
int nameidx; /* Name */
|
OverrideMap *pCmdTable; /* Command override table (can be NULL) */
|
||||||
FlagBits addflags; /* Additive flags */
|
OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */
|
||||||
};
|
int next_grp; /* Next group in the chain */
|
||||||
|
int prev_grp; /* Previous group in the chain */
|
||||||
struct AuthMethod
|
int nameidx; /* Name */
|
||||||
{
|
FlagBits addflags; /* Additive flags */
|
||||||
String name;
|
};
|
||||||
Trie *table;
|
|
||||||
};
|
struct AuthMethod
|
||||||
|
{
|
||||||
struct UserAuth
|
String name;
|
||||||
{
|
StringHashMap<AdminId> identities;
|
||||||
unsigned int index; /* Index into auth table */
|
|
||||||
int identidx; /* Index into the string table */
|
AuthMethod(const char *name)
|
||||||
};
|
: name(name)
|
||||||
|
{
|
||||||
struct AdminUser
|
}
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation */
|
static inline bool matches(const char *name, const AuthMethod *method)
|
||||||
FlagBits flags; /* Flags */
|
{
|
||||||
FlagBits eflags; /* Effective flags */
|
return strcmp(name, method->name.c_str()) == 0;
|
||||||
int nameidx; /* Name index */
|
}
|
||||||
int password; /* Password index */
|
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||||
unsigned int grp_count; /* Number of groups */
|
{
|
||||||
unsigned int grp_size; /* Size of groups table */
|
return key.hash();
|
||||||
int grp_table; /* Group table itself */
|
}
|
||||||
int next_user; /* Next user in the list */
|
};
|
||||||
int prev_user; /* Previous user in the list */
|
|
||||||
UserAuth auth; /* Auth method for this user */
|
struct UserAuth
|
||||||
unsigned int immunity_level; /* Immunity level */
|
{
|
||||||
unsigned int serialchange; /* Serial # for changes */
|
unsigned int index; /* Index into auth table */
|
||||||
};
|
int identidx; /* Index into the string table */
|
||||||
|
};
|
||||||
class AdminCache :
|
|
||||||
public IAdminSystem,
|
struct AdminUser
|
||||||
public SMGlobalClass
|
{
|
||||||
{
|
uint32_t magic; /* Magic flag, for memory validation */
|
||||||
public:
|
FlagBits flags; /* Flags */
|
||||||
AdminCache();
|
FlagBits eflags; /* Effective flags */
|
||||||
~AdminCache();
|
int nameidx; /* Name index */
|
||||||
public: //SMGlobalClass
|
int password; /* Password index */
|
||||||
void OnSourceModStartup(bool late);
|
unsigned int grp_count; /* Number of groups */
|
||||||
void OnSourceModAllInitialized();
|
unsigned int grp_size; /* Size of groups table */
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
int grp_table; /* Group table itself */
|
||||||
void OnSourceModShutdown();
|
int next_user; /* Next user in the list */
|
||||||
void OnSourceModPluginsLoaded();
|
int prev_user; /* Previous user in the list */
|
||||||
public: //IAdminSystem
|
UserAuth auth; /* Auth method for this user */
|
||||||
/** Command cache stuff */
|
unsigned int immunity_level; /* Immunity level */
|
||||||
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
|
unsigned int serialchange; /* Serial # for changes */
|
||||||
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
|
};
|
||||||
void UnsetCommandOverride(const char *cmd, OverrideType type);
|
|
||||||
/** Group cache stuff */
|
class AdminCache :
|
||||||
GroupId AddGroup(const char *group_name);
|
public IAdminSystem,
|
||||||
GroupId FindGroupByName(const char *group_name);
|
public SMGlobalClass
|
||||||
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
|
{
|
||||||
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
|
public:
|
||||||
FlagBits GetGroupAddFlags(GroupId id);
|
AdminCache();
|
||||||
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
|
~AdminCache();
|
||||||
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
|
public: //SMGlobalClass
|
||||||
void InvalidateGroup(GroupId id);
|
void OnSourceModStartup(bool late);
|
||||||
void AddGroupImmunity(GroupId id, GroupId other_id);
|
void OnSourceModAllInitialized();
|
||||||
unsigned int GetGroupImmunityCount(GroupId id);
|
void OnSourceModLevelChange(const char *mapName);
|
||||||
GroupId GetGroupImmunity(GroupId id, unsigned int number);
|
void OnSourceModShutdown();
|
||||||
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
|
void OnSourceModPluginsLoaded();
|
||||||
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
|
public: //IAdminSystem
|
||||||
void DumpAdminCache(AdminCachePart part, bool rebuild);
|
/** Command cache stuff */
|
||||||
void AddAdminListener(IAdminListener *pListener);
|
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
|
||||||
void RemoveAdminListener(IAdminListener *pListener);
|
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
|
||||||
/** User stuff */
|
void UnsetCommandOverride(const char *cmd, OverrideType type);
|
||||||
void RegisterAuthIdentType(const char *name);
|
/** Group cache stuff */
|
||||||
AdminId CreateAdmin(const char *name);
|
GroupId AddGroup(const char *group_name);
|
||||||
const char *GetAdminName(AdminId id);
|
GroupId FindGroupByName(const char *group_name);
|
||||||
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
|
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
|
||||||
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
|
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
|
||||||
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
|
FlagBits GetGroupAddFlags(GroupId id);
|
||||||
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
|
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
|
||||||
bool AdminInheritGroup(AdminId id, GroupId gid);
|
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
|
||||||
unsigned int GetAdminGroupCount(AdminId id);
|
void InvalidateGroup(GroupId id);
|
||||||
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
|
void AddGroupImmunity(GroupId id, GroupId other_id);
|
||||||
void SetAdminPassword(AdminId id, const char *password);
|
unsigned int GetGroupImmunityCount(GroupId id);
|
||||||
const char *GetAdminPassword(AdminId id);
|
GroupId GetGroupImmunity(GroupId id, unsigned int number);
|
||||||
AdminId FindAdminByIdentity(const char *auth, const char *identity);
|
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
|
||||||
bool InvalidateAdmin(AdminId id);
|
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
|
||||||
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
|
void DumpAdminCache(AdminCachePart part, bool rebuild);
|
||||||
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
|
void AddAdminListener(IAdminListener *pListener);
|
||||||
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
|
void RemoveAdminListener(IAdminListener *pListener);
|
||||||
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
|
/** User stuff */
|
||||||
bool CheckAdminFlags(AdminId id, FlagBits bits);
|
void RegisterAuthIdentType(const char *name);
|
||||||
bool CanAdminTarget(AdminId id, AdminId target);
|
AdminId CreateAdmin(const char *name);
|
||||||
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
|
const char *GetAdminName(AdminId id);
|
||||||
bool FindFlag(const char *str, AdminFlag *pFlag);
|
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
|
||||||
bool FindFlag(char c, AdminFlag *pAdmFlag);
|
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
|
||||||
FlagBits ReadFlagString(const char *flags, const char **end);
|
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
|
||||||
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
|
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
|
||||||
unsigned int GetAdminSerialChange(AdminId id);
|
bool AdminInheritGroup(AdminId id, GroupId gid);
|
||||||
bool CanAdminUseCommand(int client, const char *cmd);
|
unsigned int GetAdminGroupCount(AdminId id);
|
||||||
const char *GetGroupName(GroupId gid);
|
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
|
||||||
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
|
void SetAdminPassword(AdminId id, const char *password);
|
||||||
unsigned int GetGroupImmunityLevel(GroupId gid);
|
const char *GetAdminPassword(AdminId id);
|
||||||
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
|
AdminId FindAdminByIdentity(const char *auth, const char *identity);
|
||||||
unsigned int GetAdminImmunityLevel(AdminId id);
|
bool InvalidateAdmin(AdminId id);
|
||||||
bool CheckAccess(int client,
|
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
|
||||||
const char *cmd,
|
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
|
||||||
FlagBits flags,
|
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
|
||||||
bool override_only);
|
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
|
||||||
bool FindFlagChar(AdminFlag flag, char *c);
|
bool CheckAdminFlags(AdminId id, FlagBits bits);
|
||||||
public:
|
bool CanAdminTarget(AdminId id, AdminId target);
|
||||||
bool IsValidAdmin(AdminId id);
|
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
|
||||||
void DumpCache(FILE *fp);
|
bool FindFlag(const char *str, AdminFlag *pFlag);
|
||||||
AdminGroup *GetGroup(GroupId gid);
|
bool FindFlag(char c, AdminFlag *pAdmFlag);
|
||||||
AdminUser *GetUser(AdminId id);
|
FlagBits ReadFlagString(const char *flags, const char **end);
|
||||||
const char *GetString(int idx);
|
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
|
||||||
private:
|
unsigned int GetAdminSerialChange(AdminId id);
|
||||||
void _UnsetCommandOverride(const char *cmd);
|
bool CanAdminUseCommand(int client, const char *cmd);
|
||||||
void _UnsetCommandGroupOverride(const char *group);
|
const char *GetGroupName(GroupId gid);
|
||||||
void InvalidateGroupCache();
|
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
|
||||||
void InvalidateAdminCache(bool unlink_admins);
|
unsigned int GetGroupImmunityLevel(GroupId gid);
|
||||||
void DumpCommandOverrideCache(OverrideType type);
|
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
|
||||||
Trie *GetMethodByIndex(unsigned int index);
|
unsigned int GetAdminImmunityLevel(AdminId id);
|
||||||
bool GetMethodIndex(const char *name, unsigned int *_index);
|
bool CheckAccess(int client,
|
||||||
const char *GetMethodName(unsigned int index);
|
const char *cmd,
|
||||||
void NameFlag(const char *str, AdminFlag flag);
|
FlagBits flags,
|
||||||
public:
|
bool override_only);
|
||||||
BaseStringTable *m_pStrings;
|
bool FindFlagChar(AdminFlag flag, char *c);
|
||||||
BaseMemTable *m_pMemory;
|
bool IsValidAdmin(AdminId id);
|
||||||
Trie *m_pCmdOverrides;
|
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags);
|
||||||
Trie *m_pCmdGrpOverrides;
|
public:
|
||||||
int m_FirstGroup;
|
bool DumpCache(const char *filename);
|
||||||
int m_LastGroup;
|
AdminGroup *GetGroup(GroupId gid);
|
||||||
int m_FreeGroupList;
|
AdminUser *GetUser(AdminId id);
|
||||||
Trie *m_pGroups;
|
const char *GetString(int idx);
|
||||||
List<IAdminListener *> m_hooks;
|
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
|
||||||
List<AuthMethod> m_AuthMethods;
|
private:
|
||||||
Trie *m_pAuthTables;
|
void _UnsetCommandOverride(const char *cmd);
|
||||||
IForward *m_pCacheFwd;
|
void _UnsetCommandGroupOverride(const char *group);
|
||||||
int m_FirstUser;
|
void InvalidateGroupCache();
|
||||||
int m_LastUser;
|
void InvalidateAdminCache(bool unlink_admins);
|
||||||
int m_FreeUserList;
|
void DumpCommandOverrideCache(OverrideType type);
|
||||||
bool m_InvalidatingAdmins;
|
AuthMethod *GetMethodByIndex(unsigned int index);
|
||||||
bool m_destroying;
|
bool GetMethodIndex(const char *name, unsigned int *_index);
|
||||||
Trie *m_pLevelNames;
|
const char *GetMethodName(unsigned int index);
|
||||||
};
|
void NameFlag(const char *str, AdminFlag flag);
|
||||||
|
bool GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen);
|
||||||
extern AdminCache g_Admins;
|
public:
|
||||||
|
typedef StringHashMap<FlagBits> FlagMap;
|
||||||
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
|
||||||
|
BaseStringTable *m_pStrings;
|
||||||
|
BaseMemTable *m_pMemory;
|
||||||
|
FlagMap m_CmdOverrides;
|
||||||
|
FlagMap m_CmdGrpOverrides;
|
||||||
|
int m_FirstGroup;
|
||||||
|
int m_LastGroup;
|
||||||
|
int m_FreeGroupList;
|
||||||
|
StringHashMap<GroupId> m_Groups;
|
||||||
|
List<IAdminListener *> m_hooks;
|
||||||
|
List<AuthMethod *> m_AuthMethods;
|
||||||
|
NameHashSet<AuthMethod *> m_AuthTables;
|
||||||
|
IForward *m_pCacheFwd;
|
||||||
|
int m_FirstUser;
|
||||||
|
int m_LastUser;
|
||||||
|
int m_FreeUserList;
|
||||||
|
bool m_InvalidatingAdmins;
|
||||||
|
bool m_destroying;
|
||||||
|
StringHashMap<AdminFlag> m_LevelNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern AdminCache g_Admins;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user