Compare commits
653
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd0aaf9da9 | ||
|
|
325e95e9be | ||
|
|
c2e31deb78 | ||
|
|
c944ef18b3 | ||
|
|
14af0bae82 | ||
|
|
efba7bd82a | ||
|
|
6da2f6c8ed | ||
|
|
9e6f7a9e89 | ||
|
|
d0ab3e7bd6 | ||
|
|
a6d5212ee9 | ||
|
|
79bb037b66 | ||
|
|
ea3f491a8e | ||
|
|
aa27b10232 | ||
|
|
1ebf70b450 | ||
|
|
3a499036ac | ||
|
|
6b92f18a86 | ||
|
|
60757dde1c | ||
|
|
d5fc57316e | ||
|
|
1b47398e38 | ||
|
|
70f42dee65 | ||
|
|
08db476476 | ||
|
|
b1353e2ca4 | ||
|
|
6be9c770fe | ||
|
|
83a77bca08 | ||
|
|
1ff913c38f | ||
|
|
5383a0596a | ||
|
|
a81776f92c | ||
|
|
bcef7365b0 | ||
|
|
9e882783f9 | ||
|
|
00a663c1a3 | ||
|
|
5c047ad04b | ||
|
|
5e64de198a | ||
|
|
b92e4ff688 | ||
|
|
224d54aadd | ||
|
|
bcc6581c1c | ||
|
|
68c752bf6d | ||
|
|
a0bfda89d8 | ||
|
|
55cadc7738 | ||
|
|
4d9e94373f | ||
|
|
516c140810 | ||
|
|
6cfced238c | ||
|
|
27c73d4e3e | ||
|
|
4818aee7b9 | ||
|
|
65f52a3cad | ||
|
|
49a568bd59 | ||
|
|
1575ddb3f3 | ||
|
|
f9cdc421c3 | ||
|
|
7304747f79 | ||
|
|
17fcd5a37f | ||
|
|
d413a6bd2f | ||
|
|
154d84668b | ||
|
|
58194c5d99 | ||
|
|
844fad263a | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 |
+3
-3
@@ -14,9 +14,9 @@
|
||||
*.user
|
||||
|
||||
# Build directories
|
||||
CrazyDebug.*/
|
||||
Debug.*/
|
||||
Release.*/
|
||||
CrazyDebug*/
|
||||
Debug*/
|
||||
Release*/
|
||||
LIB-Release/
|
||||
LIB-Debug/
|
||||
|
||||
|
||||
+22
-7
@@ -73,7 +73,9 @@ class SMConfig(object):
|
||||
self.versionlib = None
|
||||
|
||||
def use_auto_versioning(self):
|
||||
return builder.backend == 'amb2'
|
||||
if builder.backend != 'amb2':
|
||||
return False
|
||||
return not getattr(builder.options, 'disable_auto_versioning', False)
|
||||
|
||||
@property
|
||||
def tag(self):
|
||||
@@ -163,14 +165,15 @@ class SMConfig(object):
|
||||
'-fno-strict-aliasing',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-Wno-uninitialized',
|
||||
'-Wno-unused',
|
||||
'-Wno-switch',
|
||||
'-Wno-format',
|
||||
'-Wno-format-security',
|
||||
'-Wno-array-bounds',
|
||||
'-msse',
|
||||
'-m32',
|
||||
]
|
||||
cxx.cxxflags += [
|
||||
'-std=c++11',
|
||||
]
|
||||
|
||||
have_gcc = cxx.vendor == 'gcc'
|
||||
have_clang = cxx.vendor == 'clang'
|
||||
@@ -181,6 +184,15 @@ class SMConfig(object):
|
||||
cxx.cflags += ['-Wno-narrowing']
|
||||
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
|
||||
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||
if have_gcc and cxx.version >= '4.8':
|
||||
cxx.cflags += ['-Wno-unused-result']
|
||||
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']
|
||||
|
||||
cxx.linkflags += ['-m32']
|
||||
cxx.cxxflags += [
|
||||
@@ -204,6 +216,8 @@ class SMConfig(object):
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
'_ITERATOR_DEBUG_LEVEL=0',
|
||||
]
|
||||
if cxx.version < 1800:
|
||||
cxx.defines += 'strtoull=_strtoui64'
|
||||
cxx.cflags += [
|
||||
'/W3',
|
||||
]
|
||||
@@ -235,7 +249,7 @@ class SMConfig(object):
|
||||
if cxx.like('gcc'):
|
||||
cxx.cflags += ['-O3']
|
||||
elif cxx.like('msvc'):
|
||||
cxx.cflags += ['/Ox']
|
||||
cxx.cflags += ['/Ox', '/Zo']
|
||||
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
||||
|
||||
# Debugging
|
||||
@@ -243,8 +257,6 @@ class SMConfig(object):
|
||||
cxx.defines += ['DEBUG', '_DEBUG']
|
||||
if cxx.like('msvc'):
|
||||
cxx.cflags += ['/Od', '/RTC1']
|
||||
if cxx.version >= 1600:
|
||||
cxx.cflags += ['/d2Zi+']
|
||||
|
||||
# This needs to be after our optimization flags which could otherwise disable it.
|
||||
if cxx.vendor == 'msvc':
|
||||
@@ -381,6 +393,9 @@ class SMConfig(object):
|
||||
if builder.target_platform in ['linux', 'mac']:
|
||||
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
||||
|
||||
if sdk.name == 'csgo' and builder.target_platform == 'linux':
|
||||
compiler.linkflags += ['-lstdc++']
|
||||
|
||||
for path in paths:
|
||||
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Please visit [our wiki](https://wiki.alliedmods.net/Contributing_to_SourceMod) for information on how to contribute to Sourcemod.
|
||||
|
||||
As a sidenote, [Travis](https://travis-ci.org/alliedmodders/sourcemod) will automatically build your PR to make sure it compiles on Linux.
|
||||
+678
@@ -1,5 +1,683 @@
|
||||
SourceMod Changelog
|
||||
|
||||
SourceMod 1.7.0 [2015-02-04]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.7.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated game compatibility for TF2, CS:GO, and Dota 2.
|
||||
- Fixed regression in SM 1.6.3 causing load failure on games older than Orangebox. (PR 237)
|
||||
- Rewrote internal Steam auth ID handling (PR 147, PR 153, PR 155, PR 162, PR 204, PR 210, PR 222, PR 246).
|
||||
--- admins.cfg now supports Steam2, Steam3, and SteamID 64 formats for the Steam auth provider.
|
||||
--- admins-simple.ini now supports Steam3 auth IDs in addition to Steam2 IDs.
|
||||
--- Command targeting now supports both Steam3 auth IDs in addition to Steam2 IDs.
|
||||
- Added default timeout for MySQL connections to avoid hangs. (PR 248).
|
||||
- SDKTools' gamerules gamedata is now far less likely to break on updates (PR 220).
|
||||
- Fixed crash with sm_dump_admcache on Windows (PR 163).
|
||||
- Fixed SDKHooks causing crash on player join/leave or plugin load/unload if gamedata missing (PR 236).
|
||||
- Changed default sm_trigger_show ConVar value to 0 / disabled.
|
||||
|
||||
Developer Changes:
|
||||
- Added new SourcePawn Transitional Syntax!
|
||||
--- New methodmap-based APIs have been added for many existing functions and handle types.
|
||||
--- New work-in-progress API doc page.
|
||||
- Added Blocked hook type to SDKHooks (PR 119) (VoiDeD).
|
||||
- Added OnTakeDamage_Alive hook type to SDKHooks (PR 149).
|
||||
- Many more File natives now support Valve FS (PR 120, PR 169, PR 178).
|
||||
- Added SetFilePermissions native (PR 43) (hlstriker).
|
||||
- Added API for iterating StringMaps (formerly "tries").
|
||||
- Added natives for accessing command line parameters (PR 164) (VoiDeD).
|
||||
- Exposed engine Message_DetermineMulticastRecipients as GetClientsInRange native. (PR 234).
|
||||
- CloseHandle (or delete) on INVALID_HANDLE is now a no-op, instead of an error (PR 74).
|
||||
- GetClientAuthString is now deprecated. Use GetClientAuthId instead.
|
||||
- Added OnCoreMapEnd to extension interface (PR 127).
|
||||
- Fixed IThreader threads leaking if they're not joined. (bug 3460, PR 241).
|
||||
- TFHoliday updates no longer require a plugin recompile (PR 217).
|
||||
- Fixed FindFlagChar returning false when passing AdminFlag_Custom6 (bug 6248, PR 203).
|
||||
- Added support for (entity) CLASSPTR and EDICT Prop_Data fields with GetEntPropEnt and SetEntPropEnt (PR 83).
|
||||
- Doubled maximum handle count per plugin to 32,768 (PR 215), (Thordin).
|
||||
- Added support for custom default values with GetEvent* natives, rather than using ""/0 for unset fields (PR 157) (VoiDeD).
|
||||
- Removed old profiler, and added new, pluggable profiler (with hooks to VProf) (PR 54).
|
||||
- Added command to dump profiler output (PR 128) (VoiDeD).
|
||||
- Fixed ICommandLine and related features being reported as unavailable on Dark Messiah.
|
||||
- Fixed OnPlayerRunCommand forward in SDKTools being unavailable on Dark Messiah.
|
||||
- SourceMod now uses some C++11 and has newer compiler requirements.
|
||||
- Added --disable-auto-versioning option to ambuild configure script.
|
||||
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.6.3 [2014-11-25]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.6.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated game support for TF2, CS:GO, No More Room in Hell, Insurgency, PVK2 and Fistful of Frags.
|
||||
- Made changes to make TF2, CSS, DoDS, HL2DM, and SDK 2013 mods less likely to break on game update (PR 174, PR 192).
|
||||
- Added support for longer key names in languages.cfg (to fix Portuguese) (bug 6282, PR 208).
|
||||
|
||||
Developer Changes:
|
||||
- Updated TF2 player condition and holiday enums (Ross "Powerlord" Bemrose) (PR 183, PR 181).
|
||||
- Add support for TF2 player conditions >= 96 for condition functions/forwards (PR 205).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.6.2 [2014-09-20]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.6.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated game support for TF2, CS:GO, No More Room in Hell and Fistful of Frags.
|
||||
- Added compatibility shim to force Steam player auth strings to be in "Steam2" rendered format (PR 136).
|
||||
- Fixed possible performance regression in DBI handling.
|
||||
|
||||
Developer Changes:
|
||||
- Added new GetClientAuthId native to retrieve player auth strings in desired format (PR 159).
|
||||
- Updated TF2 weapon and player condition enums (FlaminSarge).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.6.1 [2014-08-17]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.6.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated game support for CS:GO and Fistful of Frags.
|
||||
- Added support for Romanian language.
|
||||
- Re-added languages.cfg, missing from 1.6.0, causing all clients to use server language.
|
||||
- Fixed a regression in version 1.6.0 that caused certain SDKHooks usage patterns to cause a server crash (PR 107).
|
||||
- Improved error reporting in basebans plugin when banreasons.txt is missing (PR 115).
|
||||
- Fixed incorrect logged gravity value for sm_gravity command (Ryan "VoiDeD" Stecker) (PR 116).
|
||||
- Fixed a regression in version 1.6.0 causing SDKHook_ReloadPost hooks to not fire in plugins (Peace-Maker) (PR 96).
|
||||
- Added workaround for game bug in TF2_RemoveWeaponSlot to avoid wearable entities left on map (Ryan "VoiDeD" Stecker) (bug 6206, PR 121).
|
||||
- Removed DisableJIT option from core.cfg. (It was never meant for normal use.)
|
||||
|
||||
Developer Changes:
|
||||
- Added new TF2_RemoveWearable native (Ryan "VoiDeD" Stecker, WildCard65) (PR 114).
|
||||
- Added new functions for interacting with and playing scripted game sounds (Ross "Powerlord" Bemrose) (bug 5942, PR 65).
|
||||
- Added new StringToKeyValues natives (Ryan "VoiDeD" Stecker) (PR 74).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.6.0 [2014-07-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.6.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Added support for Dota 2 (bug 5656, bug 6068).
|
||||
- Added support for Source SDK 2013 mods (bug 5917).
|
||||
- Added support for Insurgency (bug 5951).
|
||||
- Added support for Contagion (bug 6007).
|
||||
- Added support for Blade Symphony (bug 5949).
|
||||
- Updated support for some mods that moved to SDK 2013 - No More Room In Hell, Fistful of Frags, Empires, Synergy.
|
||||
- Updated gamedata and other support for TF2, DoD:S, HL2:DM, CS:S, CS:GO, Left 4 Dead, and Nuclear Dawn.
|
||||
- Added support for customizing ban reasons in basebans.sp (bug 5762) (Matthias "House" Kollek).
|
||||
- Added support for searching all gameinfo search paths when seeking mapcycle file (bug 5839).
|
||||
- Added sm_reload_translations command (bug 5750).
|
||||
- Added support for single-file gamedata custom overrides (bug 5386) (Ondrej "RavuAlHemio" Hošek).
|
||||
- Re-enabled SteamAuthstringValidation config option by default (bug 5791, PR 20).
|
||||
- Fixed plugins not reaching ext dep lists, making dependent plugin not unload on ext unload (bug 5851) (Peace-Maker).
|
||||
- Added printing of SendProp flags to netprop dumps (bug 6082).
|
||||
- Removed support for obsolete plugin_settings.cfg (bug 5605).
|
||||
- Fixed topmenu sorting not getting refreshed after reloading sorting config (bug 6032) (Peace-Maker).
|
||||
- Fixed error log filename date sometimes being incorrect (bug 5761) (Matheus "M28" Valadares).
|
||||
- Dump handle information when a plugin is forcefully unloaded. (bug 5666).
|
||||
- Fixed sm_cancelvote not resetting rtv state. (bug 5808) (Peace-Maker).
|
||||
- Fixed Mapchooser dying on single map rotation servers (bug 5179).
|
||||
- Fixed various problems with unloading ClientPrefs and SourceMod (bug 5874).
|
||||
- Fixed "sm version" command reporting incorrect compile time in many cases (bug 6078) (SystematicMania).
|
||||
- Clear default database driver reference if backing extension is unloaded (bug 5934) (Peace-Maker).
|
||||
- Moved funcommands material and sound definitions to gamedata for easier cross-game support (bug 6085).
|
||||
- Implement a watchdog timer for scripts that take too long to execute (bug 5837).
|
||||
- Use Linux game data for offsets and signatures/symbols on OS X if Mac-specific data is not available (bug 6056).
|
||||
|
||||
Developer Changes:
|
||||
- Added an API for off-thread SQL transactions. (bug 3775, PR 26).
|
||||
- Added string literal concatenation using ellipses "..." (bug 4261, PR 5) (Peace-Maker).
|
||||
- Added support for nested datatables. (bug 5446).
|
||||
- Added PbRemoveRepeatedFieldValue native (bug 6066).
|
||||
- Added support for getting/setting protobuf enum values with PbGetInt, PbSetInt, and PbAddInt natives.
|
||||
- Removed deprecated PbReadRepeated natives that existed briefly in 1.5.0-dev prerelease versions.
|
||||
- Added RequestFrame native for one-off next-frame actions (bug 5965).
|
||||
- Added CS_DMG_HEADSHOT define for CS:S and CS:GO (PR 7) (Bara20).
|
||||
- Added CS_SLOT_KNIFE define for CS:S and CS:GO (bug 6131).
|
||||
- Updated TF_WEAPON enum (PR 37) (FlaminSarge).
|
||||
- Added TFHoliday_AprilFools to TFHoliday enum (bug 6092) (Ross "Powerlord" Bemrose).
|
||||
- Added new TF2_IsHolidayActive native to TF2 Ext (bug 6095) (Ross "Powerlord" Bemrose).
|
||||
- Switch TF2 extension to hook CTFGameRules::IsHolidayActive for holiday forward (bug 6137, PR 42).
|
||||
- Added GetPlayerJingleFile native. (bug 5690) (FlaminSarge).
|
||||
- Added PrepSDKCall_SetAddress and Address support to PrepSDKCall_SetFromConf (bug 5261).
|
||||
- Added ability to disable TopMenu Title Caching (bug 6034) (Peace-Maker).
|
||||
- Added DisplayTopMenuCategory native (bug 6033) (Peace-Maker).
|
||||
- Added support for Valve search paths to GetFileSize native (bug 5931).
|
||||
- Fixed invalid entities sometimes passed to OnEntityCreated and OnEntityDestroyed (bug 6119).
|
||||
- Fixed inconsistencies with OnClientDisconnected foward calls (bug 5988, PR 16).
|
||||
- Changed OnClientSayCommand to now pass non-silent chat triggers onward (bug 5926) (SystematicMania).
|
||||
- Changed OnClientSayCommand forwards to strip quotes from chat (bug 5986) (SystematicMania).
|
||||
- Fixed FindStringIndex native not returning INVALID_STRING_INDEX when string not found (bug 6144, PR 40).
|
||||
- Fixed GroundEntChanged hooks not being called (bug 6050) (Peace-Maker).
|
||||
- Fixed INetChannelInfo natives to no longer require clients to be ingame (bug 5775) (SystematicMania).
|
||||
- Fixed replace param being respected inconsistently in SetTrieArray (bug 6113).
|
||||
- Fixed crash creating a timer when there are no handles available. (bug 5317) (Peace-Maker).
|
||||
- Fixed crash in ReconnectClient and InactivateClient natives when IServer ptr is null (bug 6122).
|
||||
- Fixed StoreFromAddress and LoadFromAddress continuing with bad values, usually crashing after error (bug 6080).
|
||||
- Fixed compiler bug with multidimensional array variable release (bug 6100).
|
||||
- Changed float comparison operators to return false for NaN (bug 6107).
|
||||
- Added support in spcomp for sp/inc files > 32767 lines (bug 5959).
|
||||
- Fixed FindFlagChar returning '?' for Admin_Custom6.
|
||||
- Fixed AllPluginsLoaded activities happening before SM is loaded.
|
||||
- Deduplicated a number of files used by extensions by moving them to the public directory (bug 5341).
|
||||
- Removed 'state' keyword from compiler (bug 4572) (Ryan "VoiDeD" Stecker).
|
||||
- Removed LogMessageEx definition from logging.inc because it never existed (bug 5897) (Peace-Maker).
|
||||
- Removed native override API (bug 5852).
|
||||
- Call OnLibraryAdded for all available libraries (bug 5925, PR 4).
|
||||
- Made IGameConfig::GetMemSig return value clearer (bug 6081).
|
||||
- Switched StringToInt(Ex) from using strtol to strtoul internally (bug 5939).
|
||||
- Added an spcomp option to print #included files (bug 5997).
|
||||
- Recompiled Regex extension libpcre against v8.32, enabling utf8, unicode props, and jit (bug 5593).
|
||||
- Optimized native calls if statically bound (bug 5842).
|
||||
|
||||
Internal Changes:
|
||||
- Now using new AlliedModders Template Library (AMTL) in many places, https://github.com/alliedmodders/amtl
|
||||
- Ported buildscripts to new AMBuild2 platform, https://github.com/alliedmodders/ambuild
|
||||
- Moved much logic from core to logic binary to reduce file sizes and compile times (bug 5606, bug 5607, bug 5680, bug 5953, PR 12, PR 13).
|
||||
- Refactored the JIT to use a newer, simpler macro assembler. (bug 5827).
|
||||
- Added sourcepawn interpreter (bug 5902).
|
||||
- Added support for compiling spcomp with emscripten.
|
||||
- Rewrite IThreader implementation around new synchronization primitives (bug 5862).
|
||||
- Rewrite DBManager to use the new synchronization primitives (bug 5870).
|
||||
- Overhauled internals of ClientPrefs extension for improved stability (bug 5538).
|
||||
- Changed ShareSys to store C++ native lists more optimally (bug 5852).
|
||||
- Simplified NativeEntry state (bug 5852).
|
||||
- Changed NativeEntry to use Refcounted to manage (bug 5852).
|
||||
- Switched Translator and GameConfigs to hash tables (bug 5878).
|
||||
- Switched numerous subsystems from KTrie to AMTL NameHashSet (bug 5884).
|
||||
- Refactored Trie natives to use AMTL HashMap instead of KTrie (bug 5892).
|
||||
- Removed usages of memtables from many subsystems (bug 5899).
|
||||
- Changed EventHook name storage to use AMTL AString (bug 6188).
|
||||
- Replaced SH List usages in game extensions with AMTL variants (PR 23).
|
||||
- Replaced SourceHook list usages in clientprefs with AMTL (PR 25).
|
||||
- Changed floating-point operations to use SSE when available (bug 5841).
|
||||
- Moved tracker related opcodes entirely to C++.
|
||||
- Statically align the stack at function boundaries (bug 5842).
|
||||
- Removed InfoVars, reassigned DAT from EBP to ESI to preserve C++ stacktraces in JIT code (5844).
|
||||
- Fixed dereferencing potential null pointer in CPlugin::GetProperty (bug 5725).
|
||||
- Fixed memory corruption when parsing natives. (bug 5840).
|
||||
- Fixed some memory errors (bug 5904).
|
||||
- Fixed unaligned memory access in spcomp.
|
||||
- Move versioning to a static library to improve trivial build speed (bug 5997).
|
||||
- Added many missing handle security checks (bug 5595).
|
||||
- Made GetEntityClassname get and cache m_iClassname offset from worldspawn for ents not having it in datadesc (bug 5654).
|
||||
- Cache m_iEFlags offset for datamaps dump instead of getting for each ent (bug 5657).
|
||||
- Fixed mismatched delete [] on thunks in JIT CompData dtor (bug 5639).
|
||||
- Fixed various memory issues. (bug 5766).
|
||||
- Added reference counting and use it for CGameConfig and IDatabase (bug 5876).
|
||||
- Added atomic reference counting and port DBI (bug 5876).
|
||||
- Replaced usages of deprecated Sourcehook Add/Remove macros (bug 5631).
|
||||
- Fixed SDKHooks hook ent validation missing first datatable name (bug 5881).
|
||||
- Fixed case where bots leave server without disconnect notice (hibernation) (PR 20).
|
||||
- Changed FindConVar to utilize convar cache for improved performance (PR 27) (VoiDeD).
|
||||
- Gave define value (of 1) to PLATFORM defs to match the same-name defs in some SDKs (PR 10).
|
||||
- Wrapped ClientPrintf into IGamePlayer (bug 6021).
|
||||
- Consolidated FileExists usage in logic bin (bug 5931).
|
||||
- Removed hardcoded paths to tier0/vstdlib in ICommandLine lookup.
|
||||
- Use updated IServerTools iface on TF2 for getting tempent list and FindEntityByClassname (PR 33).
|
||||
- Added early exit in entity output detour if entity has no classname to prevent crash.
|
||||
- Updated SDKTools entity output functions to use core's GetEntityClassname instead of own (PR 39).
|
||||
- Consolidated SDKTools entity factory lookups.
|
||||
- Changed SDKTools PlayerRunCmd to a global vtable hook to improve performance (bug 6051).
|
||||
- Changed SDKHooks to use global vtable hooks to improve performance (bug 6070).
|
||||
- Added client validation checks to EmitSound SoundsHooks (bug 5873).
|
||||
- Added missing meta results to some pre-hooks in SDKHooks.
|
||||
- Replaced magic numbers for sm_show_activity with named constants (PR 14).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.5.3 [2014-03-22]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated support for CS:GO after multiple breaking game updates.
|
||||
- Updated gamedata support for GoldenEye: Source (Peace-Maker).
|
||||
- Fixed crash on SDKHooks extension load in Alien Swarm (bug 6059).
|
||||
- Fixed memory leak from unmanaged forwards never being freed (bug 6025).
|
||||
- Fixed possible crash when unloading the CStrike extension.
|
||||
- Fixed crash in SDKHooks Reload post-hook (Peace-Maker).
|
||||
- Fixed FakeClientCommandEx always leaking memory (bug 5678).
|
||||
- Fixed extra entity networking occuring with SetEntProp natives on some games.
|
||||
- Fixed being able to nominate same map multiple times (bug 5109).
|
||||
- Fixed spurious FindEntityByClassname error being logged on some games and platforms.
|
||||
- Fixed an Anti-Flood bypass exploit (bug 5394).
|
||||
- Removed part of Addresses gamedata error handling which could cause false errors to be logged (bug 6044).
|
||||
- Fixed mapchooser not resetting nominations count when clearing nominations list (bug 5359).
|
||||
- Improved performances of client convar query handling (bug 6003).
|
||||
|
||||
Developer Changes:
|
||||
- Added GiveAmmo native to SDKTools (bug 6039) (Peace-Maker).
|
||||
- Added SQL_SetCharset native to (re)set charset even after reconnect (bug 5786) (Peace-Maker).
|
||||
- Added support for entity references in SDKHooks natives (bug 6069).
|
||||
- Added support for server passwords to DisplayAskConnectBox stock (bug 5984) (FlaminSarge).
|
||||
- Renamed SortFunc2D parameters to match documentation (bug 6014) (Peace-Maker).
|
||||
- Fixed param order in AddToTopMenu function doc (bug 6035) (Peace-Maker).
|
||||
- Added |any| tag to WritePackCell and ReadPackCell native param/return values (bug 6001).
|
||||
- Updated SDKHook_TakeDamage native for game updates.
|
||||
- Added default infinite value for TF2_AddCondition duration.
|
||||
- Added support for conditions >= 64 in TF2_OnConditionAdded/Removed (bug 5565, bug 5976) (FlaminSarge).
|
||||
- Updated TFCond and TF customkill enum values (bug 6012) (FlaminSarge).
|
||||
- Fixed regression causing incorrect return and inability to block in TF2_OnCalcIsAttackCritical forward.
|
||||
- Fixed TE_* natives operating on incorrect data for some tempents (bug 6072).
|
||||
- Fixed CS_AliasToWeaponID not returning a valid weaponID for cz75a.
|
||||
- Fixed CS_GetWeaponPrice returning incorrect value for M4A1 in CS:GO (bug 6045).
|
||||
- Increased max gamedata byte signature length.
|
||||
- Ported SM build scripts to AMBuild2 (bug 5997).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.5.2 [2013-10-29]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated gamedata support for TF2, CS:S, CS:GO, and HL2:DM.
|
||||
- Fixed crash from regression in SDKTools SetClientListening hook refcounting (bug 5956) (KyleS).
|
||||
- Fixed potential crash when having maps with format characters in name.
|
||||
- Fixed some nextmap issues with long map names.
|
||||
- SDKTools no longer requires gamedata for sm_dump_datamaps on TF2, CS:S, HL2:DM, and DoD:S (bug 5968).
|
||||
|
||||
Developer Changes:
|
||||
- Updated TFCond and TF custom dmg enums.
|
||||
- Updated TF2 critical hit detection logic in TF2_OnCalcIsAttackCritical to handle more cases, including when criticals are disabled (bug 5894).
|
||||
- Fixed GetEngineVersion native returning a bad value when running on MM:S 1.9.x or earlier (bug 5697).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.5.1 [2013-09-10]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated gamedata support for TF2.
|
||||
- Added missing DispatchKeyValue gamedata for HL2 CTF (bug 5114) (peace-maker).
|
||||
- Fixed translations not being loaded if identifier was not two or three characters (fixes Portuguese) (bug 5888).
|
||||
- Fixed runoff voting occurring when receiving the exact number of required votes (bug 5890).
|
||||
- Fixed reserve slot plugin hiding too many slots on Orangebox gamesif SourceTV and/or Replay are present (bug 5499).
|
||||
- Fixed some crashes in TF2 and unexpected behavior in all games with SDKHook_TakeDamage due to uninitialized var.
|
||||
- Fixed attempted triggers from gagged users displaying in chat (bug 5918).
|
||||
- Fixed errors in Italian translation (Oktober).
|
||||
- Added Norwegian translation (checkster).
|
||||
|
||||
Developer Changes:
|
||||
- Added CS_UpdateClientModel native to CStrike extension for CS:S and CS:GO (bug 5905) (Drifter).
|
||||
- Fixed setting weapon param in SDKHook_TakeDamage overwriting attacker instead of setting weapon (bug 5911) (KyleS)
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.5.0 [2013-08-25]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for Counter-Strike: Global Offensive (bug 5299, bug 5579).
|
||||
- Split CS:S, TF2, DoD:S, HL2:DM, and ND to separate binaries (bug 5370, bug 5813).
|
||||
- Added support for runoff voting in mapchooser (bug 4218).
|
||||
- Added option to require Steam validation before granting admin access (bug 4837) (VoiDeD).
|
||||
- Added localization support for many more core and base plugin messages (bug 5120, bug 5146).
|
||||
- Added the ability to override RegConsoleCommand-created commands (bug 5199).
|
||||
- Added support for "fuzzy" (partial) map names in map-related natives and cmds for L4D and later (bug 5599).
|
||||
- Updated Reserved Slots to use max humans as max count (bug 5444).
|
||||
- Added support for custom maxitems on radio menus (bug 5371).
|
||||
- Improved console config editing (bug 5470).
|
||||
- Increased map name buffer sizes in mapchooser to better account for nested maps (bug 5609) (Peace-Maker).
|
||||
- Fixed JIT conflicts with SELinux (bug 5581).
|
||||
- Added logged error when PlayerRunCommand offset lookup fails (bug 5535) (GoD-Tony).
|
||||
- Fixed double print when sending psay to self (bug 5649) (Peace-Maker).
|
||||
- Fixed check against uninitialized string in extension loader (bug 5546) (KyleS).
|
||||
- Fixed possible runtime errors in basetriggers for not-ingame clients (bug 5191) (Peace-Maker).
|
||||
- Check all possible mapcycle paths on newer orangebox games (bug 5719).
|
||||
- Fixed ReadMapList not seeing maps in all valve search paths (bug 5715) (VoiDeD).
|
||||
- Fixed typo in too-many-params native error message (Peace-Maker).
|
||||
- Fixed various issues in clientprefs (bug 5538) (KyleS).
|
||||
- Removed debug printout from PerformGravity (bug 5679) (KyleS).
|
||||
- Fixed broken translating in some plugins and natives (bug 5612) (KyleS).
|
||||
- Fixed issues with COMMAND_FILTER_NO_BOTS and @bots multi-target.
|
||||
- Fixed crash in SDKHooks when throwing bad ent type error on logical ent (KyleS).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added support for CS:GO to the CStrike extension (bug 5299) (Drifter).
|
||||
- Added support for new protobuf usermessages used in newer games (bug 5579, bug 5588, bug 5590, bug 5633).
|
||||
- Added latest SDKHooks version as first-party extension.
|
||||
- Updated SQLite to version 3.7.15.1 (bug 5235).
|
||||
- Added natives for changing team score and mvp stars on CSS/CSGO (bug 5295) (Drifter).
|
||||
- Added global pre and post forwards for client chat (bug 5394) (KyleS).
|
||||
- Added TF2_CanPlayerTeleport forward to the TF2 game extension (bug 5283) (VoiDeD).
|
||||
- Added GetEntityAddress native (bug 5269) (ProdigySim).
|
||||
- Added more parameters to PlayerRunCommand forward (bug 5346) (GoD-Tony).
|
||||
- Added forwards to basecomm plugin (bug 5466) (Drifter).
|
||||
- Added symbol lookup support to gamedata on Windows (bug 5511) (GoD-Tony).
|
||||
- Exposed GetLanguageInfo in ITranslator interface (bug 5249) (VoiDeD).
|
||||
- Increase maximum .sp line length to 4095 characters. (bug 5347) (theY4Kman).
|
||||
- Improved netprop dump output (bug 5471).
|
||||
- Added int64 typename to netprop dumps (bug 5655).
|
||||
- Added GetMaxHumanPlayers native exposing IServerGameClients func (bug 5551).
|
||||
- Added WeaponIDToAlias native to CStrike extension (bug 5460) (KyleS).
|
||||
- Fixed OnLibraryAdded/Removed not being called in all plugins (bug 5431).
|
||||
- Made thread worker processing limits configurable at runtime (bug 5326).
|
||||
- Added support in TF2 ext for detection of player conds >= 64 (bug 5565).
|
||||
- Updated button defines in entity_prop_stocks (bug 5564).
|
||||
- Added GetPlayerResourceEntity to SDKTools to replace old, semi-broken TF2-only version (bug 5491).
|
||||
- Exposed third parameter of TF2's AddCond in TF2_AddCondition (bug 5641) (FlaminSarge).
|
||||
- Added GetSteamAccountID function to IPlayerHelpers and native for sp (bug 5548) (KyleS).
|
||||
- Added ISDKHooks interface with entity listeners (bug 5602) (GoD-Tony).
|
||||
- Added file upload support to webternet extension.
|
||||
- Added more alternative names for TFClass_Heavy (bug 5338) (Afronanny).
|
||||
- Throw error instead of crash when calling SetTeamScore between maps (bug 5718) (KyleS).
|
||||
- Fixed clients not being marked as in kick queue in some cases (bug 5746) (SystematicMania).
|
||||
- Made compile.sh set working dir to own dir (bug 5710) (KyleS).
|
||||
- Added CS_IsValidWeaponID native and validity checks to other natives (bug 5566) (Drifter).
|
||||
- Numerous code documentation fixups (bug 5720) (Tsunami).
|
||||
- Fixed cmd listener callback return behavior to match func doc (bug 5882).
|
||||
|
||||
Internal Changes:
|
||||
|
||||
- Fixed handle misuse in clientprefs plugin (bug 5805) (KyleS).
|
||||
- Removed call to getchar() in debug build of compiler (bug 5626) (KyleS).
|
||||
- Fixed instability issues with cloned handles (bug 5245, bug 5240) (KyleS).
|
||||
- Changed extension unload order to avoid exposing finalization window (bug 5556) (KyleS).
|
||||
- Call OnPluginEnd before finalizer hooks have run (bug 4519).
|
||||
- Fixed potential for reading out of library bounds in MemoryUtils::FindPattern.
|
||||
- Fixed typo in TF2 ext asm.c causing accidental assignment instead of compare.
|
||||
- Overhauled versioning information (bug 5453).
|
||||
- Changed from RemoveEdict to using the Kill input for TF2_RemoveWeapon.
|
||||
- Fixed accidental assignment in each of SDKTools and sp compiler (bug 5745) (KyleS).
|
||||
- Fixed potential deadlock in HandleSystem::TryAndFreeSomeHandles (bug 5665) (KyleS).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.4.7 [2013-02-06]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.7_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM).
|
||||
- Updated gamedata for Left 4 Dead 2, Nuclear Dawn, No More Room in Hell, Zombie Panic Source, CSPromod, GoldenEye Source, Synergy, The Hidden, and PVKII.
|
||||
- Added system to block malware or illegal plugins (bug 5289).
|
||||
- Fixed a potential crash when a bad entity index is passed to certain functions (bug 5539) (KyleS).
|
||||
- Added an error message for when auto plugin configs fail to be created due to write error (bug 5465) (Drifter).
|
||||
- Fixed an issue where a malformed plugin could cause crashes (bug 5478).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new values to the TFCond TF2 conditions enum (bug 5537) (FlaminSarge).
|
||||
- Updated TFHoliday TF2 holidays enum (bug 5526) (Powerlord).
|
||||
- Fixed regression in SourceMod 1.3.0 causing GetEntPropEnt, GetEntDataEnt2, and GameRules_GetPropEnt to possibly return stale (incorrect) entity indexes in place of -1.
|
||||
- Added support for < 32-bit unsigned sign extension to GameRules_GetProp lookup (already in GetEntProp since SM 1.4.0).
|
||||
- Fixed < 32-bit unsigned sign extension in GetEntProp not being applied for array prop elements (bug 5591).
|
||||
- Fixed value size auto-detection in GetEntProp and GameRules_GetProp for ep2v's new SPROP_VARINT sendprops.
|
||||
- Fixed Sort_Random sort type not including first value in array sorting functions (bug 4292) (Peace-Maker).
|
||||
- Fixed GameRules_SetPropVector writing data to unexpected addresses instead of to the gamerules proxy entity (bug 5592) (ProdigySim).
|
||||
- Fixed VoteMenuToAll stock adding bots to list (bug 5253 (VoiDeD).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.4.6 [2012-09-04]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.6_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Fixed extraneous errors resulting from a bug in 1.4.5.
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
SourceMod 1.4.5 [2012-09-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.5_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated Nuclear Dawn, Dino D-Day, and Zombie Panic gamedata.
|
||||
- Added compatibility for running on Metamod:Source 1.9.0.
|
||||
- Fixed very minor memory leaks in CStrike extension (bug 5456) (KyleS).
|
||||
- Fixed crash from plugins accessing netprops too early (bug 5297) (KyleS).
|
||||
- Fixed crash from plugins trying to access nested datadesc members (bug 5446).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new TF2 weapon and custom dmg defines.
|
||||
- Added new TF2 TFHoliday value (bug 5436) (Powerlord).
|
||||
- Fixed IClientListener::InterceptClientConnect not being able to properly block connections (bug 5461) (PimpinJuice).
|
||||
- Fixed PrepSDKCall_SetSignature native not working with symbol names on L4D2 linux (bug 5440).
|
||||
- Fixed resolution of GetProfilerTime native on non-Windows platforms.
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.4 [2012-07-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.4_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated Nuclear Dawn gamedata.
|
||||
- Fixed a crash that could occur when selecting an option on a clientprefs prefab menu (bug 5374).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new TF2 weapon and custom dmg defines.
|
||||
- Added new TF2 TFHoliday value (bug 5364) (Powerlord).
|
||||
- Updated sample extension to properly fill ninvoke with INativeInvoker ptr (bug 5340) (Afronanny).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.3 [2012-06-09]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Made clientprefs attempt to reconnect to the database on map change (bug 4745).
|
||||
- Log functions now respect sv_logecho (bug 5135).
|
||||
- Fixed client console vote output (bug 5290, bug 5205) (FlaminSarge).
|
||||
- Fixed error when reloading dependant plugins using aliased natives (bug 5302).
|
||||
- Fixed intermittent crash when looking for an invalid signature (bug 5301).
|
||||
- Fixed possible crash when reloading a plugin with an invalid binary (bug 5288).
|
||||
- Exposed extensions list to clients (bug 5221) (VoiDeD).
|
||||
- Fixed intermittent crashes in clientprefs (bug 4660).
|
||||
- Fixed crash when passing an invalid entity reference to ReferenceToEntity (bug 5330).
|
||||
- Fixed cstrike extension crash on shutdown (bug 5328).
|
||||
- Lowered threading API think time to 20ms, making threaded MySQL queries complete faster (bug 4733).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed client serials not being unique on Windows (bug 5285).
|
||||
- Fixed broken SourceTV detection on L4D1 (bug 5216).
|
||||
- Fixed Float negation operator (bug 5292).
|
||||
- Updated TF2 condition defines (bug 5259) (FlaminSarge).
|
||||
- Adding missing SetMenuNoVoteButton native declaration (bug 4522) (GoD-Tony).
|
||||
- Fixed erroneous const-qualification of name param of GetAdminUsername (bug 5267).
|
||||
- Added GetGameTickCount native (bug 5209) (GoD-Tony).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.2 [2011-04-13]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Fixed regression in SourceMod 1.4.0 causing SM to cause load errors on The Ship (bug 5216).
|
||||
- Fixed toggling and player lag issues with sm_drug command (bugs 5217, 5218) (FlaminSarge).
|
||||
|
||||
Developer Changes:
|
||||
- Updated TF2-specific defines and enums (bug 5194).
|
||||
- Fixed StoreToAddress always writing 32 bits and throwing an error (bug 5248) (ProdigySim).
|
||||
- Fixed crash with StoreToAddress if memory wasn't writable (bug 5252) (Dr!fter).
|
||||
- Fixed return value of VoteMenuToAll (bug 5254) (VoiDeD).
|
||||
- Fixed bug in command lower-casing API guarantee
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.1 [2011-12-07]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Added gamedata for Adrenaline Gamer 2 and No More Room in Hell.
|
||||
- Fixed "not connected" error in reserve slots plugin (bug 5158) (ostrel).
|
||||
- Fixed ff trigger output printing to all in triggerer's language (rather than viewer's language) (bug 5161).
|
||||
- Fixed typo in one of basebans ban reasons (bug 5188).
|
||||
- Fixed formatting error in Swedish "Vote Count" phrase (bug 5174).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed sp MaxClients not being updated on map changes after load (bug 5160).
|
||||
- Removed GLIBC_2.7 dependency from spcomp.
|
||||
- Increased buffer for sm_rcon command to fit larger responses (bug 5169).
|
||||
- BaseComm now properly registers a library allowing it to be required by other plugins (bug 5156).
|
||||
- Fixed TFHoliday enum values (bug 5155).
|
||||
- Updated TF2_OnIsHolidayActive ret behavior to match doc (bug 5155).
|
||||
- Added new TF2 deathflag and dmg custom defines (bug 5157).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.0 [2011-10-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for Max OS X (bug 4392).
|
||||
- Added support for Bloody Good Time (bug 4780).
|
||||
- Added support for E.Y.E Divine Cybermancy (bug 5035).
|
||||
- Added gamedata for Nuclear Dawn.
|
||||
- Added gamedata for International Online Soccer: Source (bug 5019).
|
||||
- Added gamedata for Half-Life 2 Capture the Flag (bug 5114).
|
||||
- Updated mapchooser and other base plugins with Nuclear Dawn specific fixes (bug 5117).
|
||||
- Fixed ServerLang value not being read properly on startup (bug 4675).
|
||||
- Added support for aliases in languages.cfg (bug 4858).
|
||||
- Added output display to sm_rcon command (bug 5018).
|
||||
- Flood protection bypass access can now be overridden with command name sm_flood_access (bug 4584).
|
||||
- Added a reset argument to sm cvars command to revset cvar values to default (bug 5043).
|
||||
- Fixed incorrect language identifiers for Chinese (both Trad. and Simplified) and Brazilian Portuguese not matching cl_language values (bug 5067).
|
||||
- Added translation support for Bulgarian (bg).
|
||||
- Fixed incorrect number of slots being hidden for reserve with sm_hideslots on Source 2009 with SourceTV or replay (bug 5094).
|
||||
- sm_hideslots changes now take effect immediately instead of waiting until a client joins or leaves (bug 5094).
|
||||
- Fixed sv_visiblemaxplayers getting stuck at previous max clients in some cases with reserves and SourceTV or replay (bug 5094).
|
||||
- Removed error logging if an optional extension is not found (bug 5112).
|
||||
- Fixed bots with semicolon in name being unkickable (bug 5120).
|
||||
- Changed strings in ice-related funcommands to be translatable (bug 4540).
|
||||
- Changed Bintools extension to use a single build for every engine (bug 4548).
|
||||
|
||||
Developer Changes:
|
||||
- Provided native interface for basecomm (bug 2594).
|
||||
- Client language detection is too late. (bug 3714) (Tony A. "GoD-Tony").
|
||||
- Added ServerCommandEx native to execute server command and retrieve output (bug 3873).
|
||||
- Added ability to update clientprefs cookies values on clients not currently connected (bug 3882) (databomb).
|
||||
- Added library "matchmaking_ds" support to gamedata lookups (bug 4158).
|
||||
- Rooted menu handles to callbacks (bug 4353).
|
||||
- Fixed corner cases with ExplodeString (bug 4629). (Michael "LumiStance").
|
||||
- Fixed return omission with else-after-return (bug 4852).
|
||||
- Added OnConditionAdded and OnConditionRemoved forwards to TF2 extension (bug 4851).
|
||||
- Added new natives and forward to the cstrike extension (bug 4732, bug 4985) (Dr!fter).
|
||||
- Added WaitingForPlayers forwards to the TF2 extension (bug 4704) (CrimsonGT).
|
||||
- Updated and added more TF2 condition, weapon, and damagecustom defines (multiple bug#s).
|
||||
- Fixed TF2_RemoveCondition not always removing conditions (bug 4981).
|
||||
- Fixed MaxClients not being updated correctly in some places with SourceTV or replay active (bug 4986).
|
||||
- Fixed some vars not being marked for init on first compile pass (bug 4643).
|
||||
- Increased symbol name limit to 63 characters (bug 4564) (javalia).
|
||||
- Fixed crash when dynamic arrays run out of memory (bug 4632).
|
||||
- Fixed a crash that could happen from looking up out-of-bounds edict or entity indexes (bug 5080).
|
||||
- Fixed client serials not getting cleared on disconnect (bug 5121).
|
||||
- Added error on declaring arrays that the compiler is too buggy to handle (bug 4977).
|
||||
- Removed reliance on gamedata for multiple SDKTools functions in ep2 and later (bug 4899).
|
||||
- Added InvalidateClient and ReconnectClient natives to SDKTools (bug 4931) (Brian "Afronanny" Simon).
|
||||
- Added ability to lookup and set values on the gamerules class (bug 4983.
|
||||
- BaseComm now uses AddCommandListener for chat hooks (bug 4991).
|
||||
- Fixed shutdown bug in SDKTools (bug 5063).
|
||||
- Fixed MM-enabled extensions continuing to load after failing MM attach (bug 5042).
|
||||
- Added GetDistGainFromSoundLevel native to SDKTools (bug 5066) (javalia).
|
||||
- Added CheckAccess native to check an AdminId's command access (bug 5083).
|
||||
- Fixed GetEntProp not sign-extending unsigned values less than 32 bits (bug 5105).
|
||||
- Fixed crashing when calling CreateEntityByName or CreateFakeClient when no map is running (now errors) (bug 5119).
|
||||
- Fixed erring in kick function (e. bad translation) causing client to become unkickable until disconnect (bug 5120).
|
||||
- Fixed KickClientEx not immediately kicking client if client was in kick queue (bug 5120).
|
||||
- Added IsClientSourceTV and IsClientReplay natives (bug 5124).
|
||||
- Added support for getting and setting individual array elements with Get/Set EntProp functions (bug 4160).
|
||||
- Added support for threaded query handles to SQL_GetInsertId and SQL_GetAffectedRows (bug 4699) (Nephyrin).
|
||||
- Added a GetGameRules function to ISDKTools for extensions to easily get the GameRules class pointer (bug 4707).
|
||||
- Added GetMessageName to IUserMessages (bug 4573) (Zach "theY4Kman" Kanzler)
|
||||
- Added HintTextMsg to IGameHelpers (bug 4950).
|
||||
- Added ProcessTargetString simple filter API (bug 4404).
|
||||
- Moved much functionality from core bins to logic bin (bug 4406, bug 4402).
|
||||
- Fixed bogus asserts in sp compiler (bug 4486, bug 4487).
|
||||
- Greatly improved sp compiler performance (~5x overall speedup) (bug 3820, bug 4493, bug 4495).
|
||||
- Changed entity output detours to use CDetour (bug 4416).
|
||||
- Enhanced nominations API (bug 4677) (CrimsonGT).
|
||||
- Added Linux support for profiling natives (bug 4927).
|
||||
- Added a new ValveCallType that allows for arbitrary |this| parameters, as well as associated features in gamedata and for reading/writing memory (bug 3520) (Downtown1).
|
||||
- Updated TF2 extension to handle Valve's changes to the "holiday" system (bug 5150).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.3.8 [2011-06-23]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.8_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Garry's Mod, Zombie Panic, and Dino D-Day.
|
||||
- Added gamedata for Eternal Silence.
|
||||
- Fixed libgcc_s.so.1 load error present on some systems (bug 4876).
|
||||
- Handle leak notices now print to error log (in addition fatal log) (bug 4929).
|
||||
- Translator now properly falls back on bad server language (bug 4861).
|
||||
- Fixed invalid client errors from bad MaxClients value when SourceTV is late-loaded (bug 4881).
|
||||
- Fixed crash on plugin unload when two commands exist with same name, different casing (bug 4698).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Updated TF2 condition defines (bug 4916).
|
||||
- Fixed var names and docs for TF2_MakeBleed native (bug 4928).
|
||||
- Removed compiler double include check (bug 4863).
|
||||
- Fixed plugin compile errors when using GetEntityClassname (bug 4798).
|
||||
|
||||
---------------------------
|
||||
|
||||
SourceMod 1.3.7 [2011-04-15]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.7_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Zombie Panic, CS ProMod, Empires, and GoldenEye: Source.
|
||||
- Added gamedata for Dino D-Day.
|
||||
- Fix precedence of voice mute flag versus specific client overrides (bug 4826).
|
||||
- Fix mistaken unhooking of voice hooks (bug 4804).
|
||||
- Fixed graphical glitches with funcommands effects in L4D1 (bug 3486).
|
||||
- Fixed bug in nominations that could cause "Unknown command" error (bug 4797).
|
||||
- Removed tv_enable hook to fix rare max client count issue (bug 4791).
|
||||
- Added missing unhooking of ClientConnect in PlayerManager (bug 4749).
|
||||
- Fixed sm_rtv printing "unknown command" (bug 4730).
|
||||
- Fixed voting crash when client console, chat, and SourceTV are enabled (bug 4676).
|
||||
- Fixed CDetour crash in TF2 extension when last plugin using forward is unloaded (bug 4713).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- SetEntProp now marks edict state as changed (bug 4855).
|
||||
- Added GetEntityClassname stock (bug 4798).
|
||||
- Fix compiler hanging when #including a directory (bug 4822).
|
||||
- Added GetEntityFlags and SetEntityFlags natives for better cross-engine compatibility. (bug 4809).
|
||||
- Fixed ClientPrefs natives not being marked optional when REQUIRE_EXTENSIONS not defined (bug 4839).
|
||||
- Changed some instances of LogMessage to LogAction (bug 4649).
|
||||
- Added some new language natives (bug 4613).
|
||||
- Fixed SetTeamScore not updating score on client (bug 2736).
|
||||
- Raised MAXPLAYERS from 64 to 65 (bug 4490).
|
||||
- Added and updated many TF2-specific defines in tf2.inc and tf2_stocks.inc.
|
||||
- Fixed TF2_GetPlayerConditionFlags no longer necessarily returning all set flags (bug 4726).
|
||||
- Fixed profiler flush not clearing, added 'report' and 'clear' (bug 4674).
|
||||
- Fixed GetPlayerDecalFile crash on L4D and L4D2 (bug 4729).
|
||||
- Fixed TF2_OnGetHoliday detour no longer firing under all circumstances (bug 4700).
|
||||
- Added TF2_IsPlayerInDuel native to TF2 extension (bug 4695).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.6 [2010-10-31]
|
||||
|
||||
@@ -132,13 +132,5 @@
|
||||
* passed. You can disable this feature by setting the value to "0".
|
||||
*/
|
||||
"SlowScriptTimeout" "8"
|
||||
|
||||
/**
|
||||
* Disable the SourcePawn just-in-time compiler. This is intended for C++ developers using
|
||||
* debugging tools and finding it difficult to inspect JIT stack frames. The interpreter
|
||||
* is not as well-tested as the JIT and will make script execution roughly 10X slower, so
|
||||
* it is not intended for general purpose use.
|
||||
*/
|
||||
"DisableJIT" "no"
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,6 @@ run.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
||||
'comma-delimited list of engine names (default: %default)')
|
||||
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||
default=False, help='Dump and upload breakpad symbols')
|
||||
run.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
||||
default=False, help='Disable the auto versioning script')
|
||||
run.Configure()
|
||||
|
||||
+6
-8
@@ -9,7 +9,6 @@ project.sources += [
|
||||
'sm_stringutil.cpp',
|
||||
'MenuVoting.cpp',
|
||||
'smn_events.cpp',
|
||||
'smn_menus.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_hooks.cpp',
|
||||
'smn_nextmap.cpp',
|
||||
@@ -31,7 +30,6 @@ project.sources += [
|
||||
'smn_console.cpp',
|
||||
'UserMessages.cpp',
|
||||
'MenuManager.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_hudtext.cpp',
|
||||
'smn_usermsgs.cpp',
|
||||
'MenuStyle_Base.cpp',
|
||||
@@ -41,7 +39,9 @@ project.sources += [
|
||||
'MenuStyle_Radio.cpp',
|
||||
'sm_autonatives.cpp',
|
||||
'sm_srvcmds.cpp',
|
||||
'ConsoleDetours.cpp'
|
||||
'ConsoleDetours.cpp',
|
||||
'vprof_tool.cpp',
|
||||
'smn_commandline.cpp',
|
||||
]
|
||||
|
||||
for sdk_name in SM.sdks:
|
||||
@@ -52,17 +52,14 @@ for sdk_name in SM.sdks:
|
||||
compiler = binary.compiler
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
# Protobuf 2.3 headers have some signed/unsigned compares. I believe that it's fixed in later versions, but Valve.
|
||||
if compiler.cxx.behavior == 'gcc':
|
||||
compiler.cflags += ['-Wno-sign-compare']
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.3.0', 'src'),
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
elif sdk.name == 'dota':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.4.1', 'src'),
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.6.1', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
||||
@@ -109,6 +106,7 @@ for sdk_name in SM.sdks:
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'network_connection.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
|
||||
|
||||
+84
-10
@@ -76,9 +76,12 @@ void CDataPack::ResetSize()
|
||||
|
||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + size);
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + size);
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
|
||||
*(char *)m_curptr = Raw;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = size;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
@@ -88,14 +91,17 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
}
|
||||
|
||||
m_curptr += size;
|
||||
m_size += sizeof(size_t) + size;
|
||||
m_size += sizeof(char) + sizeof(size_t) + size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void CDataPack::PackCell(cell_t cell)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + sizeof(cell_t));
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
*(char *)m_curptr = Cell;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
@@ -103,12 +109,15 @@ void CDataPack::PackCell(cell_t cell)
|
||||
*(cell_t *)m_curptr = cell;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
m_size += sizeof(size_t) + sizeof(cell_t);
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
void CDataPack::PackFloat(float val)
|
||||
{
|
||||
CheckSize(sizeof(size_t) + sizeof(float));
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
|
||||
|
||||
*(char *)m_curptr = Float;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(float);
|
||||
m_curptr += sizeof(size_t);
|
||||
@@ -116,15 +125,18 @@ void CDataPack::PackFloat(float val)
|
||||
*(float *)m_curptr = val;
|
||||
m_curptr += sizeof(float);
|
||||
|
||||
m_size += sizeof(size_t) + sizeof(float);
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
|
||||
}
|
||||
|
||||
void CDataPack::PackString(const char *string)
|
||||
{
|
||||
size_t len = strlen(string);
|
||||
size_t maxsize = sizeof(size_t) + len + 1;
|
||||
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
|
||||
CheckSize(maxsize);
|
||||
|
||||
*(char *)m_curptr = String;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
// Pack the string length first for buffer overrun checking.
|
||||
*(size_t *)m_curptr = len;
|
||||
m_curptr += sizeof(size_t);
|
||||
@@ -160,10 +172,16 @@ bool CDataPack::SetPosition(size_t pos) const
|
||||
|
||||
cell_t CDataPack::ReadCell() const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Cell)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
@@ -178,10 +196,16 @@ cell_t CDataPack::ReadCell() const
|
||||
|
||||
float CDataPack::ReadFloat() const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t) + sizeof(float)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Float)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
||||
{
|
||||
return 0;
|
||||
@@ -201,10 +225,15 @@ bool CDataPack::IsReadable(size_t bytes) const
|
||||
|
||||
const char *CDataPack::ReadString(size_t *len) const
|
||||
{
|
||||
if (!IsReadable(sizeof(size_t)))
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != String)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
size_t real_len = *(size_t *)m_curptr;
|
||||
|
||||
@@ -237,6 +266,11 @@ void *CDataPack::ReadMemory(size_t *size) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Raw)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
size_t bytecount = *(size_t *)m_curptr;
|
||||
m_curptr += sizeof(size_t);
|
||||
@@ -257,3 +291,43 @@ void *CDataPack::ReadMemory(size_t *size) const
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void CDataPack::PackFunction(cell_t function)
|
||||
{
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
*(char *)m_curptr = Function;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(cell_t *)m_curptr = function;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
cell_t CDataPack::ReadFunction() const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Function)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
||||
m_curptr += sizeof(cell_t);
|
||||
return val;
|
||||
}
|
||||
@@ -51,12 +51,14 @@ public: //IDataReader
|
||||
const char *ReadString(size_t *len) const;
|
||||
void *GetMemory() const;
|
||||
void *ReadMemory(size_t *size) const;
|
||||
cell_t ReadFunction() const;
|
||||
public: //IDataPack
|
||||
void ResetSize();
|
||||
void PackCell(cell_t cell);
|
||||
void PackFloat(float val);
|
||||
void PackString(const char *string);
|
||||
size_t CreateMemory(size_t size, void **addr);
|
||||
void PackFunction(cell_t function);
|
||||
public:
|
||||
void Initialize();
|
||||
private:
|
||||
@@ -66,6 +68,14 @@ private:
|
||||
mutable char *m_curptr;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
|
||||
enum DataPackType {
|
||||
Raw,
|
||||
Cell,
|
||||
Float,
|
||||
String,
|
||||
Function
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
|
||||
@@ -383,7 +383,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
{
|
||||
if (!m_CmdGrps.add(i, group))
|
||||
return false;
|
||||
i->value = NoAddRef(new CommandGroup());
|
||||
i->value = new CommandGroup();
|
||||
}
|
||||
Ref<CommandGroup> cmdgroup = i->value;
|
||||
|
||||
|
||||
+12
-2
@@ -648,8 +648,11 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
|
||||
return InvalidQueryCvarCookie;
|
||||
}
|
||||
|
||||
ConVarQuery query = {cookie, pCallback, (cell_t)hndl, IndexOfEdict(pPlayer)};
|
||||
m_ConVarQueries.push_back(query);
|
||||
if (pCallback != NULL)
|
||||
{
|
||||
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||
m_ConVarQueries.push_back(query);
|
||||
}
|
||||
#endif
|
||||
|
||||
return cookie;
|
||||
@@ -753,6 +756,13 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIn
|
||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
#endif // SE_DOTA
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
IPluginFunction *pCallback = NULL;
|
||||
cell_t value = 0;
|
||||
List<ConVarQuery>::iterator iter;
|
||||
|
||||
@@ -195,7 +195,7 @@ class GenericCommandHooker : public IConCommandLinkListener
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
|
||||
if (dispatch.thisptroffs < 0)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine ConCommand layout");
|
||||
logger->LogError("Command filter could not determine ConCommand layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ public:
|
||||
|
||||
if (!vtables.size())
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find any cvars!");
|
||||
logger->LogError("Command filter could not find any cvars!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -262,7 +262,7 @@ void CoreConfig::Initialize()
|
||||
{
|
||||
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
|
||||
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 : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
if (err == ConfigResult_Reject)
|
||||
{
|
||||
/* 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;
|
||||
@@ -469,7 +469,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||
logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||
return can_create;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||
int EventManager::GetEventDebugID()
|
||||
{
|
||||
return EVENT_DEBUG_ID_INIT;
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ public: // IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public: // IGameEventListener2
|
||||
void FireGameEvent(IGameEvent *pEvent);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||
int GetEventDebugID();
|
||||
#endif
|
||||
public:
|
||||
|
||||
+40
-18
@@ -153,6 +153,18 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
|
||||
|
||||
void CHalfLife2::InitLogicalEntData()
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_TF2 \
|
||||
|| SOURCE_ENGINE == SE_DODS \
|
||||
|| SOURCE_ENGINE == SE_HL2DM \
|
||||
|| SOURCE_ENGINE == SE_CSS \
|
||||
|| SOURCE_ENGINE == SE_SDK2013
|
||||
|
||||
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
|
||||
{
|
||||
g_EntList = servertools->GetEntityList();
|
||||
}
|
||||
#endif
|
||||
|
||||
char *addr = NULL;
|
||||
|
||||
/*
|
||||
@@ -162,21 +174,24 @@ void CHalfLife2::InitLogicalEntData()
|
||||
* If symbols aren't present (Windows or stripped Linux/Mac),
|
||||
* attempt find via LevelShutdown + offset
|
||||
*/
|
||||
if (g_pGameConf->GetMemSig("gEntList", (void **)&addr))
|
||||
if (!g_EntList)
|
||||
{
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
if (!addr)
|
||||
if (g_pGameConf->GetMemSig("gEntList", (void **) &addr))
|
||||
{
|
||||
// Key exists so notify if lookup fails, but try other method.
|
||||
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
g_EntList = reinterpret_cast<void *>(addr);
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
}
|
||||
if (!addr)
|
||||
{
|
||||
// Key exists so notify if lookup fails, but try other method.
|
||||
logger->LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
g_EntList = reinterpret_cast<void *>(addr);
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_EntList)
|
||||
@@ -186,7 +201,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
int offset;
|
||||
if (!g_pGameConf->GetOffset("gEntList", &offset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
logger->LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,7 +213,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
// If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well
|
||||
if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
logger->LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
g_EntList = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -211,7 +226,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
|
||||
if (!g_EntList && !g_pEntInfoList)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
logger->LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -219,13 +234,13 @@ void CHalfLife2::InitLogicalEntData()
|
||||
void CHalfLife2::InitCommandLine()
|
||||
{
|
||||
char error[256];
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
if (!is_original_engine)
|
||||
{
|
||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
|
||||
if (lib == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not load %s: %s", TIER0_NAME, error);
|
||||
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,11 +253,12 @@ void CHalfLife2::InitCommandLine()
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
|
||||
if (lib == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
||||
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -251,7 +267,7 @@ void CHalfLife2::InitCommandLine()
|
||||
|
||||
if (m_pGetCommandLine == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not locate any command line functionality");
|
||||
logger->LogError("Could not locate any command line functionality");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1170,6 +1186,12 @@ const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
|
||||
if (offset == -1)
|
||||
{
|
||||
CBaseEntity *pGetterEnt = ReferenceToEntity(0);
|
||||
if (pGetterEnt == NULL)
|
||||
{
|
||||
// If we don't have a world entity yet, we'll have to rely on the given entity
|
||||
pGetterEnt = pEntity;
|
||||
}
|
||||
|
||||
datamap_t *pMap = GetDataMap(pGetterEnt);
|
||||
|
||||
sm_datatable_info_t info;
|
||||
|
||||
+5
-515
@@ -39,61 +39,12 @@
|
||||
#include "logic_bridge.h"
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
Logger g_Logger;
|
||||
bool g_in_game_log_hook = false;
|
||||
|
||||
static LoggerCore g_LoggerCore;
|
||||
|
||||
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
|
||||
|
||||
/**
|
||||
* :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;
|
||||
}
|
||||
|
||||
static void HookLogPrint(const char *message)
|
||||
{
|
||||
g_in_game_log_hook = true;
|
||||
@@ -104,477 +55,16 @@ static void HookLogPrint(const char *message)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModStartup(bool late)
|
||||
void LoggerCore::OnSourceModStartup(bool late)
|
||||
{
|
||||
InitLogger(m_Mode);
|
||||
|
||||
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModAllShutdown()
|
||||
void LoggerCore::OnSourceModAllShutdown()
|
||||
{
|
||||
CloseLogger();
|
||||
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||
}
|
||||
|
||||
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, SOURCEMOD_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (!m_NrmFileName.empty())
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogMessage("Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_NrmFileName.clear();
|
||||
}
|
||||
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogError("Error log file session closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_ErrFileName.clear();
|
||||
}
|
||||
|
||||
void Logger::InitLogger(LoggingMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
m_Active = m_InitialState;
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_ErrCurDay = 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;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
|
||||
if (!sv_logecho || sv_logecho->GetBool())
|
||||
{
|
||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[3072];
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogMessageEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Mode == LoggingMode_Game)
|
||||
{
|
||||
_PrintToGameLog(vafmt, 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_NrmCurDay != 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_NrmCurDay = curtime->tm_mday;
|
||||
m_DailyPrintHdr = true;
|
||||
}
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
if (m_DailyPrintHdr)
|
||||
{
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
} else {
|
||||
goto print_error;
|
||||
}
|
||||
|
||||
return;
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (curtime->tm_mday != m_ErrCurDay)
|
||||
{
|
||||
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_ErrCurDay = curtime->tm_mday;
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
||||
if (fp)
|
||||
{
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[255];
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogFatalEx(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||
{
|
||||
/* :TODO: make this print all pretty-like
|
||||
* In fact, the pretty log printing function should be abstracted.
|
||||
* It's already implemented twice which is bad.
|
||||
*/
|
||||
|
||||
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;
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
m_Active = false;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
bool g_in_game_log_hook = false;
|
||||
|
||||
void Engine_LogPrintWrapper(const char *msg)
|
||||
{
|
||||
if (g_in_game_log_hook)
|
||||
|
||||
+1
-64
@@ -38,76 +38,13 @@
|
||||
|
||||
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
|
||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllShutdown();
|
||||
void OnSourceModLevelChange(const char *mapName);
|
||||
public:
|
||||
void InitLogger(LoggingMode mode);
|
||||
void CloseLogger();
|
||||
void EnableLogging();
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogMessageEx(const char *msg, va_list ap);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogFatalEx(const char *msg, va_list ap);
|
||||
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_NrmCurDay;
|
||||
int m_ErrCurDay;
|
||||
bool m_ErrMapStart;
|
||||
bool m_Active;
|
||||
bool m_DelayedStart;
|
||||
bool m_DailyPrintHdr;
|
||||
bool m_InitialState;
|
||||
};
|
||||
|
||||
void Engine_LogPrintWrapper(const char *msg);
|
||||
|
||||
extern bool g_in_game_log_hook;
|
||||
extern Logger g_Logger;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
|
||||
@@ -261,15 +261,6 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
|
||||
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)
|
||||
{
|
||||
m_FreeDisplays.push(display);
|
||||
@@ -336,11 +327,12 @@ void CRadioDisplay::Reset()
|
||||
keys = 0;
|
||||
}
|
||||
|
||||
void CRadioDisplay::DirectSet(const char *str, int keymap)
|
||||
bool CRadioDisplay::DirectSet(const char *str)
|
||||
{
|
||||
m_Title.clear();
|
||||
m_BufferText.assign(str);
|
||||
keys = keymap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int CRadioDisplay::GetCurrentKey()
|
||||
|
||||
@@ -101,7 +101,6 @@ public:
|
||||
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
|
||||
void FreeRadioDisplay(CRadioDisplay *display);
|
||||
CRadioMenuPlayer *GetRadioMenuPlayer(int client);
|
||||
IMenuPanel *MakeRadioDisplay(const char *str, int keys);
|
||||
private:
|
||||
CRadioMenuPlayer *m_players;
|
||||
CStack<CRadioDisplay *> m_FreeDisplays;
|
||||
@@ -129,8 +128,7 @@ public: //IMenuPanel
|
||||
bool SetCurrentKey(unsigned int key);
|
||||
int GetAmountRemaining();
|
||||
unsigned int GetApproxMemUsage();
|
||||
public:
|
||||
void DirectSet(const char *str, int keymap);
|
||||
bool DirectSet(const char *str);
|
||||
private:
|
||||
String m_BufferText;
|
||||
String m_Title;
|
||||
|
||||
@@ -75,6 +75,7 @@ public: //IMenuStyle
|
||||
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
|
||||
unsigned int GetMaxPageItems();
|
||||
unsigned int GetApproxMemUsage();
|
||||
bool IsSupported() { return true; }
|
||||
private:
|
||||
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
|
||||
private:
|
||||
@@ -105,6 +106,7 @@ public:
|
||||
bool SetCurrentKey(unsigned int key);
|
||||
int GetAmountRemaining();
|
||||
unsigned int GetApproxMemUsage();
|
||||
bool DirectSet(const char *str) { return false; }
|
||||
private:
|
||||
KeyValues *m_pKv;
|
||||
unsigned int m_NextPos;
|
||||
|
||||
+3
-2
@@ -36,6 +36,7 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcehook.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
NextMapManager g_NextMap;
|
||||
|
||||
@@ -130,7 +131,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
{
|
||||
if (g_forcedChange)
|
||||
{
|
||||
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
|
||||
logger->LogMessage("[SM] Changed map to \"%s\"", map);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
@@ -141,7 +142,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
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);
|
||||
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||
|
||||
+236
-67
@@ -403,12 +403,9 @@ void PlayerManager::RunAuthChecks()
|
||||
for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
|
||||
{
|
||||
pPlayer = &m_Players[m_AuthQueue[i]];
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
authstr = engine->GetPlayerNetworkIDString(pPlayer->m_iIndex - 1);
|
||||
#else
|
||||
authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict);
|
||||
#endif
|
||||
pPlayer->SetAuthString(authstr);
|
||||
pPlayer->UpdateAuthIds();
|
||||
|
||||
authstr = pPlayer->m_AuthID.chars();
|
||||
|
||||
if (!pPlayer->IsAuthStringValidated())
|
||||
{
|
||||
@@ -425,6 +422,8 @@ void PlayerManager::RunAuthChecks()
|
||||
unsigned int client = m_AuthQueue[i];
|
||||
m_AuthQueue[i] = 0;
|
||||
removed++;
|
||||
|
||||
const char *steamId = pPlayer->GetSteam2Id();
|
||||
|
||||
/* Send to extensions */
|
||||
List<IClientListener *>::iterator iter;
|
||||
@@ -432,7 +431,7 @@ void PlayerManager::RunAuthChecks()
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
pListener->OnClientAuthorized(client, authstr);
|
||||
pListener->OnClientAuthorized(client, steamId ? steamId : authstr);
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
break;
|
||||
@@ -444,7 +443,8 @@ void PlayerManager::RunAuthChecks()
|
||||
{
|
||||
/* :TODO: handle the case of a player disconnecting in the middle */
|
||||
m_clauth->PushCell(client);
|
||||
m_clauth->PushString(authstr);
|
||||
/* For legacy reasons, people are expecting the Steam2 id here if using Steam auth */
|
||||
m_clauth->PushString(steamId ? steamId : authstr);
|
||||
m_clauth->Execute(NULL);
|
||||
}
|
||||
|
||||
@@ -502,6 +502,9 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
/* Get the client's language */
|
||||
if (m_QueryLang)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
#else
|
||||
const char *name;
|
||||
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
||||
{
|
||||
@@ -510,6 +513,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
} else {
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
List<IClientListener *>::iterator iter;
|
||||
@@ -532,7 +536,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (!pPlayer->IsAuthorized())
|
||||
if (!pPlayer->IsAuthorized() && !pPlayer->IsFakeClient())
|
||||
{
|
||||
m_AuthQueue[++m_AuthQueue[0]] = client;
|
||||
}
|
||||
@@ -616,14 +620,7 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
{
|
||||
/* Run manual connection routines */
|
||||
char error[255];
|
||||
const char *authid;
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
authid = engine->GetPlayerNetworkIDString(client - 1);
|
||||
#else
|
||||
authid = engine->GetPlayerNetworkIDString(pEntity);
|
||||
#endif
|
||||
pPlayer->SetAuthString(authid);
|
||||
pPlayer->Authorize();
|
||||
|
||||
pPlayer->m_bFakeClient = true;
|
||||
|
||||
/*
|
||||
@@ -712,21 +709,33 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
m_clconnect_post->PushCell(client);
|
||||
m_clconnect_post->Execute(&res, NULL);
|
||||
|
||||
pPlayer->Authorize();
|
||||
|
||||
const char *steamId = pPlayer->GetSteam2Id();
|
||||
|
||||
/* Now do authorization */
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
pListener->OnClientAuthorized(client, authid);
|
||||
pListener->OnClientAuthorized(client, steamId ? steamId : pPlayer->m_AuthID.chars());
|
||||
}
|
||||
/* Finally, tell plugins */
|
||||
if (m_clauth->GetFunctionCount())
|
||||
{
|
||||
m_clauth->PushCell(client);
|
||||
m_clauth->PushString(authid);
|
||||
/* For legacy reasons, people are expecting the Steam2 id here if using Steam auth */
|
||||
m_clauth->PushString(steamId ? steamId : pPlayer->m_AuthID.chars());
|
||||
m_clauth->Execute(NULL);
|
||||
}
|
||||
pPlayer->Authorize_Post();
|
||||
}
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
else
|
||||
{
|
||||
// Not a bot
|
||||
pPlayer->m_LanguageCookie = g_ConVarManager.QueryClientConVar(pEntity, "cl_language", NULL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (playerinfo)
|
||||
{
|
||||
@@ -1227,7 +1236,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||
{
|
||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
||||
g_Logger.LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
logger->LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||
|
||||
pPlayer->Kick("NetworkID spoofing detected.");
|
||||
@@ -1541,22 +1550,47 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
}
|
||||
|
||||
/* Do we need to look for a steam id? */
|
||||
int steamIdType = 0;
|
||||
if (strncmp(&info->pattern[1], "STEAM_", 6) == 0)
|
||||
{
|
||||
size_t p, len;
|
||||
steamIdType = 2;
|
||||
}
|
||||
else if (strncmp(&info->pattern[1], "[U:", 3) == 0)
|
||||
{
|
||||
steamIdType = 3;
|
||||
}
|
||||
|
||||
if (steamIdType > 0)
|
||||
{
|
||||
char new_pattern[256];
|
||||
|
||||
strcpy(new_pattern, "STEAM_");
|
||||
len = strlen(&info->pattern[7]);
|
||||
for (p = 0; p < len; p++)
|
||||
if (steamIdType == 2)
|
||||
{
|
||||
new_pattern[6 + p] = info->pattern[7 + p];
|
||||
if (new_pattern[6 + p] == '_')
|
||||
size_t p, len;
|
||||
|
||||
strcpy(new_pattern, "STEAM_");
|
||||
len = strlen(&info->pattern[7]);
|
||||
for (p = 0; p < len; p++)
|
||||
{
|
||||
new_pattern[6 + p] = ':';
|
||||
new_pattern[6 + p] = info->pattern[7 + p];
|
||||
if (new_pattern[6 + p] == '_')
|
||||
{
|
||||
new_pattern[6 + p] = ':';
|
||||
}
|
||||
}
|
||||
new_pattern[6 + p] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t p = 0;
|
||||
char c;
|
||||
while ((c = info->pattern[p + 1]) != '\0')
|
||||
{
|
||||
new_pattern[p] = (c == '_') ? ':' : c;
|
||||
++p;
|
||||
}
|
||||
|
||||
new_pattern[p] = '\0';
|
||||
}
|
||||
new_pattern[6 + p] = '\0';
|
||||
|
||||
for (int i = 1; i <= max_clients; i++)
|
||||
{
|
||||
@@ -1568,8 +1602,10 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const char *authstr = pTarget->GetAuthString(false); // We want to make it easy for people to be kicked/banned, so don't require validation for command targets.
|
||||
if (authstr && strcmp(authstr, new_pattern) == 0)
|
||||
|
||||
// We want to make it easy for people to be kicked/banned, so don't require validation for command targets.
|
||||
const char *steamId = steamIdType == 2 ? pTarget->GetSteam2Id(false) : pTarget->GetSteam3Id(false);
|
||||
if (steamId && strcmp(steamId, new_pattern) == 0)
|
||||
{
|
||||
if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags))
|
||||
== COMMAND_TARGET_VALID)
|
||||
@@ -1862,6 +1898,24 @@ void CmdMaxplayersCallback()
|
||||
g_Players.MaxPlayersChanged();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
{
|
||||
for (int i = 1; i <= m_maxClients; i++)
|
||||
{
|
||||
if (m_Players[i].m_LanguageCookie == cookie)
|
||||
{
|
||||
unsigned int langid;
|
||||
m_Players[i].m_LangId = (translator->GetLanguageByName(cvarValue, &langid)) ? langid : translator->GetServerLanguage();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*******************
|
||||
*** PLAYER CODE ***
|
||||
@@ -1885,7 +1939,9 @@ CPlayer::CPlayer()
|
||||
m_bIsSourceTV = false;
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
@@ -1907,6 +1963,8 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
*ptr = '\0';
|
||||
}
|
||||
m_IpNoPort.assign(ip2);
|
||||
|
||||
UpdateAuthIds();
|
||||
}
|
||||
|
||||
void CPlayer::Connect()
|
||||
@@ -1931,14 +1989,112 @@ void CPlayer::Connect()
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::SetAuthString(const char *steamid)
|
||||
void CPlayer::UpdateAuthIds()
|
||||
{
|
||||
if (m_IsAuthorized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First cache engine networkid
|
||||
const char *authstr;
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
authstr = engine->GetPlayerNetworkIDString(m_iIndex - 1);
|
||||
#else
|
||||
authstr = engine->GetPlayerNetworkIDString(m_pEdict);
|
||||
#endif
|
||||
|
||||
m_AuthID.assign(steamid);
|
||||
if (!authstr)
|
||||
{
|
||||
// engine doesn't have the client's auth string just yet, we can't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_AuthID.compare(authstr) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_AuthID = authstr;
|
||||
|
||||
// Then, cache SteamId
|
||||
if (IsFakeClient())
|
||||
{
|
||||
m_SteamId = k_steamIDNil;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
const char * pAuth = GetAuthString();
|
||||
/* STEAM_0:1:123123 | STEAM_ID_LAN | STEAM_ID_PENDING */
|
||||
if (pAuth && (strlen(pAuth) > 10) && pAuth[8] != '_')
|
||||
{
|
||||
m_SteamId = CSteamID(atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1),
|
||||
k_unSteamUserDesktopInstance, k_EUniversePublic, k_EAccountTypeIndividual);
|
||||
}
|
||||
#else
|
||||
const CSteamID *steamId;
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
steamId = engine->GetClientSteamID(m_iIndex);
|
||||
#else
|
||||
steamId = engine->GetClientSteamID(m_pEdict);
|
||||
#endif
|
||||
|
||||
if (steamId)
|
||||
{
|
||||
m_SteamId = (*steamId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Now cache Steam2/3 rendered ids
|
||||
if (IsFakeClient())
|
||||
{
|
||||
m_Steam2Id = "BOT";
|
||||
m_Steam3Id = "BOT";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_SteamId.IsValid())
|
||||
{
|
||||
if (g_HL2.IsLANServer())
|
||||
{
|
||||
m_Steam2Id = "STEAM_ID_LAN";
|
||||
m_Steam3Id = "STEAM_ID_LAN";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Steam2Id = "STEAM_ID_PENDING";
|
||||
m_Steam3Id = "STEAM_ID_PENDING";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EUniverse steam2universe = m_SteamId.GetEUniverse();
|
||||
const char *keyUseInvalidUniverse = g_pGameConf->GetKeyValue("UseInvalidUniverseInSteam2IDs");
|
||||
if (keyUseInvalidUniverse && atoi(keyUseInvalidUniverse) == 1)
|
||||
{
|
||||
steam2universe = k_EUniverseInvalid;
|
||||
}
|
||||
|
||||
char szAuthBuffer[64];
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "STEAM_%u:%u:%u", steam2universe, m_SteamId.GetAccountID() & 1, m_SteamId.GetAccountID() >> 1);
|
||||
|
||||
m_Steam2Id = szAuthBuffer;
|
||||
|
||||
// TODO: make sure all hl2sdks' steamclientpublic.h have k_unSteamUserDesktopInstance.
|
||||
if (m_SteamId.GetUnAccountInstance() == 1 /* k_unSteamUserDesktopInstance */)
|
||||
{
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID());
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID(), m_SteamId.GetUnAccountInstance());
|
||||
}
|
||||
|
||||
m_Steam3Id = szAuthBuffer;
|
||||
}
|
||||
|
||||
// Ensure a valid AuthString is set before calling.
|
||||
@@ -1955,7 +2111,10 @@ void CPlayer::Disconnect()
|
||||
m_IsAuthorized = false;
|
||||
m_Name.clear();
|
||||
m_Ip.clear();
|
||||
m_AuthID.clear();
|
||||
m_AuthID = "";
|
||||
m_SteamId = k_steamIDNil;
|
||||
m_Steam2Id = "";
|
||||
m_Steam3Id = "";
|
||||
m_pEdict = NULL;
|
||||
m_Info = NULL;
|
||||
m_bAdminCheckSignalled = false;
|
||||
@@ -1965,7 +2124,9 @@ void CPlayer::Disconnect()
|
||||
m_bIsSourceTV = false;
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPlayer::SetName(const char *name)
|
||||
@@ -1995,42 +2156,50 @@ const char *CPlayer::GetAuthString(bool validated)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_AuthID.c_str();
|
||||
return m_AuthID.chars();
|
||||
}
|
||||
|
||||
const CSteamID &CPlayer::GetSteamId(bool validated)
|
||||
{
|
||||
if (validated && !IsAuthStringValidated())
|
||||
{
|
||||
static const CSteamID invalidId = k_steamIDNil;
|
||||
return invalidId;
|
||||
}
|
||||
|
||||
return m_SteamId;
|
||||
}
|
||||
|
||||
const char *CPlayer::GetSteam2Id(bool validated)
|
||||
{
|
||||
if (!m_Steam2Id.length() || (validated && !IsAuthStringValidated()))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_Steam2Id.chars();
|
||||
}
|
||||
|
||||
const char *CPlayer::GetSteam3Id(bool validated)
|
||||
{
|
||||
if (!m_Steam3Id.length() || (validated && !IsAuthStringValidated()))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_Steam3Id.chars();
|
||||
}
|
||||
|
||||
unsigned int CPlayer::GetSteamAccountID(bool validated)
|
||||
{
|
||||
if (IsFakeClient() || (validated && !IsAuthStringValidated()))
|
||||
if (!IsFakeClient() && (!validated || IsAuthStringValidated()))
|
||||
{
|
||||
return 0;
|
||||
const CSteamID &id = GetSteamId();
|
||||
if (id.IsValid())
|
||||
return id.GetAccountID();
|
||||
}
|
||||
|
||||
if (m_SteamAccountID != 0)
|
||||
{
|
||||
return m_SteamAccountID;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
const char * pAuth = GetAuthString();
|
||||
/* STEAM_0:1:123123 | STEAM_ID_LAN | STEAM_ID_PENDING */
|
||||
if (pAuth && (strlen(pAuth) > 10) && pAuth[8] != '_')
|
||||
{
|
||||
m_SteamAccountID = (atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1));
|
||||
}
|
||||
#else
|
||||
unsigned long long *steamId;
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
steamId = (unsigned long long *)engine->GetClientSteamID(m_iIndex);
|
||||
#else
|
||||
steamId = (unsigned long long *)engine->GetClientSteamID(m_pEdict);
|
||||
#endif
|
||||
|
||||
if (steamId)
|
||||
{
|
||||
m_SteamAccountID = (*steamId & 0xFFFFFFFF);
|
||||
}
|
||||
#endif
|
||||
return m_SteamAccountID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
edict_t *CPlayer::GetEdict()
|
||||
@@ -2296,7 +2465,7 @@ void CPlayer::DoBasicAdminChecks()
|
||||
}
|
||||
|
||||
/* Check steam id */
|
||||
if ((id = adminsys->FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
|
||||
if ((id = adminsys->FindAdminByIdentity("steam", m_AuthID.chars())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
if (g_Players.CheckSetAdmin(client, this, id))
|
||||
{
|
||||
|
||||
+18
-3
@@ -41,8 +41,11 @@
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_vector.h>
|
||||
#include <am-string.h>
|
||||
#include "ConVarManager.h"
|
||||
|
||||
#include <steam/steamclientpublic.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
#define PLAYER_LIFE_UNKNOWN 0
|
||||
@@ -71,6 +74,10 @@ public:
|
||||
const char *GetIPAddress();
|
||||
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();
|
||||
bool IsInGame();
|
||||
bool WasCountedAsInGame();
|
||||
@@ -103,7 +110,7 @@ private:
|
||||
void Disconnect();
|
||||
void SetName(const char *name);
|
||||
void DumpAdmin(bool deleting);
|
||||
void SetAuthString(const char *auth);
|
||||
void UpdateAuthIds();
|
||||
void Authorize();
|
||||
void Authorize_Post();
|
||||
void DoPostConnectAuthorization();
|
||||
@@ -116,7 +123,9 @@ private:
|
||||
String m_Name;
|
||||
String m_Ip;
|
||||
String m_IpNoPort;
|
||||
String m_AuthID;
|
||||
ke::AString m_AuthID;
|
||||
ke::AString m_Steam2Id;
|
||||
ke::AString m_Steam3Id;
|
||||
AdminId m_Admin;
|
||||
bool m_TempAdmin;
|
||||
edict_t *m_pEdict;
|
||||
@@ -130,7 +139,10 @@ private:
|
||||
bool m_bIsSourceTV;
|
||||
bool m_bIsReplay;
|
||||
serial_t m_Serial;
|
||||
unsigned int m_SteamAccountID;
|
||||
CSteamID m_SteamId;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
QueryCvarCookie_t m_LanguageCookie;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
@@ -211,6 +223,9 @@ public:
|
||||
unsigned int GetReplyTo();
|
||||
unsigned int SetReplyTo(unsigned int reply);
|
||||
void MaxPlayersChanged(int newvalue = -1);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||
#endif
|
||||
private:
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
void OnServerActivate();
|
||||
|
||||
+10
-1
@@ -19,6 +19,12 @@ if builder.target_platform == 'linux':
|
||||
elif builder.target_platform == 'mac':
|
||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
binary.sources += [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
@@ -33,7 +39,6 @@ binary.sources += [
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'Profiler.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
@@ -66,6 +71,10 @@ binary.sources += [
|
||||
'AdminCache.cpp',
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_menus.cpp',
|
||||
]
|
||||
if builder.target_platform == 'windows':
|
||||
binary.sources += ['thread/WinThreads.cpp']
|
||||
|
||||
+97
-23
@@ -39,15 +39,16 @@
|
||||
#include "AdminCache.h"
|
||||
#include "Translator.h"
|
||||
#include "common_logic.h"
|
||||
#include "stringutil.h"
|
||||
|
||||
#define LEVEL_STATE_NONE 0
|
||||
#define LEVEL_STATE_LEVELS 1
|
||||
#define LEVEL_STATE_FLAGS 2
|
||||
|
||||
AdminCache g_Admins;
|
||||
char g_ReverseFlags[26];
|
||||
char g_ReverseFlags[AdminFlags_TOTAL];
|
||||
AdminFlag g_FlagLetters[26];
|
||||
bool g_FlagSet[26];
|
||||
bool g_FlagCharSet[26];
|
||||
|
||||
/* Default flags */
|
||||
AdminFlag g_DefaultFlags[26] =
|
||||
@@ -71,9 +72,9 @@ public:
|
||||
memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
|
||||
for (unsigned int i=0; i<20; i++)
|
||||
{
|
||||
g_FlagSet[i] = true;
|
||||
g_FlagCharSet[i] = true;
|
||||
}
|
||||
g_FlagSet[25] = true;
|
||||
g_FlagCharSet[25] = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
@@ -103,7 +104,7 @@ private:
|
||||
{
|
||||
m_LevelState = LEVEL_STATE_NONE;
|
||||
m_IgnoreLevel = 0;
|
||||
memset(g_FlagSet, 0, sizeof(g_FlagSet));
|
||||
memset(g_FlagCharSet, 0, sizeof(g_FlagCharSet));
|
||||
}
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
@@ -163,7 +164,7 @@ private:
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
g_FlagSet[c] = true;
|
||||
g_FlagCharSet[c] = true;
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
@@ -198,11 +199,11 @@ private:
|
||||
|
||||
if (!m_bFileNameLogged)
|
||||
{
|
||||
smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
|
||||
logger->LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
|
||||
m_bFileNameLogged = true;
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
|
||||
logger->LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
|
||||
}
|
||||
private:
|
||||
bool m_bFileNameLogged;
|
||||
@@ -1056,6 +1057,65 @@ bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts Steam2 id, Steam3 id, or SteamId64 to unified, legacy
|
||||
* admin identity format. (account id part of Steam2 format)
|
||||
*/
|
||||
bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen)
|
||||
{
|
||||
int len = strlen(ident);
|
||||
if (!strcmp(ident, "BOT"))
|
||||
{
|
||||
// Bots
|
||||
strncopy(out, ident, maxlen);
|
||||
return true;
|
||||
}
|
||||
else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
|
||||
{
|
||||
// non-bot/lan Steam2 Id, strip off the STEAM_* part
|
||||
snprintf(out, maxlen, "%s", &ident[8]);
|
||||
return true;
|
||||
}
|
||||
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
|
||||
{
|
||||
// Steam3 Id, replicate the Steam2 Post-"STEAM_" part
|
||||
uint32_t accountId = strtoul(&ident[5], nullptr, 10);
|
||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 64-bit CSteamID, replicate the Steam2 Post-"STEAM_" part
|
||||
|
||||
// some constants from steamclientpublic.h
|
||||
static const uint32_t k_EAccountTypeIndividual = 1;
|
||||
static const int k_EUniverseInvalid = 0;
|
||||
static const int k_EUniverseMax = 5;
|
||||
static const unsigned int k_unSteamUserWebInstance = 4;
|
||||
|
||||
uint64_t steamId = strtoull(ident, nullptr, 10);
|
||||
if (steamId > 0)
|
||||
{
|
||||
// Make some attempt at being sure it's a valid id rather than other number,
|
||||
// even though we're only going to use the lower 32 bits.
|
||||
uint32_t accountId = steamId & 0xFFFFFFFF;
|
||||
uint32_t accountType = (steamId >> 52) & 0xF;
|
||||
int universe = steamId >> 56;
|
||||
uint32_t accountInstance = (steamId >> 32) & 0xFFFFF;
|
||||
if (accountId > 0
|
||||
&& universe > k_EUniverseInvalid && universe < k_EUniverseMax
|
||||
&& accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance
|
||||
)
|
||||
{
|
||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
|
||||
{
|
||||
if (ident[0] == '\0')
|
||||
@@ -1073,10 +1133,14 @@ bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ide
|
||||
if (!m_AuthTables.retrieve(auth, &method))
|
||||
return false;
|
||||
|
||||
/* If the id was a steam id strip off the STEAM_*: part */
|
||||
if (strcmp(auth, "steam") == 0 && strncmp(ident, "STEAM_", 6) == 0)
|
||||
/* If the auth type is steam, the id could be in a number of formats. Unify it. */
|
||||
char steamIdent[16];
|
||||
if (strcmp(auth, "steam") == 0)
|
||||
{
|
||||
ident += 8;
|
||||
if (!GetUnifiedSteamIdentity(ident, steamIdent, sizeof(steamIdent)))
|
||||
return false;
|
||||
|
||||
ident = steamIdent;
|
||||
}
|
||||
|
||||
if (method->identities.contains(ident))
|
||||
@@ -1097,10 +1161,14 @@ AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
|
||||
if (!m_AuthTables.retrieve(auth, &method))
|
||||
return INVALID_ADMIN_ID;
|
||||
|
||||
/* If the id was a steam id strip off the STEAM_*: part */
|
||||
if (strcmp(auth, "steam") == 0 && strncmp(identity, "STEAM_", 6) == 0)
|
||||
/* If the auth type is steam, the id could be in a number of formats. Unify it. */
|
||||
char steamIdent[16];
|
||||
if (strcmp(auth, "steam") == 0)
|
||||
{
|
||||
identity += 8;
|
||||
if (!GetUnifiedSteamIdentity(identity, steamIdent, sizeof(steamIdent)))
|
||||
return INVALID_ADMIN_ID;
|
||||
|
||||
identity = steamIdent;
|
||||
}
|
||||
|
||||
AdminId id;
|
||||
@@ -1517,7 +1585,7 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
|
||||
{
|
||||
if (c < 'a'
|
||||
|| c > 'z'
|
||||
|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
|
||||
|| !g_FlagCharSet[(unsigned)c - (unsigned)'a'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1532,17 +1600,13 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
|
||||
|
||||
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
|
||||
{
|
||||
if (!g_FlagSet[flag])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char flagchar = g_ReverseFlags[flag];
|
||||
if (c)
|
||||
{
|
||||
*c = g_ReverseFlags[flag];
|
||||
*c = flagchar;
|
||||
}
|
||||
|
||||
return true;
|
||||
return flagchar != '?';
|
||||
}
|
||||
|
||||
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
|
||||
@@ -1702,7 +1766,7 @@ void iterator_group_grp_override(FILE *fp, const char *key, OverrideRule rule)
|
||||
fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, str);
|
||||
}
|
||||
|
||||
void AdminCache::DumpCache(FILE *fp)
|
||||
bool AdminCache::DumpCache(const char *filename)
|
||||
{
|
||||
int *itable;
|
||||
AdminId aid;
|
||||
@@ -1711,6 +1775,12 @@ void AdminCache::DumpCache(FILE *fp)
|
||||
unsigned int num;
|
||||
AdminUser *pAdmin;
|
||||
AdminGroup *pGroup;
|
||||
|
||||
FILE *fp;
|
||||
if ((fp = fopen(filename, "wt")) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(fp, "\"Groups\"\n{\n");
|
||||
|
||||
@@ -1841,6 +1911,10 @@ void AdminCache::DumpCache(FILE *fp)
|
||||
for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next())
|
||||
iterator_glob_basic_override(fp, iter->key.chars(), iter->value);
|
||||
fprintf(fp, "}\n");
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AdminGroup *AdminCache::GetGroup(GroupId gid)
|
||||
|
||||
@@ -183,7 +183,7 @@ public: //IAdminSystem
|
||||
bool IsValidAdmin(AdminId id);
|
||||
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags);
|
||||
public:
|
||||
void DumpCache(FILE *fp);
|
||||
bool DumpCache(const char *filename);
|
||||
AdminGroup *GetGroup(GroupId gid);
|
||||
AdminUser *GetUser(AdminId id);
|
||||
const char *GetString(int idx);
|
||||
@@ -198,6 +198,7 @@ private:
|
||||
bool GetMethodIndex(const char *name, unsigned int *_index);
|
||||
const char *GetMethodName(unsigned int index);
|
||||
void NameFlag(const char *str, AdminFlag flag);
|
||||
bool GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen);
|
||||
public:
|
||||
typedef StringHashMap<FlagBits> FlagMap;
|
||||
|
||||
|
||||
+14
-3
@@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
|
||||
ke::AutoLock lock(&m_ConfigLock);
|
||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
||||
{
|
||||
smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||
if (err != SMCError_Custom)
|
||||
{
|
||||
const char *txt = textparsers->GetSMCErrorString(err);
|
||||
smcore.LogError("[SM] Line %d: %s", states.line, txt);
|
||||
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,7 +541,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
||||
{
|
||||
if (!s_OneTimeThreaderErrorMsg)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to create db threader (error unknown)");
|
||||
logger->LogError("[SM] Unable to create db threader (error unknown)");
|
||||
s_OneTimeThreaderErrorMsg = true;
|
||||
}
|
||||
m_Worker = NULL;
|
||||
@@ -615,6 +615,17 @@ void DBManager::ThreadMain()
|
||||
ke::AutoLock lock(&m_ThinkLock);
|
||||
m_ThinkQueue.push(op);
|
||||
}
|
||||
|
||||
|
||||
if (!m_Terminate)
|
||||
{
|
||||
ke::AutoUnlock unlock(&m_QueueEvent);
|
||||
#ifdef _WIN32
|
||||
Sleep(20);
|
||||
#else
|
||||
usleep(20000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Terminate)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <IPluginSys.h>
|
||||
#include <stdarg.h>
|
||||
#include "DebugReporter.h"
|
||||
#include "Logger.h"
|
||||
|
||||
DebugReport g_DbgReporter;
|
||||
|
||||
@@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
smcore.Log("[SM] %s", buffer);
|
||||
g_Logger.LogMessage("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
||||
@@ -71,12 +72,12 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
||||
|
||||
if (error)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
} else {
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
|
||||
if (func_idx != -1)
|
||||
{
|
||||
@@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
||||
sp_public_t *function;
|
||||
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,18 +107,18 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
||||
|
||||
if (error)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
} else {
|
||||
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
|
||||
IPluginDebugInfo *pDebug;
|
||||
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
_GetPluginIndex(pContext));
|
||||
return;
|
||||
}
|
||||
@@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
||||
const char *name;
|
||||
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
||||
{
|
||||
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
||||
g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +140,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
||||
|
||||
if (n_err != SP_ERROR_NATIVE)
|
||||
{
|
||||
smcore.LogError("[SM] Plugin encountered error %d: %s",
|
||||
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
|
||||
n_err,
|
||||
error->GetErrorString());
|
||||
}
|
||||
@@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
||||
const char *custerr;
|
||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
||||
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
||||
} else {
|
||||
smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
||||
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
||||
}
|
||||
}
|
||||
|
||||
if (!error->DebugInfoAvailable())
|
||||
{
|
||||
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||
_GetPluginIndex(ctx));
|
||||
return;
|
||||
}
|
||||
|
||||
CallStackInfo stk_info;
|
||||
int i = 0;
|
||||
smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
||||
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
||||
while (error->GetTraceInfo(&stk_info))
|
||||
{
|
||||
smcore.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||
i++,
|
||||
stk_info.line,
|
||||
stk_info.filename,
|
||||
|
||||
@@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
||||
{
|
||||
if (bErrorOnMissing || libsys->IsPathFile(p->GetPath()))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
}
|
||||
|
||||
p->SetError(error);
|
||||
@@ -1360,6 +1360,24 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount,
|
||||
}
|
||||
}
|
||||
|
||||
void CExtensionManager::CallOnCoreMapEnd()
|
||||
{
|
||||
IExtensionInterface *pAPI;
|
||||
List<CExtension *>::iterator iter;
|
||||
|
||||
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
||||
{
|
||||
if ((pAPI = (*iter)->GetAPI()) == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pAPI->GetExtensionVersion() > 7)
|
||||
{
|
||||
pAPI->OnCoreMapEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CVector<IExtension *> *CExtensionManager::ListExtensions()
|
||||
{
|
||||
CVector<IExtension *> *list = new CVector<IExtension *>();
|
||||
|
||||
@@ -173,6 +173,7 @@ public:
|
||||
void AddLibrary(IExtension *pSource, const char *library);
|
||||
bool LibraryExists(const char *library);
|
||||
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
void CallOnCoreMapEnd();
|
||||
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
||||
const CVector<IExtension *> *ListExtensions();
|
||||
void FreeExtensionList(const CVector<IExtension *> *list);
|
||||
|
||||
+15
-14
@@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
if (error[0] != '\0')
|
||||
{
|
||||
m_IgnoreLevel = 1;
|
||||
smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
smcore.LogError("[SM] %s", error);
|
||||
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
logger->LogError("[SM] %s", error);
|
||||
} else {
|
||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
||||
}
|
||||
@@ -335,8 +335,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
{
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
|
||||
{
|
||||
smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
}
|
||||
m_IgnoreLevel = 1;
|
||||
}
|
||||
@@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
}
|
||||
else
|
||||
{
|
||||
smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||
}
|
||||
} else if (strcmp(key, "signature") == 0) {
|
||||
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
|
||||
@@ -503,7 +503,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
|
||||
&& (!m_Offsets.retrieve(m_offset)))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
m_Class,
|
||||
m_Prop,
|
||||
m_CurFile,
|
||||
@@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
void *final_addr = NULL;
|
||||
if (addrInBase == NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_CurFile);
|
||||
}
|
||||
@@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
|
||||
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
|
||||
else
|
||||
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
|
||||
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
|
||||
#elif defined PLATFORM_POSIX
|
||||
Dl_info info;
|
||||
/* GNU only: returns 0 on error, inconsistent! >:[ */
|
||||
@@ -585,12 +585,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
||||
dlclose(handle);
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_File);
|
||||
}
|
||||
} else {
|
||||
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
||||
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_File);
|
||||
}
|
||||
@@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||
{
|
||||
const char *msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
state.col,
|
||||
@@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
const char *msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||
logger->LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
state.col,
|
||||
@@ -1082,6 +1082,7 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
|
||||
}
|
||||
|
||||
pConfig = new CGameConfig(file);
|
||||
pConfig->AddRef();
|
||||
|
||||
/* :HACKHACK: Don't parse the main config file */
|
||||
bool retval = true;
|
||||
|
||||
@@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
||||
}
|
||||
|
||||
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||
smcore.LogFatal(message, ##__VA_ARGS__); \
|
||||
smcore.LogError(message, ##__VA_ARGS__);
|
||||
logger->LogFatal(message, ##__VA_ARGS__); \
|
||||
logger->LogError(message, ##__VA_ARGS__);
|
||||
|
||||
bool HandleSystem::TryAndFreeSomeHandles()
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <am-string.h>
|
||||
#include "common_logic.h"
|
||||
|
||||
#define HANDLESYS_MAX_HANDLES (1<<14)
|
||||
#define HANDLESYS_MAX_HANDLES (1<<15)
|
||||
#define HANDLESYS_MAX_TYPES (1<<9)
|
||||
#define HANDLESYS_MAX_SUBTYPES 0xF
|
||||
#define HANDLESYS_SUBTYPE_MASK 0xF
|
||||
|
||||
@@ -0,0 +1,551 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <cstdarg>
|
||||
#include "Logger.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
Logger g_Logger;
|
||||
|
||||
/**
|
||||
* :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 {
|
||||
smcore.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 {
|
||||
smcore.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 = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
||||
FILE *fp = fopen(_filename, "r");
|
||||
if (!fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
i++;
|
||||
}
|
||||
m_NrmFileName.assign(_filename);
|
||||
|
||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
||||
if (!fp)
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (!m_NrmFileName.empty())
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogMessage("Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_NrmFileName.clear();
|
||||
}
|
||||
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogError("Error log file session closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_ErrFileName.clear();
|
||||
}
|
||||
|
||||
void Logger::InitLogger(LoggingMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
m_Active = m_InitialState;
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
m_DelayedStart = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_DailyPrintHdr = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::CloseLogger()
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
|
||||
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
|
||||
{
|
||||
static char conBuffer[4096];
|
||||
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
|
||||
smcore.ConPrint(conBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[3072];
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
char date[32];
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogMessageEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Mode == LoggingMode_Game)
|
||||
{
|
||||
_PrintToGameLog(vafmt, ap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_DelayedStart)
|
||||
{
|
||||
m_DelayedStart = false;
|
||||
_NewMapFile();
|
||||
}
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (m_Mode == LoggingMode_PerMap)
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
_NewMapFile();
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
goto print_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_NrmCurDay != curtime->tm_mday)
|
||||
{
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_DailyPrintHdr = true;
|
||||
}
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
if (m_DailyPrintHdr)
|
||||
{
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
} else {
|
||||
goto print_error;
|
||||
}
|
||||
|
||||
return;
|
||||
print_error:
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (curtime->tm_mday != m_ErrCurDay)
|
||||
{
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
||||
if (fp)
|
||||
{
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
smcore.LogToGame(msg);
|
||||
}
|
||||
|
||||
const char *Logger::GetLogFileName(LogType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LogType_Normal:
|
||||
{
|
||||
return m_NrmFileName.c_str();
|
||||
}
|
||||
case LogType_Error:
|
||||
{
|
||||
return m_ErrFileName.c_str();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoggingMode Logger::GetLoggingMode() const
|
||||
{
|
||||
return m_Mode;
|
||||
}
|
||||
|
||||
void Logger::EnableLogging()
|
||||
{
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
LogFatalEx(msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||
{
|
||||
/* :TODO: make this print all pretty-like
|
||||
* In fact, the pretty log printing function should be abstracted.
|
||||
* It's already implemented twice which is bad.
|
||||
*/
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (fp)
|
||||
{
|
||||
m_Active = true;
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
m_Active = false;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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_CLOGGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sh_string.h>
|
||||
|
||||
#include "common_logic.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
enum LogType
|
||||
{
|
||||
LogType_Normal,
|
||||
LogType_Error
|
||||
};
|
||||
|
||||
enum LoggingMode
|
||||
{
|
||||
LoggingMode_Daily,
|
||||
LoggingMode_PerMap,
|
||||
LoggingMode_Game
|
||||
};
|
||||
|
||||
class Logger : public SMGlobalClass, public ILogger
|
||||
{
|
||||
public:
|
||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
||||
m_InitialState(true)
|
||||
{
|
||||
}
|
||||
public: //SMGlobalClass
|
||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllShutdown();
|
||||
void OnSourceModLevelChange(const char *mapName);
|
||||
public:
|
||||
void InitLogger(LoggingMode mode);
|
||||
void CloseLogger();
|
||||
void EnableLogging();
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogMessageEx(const char *msg, va_list ap);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogFatalEx(const char *msg, va_list ap);
|
||||
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_NrmCurDay;
|
||||
int m_ErrCurDay;
|
||||
bool m_ErrMapStart;
|
||||
bool m_Active;
|
||||
bool m_DelayedStart;
|
||||
bool m_DailyPrintHdr;
|
||||
bool m_InitialState;
|
||||
};
|
||||
|
||||
extern Logger g_Logger;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "GameConfigs.h"
|
||||
#include "common_logic.h"
|
||||
#include "Translator.h"
|
||||
#include "Logger.h"
|
||||
|
||||
CPluginManager g_PluginSys;
|
||||
HandleType_t g_PluginType = 0;
|
||||
@@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
{
|
||||
char error[256];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
smcore.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
||||
smcore.LogError("[SM] Platform returned error: %s", error);
|
||||
g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath);
|
||||
g_Logger.LogError("[SM] Platform returned error: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de
|
||||
} else {
|
||||
if (bulletinUrl[0] != '\0')
|
||||
{
|
||||
smcore.Log("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
|
||||
g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
|
||||
} else {
|
||||
smcore.Log("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
|
||||
g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1094,7 +1095,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
|
||||
|
||||
if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
|
||||
{
|
||||
smcore.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
|
||||
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
|
||||
pl->SetErrorState(
|
||||
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
||||
"%s",
|
||||
@@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass()
|
||||
error[0] = '\0';
|
||||
if (!RunSecondPass(pPlugin, error, sizeof(error)))
|
||||
{
|
||||
smcore.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
|
||||
g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet :
|
||||
// =============================================================================
|
||||
// SourceMod
|
||||
// Copyright (C) 2004-2014 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 "ProfileTools.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
ProfileToolManager g_ProfileToolManager;
|
||||
|
||||
ProfileToolManager::ProfileToolManager()
|
||||
: active_(nullptr),
|
||||
default_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProfileToolManager::OnSourceModAllInitialized()
|
||||
{
|
||||
rootmenu->AddRootConsoleCommand2("prof", "Profiling", this);
|
||||
}
|
||||
|
||||
void
|
||||
ProfileToolManager::OnSourceModShutdown()
|
||||
{
|
||||
rootmenu->RemoveRootConsoleCommand("prof", this);
|
||||
}
|
||||
|
||||
IProfilingTool *
|
||||
ProfileToolManager::FindToolByName(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < tools_.length(); i++) {
|
||||
if (strcmp(tools_[i]->Name(), name) == 0)
|
||||
return tools_[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
render_help(const char *fmt, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
smcore.FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
rootmenu->ConsolePrint("%s", buffer);
|
||||
}
|
||||
|
||||
void
|
||||
ProfileToolManager::StartFromConsole(IProfilingTool *tool)
|
||||
{
|
||||
if (active_) {
|
||||
rootmenu->ConsolePrint("A profile is already active using %s.", active_->Name());
|
||||
return;
|
||||
}
|
||||
|
||||
active_ = tool;
|
||||
if (!active_->Start()) {
|
||||
rootmenu->ConsolePrint("Failed to attach to or start %s.", active_->Name());
|
||||
active_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
g_pSourcePawn2->SetProfilingTool(active_);
|
||||
g_pSourcePawn2->EnableProfiling();
|
||||
rootmenu->ConsolePrint("Started profiling with %s.", active_->Name());
|
||||
|
||||
default_ = active_;
|
||||
}
|
||||
|
||||
void
|
||||
ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *args)
|
||||
{
|
||||
if (tools_.length() == 0) {
|
||||
rootmenu->ConsolePrint("No profiling tools are enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args->ArgC() >= 3) {
|
||||
cmdname = args->Arg(2);
|
||||
|
||||
if (strcmp(cmdname, "list") == 0) {
|
||||
rootmenu->ConsolePrint("Profiling tools:");
|
||||
for (size_t i = 0; i < tools_.length(); i++) {
|
||||
rootmenu->DrawGenericOption(tools_[i]->Name(), tools_[i]->Description());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "stop") == 0) {
|
||||
if (!active_) {
|
||||
rootmenu->ConsolePrint("No profiler is active.");
|
||||
return;
|
||||
}
|
||||
g_pSourcePawn2->DisableProfiling();
|
||||
g_pSourcePawn2->SetProfilingTool(nullptr);
|
||||
active_->Stop(render_help);
|
||||
active_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "dump") == 0) {
|
||||
if (active_) {
|
||||
// if we have an active profiler, dump it
|
||||
active_->Dump();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->ArgC() < 4) {
|
||||
if (strcmp(cmdname, "start") == 0) {
|
||||
if (!default_) {
|
||||
default_ = FindToolByName("vprof");
|
||||
if (!default_ && tools_.length() > 0)
|
||||
default_ = tools_[0];
|
||||
if (!default_) {
|
||||
rootmenu->ConsolePrint("Could not find any profiler to use.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
StartFromConsole(default_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->ArgC() < 4) {
|
||||
rootmenu->ConsolePrint("You must specify a profiling tool name.");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *toolname = args->Arg(3);
|
||||
if (strcmp(cmdname, "start") == 0) {
|
||||
IProfilingTool *tool = FindToolByName(toolname);
|
||||
if (!tool) {
|
||||
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
|
||||
return;
|
||||
}
|
||||
StartFromConsole(tool);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "dump") == 0) {
|
||||
IProfilingTool *tool = FindToolByName(toolname);
|
||||
if (!tool) {
|
||||
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
|
||||
return;
|
||||
}
|
||||
tool->Dump();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmdname, "help") == 0) {
|
||||
IProfilingTool *tool = FindToolByName(toolname);
|
||||
if (!tool) {
|
||||
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
|
||||
return;
|
||||
}
|
||||
tool->RenderHelp(render_help);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rootmenu->ConsolePrint("Profiling commands:");
|
||||
rootmenu->DrawGenericOption("list", "List all available profiling tools.");
|
||||
rootmenu->DrawGenericOption("start", "Start a profile with a given tool.");
|
||||
rootmenu->DrawGenericOption("stop", "Stop the current profile session.");
|
||||
rootmenu->DrawGenericOption("dump", "Dumps output from the current profile session.");
|
||||
rootmenu->DrawGenericOption("help", "Display help text for a profiler.");
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet :
|
||||
// =============================================================================
|
||||
// SourceMod
|
||||
// Copyright (C) 2004-2014 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_profile_tool_manager_h_
|
||||
#define _include_sourcemod_logic_profile_tool_manager_h_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <am-vector.h>
|
||||
#include <IShareSys.h>
|
||||
#include <IRootConsoleMenu.h>
|
||||
#include "common_logic.h"
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
class ProfileToolManager
|
||||
: public SMGlobalClass,
|
||||
public IRootConsoleCommand
|
||||
{
|
||||
public:
|
||||
ProfileToolManager();
|
||||
|
||||
// SMGlobalClass
|
||||
void OnSourceModAllInitialized() KE_OVERRIDE;
|
||||
void OnSourceModShutdown() KE_OVERRIDE;
|
||||
|
||||
// IRootConsoleCommand
|
||||
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *args) KE_OVERRIDE;
|
||||
|
||||
void RegisterTool(IProfilingTool *tool) {
|
||||
tools_.append(tool);
|
||||
}
|
||||
|
||||
bool IsActive() const {
|
||||
return !!active_;
|
||||
}
|
||||
|
||||
// If we get problems with plugins not being able to balance the profile
|
||||
// scopes, we should add a safety net that automatically clears any pending
|
||||
// scopes.
|
||||
void EnterScope(const char *group, const char *name) {
|
||||
if (active_)
|
||||
active_->EnterScope(group, name);
|
||||
}
|
||||
void LeaveScope() {
|
||||
if (active_)
|
||||
active_->LeaveScope();
|
||||
}
|
||||
|
||||
IProfilingTool *FindToolByName(const char *name);
|
||||
|
||||
private:
|
||||
void StartFromConsole(IProfilingTool *tool);
|
||||
|
||||
private:
|
||||
ke::Vector<IProfilingTool *> tools_;
|
||||
IProfilingTool *active_;
|
||||
IProfilingTool *default_;
|
||||
bool enabled_;
|
||||
};
|
||||
|
||||
extern ProfileToolManager g_ProfileToolManager;
|
||||
|
||||
#endif // _include_sourcemod_logic_profile_tool_manager_h_
|
||||
@@ -1,516 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "Profiler.h"
|
||||
#include <ISourceMod.h>
|
||||
#if defined PLATFORM_POSIX
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <IPluginSys.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
ProfileEngine g_Profiler;
|
||||
IProfiler *sm_profiler = &g_Profiler;
|
||||
|
||||
#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()
|
||||
{
|
||||
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnSourceModShutdown()
|
||||
{
|
||||
rootmenu->RemoveRootConsoleCommand("profiler", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command)
|
||||
{
|
||||
if (command->ArgC() >= 3)
|
||||
{
|
||||
if (strcmp(command->Arg(2), "flush") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
Clear();
|
||||
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "report") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "clear") == 0)
|
||||
{
|
||||
Clear();
|
||||
|
||||
rootmenu->ConsolePrint("Profiler statistics cleared.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rootmenu->ConsolePrint("Profiler commands:");
|
||||
rootmenu->DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
||||
rootmenu->DrawGenericOption("report", "Flushes statistics to disk");
|
||||
rootmenu->DrawGenericOption("clear", "Clears statistics");
|
||||
}
|
||||
|
||||
bool ProfileEngine::GenerateReport(FILE *fp)
|
||||
{
|
||||
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), "<", "<", true);
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">", true);
|
||||
|
||||
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
|
||||
new_name,
|
||||
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 *report;
|
||||
|
||||
if (atom.atom_type == SP_PROF_NATIVES)
|
||||
{
|
||||
smcore.strncopy(full_name, atom.name, sizeof(full_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
IPlugin *pl;
|
||||
const char *file;
|
||||
|
||||
file = "unknown";
|
||||
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL)
|
||||
{
|
||||
file = pl->GetFilename();
|
||||
}
|
||||
|
||||
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
||||
}
|
||||
|
||||
atom_time = CalcAtomTime(atom);
|
||||
|
||||
if (!m_ReportLookup.retrieve(full_name, &report))
|
||||
{
|
||||
report = new prof_atom_report_t;
|
||||
|
||||
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
||||
report->max_time = atom_time;
|
||||
report->min_time = atom_time;
|
||||
report->num_calls = 1;
|
||||
report->total_time = atom_time;
|
||||
|
||||
m_ReportLookup.insert(full_name, report);
|
||||
m_Reports.push_back(report);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <sm_platform.h>
|
||||
#include <sh_vector.h>
|
||||
#include <sh_stack.h>
|
||||
#include <sm_namehashset.h>
|
||||
#include <stdio.h>
|
||||
#include "common_logic.h"
|
||||
#include <IRootConsoleMenu.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 */
|
||||
|
||||
static inline bool matches(const char *name, const prof_atom_report_t *report)
|
||||
{
|
||||
return strcmp(report->atom_name, name) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
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:
|
||||
NameHashSet<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 OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *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 IProfiler *sm_profiler;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
||||
@@ -375,7 +375,7 @@ PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nat
|
||||
if (i.found())
|
||||
return NULL;
|
||||
|
||||
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv));
|
||||
Ref<Native> entry = new Native(pOwner, ntv);
|
||||
m_NtvCache.insert(ntv->name, entry);
|
||||
return entry;
|
||||
}
|
||||
@@ -415,7 +415,7 @@ PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n
|
||||
|
||||
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
|
||||
|
||||
entry = Newborn<Native>(new Native(owner, fake.take()));
|
||||
entry = new Native(owner, fake.take());
|
||||
m_NtvCache.insert(name, entry);
|
||||
|
||||
return entry;
|
||||
|
||||
@@ -1077,7 +1077,7 @@ const char *TextParsers::GetSMCErrorString(SMCError err)
|
||||
NULL,
|
||||
"Stream failed to open",
|
||||
"Stream returned read error",
|
||||
NULL,
|
||||
"Callback error",
|
||||
"Un-quoted section has invalid tokens",
|
||||
"Section declared without header",
|
||||
"Section declared with unknown tokens",
|
||||
|
||||
+21
-13
@@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
|
||||
|
||||
if (!m_FileLogged)
|
||||
{
|
||||
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
m_FileLogged = true;
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
logger->LogError("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void CPhraseFile::ReparseFile()
|
||||
@@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
}
|
||||
|
||||
const char *code;
|
||||
@@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
code,
|
||||
m_File.c_str());
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s",
|
||||
logger->LogError("[SM] Error (line %d, column %d): %s",
|
||||
states.line,
|
||||
states.col,
|
||||
msg);
|
||||
@@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase()
|
||||
str_err = m_CustomError.c_str();
|
||||
}
|
||||
|
||||
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path);
|
||||
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
logger->LogError("[SM] Failed to parse language header file: \"%s\"", path);
|
||||
logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
}
|
||||
|
||||
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang))
|
||||
{
|
||||
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
|
||||
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
@@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase()
|
||||
|
||||
if (!m_Languages.size())
|
||||
{
|
||||
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
logger->LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
}
|
||||
|
||||
for (size_t i=0; i<m_Files.size(); i++)
|
||||
@@ -872,7 +872,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
|
||||
|
||||
if (!m_InLanguageSection)
|
||||
{
|
||||
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
logger->LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
@@ -887,6 +887,14 @@ SMCResult Translator::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
size_t len = strlen(key);
|
||||
|
||||
if (len >= sizeof(((Language *)0)->m_code2))
|
||||
{
|
||||
logger->LogError("[SM] Warning encountered parsing languages.cfg file.");
|
||||
logger->LogError("[SM] Invalid language code \"%s\" is too long.", key);
|
||||
}
|
||||
|
||||
AddLanguage(key, value);
|
||||
|
||||
return SMCResult_Continue;
|
||||
@@ -1025,11 +1033,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
|
||||
{
|
||||
if (fail_phrase != NULL)
|
||||
{
|
||||
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
logger->LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
}
|
||||
else
|
||||
{
|
||||
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
logger->LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -54,7 +54,7 @@ enum PhraseParseState
|
||||
|
||||
struct Language
|
||||
{
|
||||
char m_code2[4];
|
||||
char m_code2[32];
|
||||
int m_CanonicalName;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <stdarg.h>
|
||||
#include "common_logic.h"
|
||||
#include "TextParsers.h"
|
||||
#include "Profiler.h"
|
||||
#include "sm_crc32.h"
|
||||
#include "MemoryUtils.h"
|
||||
#include "stringutil.h"
|
||||
@@ -50,6 +49,8 @@
|
||||
#include "ExtensionSys.h"
|
||||
#include "ForwardSys.h"
|
||||
#include "AdminCache.h"
|
||||
#include "ProfileTools.h"
|
||||
#include "Logger.h"
|
||||
|
||||
sm_core_t smcore;
|
||||
IHandleSys *handlesys = &g_HandleSys;
|
||||
@@ -72,6 +73,9 @@ ISourcePawnEngine *g_pSourcePawn;
|
||||
ISourcePawnEngine2 *g_pSourcePawn2;
|
||||
CNativeOwner g_CoreNatives;
|
||||
IScriptManager *scripts = &g_PluginSys;
|
||||
IExtensionSys *extsys = &g_Extensions;
|
||||
ILogger *logger = &g_Logger;
|
||||
IMenuManager *menus;
|
||||
|
||||
static void AddCorePhraseFile(const char *filename)
|
||||
{
|
||||
@@ -104,16 +108,20 @@ static void DumpHandles(void (*dumpfn)(const char *fmt, ...))
|
||||
g_HandleSys.Dump(dumpfn);
|
||||
}
|
||||
|
||||
static void DumpAdminCache(FILE *f)
|
||||
static bool DumpAdminCache(const char *filename)
|
||||
{
|
||||
g_Admins.DumpCache(f);
|
||||
return g_Admins.DumpCache(filename);
|
||||
}
|
||||
|
||||
static void RegisterProfiler(IProfilingTool *tool)
|
||||
{
|
||||
g_ProfileToolManager.RegisterTool(tool);
|
||||
}
|
||||
|
||||
static sm_logic_t logic =
|
||||
{
|
||||
NULL,
|
||||
g_pThreader,
|
||||
sm_profiler,
|
||||
&g_Translator,
|
||||
stristr,
|
||||
CoreTranslate,
|
||||
@@ -128,6 +136,7 @@ static sm_logic_t logic =
|
||||
AddNatives,
|
||||
DumpHandles,
|
||||
DumpAdminCache,
|
||||
RegisterProfiler,
|
||||
&g_PluginSys,
|
||||
&g_ShareSys,
|
||||
&g_Extensions,
|
||||
@@ -135,6 +144,7 @@ static sm_logic_t logic =
|
||||
&g_Forwards,
|
||||
&g_Admins,
|
||||
NULL,
|
||||
&g_Logger,
|
||||
-1.0f
|
||||
};
|
||||
|
||||
@@ -153,6 +163,7 @@ static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
timersys = core->timersys;
|
||||
playerhelpers = core->playerhelpers;
|
||||
gamehelpers = core->gamehelpers;
|
||||
menus = core->menus;
|
||||
g_pSourcePawn = *core->spe1;
|
||||
g_pSourcePawn2 = *core->spe2;
|
||||
SMGlobalClass::head = core->listeners;
|
||||
|
||||
@@ -53,6 +53,9 @@ extern IPlayerManager *playerhelpers;
|
||||
extern IAdminSystem *adminsys;
|
||||
extern IGameHelpers *gamehelpers;
|
||||
extern IScriptManager *scripts;
|
||||
extern IExtensionSys *extsys;
|
||||
extern ILogger *logger;
|
||||
extern IMenuManager *menus;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2014 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_handle_helpers_h_
|
||||
#define _include_sourcemod_handle_helpers_h_
|
||||
|
||||
#include "common_logic.h"
|
||||
|
||||
// T must be a pointer type.
|
||||
template <typename T>
|
||||
class OpenHandle
|
||||
{
|
||||
public:
|
||||
OpenHandle()
|
||||
: t_(),
|
||||
error_(HandleError_None)
|
||||
{}
|
||||
explicit OpenHandle(T *t)
|
||||
: t_(t),
|
||||
error_(HandleError_None)
|
||||
{}
|
||||
OpenHandle(const OpenHandle &other)
|
||||
: t_(other.t_),
|
||||
error_(other.error_)
|
||||
{}
|
||||
OpenHandle(IPluginContext *cx, Handle_t handle, HandleType_t type)
|
||||
: t_(NULL)
|
||||
{
|
||||
HandleSecurity sec(cx->GetIdentity(), g_pCoreIdent);
|
||||
error_ = handlesys->ReadHandle(handle, type, &sec, (void **)&t_);
|
||||
if (error_ != HandleError_None)
|
||||
cx->ThrowNativeError("invalid handle %x (error: %d)", handle, error_);
|
||||
}
|
||||
|
||||
bool Ok() const {
|
||||
return t_ && error_ == HandleError_None;
|
||||
}
|
||||
|
||||
operator T *() const {
|
||||
assert(Ok());
|
||||
return t_;
|
||||
}
|
||||
T *operator *() const {
|
||||
assert(Ok());
|
||||
return t_;
|
||||
}
|
||||
T *operator ->() const {
|
||||
assert(Ok());
|
||||
return t_;
|
||||
}
|
||||
|
||||
OpenHandle &operator =(T *t) {
|
||||
t_ = t;
|
||||
error_ = HandleError_None;
|
||||
return *this;
|
||||
}
|
||||
OpenHandle &operator =(const OpenHandle &other) {
|
||||
t_ = other.t_;
|
||||
error_ = other.error_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *t_;
|
||||
HandleError error_;
|
||||
};
|
||||
|
||||
#endif // _include_sourcemod_handle_helpers_h_
|
||||
+29
-8
@@ -52,7 +52,7 @@ using namespace SourceHook;
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 28)
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
@@ -83,6 +83,7 @@ class IFileSystem_Logic
|
||||
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;
|
||||
@@ -90,6 +91,17 @@ public:
|
||||
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
|
||||
@@ -108,6 +120,7 @@ namespace SourceMod
|
||||
class IPhraseCollection;
|
||||
class ITranslator;
|
||||
class IGameConfig;
|
||||
class IMenuManager;
|
||||
}
|
||||
|
||||
class IVEngineServer;
|
||||
@@ -211,6 +224,15 @@ public:
|
||||
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 ILogger
|
||||
{
|
||||
public:
|
||||
virtual void LogMessage(const char *msg, ...) = 0;
|
||||
virtual void LogError(const char *msg, ...) = 0;
|
||||
virtual void LogFatal(const char *msg, ...) = 0;
|
||||
};
|
||||
|
||||
class AutoPluginList
|
||||
@@ -267,19 +289,17 @@ struct sm_core_t
|
||||
ITimerSystem *timersys;
|
||||
IPlayerManager *playerhelpers;
|
||||
IGameHelpers *gamehelpers;
|
||||
IMenuManager *menus;
|
||||
ISourcePawnEngine **spe1;
|
||||
ISourcePawnEngine2 **spe2;
|
||||
/* Functions */
|
||||
ConVar * (*FindConVar)(const char*);
|
||||
unsigned int (*strncopy)(char*, const char*, size_t);
|
||||
char * (*TrimWhitespace)(char *, size_t &);
|
||||
void (*LogError)(const char*, ...);
|
||||
void (*LogFatal)(const char*, ...);
|
||||
void (*Log)(const char*, ...);
|
||||
void (*LogToFile)(FILE *fp, const char*, ...);
|
||||
void (*LogToGame)(const char *message);
|
||||
void (*ConPrint)(const char *message);
|
||||
const char * (*GetCvarString)(ConVar*);
|
||||
bool (*GetCvarBool)(ConVar*);
|
||||
size_t (*Format)(char*, size_t, const char*, ...);
|
||||
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
|
||||
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
|
||||
@@ -317,7 +337,6 @@ struct sm_logic_t
|
||||
{
|
||||
SMGlobalClass *head;
|
||||
IThreader *threader;
|
||||
IProfiler *profiler;
|
||||
ITranslator *translator;
|
||||
const char *(*stristr)(const char *, const char *);
|
||||
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
|
||||
@@ -326,12 +345,13 @@ struct sm_logic_t
|
||||
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)();
|
||||
bool (*OnLogPrint)(const char *msg); // true to supercede
|
||||
bool (*OnLogPrint)(const char *msg); // true to supersede
|
||||
IDebugListener *debugger;
|
||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||
void (*AddNatives)(sp_nativeinfo_t *natives);
|
||||
void (*DumpHandles)(void (*dumpfn)(const char *fmt, ...));
|
||||
void (*DumpAdminCache)(FILE *);
|
||||
bool (*DumpAdminCache)(const char *filename);
|
||||
void (*RegisterProfiler)(IProfilingTool *tool);
|
||||
IScriptManager *scripts;
|
||||
IShareSys *sharesys;
|
||||
IExtensionSys *extsys;
|
||||
@@ -339,6 +359,7 @@ struct sm_logic_t
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
IdentityToken_t *core_ident;
|
||||
ILogger *logger;
|
||||
float sentinel;
|
||||
};
|
||||
|
||||
|
||||
@@ -582,5 +582,27 @@ REGISTER_NATIVES(cellArrayNatives)
|
||||
{"CloneArray", CloneArray},
|
||||
{"FindStringInArray", FindStringInArray},
|
||||
{"FindValueInArray", FindValueInArray},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"ArrayList.ArrayList", CreateArray},
|
||||
{"ArrayList.Clear", ClearArray},
|
||||
{"ArrayList.Length.get", GetArraySize},
|
||||
{"ArrayList.Resize", ResizeArray},
|
||||
{"ArrayList.Get", GetArrayCell},
|
||||
{"ArrayList.GetString", GetArrayString},
|
||||
{"ArrayList.GetArray", GetArrayArray},
|
||||
{"ArrayList.Push", PushArrayCell},
|
||||
{"ArrayList.PushString", PushArrayString},
|
||||
{"ArrayList.PushArray", PushArrayArray},
|
||||
{"ArrayList.Set", SetArrayCell},
|
||||
{"ArrayList.SetString", SetArrayString},
|
||||
{"ArrayList.SetArray", SetArrayArray},
|
||||
{"ArrayList.Erase", RemoveFromArray},
|
||||
{"ArrayList.ShiftUp", ShiftArrayUp},
|
||||
{"ArrayList.SwapAt", SwapArrayItems},
|
||||
{"ArrayList.Clone", CloneArray},
|
||||
{"ArrayList.FindString", FindStringInArray},
|
||||
{"ArrayList.FindValue", FindValueInArray},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
#include "handle_helpers.h"
|
||||
|
||||
HandleType_t htCellStack;
|
||||
|
||||
@@ -293,6 +294,79 @@ static cell_t IsStackEmpty(IPluginContext *pContext, const cell_t *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell_t ArrayStack_Pop(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
|
||||
if (!array.Ok())
|
||||
return 0;
|
||||
|
||||
if (array->size() == 0)
|
||||
return pContext->ThrowNativeError("stack is empty");
|
||||
|
||||
cell_t *blk = array->at(array->size() - 1);
|
||||
cell_t idx = (size_t)params[2];
|
||||
|
||||
cell_t rval;
|
||||
if (params[3] == 0) {
|
||||
if (idx >= array->blocksize())
|
||||
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
|
||||
rval = blk[idx];
|
||||
} else {
|
||||
if (idx >= array->blocksize() * 4)
|
||||
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
|
||||
rval = (cell_t)*((char *)blk + idx);
|
||||
}
|
||||
|
||||
array->remove(array->size() - 1);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static cell_t ArrayStack_PopString(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
|
||||
if (!array.Ok())
|
||||
return 0;
|
||||
|
||||
if (array->size() == 0)
|
||||
return pContext->ThrowNativeError("stack is empty");
|
||||
|
||||
size_t idx = array->size() - 1;
|
||||
cell_t *blk = array->at(idx);
|
||||
|
||||
cell_t *pWritten;
|
||||
pContext->LocalToPhysAddr(params[4], &pWritten);
|
||||
|
||||
size_t numWritten;
|
||||
pContext->StringToLocalUTF8(params[2], params[3], (char *)blk, &numWritten);
|
||||
*pWritten = (cell_t)numWritten;
|
||||
array->remove(idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t ArrayStack_PopArray(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
|
||||
if (!array.Ok())
|
||||
return 0;
|
||||
|
||||
if (array->size() == 0)
|
||||
return pContext->ThrowNativeError("stack is empty");
|
||||
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
size_t idx = array->size() - 1;
|
||||
cell_t *blk = array->at(idx);
|
||||
size_t indexes = array->blocksize();
|
||||
|
||||
if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
|
||||
indexes = params[3];
|
||||
|
||||
memcpy(addr, blk, sizeof(cell_t) * indexes);
|
||||
array->remove(idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(cellStackNatives)
|
||||
{
|
||||
{"CreateStack", CreateStack},
|
||||
@@ -303,5 +377,16 @@ REGISTER_NATIVES(cellStackNatives)
|
||||
{"PushStackArray", PushStackArray},
|
||||
{"PushStackCell", PushStackCell},
|
||||
{"PushStackString", PushStackString},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"ArrayStack.ArrayStack", CreateStack},
|
||||
{"ArrayStack.Pop", ArrayStack_Pop},
|
||||
{"ArrayStack.PopString", ArrayStack_PopString},
|
||||
{"ArrayStack.PopArray", ArrayStack_PopArray},
|
||||
{"ArrayStack.Push", PushStackCell},
|
||||
{"ArrayStack.PushString", PushStackString},
|
||||
{"ArrayStack.PushArray", PushStackArray},
|
||||
{"ArrayStack.Empty.get", IsStackEmpty},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -163,7 +163,7 @@ private:
|
||||
cell_t data_;
|
||||
};
|
||||
|
||||
struct CellTrie : public ke::Refcounted<CellTrie>
|
||||
struct CellTrie
|
||||
{
|
||||
StringHashMap<Entry> map;
|
||||
};
|
||||
@@ -204,8 +204,7 @@ public: //IHandleTypeDispatch
|
||||
{
|
||||
if (type == htCellTrie)
|
||||
{
|
||||
CellTrie *pTrie = (CellTrie *)object;
|
||||
pTrie->Release();
|
||||
delete (CellTrie *)object;
|
||||
} else {
|
||||
TrieSnapshot *snapshot = (TrieSnapshot *)object;
|
||||
delete snapshot;
|
||||
@@ -646,9 +645,28 @@ REGISTER_NATIVES(trieNatives)
|
||||
{"SetTrieString", SetTrieString},
|
||||
{"SetTrieValue", SetTrieValue},
|
||||
{"GetTrieSize", GetTrieSize},
|
||||
|
||||
{"CreateTrieSnapshot", CreateTrieSnapshot},
|
||||
{"TrieSnapshotLength", TrieSnapshotLength},
|
||||
{"TrieSnapshotKeyBufferSize", TrieSnapshotKeyBufferSize},
|
||||
{"GetTrieSnapshotKey", GetTrieSnapshotKey},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"StringMap.StringMap", CreateTrie},
|
||||
{"StringMap.Clear", ClearTrie},
|
||||
{"StringMap.GetArray", GetTrieArray},
|
||||
{"StringMap.GetString", GetTrieString},
|
||||
{"StringMap.GetValue", GetTrieValue},
|
||||
{"StringMap.Remove", RemoveFromTrie},
|
||||
{"StringMap.SetArray", SetTrieArray},
|
||||
{"StringMap.SetString", SetTrieString},
|
||||
{"StringMap.SetValue", SetTrieValue},
|
||||
{"StringMap.Size.get", GetTrieSize},
|
||||
{"StringMap.Snapshot", CreateTrieSnapshot},
|
||||
|
||||
{"StringMapSnapshot.Length.get", TrieSnapshotLength},
|
||||
{"StringMapSnapshot.KeyBufferSize", TrieSnapshotKeyBufferSize},
|
||||
{"StringMapSnapshot.GetKey", GetTrieSnapshotKey},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemod.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "TimerSys.h"
|
||||
#include "common_logic.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <ISourceMod.h>
|
||||
#include <ITranslator.h>
|
||||
|
||||
#include <sourcehook.h>
|
||||
#include <sh_memory.h>
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
@@ -50,9 +50,11 @@
|
||||
#endif
|
||||
|
||||
HandleType_t g_PlIter;
|
||||
ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules");
|
||||
|
||||
IForward *g_OnLogAction = NULL;
|
||||
|
||||
static ConVar *sm_datetime_format = NULL;
|
||||
|
||||
class CoreNativeHelpers :
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch
|
||||
@@ -75,6 +77,8 @@ public:
|
||||
Param_Cell,
|
||||
Param_Cell,
|
||||
Param_String);
|
||||
|
||||
sm_datetime_format = smcore.FindConVar("sm_datetime_format");
|
||||
}
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
@@ -119,14 +123,14 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess
|
||||
|
||||
g_Logger.LogMessage("[%s] %s", logtag, message);
|
||||
}
|
||||
|
||||
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
|
||||
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
|
||||
{
|
||||
@@ -138,7 +142,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
time_t t = GetAdjustedTime();
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[1], &addr);
|
||||
|
||||
@@ -168,14 +172,14 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (format == NULL)
|
||||
{
|
||||
format = const_cast<char *>(sm_datetime_format.GetString());
|
||||
format = const_cast<char *>(smcore.GetCvarString(sm_datetime_format));
|
||||
}
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
|
||||
#endif
|
||||
|
||||
time_t t = (params[4] == -1) ? GetAdjustedTime() : (time_t)params[4];
|
||||
time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4];
|
||||
size_t written = strftime(buffer, params[2], format, localtime(&t));
|
||||
|
||||
#if defined SUBPLATFORM_SECURECRT
|
||||
@@ -384,7 +388,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
pPlugin->SetErrorState(Plugin_Error, "%s", str);
|
||||
@@ -433,14 +437,14 @@ static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
|
||||
static char temp_file[PLATFORM_MAX_PATH];
|
||||
char *ptr;
|
||||
|
||||
g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
|
||||
libsys->GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
|
||||
if ((ptr = strstr(temp_str, ".smx")) != NULL)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
/* We have the raw filename! */
|
||||
UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
|
||||
g_pSM->Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
|
||||
cfg = temp_file;
|
||||
}
|
||||
|
||||
@@ -506,8 +510,8 @@ static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params)
|
||||
static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@@ -527,7 +531,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[1], &file);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (!fp)
|
||||
@@ -536,8 +540,8 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@@ -560,7 +564,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[1], &file);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (!fp)
|
||||
@@ -569,8 +573,8 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
@@ -653,10 +657,10 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
|
||||
char default_message[255];
|
||||
SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
|
||||
if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0')
|
||||
{
|
||||
UTIL_Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
|
||||
g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
|
||||
msg = default_message;
|
||||
}
|
||||
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
|
||||
@@ -743,19 +747,19 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
REGISTER_NATIVES(coreNatives)
|
||||
{
|
||||
{"AutoExecConfig", AutoExecConfig},
|
||||
{"GetPluginFilename", GetPluginFilename},
|
||||
{"GetPluginInfo", GetPluginInfo},
|
||||
{"GetPluginIterator", GetPluginIterator},
|
||||
{"GetPluginStatus", GetPluginStatus},
|
||||
{"GetSysTickCount", GetSysTickCount},
|
||||
{"ThrowError", ThrowError},
|
||||
{"GetTime", GetTime},
|
||||
{"IsPluginDebugging", IsPluginDebugging},
|
||||
{"FormatTime", FormatTime},
|
||||
{"GetPluginIterator", GetPluginIterator},
|
||||
{"MorePlugins", MorePlugins},
|
||||
{"ReadPlugin", ReadPlugin},
|
||||
{"ThrowError", ThrowError},
|
||||
{"GetPluginStatus", GetPluginStatus},
|
||||
{"GetPluginFilename", GetPluginFilename},
|
||||
{"IsPluginDebugging", IsPluginDebugging},
|
||||
{"GetPluginInfo", GetPluginInfo},
|
||||
{"SetFailState", SetFailState},
|
||||
{"FormatTime", FormatTime},
|
||||
{"GetSysTickCount", GetSysTickCount},
|
||||
{"AutoExecConfig", AutoExecConfig},
|
||||
{"MarkNativeAsOptional", MarkNativeAsOptional},
|
||||
{"RegPluginLibrary", RegPluginLibrary},
|
||||
{"LibraryExists", LibraryExists},
|
||||
@@ -770,5 +774,4 @@ REGISTER_NATIVES(coreNatives)
|
||||
{"LoadFromAddress", LoadFromAddress},
|
||||
{"StoreToAddress", StoreToAddress},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
};
|
||||
@@ -289,14 +289,20 @@ private:
|
||||
Handle_t m_MyHandle;
|
||||
};
|
||||
|
||||
enum AsyncCallbackMode {
|
||||
ACM_Old,
|
||||
ACM_New
|
||||
};
|
||||
|
||||
class TConnectOp : public IDBThreadOperation
|
||||
{
|
||||
public:
|
||||
TConnectOp(IPluginFunction *func, IDBDriver *driver, const char *_dbname, cell_t data)
|
||||
TConnectOp(IPluginFunction *func, IDBDriver *driver, const char *_dbname, AsyncCallbackMode acm, cell_t data)
|
||||
{
|
||||
m_pFunction = func;
|
||||
m_pDriver = driver;
|
||||
m_pDatabase = NULL;
|
||||
m_ACM = acm;
|
||||
m_Data = data;
|
||||
error[0] = '\0';
|
||||
strncopy(dbname, _dbname, sizeof(dbname));
|
||||
@@ -328,7 +334,8 @@ public:
|
||||
{
|
||||
m_pDatabase->Close();
|
||||
}
|
||||
m_pFunction->PushCell(BAD_HANDLE);
|
||||
if (m_ACM == ACM_Old)
|
||||
m_pFunction->PushCell(BAD_HANDLE);
|
||||
m_pFunction->PushCell(BAD_HANDLE);
|
||||
m_pFunction->PushString("Driver is unloading");
|
||||
m_pFunction->PushCell(m_Data);
|
||||
@@ -348,7 +355,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
m_pFunction->PushCell(m_pDriver->GetHandle());
|
||||
if (m_ACM == ACM_Old)
|
||||
m_pFunction->PushCell(m_pDriver->GetHandle());
|
||||
m_pFunction->PushCell(hndl);
|
||||
m_pFunction->PushString(hndl == BAD_HANDLE ? error : "");
|
||||
m_pFunction->PushCell(m_Data);
|
||||
@@ -363,6 +371,7 @@ private:
|
||||
IPluginFunction *m_pFunction;
|
||||
IDBDriver *m_pDriver;
|
||||
IDatabase *m_pDatabase;
|
||||
AsyncCallbackMode m_ACM;
|
||||
char dbname[64];
|
||||
char error[255];
|
||||
cell_t m_Data;
|
||||
@@ -401,7 +410,7 @@ static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params)
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
|
||||
static cell_t ConnectToDbAsync(IPluginContext *pContext, const cell_t *params, AsyncCallbackMode acm)
|
||||
{
|
||||
IPluginFunction *pf = pContext->GetFunctionById(params[1]);
|
||||
if (!pf)
|
||||
@@ -442,7 +451,8 @@ static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
|
||||
if (!pInfo || !driver)
|
||||
{
|
||||
pf->PushCell(BAD_HANDLE);
|
||||
pf->PushCell(BAD_HANDLE);
|
||||
if (acm == ACM_Old)
|
||||
pf->PushCell(BAD_HANDLE);
|
||||
pf->PushString(error);
|
||||
pf->PushCell(0);
|
||||
pf->Execute(NULL);
|
||||
@@ -457,7 +467,7 @@ static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
/* Finally, add to the thread if we can */
|
||||
TConnectOp *op = new TConnectOp(pf, driver, conf, params[3]);
|
||||
TConnectOp *op = new TConnectOp(pf, driver, conf, acm, params[3]);
|
||||
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
if (pPlugin->GetProperty("DisallowDBThreads", NULL)
|
||||
|| !g_DBMan.AddToThreadQueue(op, PrioQueue_High))
|
||||
@@ -471,6 +481,16 @@ static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return ConnectToDbAsync(pContext, params, ACM_Old);
|
||||
}
|
||||
|
||||
static cell_t Database_Connect(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return ConnectToDbAsync(pContext, params, ACM_New);
|
||||
}
|
||||
|
||||
static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IDBDriver *driver;
|
||||
@@ -1350,6 +1370,20 @@ static cell_t SQL_ReadDriver(IPluginContext *pContext, const cell_t *params)
|
||||
return driver->GetHandle();
|
||||
}
|
||||
|
||||
static cell_t Database_Driver_get(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IDatabase *db1=NULL;
|
||||
HandleError err;
|
||||
|
||||
if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db1))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid database Handle 1/%x (error: %d)", params[1], err);
|
||||
}
|
||||
|
||||
return db1->GetDriver()->GetHandle();
|
||||
}
|
||||
|
||||
static cell_t SQL_CheckConfig(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
@@ -1672,6 +1706,8 @@ public:
|
||||
failure_->PushCell(failIndex_);
|
||||
failure_->PushArray(data, txn_->entries.length());
|
||||
failure_->Execute(NULL);
|
||||
|
||||
handlesys->FreeHandle(dbh, &sec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1741,9 +1777,48 @@ static cell_t SQL_ExecuteTransaction(IPluginContext *pContext, const cell_t *par
|
||||
|
||||
REGISTER_NATIVES(dbNatives)
|
||||
{
|
||||
// Transitional syntax support.
|
||||
{"DBDriver.Find", SQL_GetDriver},
|
||||
{"DBDriver.GetIdentifier", SQL_GetDriverIdent},
|
||||
{"DBDriver.GetProduct", SQL_GetDriverProduct},
|
||||
|
||||
{"DBResultSet.FetchMoreResults", SQL_FetchMoreResults},
|
||||
{"DBResultSet.HasResults.get", SQL_HasResultSet},
|
||||
{"DBResultSet.RowCount.get", SQL_GetRowCount},
|
||||
{"DBResultSet.FieldCount.get", SQL_GetFieldCount},
|
||||
{"DBResultSet.AffectedRows.get", SQL_GetAffectedRows},
|
||||
{"DBResultSet.InsertId.get", SQL_GetInsertId},
|
||||
{"DBResultSet.FieldNameToNum", SQL_FieldNameToNum},
|
||||
{"DBResultSet.FieldNumToName", SQL_FieldNumToName},
|
||||
{"DBResultSet.FetchRow", SQL_FetchRow},
|
||||
{"DBResultSet.MoreRows.get", SQL_MoreRows},
|
||||
{"DBResultSet.Rewind", SQL_Rewind},
|
||||
{"DBResultSet.FetchString", SQL_FetchString},
|
||||
{"DBResultSet.FetchFloat", SQL_FetchFloat},
|
||||
{"DBResultSet.FetchInt", SQL_FetchInt},
|
||||
{"DBResultSet.IsFieldNull", SQL_IsFieldNull},
|
||||
{"DBResultSet.FetchSize", SQL_FetchSize},
|
||||
|
||||
{"Transaction.Transaction", SQL_CreateTransaction},
|
||||
{"Transaction.AddQuery", SQL_AddQuery},
|
||||
|
||||
{"DBStatement.BindInt", SQL_BindParamInt},
|
||||
{"DBStatement.BindFloat", SQL_BindParamFloat},
|
||||
{"DBStatement.BindString", SQL_BindParamString},
|
||||
|
||||
{"Database.Connect", Database_Connect},
|
||||
{"Database.Driver.get", Database_Driver_get},
|
||||
{"Database.SetCharset", SQL_SetCharset},
|
||||
{"Database.Escape", SQL_QuoteString},
|
||||
{"Database.IsSameConnection", SQL_IsSameConnection},
|
||||
{"Database.Execute", SQL_ExecuteTransaction},
|
||||
|
||||
// Note: The callback is ABI compatible so we can re-use the native.
|
||||
{"Database.Query", SQL_TQuery},
|
||||
|
||||
{"SQL_BindParamInt", SQL_BindParamInt},
|
||||
{"SQL_BindParamFloat", SQL_BindParamFloat},
|
||||
{"SQL_BindParamString", SQL_BindParamString},\
|
||||
{"SQL_BindParamString", SQL_BindParamString},
|
||||
{"SQL_CheckConfig", SQL_CheckConfig},
|
||||
{"SQL_Connect", SQL_Connect},
|
||||
{"SQL_ConnectEx", SQL_ConnectEx},
|
||||
|
||||
@@ -148,6 +148,27 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError herr;
|
||||
HandleSecurity sec;
|
||||
IDataPack *pDataPack;
|
||||
|
||||
sec.pOwner = pContext->GetIdentity();
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
pDataPack->PackFunction(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@@ -164,7 +185,7 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(cell_t)))
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
@@ -188,7 +209,7 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(float)))
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
@@ -223,6 +244,30 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError herr;
|
||||
HandleSecurity sec;
|
||||
IDataPack *pDataPack;
|
||||
|
||||
sec.pOwner = pContext->GetIdentity();
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
|
||||
}
|
||||
|
||||
return pDataPack->ReadFunction();
|
||||
}
|
||||
|
||||
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@@ -318,9 +363,11 @@ REGISTER_NATIVES(datapacknatives)
|
||||
{"WritePackCell", smn_WritePackCell},
|
||||
{"WritePackFloat", smn_WritePackFloat},
|
||||
{"WritePackString", smn_WritePackString},
|
||||
{"WritePackFunction", smn_WritePackFunction},
|
||||
{"ReadPackCell", smn_ReadPackCell},
|
||||
{"ReadPackFloat", smn_ReadPackFloat},
|
||||
{"ReadPackString", smn_ReadPackString},
|
||||
{"ReadPackFunction", smn_ReadPackFunction},
|
||||
{"ResetPack", smn_ResetPack},
|
||||
{"GetPackPosition", smn_GetPackPosition},
|
||||
{"SetPackPosition", smn_SetPackPosition},
|
||||
|
||||
@@ -441,6 +441,7 @@ REGISTER_NATIVES(nativeNatives)
|
||||
{"GetNativeArray", GetNativeArray},
|
||||
{"GetNativeCell", GetNativeCell},
|
||||
{"GetNativeCellRef", GetNativeCellRef},
|
||||
{"GetNativeFunction", GetNativeCell},
|
||||
{"GetNativeString", GetNativeString},
|
||||
{"GetNativeStringLength", GetNativeStringLength},
|
||||
{"FormatNativeString", FormatNativeString},
|
||||
|
||||
+609
-396
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,7 @@
|
||||
#include "MersenneTwister.h"
|
||||
#include <IPluginSys.h>
|
||||
#include <am-utility.h>
|
||||
#include <am-float.h>
|
||||
|
||||
/****************************************
|
||||
* *
|
||||
|
||||
@@ -53,6 +53,10 @@ static cell_t sm_IsValidHandle(IPluginContext *pContext, const cell_t *params)
|
||||
static cell_t sm_CloseHandle(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
|
||||
if (!hndl)
|
||||
return 0;
|
||||
|
||||
HandleSecurity sec;
|
||||
|
||||
sec.pIdentity = NULL;
|
||||
|
||||
@@ -202,8 +202,8 @@ public:
|
||||
{
|
||||
errmsg = "Unknown error";
|
||||
}
|
||||
smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||
logger->LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
logger->LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -29,20 +29,16 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "common_logic.h"
|
||||
#include <sh_stack.h>
|
||||
#include "MenuManager.h"
|
||||
#include "MenuStyle_Valve.h"
|
||||
#include "MenuStyle_Radio.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <IMenuManager.h>
|
||||
#include <IPlayerHelpers.h>
|
||||
#include "DebugReporter.h"
|
||||
#if defined MENU_DEBUG
|
||||
#include "Logger.h"
|
||||
#endif
|
||||
#include "ChatTriggers.h"
|
||||
#include "logic_bridge.h"
|
||||
#include "sourcemod.h"
|
||||
#include <ISourceMod.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined CreateMenu
|
||||
#undef CreateMenu
|
||||
@@ -68,6 +64,50 @@ enum MenuAction
|
||||
MenuAction_DisplayItem = (1<<9), /**< the odd duck */
|
||||
};
|
||||
|
||||
static HandleError ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
||||
{
|
||||
static HandleType_t menuType = NO_HANDLE_TYPE;
|
||||
if (menuType == NO_HANDLE_TYPE && !handlesys->FindHandleType("IBaseMenu", &menuType))
|
||||
{
|
||||
// This should never happen so exact error doesn't matter.
|
||||
return HandleError_Index;
|
||||
}
|
||||
|
||||
HandleSecurity sec;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
sec.pOwner = NULL;
|
||||
return handlesys->ReadHandle(handle, menuType, &sec, (void **)menu);
|
||||
}
|
||||
|
||||
static HandleError ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
||||
{
|
||||
static HandleType_t styleType = NO_HANDLE_TYPE;
|
||||
if (styleType == NO_HANDLE_TYPE && !handlesys->FindHandleType("IMenuStyle", &styleType))
|
||||
{
|
||||
// This should never happen so exact error doesn't matter.
|
||||
return HandleError_Index;
|
||||
}
|
||||
|
||||
HandleSecurity sec;
|
||||
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
sec.pOwner = g_pCoreIdent;
|
||||
|
||||
return handlesys->ReadHandle(handle, styleType, &sec, (void **)style);
|
||||
}
|
||||
|
||||
static IMenuStyle &ValveMenuStyle()
|
||||
{
|
||||
static IMenuStyle *valveMenuStyle = menus->FindStyleByName("valve");
|
||||
return *valveMenuStyle;
|
||||
}
|
||||
|
||||
static IMenuStyle &RadioMenuStyle()
|
||||
{
|
||||
static IMenuStyle *radioMenuStyle = menus->FindStyleByName("radio");
|
||||
return *radioMenuStyle;
|
||||
}
|
||||
|
||||
class CPanelHandler : public IMenuHandler
|
||||
{
|
||||
friend class MenuNativeHelpers;
|
||||
@@ -269,13 +309,13 @@ void CPanelHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
|
||||
{
|
||||
if (m_pFunc)
|
||||
{
|
||||
unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
|
||||
unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
|
||||
m_pFunc->PushCell(BAD_HANDLE);
|
||||
m_pFunc->PushCell(MenuAction_Select);
|
||||
m_pFunc->PushCell(client);
|
||||
m_pFunc->PushCell(item);
|
||||
m_pFunc->Execute(NULL);
|
||||
g_ChatTriggers.SetReplyTo(old_reply);
|
||||
playerhelpers->SetReplyTo(old_reply);
|
||||
}
|
||||
g_MenuHelpers.FreePanelHandler(this);
|
||||
}
|
||||
@@ -330,18 +370,18 @@ void CMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item,
|
||||
|
||||
s_CurSelectPosition = &first_item;
|
||||
|
||||
unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
|
||||
unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
|
||||
DoAction(menu, MenuAction_Select, client, item);
|
||||
g_ChatTriggers.SetReplyTo(old_reply);
|
||||
playerhelpers->SetReplyTo(old_reply);
|
||||
|
||||
s_CurSelectPosition = old_pos;
|
||||
}
|
||||
|
||||
void CMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
|
||||
{
|
||||
unsigned int old_reply = g_ChatTriggers.SetReplyTo(SM_REPLY_CHAT);
|
||||
unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
|
||||
DoAction(menu, MenuAction_Cancel, client, (cell_t)reason);
|
||||
g_ChatTriggers.SetReplyTo(old_reply);
|
||||
playerhelpers->SetReplyTo(old_reply);
|
||||
}
|
||||
|
||||
void CMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
|
||||
@@ -470,7 +510,7 @@ void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *
|
||||
if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
logicore.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
|
||||
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
|
||||
no_call = true;
|
||||
} else {
|
||||
cell_t target_offs = sizeof(cell_t) * results->num_clients;
|
||||
@@ -503,7 +543,7 @@ void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *
|
||||
if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
logicore.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
|
||||
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
|
||||
no_call = true;
|
||||
} else {
|
||||
cell_t target_offs = sizeof(cell_t) * results->num_items;
|
||||
@@ -592,14 +632,14 @@ inline IMenuStyle *GetStyleFromCell(cell_t cell)
|
||||
|
||||
if (cell == MenuStyle_Valve)
|
||||
{
|
||||
return &g_ValveMenuStyle;
|
||||
return &ValveMenuStyle();
|
||||
} else if (cell == MenuStyle_Radio
|
||||
&& g_RadioMenuStyle.IsSupported())
|
||||
&& RadioMenuStyle().IsSupported())
|
||||
{
|
||||
return &g_RadioMenuStyle;
|
||||
return &RadioMenuStyle();
|
||||
}
|
||||
|
||||
return g_Menus.GetDefaultStyle();
|
||||
return menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
/***********************************
|
||||
@@ -608,7 +648,7 @@ inline IMenuStyle *GetStyleFromCell(cell_t cell)
|
||||
|
||||
static cell_t CreateMenu(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IMenuStyle *style = g_Menus.GetDefaultStyle();
|
||||
IMenuStyle *style = menus->GetDefaultStyle();
|
||||
IPluginFunction *pFunction;
|
||||
|
||||
if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
|
||||
@@ -635,7 +675,7 @@ static cell_t DisplayMenu(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -649,7 +689,7 @@ static cell_t DisplayMenuAtItem(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -659,7 +699,7 @@ static cell_t DisplayMenuAtItem(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (g_Menus.IsVoteInProgress())
|
||||
if (menus->IsVoteInProgress())
|
||||
{
|
||||
return pContext->ThrowNativeError("A vote is already in progress");
|
||||
}
|
||||
@@ -668,7 +708,7 @@ static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -682,7 +722,7 @@ static cell_t VoteMenu(IPluginContext *pContext, const cell_t *params)
|
||||
flags = params[5];
|
||||
}
|
||||
|
||||
if (!g_Menus.StartVote(menu, params[3], addr, params[4], flags))
|
||||
if (!menus->StartVote(menu, params[3], addr, params[4], flags))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -696,7 +736,7 @@ static cell_t AddMenuItem(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -717,7 +757,7 @@ static cell_t InsertMenuItem(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -738,7 +778,7 @@ static cell_t RemoveMenuItem(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -752,7 +792,7 @@ static cell_t RemoveAllMenuItems(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -768,7 +808,7 @@ static cell_t GetMenuItem(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -797,7 +837,7 @@ static cell_t SetMenuPagination(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -811,7 +851,7 @@ static cell_t GetMenuPagination(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -825,7 +865,7 @@ static cell_t GetMenuItemCount(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -839,13 +879,13 @@ static cell_t SetMenuTitle(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
||||
|
||||
menu->SetDefaultTitle(buffer);
|
||||
|
||||
@@ -858,7 +898,7 @@ static cell_t GetMenuTitle(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -877,7 +917,7 @@ static cell_t CreatePanelFromMenu(IPluginContext *pContext, const cell_t *params
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -898,7 +938,7 @@ static cell_t GetMenuExitButton(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -912,7 +952,7 @@ static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *para
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -926,7 +966,7 @@ static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -952,7 +992,7 @@ static cell_t SetMenuNoVoteButton(IPluginContext *pContext, const cell_t *params
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -978,7 +1018,7 @@ static cell_t SetMenuExitBackButton(IPluginContext *pContext, const cell_t *para
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -1003,19 +1043,19 @@ static cell_t CancelMenu(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
g_Menus.CancelMenu(menu);
|
||||
menus->CancelMenu(menu);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t IsVoteInProgress(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Menus.IsVoteInProgress() ? 1 : 0;
|
||||
return menus->IsVoteInProgress() ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -1024,7 +1064,7 @@ static cell_t GetMenuStyle(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -1051,12 +1091,12 @@ static cell_t CreatePanel(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (hndl != 0)
|
||||
{
|
||||
if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
if ((err = ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
} else {
|
||||
style = g_Menus.GetDefaultStyle();
|
||||
style = menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
IMenuPanel *panel = style->CreatePanel();
|
||||
@@ -1079,12 +1119,12 @@ static cell_t CreateMenuEx(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (hndl != 0)
|
||||
{
|
||||
if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
if ((err = ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
} else {
|
||||
style = g_Menus.GetDefaultStyle();
|
||||
style = menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
IPluginFunction *pFunction;
|
||||
@@ -1114,12 +1154,12 @@ static cell_t GetClientMenu(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (hndl != 0)
|
||||
{
|
||||
if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
if ((err = ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
} else {
|
||||
style = g_Menus.GetDefaultStyle();
|
||||
style = menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
return style->GetClientMenu(params[1], NULL);
|
||||
@@ -1133,12 +1173,12 @@ static cell_t CancelClientMenu(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (hndl != 0)
|
||||
{
|
||||
if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
if ((err = ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
} else {
|
||||
style = g_Menus.GetDefaultStyle();
|
||||
style = menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
return style->CancelClientMenu(params[1], params[2] ? true : false) ? 1 : 0;
|
||||
@@ -1152,12 +1192,12 @@ static cell_t GetMaxPageItems(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (hndl != 0)
|
||||
{
|
||||
if ((err=g_Menus.ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
if ((err = ReadStyleHandle(params[1], &style)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("MenuStyle handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
} else {
|
||||
style = g_Menus.GetDefaultStyle();
|
||||
style = menus->GetDefaultStyle();
|
||||
}
|
||||
|
||||
return style->GetMaxPageItems();
|
||||
@@ -1354,7 +1394,7 @@ static cell_t GetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -1368,7 +1408,7 @@ static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -1380,12 +1420,12 @@ static cell_t SetMenuOptionFlags(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t CancelVote(IPluginContext *pContxt, const cell_t *params)
|
||||
{
|
||||
if (!g_Menus.IsVoteInProgress())
|
||||
if (!menus->IsVoteInProgress())
|
||||
{
|
||||
return pContxt->ThrowNativeError("No vote is in progress");
|
||||
}
|
||||
|
||||
g_Menus.CancelVoting();
|
||||
menus->CancelVoting();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1396,7 +1436,7 @@ static cell_t SetVoteResultCallback(IPluginContext *pContext, const cell_t *para
|
||||
HandleError err;
|
||||
IBaseMenu *menu;
|
||||
|
||||
if ((err=g_Menus.ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
if ((err = ReadMenuHandle(params[1], &menu)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
|
||||
}
|
||||
@@ -1422,7 +1462,7 @@ static cell_t SetVoteResultCallback(IPluginContext *pContext, const cell_t *para
|
||||
|
||||
static cell_t CheckVoteDelay(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Menus.GetRemainingVoteDelay();
|
||||
return menus->GetRemainingVoteDelay();
|
||||
}
|
||||
|
||||
static cell_t GetMenuSelectionPosition(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -1441,17 +1481,17 @@ static cell_t IsClientInVotePool(IPluginContext *pContext, const cell_t *params)
|
||||
IGamePlayer *pPlayer;
|
||||
|
||||
client = params[1];
|
||||
if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
|
||||
if ((pPlayer = playerhelpers->GetGamePlayer(client)) == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid client index %d", client);
|
||||
}
|
||||
|
||||
if (!g_Menus.IsVoteInProgress())
|
||||
if (!menus->IsVoteInProgress())
|
||||
{
|
||||
return pContext->ThrowNativeError("No vote is in progress");
|
||||
}
|
||||
|
||||
return g_Menus.IsClientInVotePool(client) ? 1 : 0;
|
||||
return menus->IsClientInVotePool(client) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t RedrawClientVoteMenu(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -1460,17 +1500,17 @@ static cell_t RedrawClientVoteMenu(IPluginContext *pContext, const cell_t *param
|
||||
IGamePlayer *pPlayer;
|
||||
|
||||
client = params[1];
|
||||
if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
|
||||
if ((pPlayer = playerhelpers->GetGamePlayer(client)) == NULL)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid client index %d", client);
|
||||
}
|
||||
|
||||
if (!g_Menus.IsVoteInProgress())
|
||||
if (!menus->IsVoteInProgress())
|
||||
{
|
||||
return pContext->ThrowNativeError("No vote is in progress");
|
||||
}
|
||||
|
||||
if (!g_Menus.IsClientInVotePool(client))
|
||||
if (!menus->IsClientInVotePool(client))
|
||||
{
|
||||
return pContext->ThrowNativeError("Client is not in the voting pool");
|
||||
}
|
||||
@@ -1481,7 +1521,7 @@ static cell_t RedrawClientVoteMenu(IPluginContext *pContext, const cell_t *param
|
||||
revote = false;
|
||||
}
|
||||
|
||||
return g_Menus.RedrawClientVoteMenu2(client, revote) ? 1 : 0;
|
||||
return menus->RedrawClientVoteMenu2(client, revote) ? 1 : 0;
|
||||
}
|
||||
|
||||
class EmptyMenuHandler : public IMenuHandler
|
||||
@@ -1492,7 +1532,7 @@ public:
|
||||
static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
int client = params[1];
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
|
||||
if (pPlayer == NULL)
|
||||
{
|
||||
@@ -1503,7 +1543,7 @@ static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Client %d is not in game", client);
|
||||
}
|
||||
|
||||
if (!g_RadioMenuStyle.IsSupported())
|
||||
if (!RadioMenuStyle().IsSupported())
|
||||
{
|
||||
return pContext->ThrowNativeError("Radio menus are not supported on this mod");
|
||||
}
|
||||
@@ -1511,13 +1551,16 @@ static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[2], &str);
|
||||
|
||||
IMenuPanel *pPanel = g_RadioMenuStyle.MakeRadioDisplay(str, params[4]);
|
||||
IMenuPanel *pPanel = RadioMenuStyle().CreatePanel();
|
||||
|
||||
if (pPanel == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pPanel->DirectSet(str);
|
||||
pPanel->SetSelectableKeys(params[4]);
|
||||
|
||||
IMenuHandler *pHandler;
|
||||
CPanelHandler *pActualHandler = NULL;
|
||||
if (params[5] != -1)
|
||||
@@ -1602,6 +1645,47 @@ REGISTER_NATIVES(menuNatives)
|
||||
{"SetVoteResultCallback", SetVoteResultCallback},
|
||||
{"VoteMenu", VoteMenu},
|
||||
{"SetMenuNoVoteButton", SetMenuNoVoteButton},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"Panel.Panel", CreatePanel},
|
||||
{"Panel.TextRemaining.get", GetPanelTextRemaining},
|
||||
{"Panel.CurrentKey.get", GetPanelCurrentKey},
|
||||
{"Panel.CurrentKey.set", SetPanelCurrentKey},
|
||||
{"Panel.Style", GetPanelStyle},
|
||||
{"Panel.CanDrawFlags", CanPanelDrawFlags},
|
||||
{"Panel.SetTitle", SetPanelTitle},
|
||||
{"Panel.SetKeys", SetPanelKeys},
|
||||
{"Panel.Send", SendPanelToClient},
|
||||
{"Panel.DrawItem", DrawPanelItem},
|
||||
{"Panel.DrawText", DrawPanelText},
|
||||
|
||||
{"Menu.Menu", CreateMenu},
|
||||
{"Menu.Display", DisplayMenu},
|
||||
{"Menu.DisplayAt", DisplayMenuAtItem},
|
||||
{"Menu.AddItem", AddMenuItem},
|
||||
{"Menu.InsertItem", InsertMenuItem},
|
||||
{"Menu.RemoveItem", RemoveMenuItem},
|
||||
{"Menu.RemoveAllItems", RemoveAllMenuItems},
|
||||
{"Menu.GetItem", GetMenuItem},
|
||||
{"Menu.GetTitle", GetMenuTitle},
|
||||
{"Menu.SetTitle", SetMenuTitle},
|
||||
{"Menu.ToPanel", CreatePanelFromMenu},
|
||||
{"Menu.Cancel", CancelMenu},
|
||||
{"Menu.DisplayVote", VoteMenu},
|
||||
{"Menu.Pagination.get", GetMenuPagination},
|
||||
{"Menu.Pagination.set", SetMenuPagination},
|
||||
{"Menu.OptionFlags.get", GetMenuOptionFlags},
|
||||
{"Menu.OptionFlags.set", SetMenuOptionFlags},
|
||||
{"Menu.ExitButton.get", GetMenuExitButton},
|
||||
{"Menu.ExitButton.set", SetMenuExitButton},
|
||||
{"Menu.ExitBackButton.get", GetMenuExitBackButton},
|
||||
{"Menu.ExitBackButton.set", SetMenuExitBackButton},
|
||||
{"Menu.NoVoteButton.set", SetMenuNoVoteButton},
|
||||
{"Menu.VoteResultCallback.set", SetVoteResultCallback},
|
||||
{"Menu.ItemCount.get", GetMenuItemCount},
|
||||
{"Menu.Style.get", GetMenuStyle},
|
||||
{"Menu.Selection.get", GetMenuSelectionPosition},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
+88
-16
@@ -37,12 +37,21 @@
|
||||
#include <ITranslator.h>
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
#include "GameConfigs.h"
|
||||
#include "CellArray.h"
|
||||
#include "AutoHandleRooter.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
#ifndef PRIu64
|
||||
#ifdef _WIN32
|
||||
#define PRIu64 "I64u"
|
||||
#else
|
||||
#define PRIu64 "llu"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const int kActivityNone = 0;
|
||||
static const int kActivityNonAdmins = 1; // Show admin activity to non-admins anonymously.
|
||||
static const int kActivityNonAdminsNames = 2; // If 1 is specified, admin names will be shown.
|
||||
@@ -120,7 +129,7 @@ public: //ICommandTargetProcessor
|
||||
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
|
||||
AutoHandleCloner ahc(hndl, sec);
|
||||
if (ahc.getClone() == BAD_HANDLE) {
|
||||
smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
|
||||
logger->LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
|
||||
delete array;
|
||||
return false;
|
||||
}
|
||||
@@ -322,9 +331,17 @@ static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
|
||||
// Must match clients.inc
|
||||
enum class AuthIdType
|
||||
{
|
||||
Engine = 0,
|
||||
Steam2,
|
||||
Steam3,
|
||||
SteamId64,
|
||||
};
|
||||
|
||||
static cell_t SteamIdToLocal(IPluginContext *pCtx, int index, AuthIdType authType, cell_t local_addr, size_t bytes, bool validate)
|
||||
{
|
||||
int index = params[1];
|
||||
if ((index < 1) || (index > playerhelpers->GetMaxClients()))
|
||||
{
|
||||
return pCtx->ThrowNativeError("Client index %d is invalid", index);
|
||||
@@ -335,25 +352,79 @@ static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Client %d is not connected", index);
|
||||
}
|
||||
|
||||
bool validate = true;
|
||||
if (params[0] > 3)
|
||||
{
|
||||
validate = !!params[4];
|
||||
}
|
||||
|
||||
const char *authstr = pPlayer->GetAuthString(validate);
|
||||
|
||||
if (!authstr || authstr[0] == '\0')
|
||||
|
||||
const char *authstr;
|
||||
|
||||
switch (authType)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
case AuthIdType::Engine:
|
||||
authstr = pPlayer->GetAuthString(validate);
|
||||
if (!authstr || authstr[0] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), authstr);
|
||||
pCtx->StringToLocal(local_addr, bytes, authstr);
|
||||
break;
|
||||
case AuthIdType::Steam2:
|
||||
authstr = pPlayer->GetSteam2Id(validate);
|
||||
if (!authstr || authstr[0] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCtx->StringToLocal(local_addr, bytes, authstr);
|
||||
break;
|
||||
case AuthIdType::Steam3:
|
||||
authstr = pPlayer->GetSteam3Id(validate);
|
||||
if (!authstr || authstr[0] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCtx->StringToLocal(local_addr, bytes, authstr);
|
||||
break;
|
||||
|
||||
case AuthIdType::SteamId64:
|
||||
{
|
||||
if (pPlayer->IsFakeClient() || gamehelpers->IsLANServer())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t steamId = pPlayer->GetSteamId64(validate);
|
||||
if (steamId == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char szAuth[64];
|
||||
snprintf(szAuth, sizeof(szAuth), "%" PRIu64, steamId);
|
||||
|
||||
pCtx->StringToLocal(local_addr, bytes, szAuth);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
bool validate = true;
|
||||
if (params[0] >= 4)
|
||||
{
|
||||
validate = !!params[4];
|
||||
}
|
||||
|
||||
return SteamIdToLocal(pCtx, params[1], AuthIdType::Steam2, params[2], (size_t)params[3], validate);
|
||||
}
|
||||
|
||||
static cell_t sm_GetClientAuthId(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
return SteamIdToLocal(pCtx, params[1], (AuthIdType)params[2], params[3], (size_t)params[4], params[5] != 0);
|
||||
}
|
||||
|
||||
static cell_t sm_GetSteamAccountID(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
int index = params[1];
|
||||
@@ -1540,6 +1611,7 @@ REGISTER_NATIVES(playernatives)
|
||||
{ "CanUserTarget", CanUserTarget },
|
||||
{ "ChangeClientTeam", ChangeClientTeam },
|
||||
{ "GetClientAuthString", sm_GetClientAuthStr },
|
||||
{ "GetClientAuthId", sm_GetClientAuthId },
|
||||
{ "GetSteamAccountID", sm_GetSteamAccountID },
|
||||
{ "GetClientCount", sm_GetClientCount },
|
||||
{ "GetClientInfo", sm_GetClientInfo },
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include "ProfileTools.h"
|
||||
|
||||
struct Profiler
|
||||
{
|
||||
@@ -185,12 +186,42 @@ static cell_t GetProfilerTime(IPluginContext *pContext, const cell_t *params)
|
||||
return sp_ftoc(fTime);
|
||||
}
|
||||
|
||||
static cell_t EnterProfilingEvent(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *group;
|
||||
pContext->LocalToString(params[1], &group);
|
||||
|
||||
char *name;
|
||||
pContext->LocalToString(params[2], &name);
|
||||
|
||||
const char *groupname = NULL;
|
||||
if (strcmp(group, "all") != 0)
|
||||
groupname = group;
|
||||
|
||||
g_ProfileToolManager.EnterScope(groupname, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t LeaveProfilingEvent(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
g_ProfileToolManager.LeaveScope();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t IsProfilingActive(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_ProfileToolManager.IsActive() ? 1 : 0;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(profilerNatives)
|
||||
{
|
||||
{"CreateProfiler", CreateProfiler},
|
||||
{"GetProfilerTime", GetProfilerTime},
|
||||
{"StartProfiling", StartProfiling},
|
||||
{"StopProfiling", StopProfiling},
|
||||
{"EnterProfilingEvent", EnterProfilingEvent},
|
||||
{"LeaveProfilingEvent", LeaveProfilingEvent},
|
||||
{"IsProfilingActive", IsProfilingActive},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "common_logic.h"
|
||||
#include <ITextParsers.h>
|
||||
#include <ISourceMod.h>
|
||||
#include "handle_helpers.h"
|
||||
|
||||
HandleType_t g_TypeSMC = 0;
|
||||
|
||||
@@ -199,90 +200,51 @@ static cell_t SMC_CreateParser(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t SMC_SetParseStart(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = (Handle_t)params[1];
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, &sec, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->parse_start = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMC_SetParseEnd(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = (Handle_t)params[1];
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, &sec, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->parse_end = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMC_SetReaders(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = (Handle_t)params[1];
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, &sec, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->new_section = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
parse->key_value = pContext->GetFunctionById((funcid_t)params[3]);
|
||||
parse->end_section = pContext->GetFunctionById((funcid_t)params[4]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMC_SetRawLine(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = (Handle_t)params[1];
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, &sec, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->raw_line = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = (Handle_t)params[1];
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, &sec, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
char *file;
|
||||
pContext->LocalToString(params[2], &file);
|
||||
@@ -299,21 +261,63 @@ static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
*c_line = states.line;
|
||||
*c_col = states.col;
|
||||
|
||||
return (cell_t)p_err;
|
||||
}
|
||||
|
||||
static cell_t SMC_GetErrorString(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
const char *str = textparsers->GetSMCErrorString((SMCError)params[1]);
|
||||
|
||||
if (!str)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pContext->StringToLocal(params[2], params[3], str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMCParser_OnEnterSection_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->new_section = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMCParser_OnLeaveSection_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->end_section = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMCParser_OnKeyValue_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
parse->key_value = pContext->GetFunctionById((funcid_t)params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SMCParser_GetErrorString(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
OpenHandle<ParseInfo> parse(pContext, params[1], g_TypeSMC);
|
||||
if (!parse.Ok())
|
||||
return 0;
|
||||
|
||||
const char *str = "no error";
|
||||
if (params[2]) {
|
||||
str = textparsers->GetSMCErrorString((SMCError)params[2]);
|
||||
if (!str)
|
||||
str = "unknown error";
|
||||
}
|
||||
|
||||
pContext->StringToLocal(params[3], params[4], str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -326,5 +330,17 @@ REGISTER_NATIVES(textNatives)
|
||||
{"SMC_SetParseEnd", SMC_SetParseEnd},
|
||||
{"SMC_SetReaders", SMC_SetReaders},
|
||||
{"SMC_SetRawLine", SMC_SetRawLine},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"SMCParser.SMCParser", SMC_CreateParser},
|
||||
{"SMCParser.ParseFile", SMC_ParseFile},
|
||||
{"SMCParser.OnStart.set", SMC_SetParseStart},
|
||||
{"SMCParser.OnEnd.set", SMC_SetParseEnd},
|
||||
{"SMCParser.OnEnterSection.set", SMCParser_OnEnterSection_set},
|
||||
{"SMCParser.OnLeaveSection.set", SMCParser_OnLeaveSection_set},
|
||||
{"SMCParser.OnKeyValue.set", SMCParser_OnKeyValue_set},
|
||||
{"SMCParser.OnRawLine.set", SMC_SetRawLine},
|
||||
{"SMCParser.GetErrorString", SMCParser_GetErrorString},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
+59
-39
@@ -43,6 +43,7 @@
|
||||
#include "logic_bridge.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "MenuManager.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "ConCmdManager.h"
|
||||
#include "IDBDriver.h"
|
||||
@@ -86,6 +87,7 @@ IExtensionSys *extsys;
|
||||
IHandleSys *handlesys;
|
||||
IForwardManager *forwardsys;
|
||||
IAdminSystem *adminsys;
|
||||
ILogger *logger;
|
||||
|
||||
class VEngineServer_Logic : public IVEngineServer_Logic
|
||||
{
|
||||
@@ -146,6 +148,10 @@ public:
|
||||
{
|
||||
return filesystem->FindNext(handle);
|
||||
}
|
||||
bool FindIsDirectory(FileFindHandle_t handle)
|
||||
{
|
||||
return filesystem->FindIsDirectory(handle);
|
||||
}
|
||||
void FindClose(FileFindHandle_t handle)
|
||||
{
|
||||
filesystem->FindClose(handle);
|
||||
@@ -174,6 +180,50 @@ public:
|
||||
{
|
||||
return filesystem->Size(pFileName, pPathID);
|
||||
}
|
||||
int Read(void* pOutput, int size, FileHandle_t file)
|
||||
{
|
||||
return filesystem->Read(pOutput, size, file);
|
||||
}
|
||||
int Write(void const* pInput, int size, FileHandle_t file)
|
||||
{
|
||||
return filesystem->Write(pInput, size, file);
|
||||
}
|
||||
void Seek(FileHandle_t file, int pos, int seekType)
|
||||
{
|
||||
filesystem->Seek(file, pos, (FileSystemSeek_t) seekType);
|
||||
}
|
||||
unsigned int Tell(FileHandle_t file)
|
||||
{
|
||||
return filesystem->Tell(file);
|
||||
}
|
||||
int FPrint(FileHandle_t file, const char *pData)
|
||||
{
|
||||
return filesystem->FPrintf(file, "%s", pData);
|
||||
}
|
||||
void Flush(FileHandle_t file)
|
||||
{
|
||||
filesystem->Flush(file);
|
||||
}
|
||||
bool IsOk(FileHandle_t file)
|
||||
{
|
||||
return filesystem->IsOk(file);
|
||||
}
|
||||
void RemoveFile(const char *pRelativePath, const char *pathID)
|
||||
{
|
||||
filesystem->RemoveFile(pRelativePath, pathID);
|
||||
}
|
||||
void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID)
|
||||
{
|
||||
filesystem->RenameFile(pOldPath, pNewPath, pathID);
|
||||
}
|
||||
bool IsDirectory(const char *pFileName, const char *pathID)
|
||||
{
|
||||
return filesystem->IsDirectory(pFileName, pathID);
|
||||
}
|
||||
void CreateDirHierarchy(const char *path, const char *pathID)
|
||||
{
|
||||
filesystem->CreateDirHierarchy(path, pathID);
|
||||
}
|
||||
};
|
||||
|
||||
static VFileSystem_Logic logic_filesystem;
|
||||
@@ -251,46 +301,13 @@ static VPlayerInfo_Logic logic_playerinfo;
|
||||
|
||||
static ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)");
|
||||
static ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection");
|
||||
static ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules");
|
||||
|
||||
static ConVar *find_convar(const char *name)
|
||||
{
|
||||
return icvar->FindVar(name);
|
||||
}
|
||||
|
||||
static void log_error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogErrorEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_fatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogFatalEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_message(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogMessageEx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_to_file(FILE *fp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
g_Logger.LogToOpenFileEx(fp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_to_game(const char *message)
|
||||
{
|
||||
Engine_LogPrintWrapper(message);
|
||||
@@ -306,6 +323,11 @@ static const char *get_cvar_string(ConVar* cvar)
|
||||
return cvar->GetString();
|
||||
}
|
||||
|
||||
static bool get_cvar_bool(ConVar* cvar)
|
||||
{
|
||||
return cvar->GetBool();
|
||||
}
|
||||
|
||||
static bool get_game_name(char *buffer, size_t maxlength)
|
||||
{
|
||||
KeyValues *pGameInfo = new KeyValues("GameInfo");
|
||||
@@ -555,19 +577,17 @@ static sm_core_t core_bridge =
|
||||
&g_Timers,
|
||||
&g_Players,
|
||||
&g_HL2,
|
||||
&g_Menus,
|
||||
&g_pSourcePawn,
|
||||
&g_pSourcePawn2,
|
||||
/* Functions */
|
||||
find_convar,
|
||||
strncopy,
|
||||
UTIL_TrimWhitespace,
|
||||
log_error,
|
||||
log_fatal,
|
||||
log_message,
|
||||
log_to_file,
|
||||
log_to_game,
|
||||
conprint,
|
||||
get_cvar_string,
|
||||
get_cvar_bool,
|
||||
UTIL_Format,
|
||||
UTIL_FormatArgs,
|
||||
gnprintf,
|
||||
@@ -628,7 +648,6 @@ void InitLogicBridge()
|
||||
glob->m_pGlobalClassNext = logicore.head;
|
||||
|
||||
g_pThreader = logicore.threader;
|
||||
g_pSourcePawn2->SetProfiler(logicore.profiler);
|
||||
translator = logicore.translator;
|
||||
scripts = logicore.scripts;
|
||||
sharesys = logicore.sharesys;
|
||||
@@ -637,6 +656,7 @@ void InitLogicBridge()
|
||||
handlesys = logicore.handlesys;
|
||||
forwardsys = logicore.forwardsys;
|
||||
adminsys = logicore.adminsys;
|
||||
logger = logicore.logger;
|
||||
}
|
||||
|
||||
bool StartLogicBridge(char *error, size_t maxlength)
|
||||
|
||||
@@ -48,5 +48,6 @@ extern IExtensionSys *extsys;
|
||||
extern IHandleSys *handlesys;
|
||||
extern IForwardManager *forwardsys;
|
||||
extern IAdminSystem *adminsys;
|
||||
extern ILogger *logger;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */
|
||||
|
||||
+1
-7
@@ -424,21 +424,15 @@ CON_COMMAND(sm_reload_translations, "Reparses all loaded translation files")
|
||||
|
||||
CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging")
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
|
||||
|
||||
if ((fp = fopen(buffer, "wt")) == NULL)
|
||||
if (!logicore.DumpAdminCache(buffer))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
logicore.DumpAdminCache(fp);
|
||||
|
||||
g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "logic_bridge.h"
|
||||
#include "sourcemod.h"
|
||||
#include <am-utility.h>
|
||||
#include <am-float.h>
|
||||
|
||||
#define LADJUST 0x00000004 /* left adjustment */
|
||||
#define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
|
||||
|
||||
@@ -717,6 +717,39 @@ REGISTER_NATIVES(bitbufnatives)
|
||||
{"BfReadVecNormal", smn_BfReadVecNormal},
|
||||
{"BfReadAngles", smn_BfReadAngles},
|
||||
{"BfGetNumBytesLeft", smn_BfGetNumBytesLeft},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"BfWrite.WriteBool", smn_BfWriteBool},
|
||||
{"BfWrite.WriteByte", smn_BfWriteByte},
|
||||
{"BfWrite.WriteChar", smn_BfWriteChar},
|
||||
{"BfWrite.WriteShort", smn_BfWriteShort},
|
||||
{"BfWrite.WriteWord", smn_BfWriteWord},
|
||||
{"BfWrite.WriteNum", smn_BfWriteNum},
|
||||
{"BfWrite.WriteFloat", smn_BfWriteFloat},
|
||||
{"BfWrite.WriteString", smn_BfWriteString},
|
||||
{"BfWrite.WriteEntity", smn_BfWriteEntity},
|
||||
{"BfWrite.WriteAngle", smn_BfWriteAngle},
|
||||
{"BfWrite.WriteCoord", smn_BfWriteCoord},
|
||||
{"BfWrite.WriteVecCoord", smn_BfWriteVecCoord},
|
||||
{"BfWrite.WriteVecNormal", smn_BfWriteVecNormal},
|
||||
{"BfWrite.WriteAngles", smn_BfWriteAngles},
|
||||
|
||||
{"BfRead.ReadBool", smn_BfReadBool},
|
||||
{"BfRead.ReadByte", smn_BfReadByte},
|
||||
{"BfRead.ReadChar", smn_BfReadChar},
|
||||
{"BfRead.ReadShort", smn_BfReadShort},
|
||||
{"BfRead.ReadWord", smn_BfReadWord},
|
||||
{"BfRead.ReadNum", smn_BfReadNum},
|
||||
{"BfRead.ReadFloat", smn_BfReadFloat},
|
||||
{"BfRead.ReadString", smn_BfReadString},
|
||||
{"BfRead.ReadEntity", smn_BfReadEntity},
|
||||
{"BfRead.ReadAngle", smn_BfReadAngle},
|
||||
{"BfRead.ReadCoord", smn_BfReadCoord},
|
||||
{"BfRead.ReadVecCoord", smn_BfReadVecCoord},
|
||||
{"BfRead.ReadVecNormal", smn_BfReadVecNormal},
|
||||
{"BfRead.ReadAngles", smn_BfReadAngles},
|
||||
{"BfRead.BytesLeft.get", smn_BfGetNumBytesLeft},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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 "HalfLife2.h"
|
||||
|
||||
static cell_t sm_GetCommandLine(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
ICommandLine *pCmdLine = g_HL2.GetValveCommandLine();
|
||||
|
||||
if (pCmdLine == NULL)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to get valve command line");
|
||||
}
|
||||
|
||||
const char *commandLine = pCmdLine->GetCmdLine();
|
||||
|
||||
if (commandLine == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCtx->StringToLocal(params[1], params[2], commandLine);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_GetCommandLineParam(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
ICommandLine *pCmdLine = g_HL2.GetValveCommandLine();
|
||||
|
||||
if (pCmdLine == NULL)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to get valve command line");
|
||||
}
|
||||
|
||||
char *param = NULL;
|
||||
char *defValue = NULL;
|
||||
pCtx->LocalToString(params[1], ¶m);
|
||||
pCtx->LocalToString(params[4], ¶m);
|
||||
|
||||
const char *value = pCmdLine->ParmValue(param, defValue);
|
||||
|
||||
pCtx->StringToLocal(params[2], params[3], value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_GetCommandLineParamInt(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
ICommandLine *pCmdLine = g_HL2.GetValveCommandLine();
|
||||
|
||||
if (pCmdLine == NULL)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to get valve command line");
|
||||
}
|
||||
|
||||
char *param = NULL;
|
||||
pCtx->LocalToString(params[1], ¶m);
|
||||
|
||||
return pCmdLine->ParmValue(param, params[2]);
|
||||
}
|
||||
|
||||
static cell_t sm_GetCommandLineParamFloat(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
ICommandLine *pCmdLine = g_HL2.GetValveCommandLine();
|
||||
|
||||
if (pCmdLine == NULL)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to get valve command line");
|
||||
}
|
||||
|
||||
char *param = NULL;
|
||||
pCtx->LocalToString(params[1], ¶m);
|
||||
|
||||
float value = pCmdLine->ParmValue(param, sp_ctof(params[2]));
|
||||
|
||||
return sp_ftoc(value);
|
||||
}
|
||||
|
||||
static cell_t sm_FindCommandLineParam(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
ICommandLine *pCmdLine = g_HL2.GetValveCommandLine();
|
||||
|
||||
if (pCmdLine == NULL)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Unable to get valve command line");
|
||||
}
|
||||
|
||||
char *param = NULL;
|
||||
pCtx->LocalToString(params[1], ¶m);
|
||||
|
||||
return pCmdLine->FindParm(param);
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(commandlinenatives)
|
||||
{
|
||||
{"GetCommandLine", sm_GetCommandLine},
|
||||
{"GetCommandLineParam", sm_GetCommandLineParam},
|
||||
{"GetCommandLineParamInt", sm_GetCommandLineParamInt},
|
||||
{"GetCommandLineParamFloat", sm_GetCommandLineParamFloat},
|
||||
{"FindCommandLineParam", sm_FindCommandLineParam},
|
||||
{NULL, NULL},
|
||||
};
|
||||
+78
-10
@@ -1182,28 +1182,19 @@ static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
|
||||
}
|
||||
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client %d is not connected", params[1]);
|
||||
}
|
||||
|
||||
if (pPlayer->IsFakeClient())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client %d is fake and cannot be targeted", params[1]);
|
||||
}
|
||||
|
||||
INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
|
||||
if (netchan == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
netchan->SendData(buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1216,7 +1207,7 @@ static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (strcasecmp(name, "sm") == 0)
|
||||
{
|
||||
g_Logger.LogError("Request to register \"sm\" command denied.");
|
||||
logger->LogError("Request to register \"sm\" command denied.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1247,6 +1238,59 @@ static cell_t RemoveCommandListener(IPluginContext *pContext, const cell_t *para
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t ConVar_BoolValue_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static cell_t new_params[5] = {
|
||||
4,
|
||||
params[1],
|
||||
params[2],
|
||||
0, /* Default replicate setting. */
|
||||
0, /* Default replicate setting. */
|
||||
};
|
||||
|
||||
return sm_SetConVarNum(pContext, new_params);
|
||||
}
|
||||
|
||||
static cell_t ConVar_IntValue_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static cell_t new_params[5] = {
|
||||
4,
|
||||
params[1],
|
||||
params[2],
|
||||
0, /* Default replicate setting. */
|
||||
0, /* Default replicate setting. */
|
||||
};
|
||||
|
||||
return sm_SetConVarNum(pContext, new_params);
|
||||
}
|
||||
|
||||
static cell_t ConVar_FloatValue_set(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static cell_t new_params[5] = {
|
||||
4,
|
||||
params[1],
|
||||
params[2],
|
||||
0, /* Default replicate setting. */
|
||||
0, /* Default replicate setting. */
|
||||
};
|
||||
|
||||
return sm_SetConVarFloat(pContext, new_params);
|
||||
}
|
||||
|
||||
static cell_t ConVar_ReplicateToClient(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
// Old version is (client, handle, value).
|
||||
// New version is (handle, client, value).
|
||||
static cell_t new_params[4] = {
|
||||
3,
|
||||
params[2],
|
||||
params[1],
|
||||
params[3],
|
||||
};
|
||||
|
||||
return SendConVarValue(pContext, new_params);
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(consoleNatives)
|
||||
{
|
||||
{"CreateConVar", sm_CreateConVar},
|
||||
@@ -1287,5 +1331,29 @@ REGISTER_NATIVES(consoleNatives)
|
||||
{"SendConVarValue", SendConVarValue},
|
||||
{"AddCommandListener", AddCommandListener},
|
||||
{"RemoveCommandListener", RemoveCommandListener},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"ConVar.BoolValue.get", sm_GetConVarBool},
|
||||
{"ConVar.BoolValue.set", ConVar_BoolValue_set},
|
||||
{"ConVar.FloatValue.get", sm_GetConVarFloat},
|
||||
{"ConVar.FloatValue.set", ConVar_FloatValue_set},
|
||||
{"ConVar.IntValue.get", sm_GetConVarInt},
|
||||
{"ConVar.IntValue.set", ConVar_IntValue_set},
|
||||
{"ConVar.Flags.get", sm_GetConVarFlags},
|
||||
{"ConVar.Flags.set", sm_SetConVarFlags},
|
||||
{"ConVar.SetBool", sm_SetConVarNum},
|
||||
{"ConVar.SetInt", sm_SetConVarNum},
|
||||
{"ConVar.SetFloat", sm_SetConVarFloat},
|
||||
{"ConVar.GetString", sm_GetConVarString},
|
||||
{"ConVar.SetString", sm_SetConVarString},
|
||||
{"ConVar.RestoreDefault", sm_ResetConVar},
|
||||
{"ConVar.GetDefault", GetConVarDefault},
|
||||
{"ConVar.GetBounds", sm_GetConVarBounds},
|
||||
{"ConVar.SetBounds", sm_SetConVarBounds},
|
||||
{"ConVar.GetName", sm_GetConVarName},
|
||||
{"ConVar.ReplicateToClient", ConVar_ReplicateToClient},
|
||||
{"ConVar.AddChangeHook", sm_HookConVarChange},
|
||||
{"ConVar.RemoveChangeHook", sm_UnhookConVarChange},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
+112
-30
@@ -1519,6 +1519,13 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum PropEntType
|
||||
{
|
||||
PropEnt_Handle,
|
||||
PropEnt_Entity,
|
||||
PropEnt_Edict,
|
||||
};
|
||||
|
||||
static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CBaseEntity *pEntity;
|
||||
@@ -1526,6 +1533,7 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
int offset;
|
||||
int bit_count;
|
||||
edict_t *pEdict;
|
||||
PropEntType type;
|
||||
|
||||
int element = 0;
|
||||
if (params[0] >= 4)
|
||||
@@ -1548,12 +1556,23 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
FIND_PROP_DATA(td);
|
||||
|
||||
if (td->fieldType != FIELD_EHANDLE)
|
||||
switch (td->fieldType)
|
||||
{
|
||||
return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
|
||||
case FIELD_EHANDLE:
|
||||
type = PropEnt_Handle;
|
||||
break;
|
||||
case FIELD_CLASSPTR:
|
||||
type = PropEnt_Entity;
|
||||
break;
|
||||
#if SOURCE_ENGINE != SE_DOTA
|
||||
case FIELD_EDICT:
|
||||
type = PropEnt_Edict;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)",
|
||||
prop,
|
||||
td->fieldType,
|
||||
FIELD_EHANDLE);
|
||||
td->fieldType);
|
||||
}
|
||||
|
||||
CHECK_SET_PROP_DATA_OFFSET();
|
||||
@@ -1562,6 +1581,7 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
case Prop_Send:
|
||||
{
|
||||
type = PropEnt_Handle;
|
||||
FIND_PROP_SEND(DPT_Int, "integer");
|
||||
break;
|
||||
}
|
||||
@@ -1571,13 +1591,34 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
}
|
||||
|
||||
CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
|
||||
CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex());
|
||||
switch (type)
|
||||
{
|
||||
case PropEnt_Handle:
|
||||
{
|
||||
CBaseHandle &hndl = *(CBaseHandle *) ((uint8_t *) pEntity + offset);
|
||||
CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex());
|
||||
|
||||
if (!pHandleEntity || hndl != reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
|
||||
return -1;
|
||||
if (!pHandleEntity || hndl != reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
|
||||
return -1;
|
||||
|
||||
return g_HL2.EntityToBCompatRef(pHandleEntity);
|
||||
return g_HL2.EntityToBCompatRef(pHandleEntity);
|
||||
}
|
||||
case PropEnt_Entity:
|
||||
{
|
||||
CBaseEntity *pPropEntity = *(CBaseEntity **) ((uint8_t *) pEntity + offset);
|
||||
return g_HL2.EntityToBCompatRef(pPropEntity);
|
||||
}
|
||||
case PropEnt_Edict:
|
||||
{
|
||||
edict_t *pEdict = *(edict_t **) ((uint8_t *) pEntity + offset);
|
||||
if (!pEdict || pEdict->IsFree())
|
||||
return -1;
|
||||
|
||||
return IndexOfEdict(pEdict);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -1587,6 +1628,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
int offset;
|
||||
int bit_count;
|
||||
edict_t *pEdict;
|
||||
PropEntType type;
|
||||
|
||||
int element = 0;
|
||||
if (params[0] >= 5)
|
||||
@@ -1609,12 +1651,25 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
FIND_PROP_DATA(td);
|
||||
|
||||
if (td->fieldType != FIELD_EHANDLE)
|
||||
switch (td->fieldType)
|
||||
{
|
||||
return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)",
|
||||
case FIELD_EHANDLE:
|
||||
type = PropEnt_Handle;
|
||||
break;
|
||||
case FIELD_CLASSPTR:
|
||||
type = PropEnt_Entity;
|
||||
break;
|
||||
#if SOURCE_ENGINE != SE_DOTA
|
||||
case FIELD_EDICT:
|
||||
type = PropEnt_Edict;
|
||||
if (!pEdict)
|
||||
return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)",
|
||||
prop,
|
||||
td->fieldType,
|
||||
FIELD_EHANDLE);
|
||||
td->fieldType);
|
||||
}
|
||||
|
||||
CHECK_SET_PROP_DATA_OFFSET();
|
||||
@@ -1623,6 +1678,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
case Prop_Send:
|
||||
{
|
||||
type = PropEnt_Handle;
|
||||
FIND_PROP_SEND(DPT_Int, "integer");
|
||||
break;
|
||||
}
|
||||
@@ -1632,28 +1688,54 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
}
|
||||
|
||||
CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
|
||||
|
||||
if (params[4] == -1)
|
||||
CBaseEntity *pOther = GetEntity(params[4]);
|
||||
if (!pOther && params[4] != -1)
|
||||
{
|
||||
hndl.Set(NULL);
|
||||
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity *pOther = GetEntity(params[4]);
|
||||
|
||||
if (!pOther)
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]);
|
||||
switch (type)
|
||||
{
|
||||
case PropEnt_Handle:
|
||||
{
|
||||
CBaseHandle &hndl = *(CBaseHandle *) ((uint8_t *) pEntity + offset);
|
||||
hndl.Set((IHandleEntity *) pOther);
|
||||
|
||||
if (params[2] == Prop_Send && (pEdict != NULL))
|
||||
{
|
||||
g_HL2.SetEdictStateChanged(pEdict, offset);
|
||||
}
|
||||
}
|
||||
|
||||
IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
|
||||
hndl.Set(pHandleEnt);
|
||||
}
|
||||
|
||||
if (params[2] == Prop_Send && (pEdict != NULL))
|
||||
{
|
||||
g_HL2.SetEdictStateChanged(pEdict, offset);
|
||||
break;
|
||||
|
||||
case PropEnt_Entity:
|
||||
{
|
||||
*(CBaseEntity **) ((uint8_t *) pEntity + offset) = pOther;
|
||||
break;
|
||||
}
|
||||
|
||||
case PropEnt_Edict:
|
||||
{
|
||||
edict_t *pOtherEdict = NULL;
|
||||
if (pOther)
|
||||
{
|
||||
IServerNetworkable *pNetworkable = ((IServerUnknown *) pOther)->GetNetworkable();
|
||||
if (!pNetworkable)
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]);
|
||||
}
|
||||
|
||||
pOtherEdict = pNetworkable->GetEdict();
|
||||
if (!pOtherEdict || pOtherEdict->IsFree())
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]);
|
||||
}
|
||||
}
|
||||
|
||||
*(edict_t **) ((uint8_t *) pEntity + offset) = pOtherEdict;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+44
-4
@@ -207,7 +207,13 @@ static cell_t sm_GetEventBool(IPluginContext *pContext, const cell_t *params)
|
||||
char *key;
|
||||
pContext->LocalToString(params[2], &key);
|
||||
|
||||
return pInfo->pEvent->GetBool(key);
|
||||
bool defValue = false;
|
||||
if (params[0] > 2)
|
||||
{
|
||||
defValue = !!params[3];
|
||||
}
|
||||
|
||||
return pInfo->pEvent->GetBool(key, defValue);
|
||||
}
|
||||
|
||||
static cell_t sm_GetEventInt(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -226,7 +232,13 @@ static cell_t sm_GetEventInt(IPluginContext *pContext, const cell_t *params)
|
||||
char *key;
|
||||
pContext->LocalToString(params[2], &key);
|
||||
|
||||
return pInfo->pEvent->GetInt(key);
|
||||
int defValue = 0;
|
||||
if (params[0] > 2)
|
||||
{
|
||||
defValue = params[3];
|
||||
}
|
||||
|
||||
return pInfo->pEvent->GetInt(key, defValue);
|
||||
}
|
||||
|
||||
static cell_t sm_GetEventFloat(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -245,7 +257,13 @@ static cell_t sm_GetEventFloat(IPluginContext *pContext, const cell_t *params)
|
||||
char *key;
|
||||
pContext->LocalToString(params[2], &key);
|
||||
|
||||
float value = pInfo->pEvent->GetFloat(key);
|
||||
float defValue = 0.0f;
|
||||
if (params[0] > 2)
|
||||
{
|
||||
defValue = sp_ctof(params[3]);
|
||||
}
|
||||
|
||||
float value = pInfo->pEvent->GetFloat(key, defValue);
|
||||
|
||||
return sp_ftoc(value);
|
||||
}
|
||||
@@ -266,7 +284,14 @@ static cell_t sm_GetEventString(IPluginContext *pContext, const cell_t *params)
|
||||
char *key;
|
||||
pContext->LocalToString(params[2], &key);
|
||||
|
||||
pContext->StringToLocalUTF8(params[3], params[4], pInfo->pEvent->GetString(key), NULL);
|
||||
char *defValue = NULL;
|
||||
if (params[0] > 4)
|
||||
{
|
||||
pContext->LocalToString(params[5], &defValue);
|
||||
}
|
||||
|
||||
const char *value = pInfo->pEvent->GetString(key, defValue ? defValue : "");
|
||||
pContext->StringToLocalUTF8(params[3], params[4], value, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -393,6 +418,21 @@ REGISTER_NATIVES(gameEventNatives)
|
||||
{"SetEventFloat", sm_SetEventFloat},
|
||||
{"SetEventString", sm_SetEventString},
|
||||
{"SetEventBroadcast", sm_SetEventBroadcast},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"Event.Fire", sm_FireEvent},
|
||||
{"Event.Cancel", sm_CancelCreatedEvent},
|
||||
{"Event.GetName", sm_GetEventName},
|
||||
{"Event.GetBool", sm_GetEventBool},
|
||||
{"Event.GetInt", sm_GetEventInt},
|
||||
{"Event.GetFloat", sm_GetEventFloat},
|
||||
{"Event.GetString", sm_GetEventString},
|
||||
{"Event.SetBool", sm_SetEventBool},
|
||||
{"Event.SetInt", sm_SetEventInt},
|
||||
{"Event.SetFloat", sm_SetEventFloat},
|
||||
{"Event.SetString", sm_SetEventString},
|
||||
{"Event.BroadcastDisabled.set", sm_SetEventBroadcast},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
+47
-3
@@ -35,9 +35,11 @@
|
||||
#include "PlayerManager.h"
|
||||
#include "HalfLife2.h"
|
||||
|
||||
#include <vstdlib/random.h>
|
||||
|
||||
static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
engrandom->SetSeed(params[1]);
|
||||
::RandomSeed(params[1]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -47,14 +49,14 @@ static cell_t GetRandomFloat(IPluginContext *pContext, const cell_t *params)
|
||||
float fMin = sp_ctof(params[1]);
|
||||
float fMax = sp_ctof(params[2]);
|
||||
|
||||
float fRandom = engrandom->RandomFloat(fMin, fMax);
|
||||
float fRandom = ::RandomFloat(fMin, fMax);
|
||||
|
||||
return sp_ftoc(fRandom);
|
||||
}
|
||||
|
||||
static cell_t GetRandomInt(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return engrandom->RandomInt(params[1], params[2]);
|
||||
return ::RandomInt(params[1], params[2]);
|
||||
}
|
||||
|
||||
static cell_t IsMapValid(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -570,6 +572,47 @@ static cell_t ReferenceToBCompatRef(IPluginContext *pContext, const cell_t *para
|
||||
return g_HL2.ReferenceToBCompatRef(params[1]);
|
||||
}
|
||||
|
||||
// Must match ClientRangeType enum in halflife.inc
|
||||
enum class ClientRangeType : cell_t
|
||||
{
|
||||
Visibility = 0,
|
||||
Audibility,
|
||||
};
|
||||
|
||||
static cell_t GetClientsInRange(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *origin;
|
||||
pContext->LocalToPhysAddr(params[1], &origin);
|
||||
|
||||
Vector vOrigin(sp_ctof(origin[0]), sp_ctof(origin[1]), sp_ctof(origin[2]));
|
||||
|
||||
ClientRangeType rangeType = (ClientRangeType) params[2];
|
||||
|
||||
CBitVec<ABSOLUTE_PLAYER_LIMIT> players;
|
||||
engine->Message_DetermineMulticastRecipients(rangeType == ClientRangeType::Audibility, vOrigin, players);
|
||||
|
||||
cell_t *outPlayers;
|
||||
pContext->LocalToPhysAddr(params[3], &outPlayers);
|
||||
|
||||
int maxPlayers = params[4];
|
||||
int curPlayers = 0;
|
||||
|
||||
int index = players.FindNextSetBit(0);
|
||||
while (index > -1 && curPlayers < maxPlayers)
|
||||
{
|
||||
int entidx = index + 1;
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(entidx);
|
||||
if (pPlayer && pPlayer->IsInGame())
|
||||
{
|
||||
outPlayers[curPlayers++] = entidx;
|
||||
}
|
||||
|
||||
index = players.FindNextSetBit(index + 1);
|
||||
}
|
||||
|
||||
return curPlayers;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(halflifeNatives)
|
||||
{
|
||||
{"CreateFakeClient", CreateFakeClient},
|
||||
@@ -605,5 +648,6 @@ REGISTER_NATIVES(halflifeNatives)
|
||||
{"EntIndexToEntRef", IndexToReference},
|
||||
{"EntRefToEntIndex", ReferenceToIndex},
|
||||
{"MakeCompatEntRef", ReferenceToBCompatRef},
|
||||
{"GetClientsInRange", GetClientsInRange},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -797,6 +797,32 @@ static cell_t smn_FileToKeyValues(IPluginContext *pCtx, const cell_t *params)
|
||||
return g_HL2.KVLoadFromFile(kv, basefilesystem, path);
|
||||
}
|
||||
|
||||
static cell_t smn_StringToKeyValues(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError herr;
|
||||
HandleSecurity sec;
|
||||
KeyValueStack *pStk;
|
||||
KeyValues *kv;
|
||||
|
||||
sec.pOwner = NULL;
|
||||
sec.pIdentity = g_pCoreIdent;
|
||||
|
||||
if ((herr=handlesys->ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
|
||||
}
|
||||
|
||||
char *buffer;
|
||||
char *resourceName;
|
||||
pCtx->LocalToString(params[2], &buffer);
|
||||
pCtx->LocalToString(params[3], &resourceName);
|
||||
|
||||
kv = pStk->pCurRoot.front();
|
||||
return kv->LoadFromBuffer(resourceName, buffer);
|
||||
}
|
||||
|
||||
static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@@ -1075,6 +1101,18 @@ static cell_t smn_KvGetSectionSymbol(IPluginContext *pCtx, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t KeyValues_Import(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
// This version takes (dest, src). The original is (src, dest).
|
||||
cell_t new_params[3] = {
|
||||
2,
|
||||
params[2],
|
||||
params[1],
|
||||
};
|
||||
|
||||
return smn_CopySubkeys(pContext, new_params);
|
||||
}
|
||||
|
||||
static KeyValueNatives s_KeyValueNatives;
|
||||
|
||||
REGISTER_NATIVES(keyvaluenatives)
|
||||
@@ -1101,6 +1139,7 @@ REGISTER_NATIVES(keyvaluenatives)
|
||||
{"KvGetDataType", smn_KvGetDataType},
|
||||
{"KeyValuesToFile", smn_KeyValuesToFile},
|
||||
{"FileToKeyValues", smn_FileToKeyValues},
|
||||
{"StringToKeyValues", smn_StringToKeyValues},
|
||||
{"KvSetEscapeSequences", smn_KvSetEscapeSequences},
|
||||
{"KvDeleteThis", smn_KvDeleteThis},
|
||||
{"KvDeleteKey", smn_KvDeleteKey},
|
||||
@@ -1112,5 +1151,42 @@ REGISTER_NATIVES(keyvaluenatives)
|
||||
{"KvGetSectionSymbol", smn_KvGetSectionSymbol},
|
||||
{"KvGetVector", smn_KvGetVector},
|
||||
{"KvSetVector", smn_KvSetVector},
|
||||
|
||||
// Transitional syntax support.
|
||||
{"KeyValues.KeyValues", smn_CreateKeyValues},
|
||||
{"KeyValues.SetString", smn_KvSetString},
|
||||
{"KeyValues.SetNum", smn_KvSetNum},
|
||||
{"KeyValues.SetUInt64", smn_KvSetUInt64},
|
||||
{"KeyValues.SetFloat", smn_KvSetFloat},
|
||||
{"KeyValues.SetColor", smn_KvSetColor},
|
||||
{"KeyValues.GetString", smn_KvGetString},
|
||||
{"KeyValues.GetNum", smn_KvGetNum},
|
||||
{"KeyValues.GetFloat", smn_KvGetFloat},
|
||||
{"KeyValues.GetColor", smn_KvGetColor},
|
||||
{"KeyValues.GetUInt64", smn_KvGetUInt64},
|
||||
{"KeyValues.JumpToKey", smn_KvJumpToKey},
|
||||
{"KeyValues.JumpToKeySymbol", smn_KvJumpToKeySymbol},
|
||||
{"KeyValues.GotoNextKey", smn_KvGotoNextKey},
|
||||
{"KeyValues.GotoFirstSubKey", smn_KvGotoFirstSubKey},
|
||||
{"KeyValues.GoBack", smn_KvGoBack},
|
||||
{"KeyValues.Rewind", smn_KvRewind},
|
||||
{"KeyValues.GetSectionName", smn_KvGetSectionName},
|
||||
{"KeyValues.SetSectionName", smn_KvSetSectionName},
|
||||
{"KeyValues.GetDataType", smn_KvGetDataType},
|
||||
{"KeyValues.SetEscapeSequences", smn_KvSetEscapeSequences},
|
||||
{"KeyValues.DeleteThis", smn_KvDeleteThis},
|
||||
{"KeyValues.DeleteKey", smn_KvDeleteKey},
|
||||
{"KeyValues.NodesInStack", smn_KvNodesInStack},
|
||||
{"KeyValues.SavePosition", smn_KvSavePosition},
|
||||
{"KeyValues.FindKeyById", smn_FindKeyById},
|
||||
{"KeyValues.GetNameSymbol", smn_GetNameSymbol},
|
||||
{"KeyValues.GetSectionSymbol", smn_KvGetSectionSymbol},
|
||||
{"KeyValues.GetVector", smn_KvGetVector},
|
||||
{"KeyValues.SetVector", smn_KvSetVector},
|
||||
{"KeyValues.Import", KeyValues_Import},
|
||||
{"KeyValues.ImportFromFile", smn_FileToKeyValues},
|
||||
{"KeyValues.ImportFromString", smn_StringToKeyValues},
|
||||
{"KeyValues.ExportToFile", smn_KeyValuesToFile},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
+33
-1
@@ -811,6 +811,38 @@ REGISTER_NATIVES(protobufnatives)
|
||||
{"PbReadMessage", smn_PbReadMessage},
|
||||
{"PbReadRepeatedMessage", smn_PbReadRepeatedMessage},
|
||||
{"PbAddMessage", smn_PbAddMessage},
|
||||
|
||||
// Transitional syntax.
|
||||
{"Protobuf.ReadInt", smn_PbReadInt},
|
||||
{"Protobuf.ReadFloat", smn_PbReadFloat},
|
||||
{"Protobuf.ReadBool", smn_PbReadBool},
|
||||
{"Protobuf.ReadString", smn_PbReadString},
|
||||
{"Protobuf.ReadColor", smn_PbReadColor},
|
||||
{"Protobuf.ReadAngle", smn_PbReadAngle},
|
||||
{"Protobuf.ReadVector", smn_PbReadVector},
|
||||
{"Protobuf.ReadVector2D", smn_PbReadVector2D},
|
||||
{"Protobuf.GetRepeatedFieldCount", smn_PbGetRepeatedFieldCount},
|
||||
{"Protobuf.SetInt", smn_PbSetInt},
|
||||
{"Protobuf.SetFloat", smn_PbSetFloat},
|
||||
{"Protobuf.SetBool", smn_PbSetBool},
|
||||
{"Protobuf.SetString", smn_PbSetString},
|
||||
{"Protobuf.SetColor", smn_PbSetColor},
|
||||
{"Protobuf.SetAngle", smn_PbSetAngle},
|
||||
{"Protobuf.SetVector", smn_PbSetVector},
|
||||
{"Protobuf.SetVector2D", smn_PbSetVector2D},
|
||||
{"Protobuf.AddInt", smn_PbAddInt},
|
||||
{"Protobuf.AddFloat", smn_PbAddFloat},
|
||||
{"Protobuf.AddBool", smn_PbAddBool},
|
||||
{"Protobuf.AddString", smn_PbAddString},
|
||||
{"Protobuf.AddColor", smn_PbAddColor},
|
||||
{"Protobuf.AddAngle", smn_PbAddAngle},
|
||||
{"Protobuf.AddVector", smn_PbAddVector},
|
||||
{"Protobuf.AddVector2D", smn_PbAddVector2D},
|
||||
{"Protobuf.RemoveRepeatedFieldValue", smn_PbRemoveRepeatedFieldValue},
|
||||
{"Protobuf.ReadMessage", smn_PbReadMessage},
|
||||
{"Protobuf.ReadRepeatedMessage", smn_PbReadRepeatedMessage},
|
||||
{"Protobuf.AddMessage", smn_PbAddMessage},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -820,7 +852,7 @@ REGISTER_NATIVES(protobufnatives)
|
||||
@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@ @@@@@@@@@@@@@
|
||||
@@@@@@@@ @@@@@@@@@@@@@
|
||||
@@@@@@@@ o @@@@@@@@@@@@@
|
||||
@@@@@@ @@@@@@@@@@@@@@@
|
||||
0000 @@@@@@@@@@@@@@@@@@@@@
|
||||
000000000 @@@@@@@@@@@@@@@@@@@
|
||||
|
||||
@@ -45,13 +45,15 @@ ISmmPluginManager *g_pMMPlugins = NULL;
|
||||
CGlobalVars *gpGlobals = NULL;
|
||||
ICvar *icvar = NULL;
|
||||
IGameEventManager2 *gameevents = NULL;
|
||||
IUniformRandomStream *engrandom = NULL;
|
||||
CallClass<IVEngineServer> *enginePatch = NULL;
|
||||
CallClass<IServerGameDLL> *gamedllPatch = NULL;
|
||||
IPlayerInfoManager *playerinfo = NULL;
|
||||
IBaseFileSystem *basefilesystem = NULL;
|
||||
IFileSystem *filesystem = NULL;
|
||||
IEngineSound *enginesound = NULL;
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
IServerTools *servertools = NULL;
|
||||
#endif
|
||||
IServerPluginHelpers *serverpluginhelpers = NULL;
|
||||
IServerPluginCallbacks *vsp_interface = NULL;
|
||||
int vsp_version = 0;
|
||||
@@ -67,10 +69,12 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen
|
||||
GET_V_IFACE_CURRENT(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, engrandom, IUniformRandomStream, VENGINE_SERVER_RANDOM_INTERFACE_VERSION);
|
||||
GET_V_IFACE_CURRENT(GetFileSystemFactory, basefilesystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION);
|
||||
GET_V_IFACE_CURRENT(GetFileSystemFactory, filesystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION);
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, enginesound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
GET_V_IFACE_CURRENT(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION);
|
||||
#endif
|
||||
#if SOURCE_ENGINE != SE_DOTA
|
||||
GET_V_IFACE_CURRENT(GetEngineFactory, serverpluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
|
||||
#endif
|
||||
@@ -167,7 +171,7 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
|
||||
/* This shouldn't happen */
|
||||
if (!iface)
|
||||
{
|
||||
g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater.");
|
||||
logger->LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -47,9 +47,9 @@
|
||||
#include <eiface.h>
|
||||
#include <igameevents.h>
|
||||
#include <iplayerinfo.h>
|
||||
#include <random.h>
|
||||
#include <filesystem.h>
|
||||
#include <IEngineSound.h>
|
||||
#include <toolframework/itoolentity.h>
|
||||
|
||||
#ifndef METAMOD_PLAPI_VERSION
|
||||
#include <metamod_wrappers.h>
|
||||
@@ -98,11 +98,13 @@ extern CGlobalVars *gpGlobals;
|
||||
extern IGameEventManager2 *gameevents;
|
||||
extern SourceHook::CallClass<IVEngineServer> *enginePatch;
|
||||
extern SourceHook::CallClass<IServerGameDLL> *gamedllPatch;
|
||||
extern IUniformRandomStream *engrandom;
|
||||
extern IPlayerInfoManager *playerinfo;
|
||||
extern IBaseFileSystem *basefilesystem;
|
||||
extern IFileSystem *filesystem;
|
||||
extern IEngineSound *enginesound;
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
extern IServerTools *servertools;
|
||||
#endif
|
||||
extern IServerPluginHelpers *serverpluginhelpers;
|
||||
extern IServerPluginCallbacks *vsp_interface;
|
||||
extern int vsp_version;
|
||||
|
||||
+5
-4
@@ -395,6 +395,7 @@ void SourceModBase::LevelShutdown()
|
||||
{
|
||||
g_pOnMapEnd->Execute(NULL);
|
||||
}
|
||||
extsys->CallOnCoreMapEnd();
|
||||
|
||||
g_Timers.RemoveMapChangeTimers();
|
||||
|
||||
@@ -572,9 +573,9 @@ void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
||||
|
||||
if (tag)
|
||||
{
|
||||
g_Logger.LogMessage("[%s] %s", tag, buffer);
|
||||
logger->LogMessage("[%s] %s", tag, buffer);
|
||||
} else {
|
||||
g_Logger.LogMessage("%s", buffer);
|
||||
logger->LogMessage("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,9 +592,9 @@ void SourceModBase::LogError(IExtension *pExt, const char *format, ...)
|
||||
|
||||
if (tag)
|
||||
{
|
||||
g_Logger.LogError("[%s] %s", tag, buffer);
|
||||
logger->LogError("[%s] %s", tag, buffer);
|
||||
} else {
|
||||
g_Logger.LogError("%s", buffer);
|
||||
logger->LogError("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet :
|
||||
// =============================================================================
|
||||
// SourceMod
|
||||
// Copyright (C) 2004-2014 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 "vprof_tool.h"
|
||||
#include "logic_bridge.h"
|
||||
#include "sourcemod.h"
|
||||
#include "sourcemm_api.h"
|
||||
|
||||
#define VPROF_ENABLED
|
||||
#define RAD_TELEMETRY_DISABLED
|
||||
#include <tier0/vprof.h>
|
||||
|
||||
VProfTool sVProfTool;
|
||||
|
||||
VProfTool::VProfTool()
|
||||
: active_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::OnSourceModAllInitialized()
|
||||
{
|
||||
logicore.RegisterProfiler(this);
|
||||
}
|
||||
|
||||
const char *
|
||||
VProfTool::Name()
|
||||
{
|
||||
return "vprof";
|
||||
}
|
||||
|
||||
const char *
|
||||
VProfTool::Description()
|
||||
{
|
||||
return "Valve built-in profiler";
|
||||
}
|
||||
|
||||
bool
|
||||
VProfTool::Start()
|
||||
{
|
||||
g_VProfCurrentProfile.Start();
|
||||
return IsActive();
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::Stop(void (*render)(const char *fmt, ...))
|
||||
{
|
||||
g_VProfCurrentProfile.Stop();
|
||||
RenderHelp(render);
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::Dump()
|
||||
{
|
||||
g_VProfCurrentProfile.Pause();
|
||||
g_VProfCurrentProfile.OutputReport(VPRT_FULL);
|
||||
g_VProfCurrentProfile.Resume();
|
||||
}
|
||||
|
||||
bool
|
||||
VProfTool::IsActive()
|
||||
{
|
||||
return g_VProfCurrentProfile.IsEnabled();
|
||||
}
|
||||
|
||||
bool
|
||||
VProfTool::IsAttached()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::EnterScope(const char *group, const char *name)
|
||||
{
|
||||
if (IsActive()) {
|
||||
if (!group)
|
||||
group = VPROF_BUDGETGROUP_OTHER_UNACCOUNTED;
|
||||
g_VProfCurrentProfile.EnterScope(name, 1, group, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::LeaveScope()
|
||||
{
|
||||
if (IsActive())
|
||||
g_VProfCurrentProfile.ExitScope();
|
||||
}
|
||||
|
||||
void
|
||||
VProfTool::RenderHelp(void (*render)(const char *fmt, ...))
|
||||
{
|
||||
render("Use 'sm prof dump vprof' or one of the vprof_generate_report commands in your console to analyze a profile session.");
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet :
|
||||
// =============================================================================
|
||||
// SourceMod
|
||||
// Copyright (C) 2004-2014 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_vprof_bridge_h_
|
||||
#define _include_sourcemod_core_vprof_bridge_h_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include "sm_globals.h"
|
||||
#include <am-utility.h>
|
||||
|
||||
class VProfTool
|
||||
: public IProfilingTool,
|
||||
public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
VProfTool();
|
||||
|
||||
// IProfilingTool
|
||||
const char *Name() KE_OVERRIDE;
|
||||
const char *Description() KE_OVERRIDE;
|
||||
bool Start() KE_OVERRIDE;
|
||||
void Stop(void (*render)(const char *fmt, ...)) KE_OVERRIDE;
|
||||
void Dump() KE_OVERRIDE;
|
||||
bool IsActive() KE_OVERRIDE;
|
||||
bool IsAttached() KE_OVERRIDE;
|
||||
void EnterScope(const char *group, const char *name) KE_OVERRIDE;
|
||||
void LeaveScope() KE_OVERRIDE;
|
||||
void RenderHelp(void (*render)(const char *fmt, ...)) KE_OVERRIDE;
|
||||
|
||||
// SMGlobalClass
|
||||
void OnSourceModAllInitialized() KE_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool active_;
|
||||
};
|
||||
|
||||
#endif // _include_sourcemod_core_vprof_bridge_h_
|
||||
@@ -8,6 +8,10 @@ binary.compiler.cxxincludes += [
|
||||
os.path.join(builder.sourcePath, 'public', 'jit'),
|
||||
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
||||
]
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
binary.sources += [
|
||||
'extension.cpp',
|
||||
|
||||
@@ -5,6 +5,10 @@ binary = SM.ExtLibrary(builder, 'clientprefs.ext')
|
||||
binary.compiler.cxxincludes += [
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook'),
|
||||
]
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
binary.sources += [
|
||||
'extension.cpp',
|
||||
|
||||
@@ -159,7 +159,7 @@ void CookieManager::OnClientAuthorized(int client, const char *authstring)
|
||||
g_ClientPrefs.AttemptReconnection();
|
||||
|
||||
TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
|
||||
UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
|
||||
UTIL_strncpy(op->m_params.steamId, GetPlayerCompatAuthId(player), MAX_NAME_LENGTH);
|
||||
|
||||
g_ClientPrefs.AddQueryToQueue(op);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ void CookieManager::OnClientDisconnecting(int client)
|
||||
|
||||
if (player)
|
||||
{
|
||||
pAuth = player->GetAuthString();
|
||||
pAuth = GetPlayerCompatAuthId(player);
|
||||
g_ClientPrefs.ClearQueryCache(player->GetSerial());
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect()
|
||||
char error[256];
|
||||
int errCode = 0;
|
||||
|
||||
Database = Newborn<IDatabase>(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error)));
|
||||
|
||||
if (!Database)
|
||||
{
|
||||
@@ -349,32 +349,11 @@ void ClientPrefs::ProcessQueryCache()
|
||||
cachedQueries.clear();
|
||||
}
|
||||
|
||||
size_t IsAuthIdConnected(char *authID)
|
||||
const char *GetPlayerCompatAuthId(IGamePlayer *pPlayer)
|
||||
{
|
||||
IGamePlayer *player;
|
||||
const char *authString;
|
||||
|
||||
for (int playerIndex = playerhelpers->GetMaxClients()+1; --playerIndex > 0;)
|
||||
{
|
||||
player = playerhelpers->GetGamePlayer(playerIndex);
|
||||
if (player == NULL || !player->IsConnected())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
authString = player->GetAuthString();
|
||||
|
||||
if (authString == NULL || authString[0] == '\0')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(authString, authID) == 0)
|
||||
{
|
||||
return playerIndex;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
/* For legacy reasons, OnClientAuthorized gives the Steam2 id here if using Steam auth */
|
||||
const char *steamId = pPlayer->GetSteam2Id();
|
||||
return steamId ? steamId : pPlayer->GetAuthString();
|
||||
}
|
||||
|
||||
void ClientPrefs::CatchLateLoadClients()
|
||||
@@ -394,7 +373,7 @@ void ClientPrefs::CatchLateLoadClients()
|
||||
continue;
|
||||
}
|
||||
|
||||
g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
|
||||
g_CookieManager.OnClientAuthorized(i, GetPlayerCompatAuthId(pPlayer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
size_t IsAuthIdConnected(char *authID);
|
||||
const char *GetPlayerCompatAuthId(IGamePlayer *pPlayer);
|
||||
|
||||
extern sp_nativeinfo_t g_ClientPrefNatives[];
|
||||
|
||||
|
||||
@@ -83,6 +83,31 @@ cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
|
||||
NULL);
|
||||
}
|
||||
|
||||
size_t IsAuthIdConnected(char *authID)
|
||||
{
|
||||
IGamePlayer *player;
|
||||
const char *authString;
|
||||
|
||||
for (int playerIndex = playerhelpers->GetMaxClients()+1; --playerIndex > 0;)
|
||||
{
|
||||
player = playerhelpers->GetGamePlayer(playerIndex);
|
||||
if (player == NULL || !player->IsAuthorized())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(player->GetAuthString(), authID)
|
||||
|| !strcmp(player->GetSteam2Id(), authID)
|
||||
|| !strcmp(player->GetSteam3Id(), authID)
|
||||
)
|
||||
{
|
||||
return playerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
g_ClientPrefs.AttemptReconnection();
|
||||
|
||||
@@ -61,9 +61,21 @@ DETOUR_DECL_MEMBER1(DetourHandleBuy, int, const char *, weapon)
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
|
||||
#elif defined(WIN32)
|
||||
DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, CEconItemView *, pEconItem, int, iUnknown)
|
||||
#else
|
||||
DETOUR_DECL_MEMBER3(DetourWeaponPrice, int, CEconItemView *, pEconItem, int, iUnknown, float, fUnknown)
|
||||
#endif
|
||||
{
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)();
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)();
|
||||
#elif defined(WIN32)
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(pEconItem, iUnknown);
|
||||
#else
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(pEconItem, iUnknown, fUnknown);
|
||||
#endif
|
||||
|
||||
if (lastclient == -1)
|
||||
return price;
|
||||
|
||||
@@ -71,19 +83,6 @@ DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
|
||||
|
||||
return CallPriceForward(lastclient, weapon_name, price);
|
||||
}
|
||||
#else
|
||||
DETOUR_DECL_MEMBER2(DetourWeaponPrice, int, const char *, szAttribute, CEconItemView *, pEconItem)
|
||||
{
|
||||
int price = DETOUR_MEMBER_CALL(DetourWeaponPrice)(szAttribute, pEconItem);
|
||||
|
||||
if(lastclient == -1 || strcmp(szAttribute, "in game price") != 0)
|
||||
return price;
|
||||
|
||||
const char *weapon_name = reinterpret_cast<char *>(this+weaponNameOffset);
|
||||
|
||||
return CallPriceForward(lastclient, weapon_name, price);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32)
|
||||
DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
|
||||
@@ -152,12 +151,20 @@ DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
|
||||
#endif
|
||||
}
|
||||
|
||||
DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, something, bool, toss)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, Vector, vec, bool, unknown)
|
||||
#else
|
||||
DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, bDropShield, bool, bThrowForward)
|
||||
#endif
|
||||
{
|
||||
if (g_pIgnoreCSWeaponDropDetour)
|
||||
{
|
||||
g_pIgnoreCSWeaponDropDetour = false;
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, something, toss);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, vec, unknown);
|
||||
#else
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bDropShield, bThrowForward);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,8 +177,14 @@ DETOUR_DECL_MEMBER3(DetourCSWeaponDrop, void, CBaseEntity *, weapon, bool, somet
|
||||
g_pCSWeaponDropForward->Execute(&result);
|
||||
|
||||
|
||||
if (result == Pl_Continue)
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, something, toss);
|
||||
if (result >= Pl_Continue)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, vec, unknown);
|
||||
#else
|
||||
DETOUR_MEMBER_CALL(DetourCSWeaponDrop)(weapon, bDropShield, bThrowForward);
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -187,8 +200,15 @@ bool CreateWeaponPriceDetour()
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, "GetAttributeInt");
|
||||
#if SOURCE_ENGINE == SE_CSGO && defined(WIN32)
|
||||
void *pGetWeaponPriceAddress = GetWeaponPriceFunction();
|
||||
|
||||
if(!pGetWeaponPriceAddress)
|
||||
{
|
||||
g_pSM->LogError(myself, "GetWeaponPrice detour could not be initialized - Disabled OnGetWeaponPrice forward.");
|
||||
}
|
||||
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, pGetWeaponPriceAddress);
|
||||
#else
|
||||
DWeaponPrice = DETOUR_CREATE_MEMBER(DetourWeaponPrice, "GetWeaponPrice");
|
||||
#endif
|
||||
|
||||
@@ -226,6 +226,20 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
|
||||
static ICallWrapper *pWrapper = NULL;
|
||||
if (!pWrapper)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
REGISTER_NATIVE_ADDR("CSWeaponDrop",
|
||||
PassInfo pass[3]; \
|
||||
pass[0].flags = PASSFLAG_BYVAL; \
|
||||
pass[0].type = PassType_Basic; \
|
||||
pass[0].size = sizeof(CBaseEntity *); \
|
||||
pass[1].flags = PASSFLAG_BYVAL; \
|
||||
pass[1].type = PassType_Basic; \
|
||||
pass[1].size = sizeof(Vector); \
|
||||
pass[2].flags = PASSFLAG_BYVAL; \
|
||||
pass[2].type = PassType_Basic; \
|
||||
pass[2].size = sizeof(bool); \
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 3))
|
||||
#else
|
||||
REGISTER_NATIVE_ADDR("CSWeaponDrop",
|
||||
PassInfo pass[3]; \
|
||||
pass[0].flags = PASSFLAG_BYVAL; \
|
||||
@@ -238,6 +252,7 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
|
||||
pass[2].type = PassType_Basic; \
|
||||
pass[2].size = sizeof(bool); \
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 3))
|
||||
#endif
|
||||
}
|
||||
|
||||
CBaseEntity *pEntity;
|
||||
@@ -270,7 +285,11 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
|
||||
if (params[4] == 1 && g_pCSWeaponDropDetoured)
|
||||
g_pIgnoreCSWeaponDropDetour = true;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool) + sizeof(Vector)];
|
||||
#else
|
||||
unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool) * 2];
|
||||
#endif
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
// <psychonic> first one is always false. second is true to toss, false to just drop
|
||||
@@ -278,9 +297,15 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
*(CBaseEntity **)vptr = pWeapon;
|
||||
vptr += sizeof(CBaseEntity *);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
*(Vector *)vptr = vec3_origin;
|
||||
vptr += sizeof(Vector);
|
||||
*(bool *)vptr = false;
|
||||
#else
|
||||
*(bool *)vptr = false;
|
||||
vptr += sizeof(bool);
|
||||
*(bool *)vptr = (params[3]) ? true : false;
|
||||
#endif
|
||||
|
||||
pWrapper->Execute(vstk, NULL);
|
||||
|
||||
@@ -347,12 +372,10 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
float delay = sp_ctof(params[1]);
|
||||
int reason = params[2];
|
||||
signed int unknown = 1;//We might want to find what this is?
|
||||
__asm
|
||||
{
|
||||
push reason
|
||||
movss xmm1, delay
|
||||
mov edi, unknown
|
||||
mov ecx, gamerules
|
||||
call addr
|
||||
}
|
||||
@@ -396,6 +419,7 @@ static cell_t CS_GetTranslatedWeaponAlias(IPluginContext *pContext, const cell_t
|
||||
|
||||
static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
|
||||
if (!IsValidWeaponID(params[2]))
|
||||
return pContext->ThrowNativeError("Invalid WeaponID passed for this game");
|
||||
|
||||
@@ -403,6 +427,7 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
//Hard code return values for weapons that dont call GetWeaponPrice and always use default value.
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|
||||
if (id == WEAPON_C4 || id == WEAPON_KNIFE || id == WEAPON_KNIFE_GG)
|
||||
return 0;
|
||||
#else
|
||||
@@ -435,23 +460,49 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
static ICallWrapper *pWrapper = NULL;
|
||||
|
||||
#if defined(WIN32)
|
||||
if(!pWrapper)
|
||||
{
|
||||
void *pGetWeaponPrice = GetWeaponPriceFunction();
|
||||
if(!pGetWeaponPrice)
|
||||
{
|
||||
return pContext->ThrowNativeError("Failed to locate function");
|
||||
}
|
||||
|
||||
PassInfo pass[2];
|
||||
PassInfo ret;
|
||||
pass[0].flags = PASSFLAG_BYVAL;
|
||||
pass[0].type = PassType_Basic;
|
||||
pass[0].size = sizeof(CEconItemView *);
|
||||
pass[1].flags = PASSFLAG_BYVAL;
|
||||
pass[1].type = PassType_Basic;
|
||||
pass[1].size = sizeof(int);
|
||||
ret.flags = PASSFLAG_BYVAL;
|
||||
ret.type = PassType_Basic;
|
||||
ret.size = sizeof(int);
|
||||
pWrapper = g_pBinTools->CreateCall(pGetWeaponPrice, CallConv_ThisCall, &ret, pass, 2);
|
||||
}
|
||||
#else
|
||||
if (!pWrapper)
|
||||
{
|
||||
REGISTER_NATIVE_ADDR("GetAttributeInt",
|
||||
PassInfo pass[2]; \
|
||||
REGISTER_NATIVE_ADDR("GetWeaponPrice",
|
||||
PassInfo pass[3]; \
|
||||
PassInfo ret; \
|
||||
pass[0].flags = PASSFLAG_BYVAL; \
|
||||
pass[0].type = PassType_Basic; \
|
||||
pass[0].size = sizeof(char *); \
|
||||
pass[0].size = sizeof(CEconItemView *); \
|
||||
pass[1].flags = PASSFLAG_BYVAL; \
|
||||
pass[1].type = PassType_Basic; \
|
||||
pass[1].size = sizeof(CEconItemView *); \
|
||||
pass[1].size = sizeof(int); \
|
||||
pass[2].flags = PASSFLAG_BYVAL; \
|
||||
pass[2].type = PassType_Float; \
|
||||
pass[2].size = sizeof(float); \
|
||||
ret.flags = PASSFLAG_BYVAL; \
|
||||
ret.type = PassType_Basic; \
|
||||
ret.size = sizeof(int); \
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &ret, pass, 2))
|
||||
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &ret, pass, 3))
|
||||
}
|
||||
|
||||
#endif
|
||||
// Get a CEconItemView for the m4
|
||||
// Found in CCSPlayer::HandleCommand_Buy_Internal
|
||||
// Linux a1 - CCSPlayer *pEntity, v5 - Player Team, a3 - ItemLoadoutSlot -1 use default loadoutslot:
|
||||
@@ -529,14 +580,22 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
|
||||
pGetView->Execute(vstk_view, &view);
|
||||
}
|
||||
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(char *)];
|
||||
#if defined(WIN32)
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(int)];
|
||||
#else
|
||||
unsigned char vstk[sizeof(void *) * 2 + sizeof(int) + sizeof(float)];
|
||||
#endif
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
*(void **)vptr = info;
|
||||
vptr += sizeof(void *);
|
||||
*(const char **)vptr = "in game price";
|
||||
vptr += sizeof(const char *);
|
||||
*(CEconItemView **)vptr = view;
|
||||
vptr += sizeof(CEconItemView *);
|
||||
*(int *)vptr = 0;
|
||||
#if !defined(WIN32)
|
||||
vptr += sizeof(int);
|
||||
*(float *)vptr = 1.0;
|
||||
#endif
|
||||
|
||||
int price = 0;
|
||||
pWrapper->Execute(vstk, &price);
|
||||
|
||||
@@ -229,6 +229,56 @@ const char *WeaponIDToAlias(int weaponID)
|
||||
#endif
|
||||
return alias;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO && defined(WIN32)
|
||||
void *GetWeaponPriceFunction()
|
||||
{
|
||||
static void *pGetWeaponPriceAddress = NULL;
|
||||
|
||||
if(pGetWeaponPriceAddress == NULL)
|
||||
{
|
||||
void *pAddress = NULL;
|
||||
int offset = 0;
|
||||
int callOffset = 0;
|
||||
const char* byteCheck = NULL;
|
||||
|
||||
if(!g_pGameConf->GetMemSig("GetWeaponPrice", &pAddress) || pAddress == NULL)
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPrice address.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!g_pGameConf->GetOffset("GetWeaponPriceFunc", &offset))
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPriceFunc offset.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
byteCheck = g_pGameConf->GetKeyValue("GetWeaponPriceByteCheck");
|
||||
|
||||
if(byteCheck == NULL)
|
||||
{
|
||||
g_pSM->LogError(myself, "Failed to get GetWeaponPriceByteCheck keyvalue.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t iByte = strtoul(byteCheck, NULL, 16);
|
||||
|
||||
if(iByte != *(uint8_t *)((intptr_t)pAddress + (offset-1)))
|
||||
{
|
||||
g_pSM->LogError(myself, "GetWeaponPrice Byte check failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callOffset = *(uint32_t *)((intptr_t)pAddress + offset);
|
||||
|
||||
pGetWeaponPriceAddress = (void *)((intptr_t)pAddress + offset + callOffset + sizeof(int));
|
||||
}
|
||||
|
||||
return pGetWeaponPriceAddress;
|
||||
}
|
||||
#endif
|
||||
|
||||
int GetRealWeaponID(int weaponId)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|
||||
@@ -165,4 +165,6 @@ int GetFakeWeaponID(int weaponId);
|
||||
|
||||
bool IsValidWeaponID(int weaponId);
|
||||
|
||||
void *GetWeaponPriceFunction();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,10 @@ binary.compiler.includes += [
|
||||
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'include')
|
||||
]
|
||||
binary.compiler.defines += ['CURL_STATICLIB']
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
binary.compiler.postlink += [libcurl.binary]
|
||||
if builder.target_platform == 'linux':
|
||||
binary.compiler.postlink += ['-lrt']
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import os
|
||||
|
||||
binary = SM.ExtLibrary(builder, 'geoip.ext')
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
if builder.target_platform == 'windows':
|
||||
binary.compiler.postlink += ['wsock32.lib']
|
||||
|
||||
|
||||
@@ -7,14 +7,20 @@ if SM.mysql_root:
|
||||
os.path.join(SM.mysql_root, 'include'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||
]
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
if builder.target_platform == 'linux' or builder.target_platform == 'mac':
|
||||
binary.compiler.postlink += [
|
||||
os.path.join(SM.mysql_root, 'lib', 'libmysqlclient_r.a'),
|
||||
'-lz',
|
||||
'-lpthread',
|
||||
'-lm'
|
||||
'-lm',
|
||||
]
|
||||
if builder.target_platform == 'linux':
|
||||
binary.compiler.postlink += ['-lrt']
|
||||
elif builder.target_platform == 'windows':
|
||||
binary.compiler.postlink += [
|
||||
os.path.join(SM.mysql_root, 'lib', 'opt', 'mysqlclient.lib'),
|
||||
|
||||
@@ -101,6 +101,9 @@ MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent)
|
||||
m_Info.driver = NULL;
|
||||
m_Info.maxTimeout = info->maxTimeout;
|
||||
m_Info.port = info->port;
|
||||
|
||||
// DBI, for historical reasons, guarantees an initial refcount of 1.
|
||||
AddRef();
|
||||
}
|
||||
|
||||
MyDatabase::~MyDatabase()
|
||||
|
||||
@@ -96,11 +96,16 @@ MYSQL *Connect(const DatabaseInfo *info, char *error, size_t maxlength)
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
const char *host = NULL, *socket = NULL;
|
||||
|
||||
decltype(info->maxTimeout) timeout = 60;
|
||||
if (info->maxTimeout > 0)
|
||||
{
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&(info->maxTimeout));
|
||||
timeout = info->maxTimeout;
|
||||
}
|
||||
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (const char *)&timeout);
|
||||
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&timeout);
|
||||
|
||||
/* Have MySQL automatically reconnect if it times out or loses connection.
|
||||
* This will prevent "MySQL server has gone away" errors after a while.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,10 @@ binary = SM.ExtLibrary(builder, 'regex.ext')
|
||||
binary.compiler.cxxincludes += [
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook'),
|
||||
]
|
||||
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.vendor == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
if builder.target_platform == 'linux':
|
||||
path = os.path.join(builder.sourcePath, 'extensions', 'regex', 'lib_linux', 'libpcre.a')
|
||||
|
||||
@@ -106,7 +106,7 @@ static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
|
||||
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
if (!x)
|
||||
@@ -159,7 +159,7 @@ static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
|
||||
{
|
||||
return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
|
||||
return pCtx->ThrowNativeError("Invalid regex handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
if (!x)
|
||||
|
||||
+162
-145
@@ -88,6 +88,10 @@ HookTypeData g_HookTypes[SDKHook_MAXHOOKS] =
|
||||
{"Reload", "DT_BaseCombatWeapon", false},
|
||||
{"ReloadPost", "DT_BaseCombatWeapon", false},
|
||||
{"GetMaxHealth", "", false},
|
||||
{"Blocked", "", false},
|
||||
{"BlockedPost", "", false},
|
||||
{"OnTakeDamageAlive", "DT_BaseCombatCharacter", false},
|
||||
{"OnTakeDamageAlivePost", "DT_BaseCombatCharacter", false},
|
||||
};
|
||||
|
||||
SDKHooks g_Interface;
|
||||
@@ -166,6 +170,7 @@ SH_DECL_MANUALHOOK0(GetMaxHealth, 0, 0, 0, int);
|
||||
#endif
|
||||
SH_DECL_MANUALHOOK1_void(GroundEntChanged, 0, 0, 0, void *);
|
||||
SH_DECL_MANUALHOOK1(OnTakeDamage, 0, 0, 0, int, CTakeDamageInfoHack &);
|
||||
SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, int, CTakeDamageInfoHack &);
|
||||
SH_DECL_MANUALHOOK0_void(PreThink, 0, 0, 0);
|
||||
SH_DECL_MANUALHOOK0_void(PostThink, 0, 0, 0);
|
||||
SH_DECL_MANUALHOOK0(Reload, 0, 0, 0, bool);
|
||||
@@ -191,6 +196,7 @@ SH_DECL_MANUALHOOK1(Weapon_CanUse, 0, 0, 0, bool, CBaseCombatWeapon *);
|
||||
SH_DECL_MANUALHOOK3_void(Weapon_Drop, 0, 0, 0, CBaseCombatWeapon *, const Vector *, const Vector *);
|
||||
SH_DECL_MANUALHOOK1_void(Weapon_Equip, 0, 0, 0, CBaseCombatWeapon *);
|
||||
SH_DECL_MANUALHOOK2(Weapon_Switch, 0, 0, 0, bool, CBaseCombatWeapon *, int);
|
||||
SH_DECL_MANUALHOOK1_void(Blocked, 0, 0, 0, CBaseEntity *);
|
||||
|
||||
|
||||
/**
|
||||
@@ -213,6 +219,26 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer[0] = '\0';
|
||||
if (!gameconfs->LoadGameConfigFile("sdkhooks.games", &g_pGameConf, buffer, sizeof(buffer)))
|
||||
{
|
||||
if (buffer[0])
|
||||
{
|
||||
g_pSM->Format(error, maxlength, "Could not read sdkhooks.games gamedata: %s", buffer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CUtlVector<IEntityListener *> *entListeners = EntListeners();
|
||||
if (!entListeners)
|
||||
{
|
||||
g_pSM->Format(error, maxlength, "Failed to setup entity listeners");
|
||||
return false;
|
||||
}
|
||||
|
||||
entListeners->AddToTail(this);
|
||||
|
||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||
sharesys->AddNatives(myself, g_Natives);
|
||||
sharesys->RegisterLibrary(myself, "sdkhooks");
|
||||
@@ -231,26 +257,6 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
#endif
|
||||
g_pOnLevelInit = forwards->CreateForward("OnLevelInit", ET_Hook, 2, NULL, Param_String, Param_String);
|
||||
|
||||
buffer[0] = '\0';
|
||||
if (!gameconfs->LoadGameConfigFile("sdkhooks.games", &g_pGameConf, buffer, sizeof(buffer)))
|
||||
{
|
||||
if (buffer[0])
|
||||
{
|
||||
g_pSM->Format(error, maxlength, "Could not read sdkhooks.games gamedata: %s", buffer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CUtlVector<IEntityListener *> *entListeners = EntListeners();
|
||||
if (!entListeners)
|
||||
{
|
||||
g_pSM->Format(error, maxlength, "Failed to setup entity listeners");
|
||||
return false;
|
||||
}
|
||||
|
||||
entListeners->AddToTail(this);
|
||||
|
||||
SetupHooks();
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
@@ -438,6 +444,21 @@ FeatureStatus SDKHooks::GetFeatureStatus(FeatureType type, const char *name)
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
|
||||
static void PopulateCallbackList(const ke::Vector<HookList> &source, ke::Vector<IPluginFunction *> &destination, int entity)
|
||||
{
|
||||
destination.ensure(8); /* Skip trivial allocations as AMTL uses length<<1. */
|
||||
for (size_t iter = 0; iter < source.length(); ++iter)
|
||||
{
|
||||
if (source[iter].entity != entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
destination.append(source[iter].callback);
|
||||
}
|
||||
}
|
||||
|
||||
cell_t SDKHooks::Call(int entity, SDKHookType type, int other)
|
||||
{
|
||||
return Call(gamehelpers->ReferenceToEntity(entity), type, gamehelpers->ReferenceToEntity(other));
|
||||
@@ -461,17 +482,14 @@ cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther)
|
||||
continue;
|
||||
}
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEnt);
|
||||
int other = gamehelpers->EntityToBCompatRef(pOther);
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(other);
|
||||
|
||||
@@ -500,6 +518,7 @@ void SDKHooks::SetupHooks()
|
||||
CHECKOFFSET(FireBullets, false, true);
|
||||
CHECKOFFSET(GroundEntChanged, false, true);
|
||||
CHECKOFFSET(OnTakeDamage, true, true);
|
||||
CHECKOFFSET(OnTakeDamage_Alive,true, true);
|
||||
CHECKOFFSET(PreThink, true, true);
|
||||
CHECKOFFSET(PostThink, true, true);
|
||||
CHECKOFFSET(Reload, true, true);
|
||||
@@ -517,6 +536,7 @@ void SDKHooks::SetupHooks()
|
||||
CHECKOFFSET_W(Equip, true, true);
|
||||
CHECKOFFSET_W(Switch, true, true);
|
||||
CHECKOFFSET(VPhysicsUpdate, true, true);
|
||||
CHECKOFFSET(Blocked, true, true);
|
||||
|
||||
// this one is in a class all its own -_-
|
||||
offset = 0;
|
||||
@@ -591,6 +611,12 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac
|
||||
case SDKHook_OnTakeDamagePost:
|
||||
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamagePost), true);
|
||||
break;
|
||||
case SDKHook_OnTakeDamage_Alive:
|
||||
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_Alive), false);
|
||||
break;
|
||||
case SDKHook_OnTakeDamage_AlivePost:
|
||||
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_AlivePost), true);
|
||||
break;
|
||||
case SDKHook_PreThink:
|
||||
hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThink), false);
|
||||
break;
|
||||
@@ -687,6 +713,12 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac
|
||||
case SDKHook_ShouldCollide:
|
||||
hookid = SH_ADD_MANUALVPHOOK(ShouldCollide, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ShouldCollide), false);
|
||||
break;
|
||||
case SDKHook_Blocked:
|
||||
hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Blocked), false);
|
||||
break;
|
||||
case SDKHook_BlockedPost:
|
||||
hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_BlockedPost), true);
|
||||
break;
|
||||
}
|
||||
|
||||
vhook.SetHookID(hookid);
|
||||
@@ -862,9 +894,6 @@ bool SDKHooks::Hook_LevelInit(char const *pMapName, char const *pMapEntities, ch
|
||||
g_pOnLevelInit->PushStringEx(g_szMapEntities, sizeof(g_szMapEntities), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
g_pOnLevelInit->Execute(&result);
|
||||
|
||||
if(result >= Pl_Handled)
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
||||
|
||||
if(result == Pl_Changed)
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_HANDLED, true, &IServerGameDLL::LevelInit, (pMapName, g_szMapEntities, pOldLevel, pLandmarkName, loadGame, background));
|
||||
|
||||
@@ -914,15 +943,11 @@ void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info)
|
||||
|
||||
const char *weapon = pInfo->GetWeaponName();
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(info.m_iShots);
|
||||
callback->PushString(weapon?weapon:"");
|
||||
@@ -956,15 +981,11 @@ int SDKHooks::Hook_GetMaxHealth()
|
||||
|
||||
cell_t res = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCellByRef(&new_max);
|
||||
callback->Execute(&res);
|
||||
@@ -985,12 +1006,12 @@ void SDKHooks::Hook_GroundEntChangedPost(void *pVar)
|
||||
Call(META_IFACEPTR(CBaseEntity), SDKHook_GroundEntChangedPost);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
int SDKHooks::HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType)
|
||||
{
|
||||
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
||||
|
||||
CVTableHook vhook(pEntity);
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_OnTakeDamage];
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[hookType];
|
||||
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
||||
{
|
||||
if (vhook != vtablehooklist[entry]->vtablehook)
|
||||
@@ -1006,22 +1027,18 @@ int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
int weapon = info.GetWeapon();
|
||||
|
||||
Vector force = info.GetDamageForce();
|
||||
cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
|
||||
cell_t damageForce[3] = { sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z) };
|
||||
|
||||
Vector pos = info.GetDamagePosition();
|
||||
cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
|
||||
cell_t damagePosition[3] = { sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z) };
|
||||
|
||||
cell_t res, ret = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCellByRef(&attacker);
|
||||
callback->PushCellByRef(&inflictor);
|
||||
@@ -1029,23 +1046,23 @@ int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
callback->PushCellByRef(&damagetype);
|
||||
callback->PushCellByRef(&weapon);
|
||||
callback->PushArray(damageForce, 3, SM_PARAM_COPYBACK);
|
||||
callback->PushArray(damagePosition, 3, SM_PARAM_COPYBACK);
|
||||
callback->PushArray(damagePosition, 3, SM_PARAM_COPYBACK);
|
||||
callback->PushCell(info.GetDamageCustom());
|
||||
callback->Execute(&res);
|
||||
|
||||
if(res >= ret)
|
||||
if (res >= ret)
|
||||
{
|
||||
ret = res;
|
||||
if(ret == Pl_Changed)
|
||||
if (ret == Pl_Changed)
|
||||
{
|
||||
CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
|
||||
if(!pEntAttacker)
|
||||
if (!pEntAttacker)
|
||||
{
|
||||
callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for attacker is invalid", attacker);
|
||||
RETURN_META_VALUE(MRES_IGNORED, 0);
|
||||
}
|
||||
CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
|
||||
if(!pEntInflictor)
|
||||
if (!pEntInflictor)
|
||||
{
|
||||
callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for inflictor is invalid", inflictor);
|
||||
RETURN_META_VALUE(MRES_IGNORED, 0);
|
||||
@@ -1067,12 +1084,12 @@ int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ret >= Pl_Handled)
|
||||
|
||||
if (ret >= Pl_Handled)
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, 1);
|
||||
|
||||
if(ret == Pl_Changed)
|
||||
RETURN_META_VALUE(MRES_HANDLED, 1);
|
||||
if (ret == Pl_Changed)
|
||||
RETURN_META_VALUE(MRES_HANDLED, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1080,12 +1097,12 @@ int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
RETURN_META_VALUE(MRES_IGNORED, 0);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
||||
int SDKHooks::HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType)
|
||||
{
|
||||
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
||||
|
||||
CVTableHook vhook(pEntity);
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_OnTakeDamagePost];
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[hookType];
|
||||
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
||||
{
|
||||
if (vhook != vtablehooklist[entry]->vtablehook)
|
||||
@@ -1095,15 +1112,11 @@ int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
||||
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(info.GetAttacker());
|
||||
callback->PushCell(info.GetInflictor());
|
||||
@@ -1112,11 +1125,11 @@ int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
||||
callback->PushCell(info.GetWeapon());
|
||||
|
||||
Vector force = info.GetDamageForce();
|
||||
cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
|
||||
cell_t damageForce[3] = { sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z) };
|
||||
callback->PushArray(damageForce, 3);
|
||||
|
||||
Vector pos = info.GetDamagePosition();
|
||||
cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
|
||||
cell_t damagePosition[3] = { sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z) };
|
||||
callback->PushArray(damagePosition, 3);
|
||||
|
||||
callback->PushCell(info.GetDamageCustom());
|
||||
@@ -1130,6 +1143,26 @@ int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
||||
RETURN_META_VALUE(MRES_IGNORED, 0);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
||||
{
|
||||
return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
||||
{
|
||||
return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamagePost);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamage_Alive(CTakeDamageInfoHack &info)
|
||||
{
|
||||
return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage_Alive);
|
||||
}
|
||||
|
||||
int SDKHooks::Hook_OnTakeDamage_AlivePost(CTakeDamageInfoHack &info)
|
||||
{
|
||||
return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamage_AlivePost);
|
||||
}
|
||||
|
||||
void SDKHooks::Hook_PreThink()
|
||||
{
|
||||
Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThink);
|
||||
@@ -1168,15 +1201,11 @@ bool SDKHooks::Hook_Reload()
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
cell_t res = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->Execute(&res);
|
||||
}
|
||||
@@ -1195,7 +1224,7 @@ bool SDKHooks::Hook_ReloadPost()
|
||||
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
||||
|
||||
CVTableHook vhook(pEntity);
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Reload];
|
||||
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_ReloadPost];
|
||||
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
||||
{
|
||||
if (vhook != vtablehooklist[entry]->vtablehook)
|
||||
@@ -1206,15 +1235,11 @@ bool SDKHooks::Hook_ReloadPost()
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
cell_t origreturn = META_RESULT_ORIG_RET(bool) ? 1 : 0;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(origreturn);
|
||||
callback->Execute(NULL);
|
||||
@@ -1253,15 +1278,11 @@ bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask)
|
||||
cell_t origRet = ((META_RESULT_STATUS >= MRES_OVERRIDE)?(META_RESULT_OVERRIDE_RET(bool)):(META_RESULT_ORIG_RET(bool))) ? 1 : 0;
|
||||
cell_t res = 0;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(collisionGroup);
|
||||
callback->PushCell(contentsMask);
|
||||
@@ -1301,15 +1322,11 @@ void SDKHooks::Hook_Spawn()
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
cell_t res = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->Execute(&res);
|
||||
}
|
||||
@@ -1399,15 +1416,11 @@ void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir,
|
||||
int ammotype = info.GetAmmoType();
|
||||
cell_t res, ret = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCellByRef(&attacker);
|
||||
callback->PushCellByRef(&inflictor);
|
||||
@@ -1477,15 +1490,11 @@ void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vec
|
||||
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(info.GetAttacker());
|
||||
callback->PushCell(info.GetInflictor());
|
||||
@@ -1521,15 +1530,11 @@ void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE
|
||||
int caller = gamehelpers->EntityToBCompatRef(pCaller);
|
||||
cell_t ret = Pl_Continue;
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(activator);
|
||||
callback->PushCell(caller);
|
||||
@@ -1564,15 +1569,11 @@ void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T
|
||||
int activator = gamehelpers->EntityToBCompatRef(pActivator);
|
||||
int caller = gamehelpers->EntityToBCompatRef(pCaller);
|
||||
|
||||
ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
|
||||
for (entry = 0; entry < pawnlist.length(); ++entry)
|
||||
ke::Vector<IPluginFunction *> callbackList;
|
||||
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
||||
for (entry = 0; entry < callbackList.length(); ++entry)
|
||||
{
|
||||
if (entity != pawnlist[entry].entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPluginFunction *callback = pawnlist[entry].callback;
|
||||
IPluginFunction *callback = callbackList[entry];
|
||||
callback->PushCell(entity);
|
||||
callback->PushCell(activator);
|
||||
callback->PushCell(caller);
|
||||
@@ -1612,6 +1613,22 @@ void SDKHooks::Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics)
|
||||
Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdatePost);
|
||||
}
|
||||
|
||||
void SDKHooks::Hook_Blocked(CBaseEntity *pOther)
|
||||
{
|
||||
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Blocked, pOther);
|
||||
|
||||
if(result >= Pl_Handled)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void SDKHooks::Hook_BlockedPost(CBaseEntity *pOther)
|
||||
{
|
||||
Call(META_IFACEPTR(CBaseEntity), SDKHook_BlockedPost, pOther);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
bool SDKHooks::Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon)
|
||||
{
|
||||
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchTo, pWeapon);
|
||||
|
||||
+354
-342
@@ -1,349 +1,361 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
#include <ISDKHooks.h>
|
||||
#include <IBinTools.h>
|
||||
#include <convar.h>
|
||||
#include <sh_list.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <vtable_hook_helper.h>
|
||||
|
||||
#include <iplayerinfo.h>
|
||||
#include <shareddefs.h>
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
#include <itoolentity.h>
|
||||
#endif
|
||||
|
||||
#include "takedamageinfohack.h"
|
||||
|
||||
#ifndef METAMOD_PLAPI_VERSION
|
||||
#define GetCGlobals pGlobals
|
||||
#define GetEngineFactory engineFactory
|
||||
#define GetServerFactory serverFactory
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE >= SE_CSS && SOURCE_ENGINE != SE_LEFT4DEAD
|
||||
#define GETMAXHEALTH_IS_VIRTUAL
|
||||
#endif
|
||||
#if SOURCE_ENGINE != SE_HL2DM && SOURCE_ENGINE != SE_DODS && SOURCE_ENGINE != SE_CSS && SOURCE_ENGINE != SE_TF2 && SOURCE_ENGINE != SE_LEFT4DEAD2 && SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_NUCLEARDAWN
|
||||
#define GAMEDESC_CAN_CHANGE
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
class CEntityKeyValues;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Globals
|
||||
*/
|
||||
|
||||
struct HookTypeData
|
||||
{
|
||||
const char *name;
|
||||
const char *dtReq;
|
||||
bool supported;
|
||||
};
|
||||
|
||||
enum SDKHookType
|
||||
{
|
||||
SDKHook_EndTouch,
|
||||
SDKHook_FireBulletsPost,
|
||||
SDKHook_OnTakeDamage,
|
||||
SDKHook_OnTakeDamagePost,
|
||||
SDKHook_PreThink,
|
||||
SDKHook_PostThink,
|
||||
SDKHook_SetTransmit,
|
||||
SDKHook_Spawn,
|
||||
SDKHook_StartTouch,
|
||||
SDKHook_Think,
|
||||
SDKHook_Touch,
|
||||
SDKHook_TraceAttack,
|
||||
SDKHook_TraceAttackPost,
|
||||
SDKHook_WeaponCanSwitchTo,
|
||||
SDKHook_WeaponCanUse,
|
||||
SDKHook_WeaponDrop,
|
||||
SDKHook_WeaponEquip,
|
||||
SDKHook_WeaponSwitch,
|
||||
SDKHook_ShouldCollide,
|
||||
SDKHook_PreThinkPost,
|
||||
SDKHook_PostThinkPost,
|
||||
SDKHook_ThinkPost,
|
||||
SDKHook_EndTouchPost,
|
||||
SDKHook_GroundEntChangedPost,
|
||||
SDKHook_SpawnPost,
|
||||
SDKHook_StartTouchPost,
|
||||
SDKHook_TouchPost,
|
||||
SDKHook_VPhysicsUpdate,
|
||||
SDKHook_VPhysicsUpdatePost,
|
||||
SDKHook_WeaponCanSwitchToPost,
|
||||
SDKHook_WeaponCanUsePost,
|
||||
SDKHook_WeaponDropPost,
|
||||
SDKHook_WeaponEquipPost,
|
||||
SDKHook_WeaponSwitchPost,
|
||||
SDKHook_Use,
|
||||
SDKHook_UsePost,
|
||||
SDKHook_Reload,
|
||||
SDKHook_ReloadPost,
|
||||
SDKHook_GetMaxHealth,
|
||||
SDKHook_MAXHOOKS
|
||||
};
|
||||
|
||||
enum HookReturn
|
||||
{
|
||||
HookRet_Successful,
|
||||
HookRet_InvalidEntity,
|
||||
HookRet_InvalidHookType,
|
||||
HookRet_NotSupported,
|
||||
HookRet_BadEntForHookType,
|
||||
};
|
||||
|
||||
#if SOURCE_ENGINE >= SE_CSS
|
||||
typedef void *(*ReticulateSplines)();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Classes
|
||||
*/
|
||||
|
||||
class IPhysicsObject;
|
||||
class CDmgAccumulator;
|
||||
typedef CBaseEntity CBaseCombatWeapon;
|
||||
|
||||
struct HookList
|
||||
{
|
||||
public:
|
||||
int entity;
|
||||
IPluginFunction *callback;
|
||||
};
|
||||
|
||||
class CVTableList
|
||||
{
|
||||
public:
|
||||
CVTableList() : vtablehook(NULL)
|
||||
{
|
||||
};
|
||||
|
||||
~CVTableList()
|
||||
{
|
||||
delete vtablehook;
|
||||
};
|
||||
public:
|
||||
CVTableHook *vtablehook;
|
||||
ke::Vector<HookList> hooks;
|
||||
};
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
#include <ISDKHooks.h>
|
||||
#include <IBinTools.h>
|
||||
#include <convar.h>
|
||||
#include <sh_list.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <vtable_hook_helper.h>
|
||||
|
||||
#include <iplayerinfo.h>
|
||||
#include <shareddefs.h>
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
#include <itoolentity.h>
|
||||
#endif
|
||||
|
||||
#include "takedamageinfohack.h"
|
||||
|
||||
#ifndef METAMOD_PLAPI_VERSION
|
||||
#define GetCGlobals pGlobals
|
||||
#define GetEngineFactory engineFactory
|
||||
#define GetServerFactory serverFactory
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE >= SE_CSS && SOURCE_ENGINE != SE_LEFT4DEAD
|
||||
#define GETMAXHEALTH_IS_VIRTUAL
|
||||
#endif
|
||||
#if SOURCE_ENGINE != SE_HL2DM && SOURCE_ENGINE != SE_DODS && SOURCE_ENGINE != SE_CSS && SOURCE_ENGINE != SE_TF2 && SOURCE_ENGINE != SE_LEFT4DEAD2 && SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_NUCLEARDAWN
|
||||
#define GAMEDESC_CAN_CHANGE
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
class CEntityKeyValues;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Globals
|
||||
*/
|
||||
|
||||
struct HookTypeData
|
||||
{
|
||||
const char *name;
|
||||
const char *dtReq;
|
||||
bool supported;
|
||||
};
|
||||
|
||||
enum SDKHookType
|
||||
{
|
||||
SDKHook_EndTouch,
|
||||
SDKHook_FireBulletsPost,
|
||||
SDKHook_OnTakeDamage,
|
||||
SDKHook_OnTakeDamagePost,
|
||||
SDKHook_PreThink,
|
||||
SDKHook_PostThink,
|
||||
SDKHook_SetTransmit,
|
||||
SDKHook_Spawn,
|
||||
SDKHook_StartTouch,
|
||||
SDKHook_Think,
|
||||
SDKHook_Touch,
|
||||
SDKHook_TraceAttack,
|
||||
SDKHook_TraceAttackPost,
|
||||
SDKHook_WeaponCanSwitchTo,
|
||||
SDKHook_WeaponCanUse,
|
||||
SDKHook_WeaponDrop,
|
||||
SDKHook_WeaponEquip,
|
||||
SDKHook_WeaponSwitch,
|
||||
SDKHook_ShouldCollide,
|
||||
SDKHook_PreThinkPost,
|
||||
SDKHook_PostThinkPost,
|
||||
SDKHook_ThinkPost,
|
||||
SDKHook_EndTouchPost,
|
||||
SDKHook_GroundEntChangedPost,
|
||||
SDKHook_SpawnPost,
|
||||
SDKHook_StartTouchPost,
|
||||
SDKHook_TouchPost,
|
||||
SDKHook_VPhysicsUpdate,
|
||||
SDKHook_VPhysicsUpdatePost,
|
||||
SDKHook_WeaponCanSwitchToPost,
|
||||
SDKHook_WeaponCanUsePost,
|
||||
SDKHook_WeaponDropPost,
|
||||
SDKHook_WeaponEquipPost,
|
||||
SDKHook_WeaponSwitchPost,
|
||||
SDKHook_Use,
|
||||
SDKHook_UsePost,
|
||||
SDKHook_Reload,
|
||||
SDKHook_ReloadPost,
|
||||
SDKHook_GetMaxHealth,
|
||||
SDKHook_Blocked,
|
||||
SDKHook_BlockedPost,
|
||||
SDKHook_OnTakeDamage_Alive,
|
||||
SDKHook_OnTakeDamage_AlivePost,
|
||||
SDKHook_MAXHOOKS
|
||||
};
|
||||
|
||||
enum HookReturn
|
||||
{
|
||||
HookRet_Successful,
|
||||
HookRet_InvalidEntity,
|
||||
HookRet_InvalidHookType,
|
||||
HookRet_NotSupported,
|
||||
HookRet_BadEntForHookType,
|
||||
};
|
||||
|
||||
#if SOURCE_ENGINE >= SE_CSS
|
||||
typedef void *(*ReticulateSplines)();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Classes
|
||||
*/
|
||||
|
||||
class IPhysicsObject;
|
||||
class CDmgAccumulator;
|
||||
typedef CBaseEntity CBaseCombatWeapon;
|
||||
|
||||
struct HookList
|
||||
{
|
||||
public:
|
||||
int entity;
|
||||
IPluginFunction *callback;
|
||||
};
|
||||
|
||||
class CVTableList
|
||||
{
|
||||
public:
|
||||
CVTableList() : vtablehook(NULL)
|
||||
{
|
||||
};
|
||||
|
||||
~CVTableList()
|
||||
{
|
||||
delete vtablehook;
|
||||
};
|
||||
public:
|
||||
CVTableHook *vtablehook;
|
||||
ke::Vector<HookList> hooks;
|
||||
};
|
||||
|
||||
class IEntityListener
|
||||
{
|
||||
public:
|
||||
virtual void OnEntityCreated( CBaseEntity *pEntity ) {};
|
||||
virtual void OnEntitySpawned( CBaseEntity *pEntity ) {};
|
||||
virtual void OnEntityDeleted( CBaseEntity *pEntity ) {};
|
||||
};
|
||||
|
||||
class SDKHooks :
|
||||
public SDKExtension,
|
||||
public IConCommandBaseAccessor,
|
||||
public IPluginsListener,
|
||||
public IFeatureProvider,
|
||||
public IEntityListener,
|
||||
public IClientListener,
|
||||
public ISDKHooks
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
* Note: It is is a good idea to add natives here, if any are provided.
|
||||
*/
|
||||
virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
//virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
/**
|
||||
* @brief this is called when Core wants to know if your extension is working.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @return True if working, false otherwise.
|
||||
*/
|
||||
//virtual bool QueryRunning(char *error, size_t maxlength);
|
||||
|
||||
/** Returns version string */
|
||||
virtual const char *GetExtensionVerString();
|
||||
|
||||
/** Returns date string */
|
||||
virtual const char *GetExtensionDateString();
|
||||
|
||||
public:
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @param late Whether or not Metamod considers this a late load.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod's pause state is changing.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param paused Pause state being set.
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
|
||||
#endif
|
||||
|
||||
public: // IPluginsListener
|
||||
virtual void OnPluginLoaded(IPlugin *plugin);
|
||||
virtual void OnPluginUnloaded(IPlugin *plugin);
|
||||
|
||||
public: // IConCommandBaseAccessor
|
||||
virtual bool RegisterConCommandBase(ConCommandBase *pVar);
|
||||
|
||||
public: // IFeatureProvider
|
||||
virtual FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||
|
||||
public: // IEntityListener
|
||||
virtual void OnEntityCreated(CBaseEntity *pEntity);
|
||||
virtual void OnEntityDeleted(CBaseEntity *pEntity);
|
||||
|
||||
public: // IClientListener
|
||||
virtual void OnClientPutInServer(int client);
|
||||
virtual void OnClientDisconnecting(int client);
|
||||
|
||||
public: // ISDKHooks
|
||||
virtual void AddEntityListener(ISMEntityListener *listener);
|
||||
virtual void RemoveEntityListener(ISMEntityListener *listener);
|
||||
|
||||
private:
|
||||
SourceHook::List<ISMEntityListener *> m_EntListeners;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
};
|
||||
|
||||
class SDKHooks :
|
||||
public SDKExtension,
|
||||
public IConCommandBaseAccessor,
|
||||
public IPluginsListener,
|
||||
public IFeatureProvider,
|
||||
public IEntityListener,
|
||||
public IClientListener,
|
||||
public ISDKHooks
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
* Note: It is is a good idea to add natives here, if any are provided.
|
||||
*/
|
||||
virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
//virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
/**
|
||||
* @brief this is called when Core wants to know if your extension is working.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @return True if working, false otherwise.
|
||||
*/
|
||||
//virtual bool QueryRunning(char *error, size_t maxlength);
|
||||
|
||||
/** Returns version string */
|
||||
virtual const char *GetExtensionVerString();
|
||||
|
||||
/** Returns date string */
|
||||
virtual const char *GetExtensionDateString();
|
||||
|
||||
public:
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @param late Whether or not Metamod considers this a late load.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod's pause state is changing.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param paused Pause state being set.
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
|
||||
#endif
|
||||
|
||||
public: // IPluginsListener
|
||||
virtual void OnPluginLoaded(IPlugin *plugin);
|
||||
virtual void OnPluginUnloaded(IPlugin *plugin);
|
||||
|
||||
public: // IConCommandBaseAccessor
|
||||
virtual bool RegisterConCommandBase(ConCommandBase *pVar);
|
||||
|
||||
public: // IFeatureProvider
|
||||
virtual FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||
|
||||
public: // IEntityListener
|
||||
virtual void OnEntityCreated(CBaseEntity *pEntity);
|
||||
virtual void OnEntityDeleted(CBaseEntity *pEntity);
|
||||
|
||||
public: // IClientListener
|
||||
virtual void OnClientPutInServer(int client);
|
||||
virtual void OnClientDisconnecting(int client);
|
||||
|
||||
public: // ISDKHooks
|
||||
virtual void AddEntityListener(ISMEntityListener *listener);
|
||||
virtual void RemoveEntityListener(ISMEntityListener *listener);
|
||||
|
||||
private:
|
||||
SourceHook::List<ISMEntityListener *> m_EntListeners;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
cell_t Call(int entity, SDKHookType type, int other=INVALID_EHANDLE_INDEX);
|
||||
cell_t Call(CBaseEntity *pEnt, SDKHookType type, int other=INVALID_EHANDLE_INDEX);
|
||||
cell_t Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther);
|
||||
void SetupHooks();
|
||||
|
||||
HookReturn Hook(int entity, SDKHookType type, IPluginFunction *pCallback);
|
||||
void Unhook(int entity, SDKHookType type, IPluginFunction *pCallback);
|
||||
|
||||
/**
|
||||
* IServerGameDLL & IVEngineServer Hook Handlers
|
||||
*/
|
||||
#ifdef GAMEDESC_CAN_CHANGE
|
||||
const char *Hook_GetGameDescription();
|
||||
#endif
|
||||
const char *Hook_GetMapEntitiesString();
|
||||
bool Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
|
||||
|
||||
/**
|
||||
* CBaseEntity Hook Handlers
|
||||
*/
|
||||
void Hook_EndTouch(CBaseEntity *pOther);
|
||||
void Hook_EndTouchPost(CBaseEntity *pOther);
|
||||
void Hook_FireBulletsPost(const FireBulletsInfo_t &info);
|
||||
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
||||
int Hook_GetMaxHealth();
|
||||
#endif
|
||||
void Hook_GroundEntChangedPost(void *pVar);
|
||||
int Hook_OnTakeDamage(CTakeDamageInfoHack &info);
|
||||
int Hook_OnTakeDamagePost(CTakeDamageInfoHack &info);
|
||||
void Hook_PreThink();
|
||||
void Hook_PreThinkPost();
|
||||
void Hook_PostThink();
|
||||
void Hook_PostThinkPost();
|
||||
bool Hook_Reload();
|
||||
bool Hook_ReloadPost();
|
||||
void Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways);
|
||||
bool Hook_ShouldCollide(int collisonGroup, int contentsMask);
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
void Hook_Spawn(CEntityKeyValues *kv);
|
||||
void Hook_SpawnPost(CEntityKeyValues *kv);
|
||||
#else
|
||||
void Hook_Spawn();
|
||||
void Hook_SpawnPost();
|
||||
#endif
|
||||
void Hook_StartTouch(CBaseEntity *pOther);
|
||||
void Hook_StartTouchPost(CBaseEntity *pOther);
|
||||
void Hook_Think();
|
||||
void Hook_ThinkPost();
|
||||
void Hook_Touch(CBaseEntity *pOther);
|
||||
void Hook_TouchPost(CBaseEntity *pOther);
|
||||
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013
|
||||
void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator);
|
||||
void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator);
|
||||
#else
|
||||
void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
#endif
|
||||
void Hook_UpdateOnRemove();
|
||||
void Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_VPhysicsUpdate(IPhysicsObject *pPhysics);
|
||||
void Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics);
|
||||
bool Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon);
|
||||
void Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity);
|
||||
void Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity);
|
||||
void Hook_WeaponEquip(CBaseCombatWeapon *pWeapon);
|
||||
void Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex);
|
||||
bool Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex);
|
||||
|
||||
private:
|
||||
void HandleEntityCreated(CBaseEntity *pEntity, int ref);
|
||||
void HandleEntityDeleted(CBaseEntity *pEntity, int ref);
|
||||
void Unhook(CBaseEntity *pEntity);
|
||||
void Unhook(IPluginContext *pContext);
|
||||
};
|
||||
|
||||
extern CGlobalVars *gpGlobals;
|
||||
extern ke::Vector<CVTableList *> g_HookList[SDKHook_MAXHOOKS];
|
||||
|
||||
extern ICvar *icvar;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
extern IServerTools *servertools;
|
||||
#endif
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
cell_t Call(CBaseEntity *pEnt, SDKHookType type, int other=INVALID_EHANDLE_INDEX);
|
||||
cell_t Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther);
|
||||
void SetupHooks();
|
||||
|
||||
HookReturn Hook(int entity, SDKHookType type, IPluginFunction *pCallback);
|
||||
void Unhook(int entity, SDKHookType type, IPluginFunction *pCallback);
|
||||
|
||||
/**
|
||||
* IServerGameDLL & IVEngineServer Hook Handlers
|
||||
*/
|
||||
#ifdef GAMEDESC_CAN_CHANGE
|
||||
const char *Hook_GetGameDescription();
|
||||
#endif
|
||||
const char *Hook_GetMapEntitiesString();
|
||||
bool Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
|
||||
|
||||
/**
|
||||
* CBaseEntity Hook Handlers
|
||||
*/
|
||||
void Hook_EndTouch(CBaseEntity *pOther);
|
||||
void Hook_EndTouchPost(CBaseEntity *pOther);
|
||||
void Hook_FireBulletsPost(const FireBulletsInfo_t &info);
|
||||
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
||||
int Hook_GetMaxHealth();
|
||||
#endif
|
||||
void Hook_GroundEntChangedPost(void *pVar);
|
||||
int Hook_OnTakeDamage(CTakeDamageInfoHack &info);
|
||||
int Hook_OnTakeDamagePost(CTakeDamageInfoHack &info);
|
||||
int Hook_OnTakeDamage_Alive(CTakeDamageInfoHack &info);
|
||||
int Hook_OnTakeDamage_AlivePost(CTakeDamageInfoHack &info);
|
||||
void Hook_PreThink();
|
||||
void Hook_PreThinkPost();
|
||||
void Hook_PostThink();
|
||||
void Hook_PostThinkPost();
|
||||
bool Hook_Reload();
|
||||
bool Hook_ReloadPost();
|
||||
void Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways);
|
||||
bool Hook_ShouldCollide(int collisonGroup, int contentsMask);
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
void Hook_Spawn(CEntityKeyValues *kv);
|
||||
void Hook_SpawnPost(CEntityKeyValues *kv);
|
||||
#else
|
||||
void Hook_Spawn();
|
||||
void Hook_SpawnPost();
|
||||
#endif
|
||||
void Hook_StartTouch(CBaseEntity *pOther);
|
||||
void Hook_StartTouchPost(CBaseEntity *pOther);
|
||||
void Hook_Think();
|
||||
void Hook_ThinkPost();
|
||||
void Hook_Touch(CBaseEntity *pOther);
|
||||
void Hook_TouchPost(CBaseEntity *pOther);
|
||||
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013
|
||||
void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator);
|
||||
void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator);
|
||||
#else
|
||||
void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
#endif
|
||||
void Hook_UpdateOnRemove();
|
||||
void Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_VPhysicsUpdate(IPhysicsObject *pPhysics);
|
||||
void Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics);
|
||||
void Hook_Blocked(CBaseEntity *pOther);
|
||||
void Hook_BlockedPost(CBaseEntity *pOther);
|
||||
bool Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon);
|
||||
void Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity);
|
||||
void Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity);
|
||||
void Hook_WeaponEquip(CBaseCombatWeapon *pWeapon);
|
||||
void Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon);
|
||||
bool Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex);
|
||||
bool Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex);
|
||||
|
||||
private:
|
||||
void HandleEntityCreated(CBaseEntity *pEntity, int ref);
|
||||
void HandleEntityDeleted(CBaseEntity *pEntity, int ref);
|
||||
void Unhook(CBaseEntity *pEntity);
|
||||
void Unhook(IPluginContext *pContext);
|
||||
|
||||
private:
|
||||
int HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType);
|
||||
int HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType);
|
||||
};
|
||||
|
||||
extern CGlobalVars *gpGlobals;
|
||||
extern ke::Vector<CVTableList *> g_HookList[SDKHook_MAXHOOKS];
|
||||
|
||||
extern ICvar *icvar;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
extern IServerTools *servertools;
|
||||
#endif
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user