Compare commits
2344 Commits
amxmodx-1.
...
master
Author | SHA1 | Date | |
---|---|---|---|
ba37f2f428 | |||
0de7beb351 | |||
4d38b9c73b | |||
03cdb55266 | |||
950e63d62f | |||
0a0a8bc13d | |||
63c18bba6c | |||
338e8307f8 | |||
475b1cdc29 | |||
e5c519cf07 | |||
|
df6b589ba1 | ||
|
fde732f66d | ||
|
49a8b959b3 | ||
|
ec82e3f34c | ||
|
8ee3da24cb | ||
|
6e8554d1d2 | ||
|
275be8b0a8 | ||
|
f8ac58c839 | ||
|
e8909c1583 | ||
|
3cda059669 | ||
|
5dcda02b65 | ||
|
e6d9d9b71c | ||
|
2563bf6c26 | ||
|
c61735130d | ||
|
cac80584a0 | ||
|
3eefe5562e | ||
|
c317dc55c7 | ||
|
8fefd48af2 | ||
|
f37f9d1c66 | ||
|
8413946ace | ||
|
be9ccc42eb | ||
|
fb7ab6d08d | ||
|
01e60834fa | ||
|
3289b3c63c | ||
|
e17d37abe3 | ||
|
51c3f1b195 | ||
|
2c8be75057 | ||
|
10db2e5c85 | ||
|
05f86f05c0 | ||
|
36d5aa97b1 | ||
|
b8c490b5e6 | ||
|
301701b1da | ||
|
5b1b844184 | ||
|
6c9c37eb45 | ||
|
d88b7e3c98 | ||
|
6b9d82fa60 | ||
|
08494d0d66 | ||
|
97b03ea567 | ||
|
344fb3d410 | ||
|
37cbccef6a | ||
|
7fb6440ce9 | ||
|
1a1b16614a | ||
|
af32a9790b | ||
|
2e5e3ce060 | ||
|
c58daeafca | ||
|
7fef58c374 | ||
|
3c1856f7af | ||
|
9fbf91ded0 | ||
|
3d517d69e2 | ||
|
70d1aff519 | ||
|
bee4b47b07 | ||
|
8c6b0f84bb | ||
|
a4e929eedc | ||
|
c81f68aac3 | ||
|
03f4c7dd2c | ||
|
7cb045c688 | ||
|
73f3afa95f | ||
|
2fadf887e6 | ||
|
1027df054a | ||
|
2e3c105c7d | ||
|
ff2fc19b08 | ||
|
f4fefd0bb4 | ||
|
b26118006a | ||
|
ed1ab00faf | ||
|
6d6a41b894 | ||
|
b9b4001bf9 | ||
|
1bc342a692 | ||
|
368bde1d07 | ||
|
51ede1097d | ||
|
a5f2b5539f | ||
|
307e71455a | ||
|
b60f58ac34 | ||
|
6ef40779e7 | ||
|
18a5f6f5ea | ||
|
d3ef881f31 | ||
|
0eba9b3708 | ||
|
0ccba67006 | ||
|
c86813697a | ||
|
4f6b779bf4 | ||
|
d819df80f9 | ||
|
5120deaf74 | ||
|
d01aa5762f | ||
|
8930ecf7c5 | ||
|
aa06e5ab93 | ||
|
8309a1e06b | ||
|
7a44e6ec66 | ||
|
0bd69445f9 | ||
|
5a257a7a42 | ||
|
136cc23463 | ||
|
024003d6f0 | ||
|
abba8f1a7c | ||
|
16c5e4b34b | ||
|
132277bfdc | ||
|
f1332bb4af | ||
|
d659761195 | ||
|
8a57a94480 | ||
|
0409910e1f | ||
|
c392d358a7 | ||
|
a901a127eb | ||
|
2f90940c3f | ||
|
e66b466745 | ||
|
9068f3c95a | ||
|
d2e71dd1f2 | ||
|
58e552ceff | ||
|
8a19774edd | ||
|
66876f89cd | ||
|
d18cc72510 | ||
|
179b802c7b | ||
|
aba5897818 | ||
|
ee2d846e0d | ||
|
a6897ec39b | ||
|
8aabf09067 | ||
|
b5fb4611cd | ||
|
f41aeef8b0 | ||
|
7561426bd4 | ||
|
1bac8319c4 | ||
|
c6eb8a11d8 | ||
|
6aa012f062 | ||
|
887dd5b6d1 | ||
|
703a6872bc | ||
|
71eb9fe0d8 | ||
|
096dae9095 | ||
|
1eb8a7f8c2 | ||
|
8cbbf71f0c | ||
|
6923c1b209 | ||
|
de93fa0824 | ||
|
118f33a83e | ||
|
bc0d83bc92 | ||
|
bc36bb23df | ||
|
00967632d5 | ||
|
74171687f7 | ||
|
88d9145524 | ||
|
50971fd9d0 | ||
|
45c2e90a3f | ||
|
a6ccf82419 | ||
|
3c3ac7a36c | ||
|
41abeb3322 | ||
|
1e89e4c685 | ||
|
653c5edcf4 | ||
|
302d127f6f | ||
|
0eeda72922 | ||
|
cb1941c99a | ||
|
51adc75e96 | ||
|
8882bd5ca0 | ||
|
0928d7a6fe | ||
|
e502c61f2c | ||
|
38848ff636 | ||
|
59ce7064c7 | ||
|
8cee128e50 | ||
|
7ddc462135 | ||
|
cd76998995 | ||
|
48c0ae1711 | ||
|
85124d3417 | ||
|
8b1a83f085 | ||
|
3fb981f6be | ||
|
388a68e694 | ||
|
60e2109b4f | ||
|
ca7e289273 | ||
|
437ad0f8ec | ||
|
32ff785d85 | ||
|
2d607b6d68 | ||
|
9c21bcd18b | ||
|
dcdd5a1442 | ||
|
072095445e | ||
|
486da2f44b | ||
|
681acffee9 | ||
|
dfd835eba5 | ||
|
ecbff2e8f1 | ||
|
55f01c9488 | ||
|
49c219e6a2 | ||
|
cccb8c84af | ||
|
3dc5ec0331 | ||
|
12664d9427 | ||
|
365a0559b3 | ||
|
62052ee590 | ||
|
0aa97dee3f | ||
|
4c55da4de9 | ||
|
0f667692b1 | ||
|
6addd9c074 | ||
|
295d09df8b | ||
|
1cc7786a4c | ||
|
f301fbaf08 | ||
|
05cd0af3a5 | ||
|
97fc80dd03 | ||
|
d3ca82411a | ||
|
3e91def7f0 | ||
|
96a74ec654 | ||
|
4f3b9e7a60 | ||
|
df819beab5 | ||
|
7ecc62aaef | ||
|
ef570a987a | ||
|
09548bfd2c | ||
|
2e0c240573 | ||
|
dc59d826a3 | ||
|
35788efa07 | ||
|
ac6364bfdc | ||
|
6655fe7c28 | ||
|
bb31835dea | ||
|
bd67978c3a | ||
|
ede7b69b25 | ||
|
7b2ef405a3 | ||
|
8264328235 | ||
|
113c50b1fa | ||
|
340e2b9df2 | ||
|
3486a7d7fc | ||
|
e1d1004cd6 | ||
|
8940de5956 | ||
|
304af5055e | ||
|
7c07ae6099 | ||
|
1c39c85929 | ||
|
5b07b25d62 | ||
|
6bed09db57 | ||
|
ca69c36c1e | ||
|
f623126fe1 | ||
|
f392c90729 | ||
|
fd64327313 | ||
|
38cd5ab1cd | ||
|
5947926a09 | ||
|
ea7ffafd88 | ||
|
ba083deb1e | ||
|
f365c943b7 | ||
|
9417ec188d | ||
|
af56d964c1 | ||
|
7c7ad3d3c0 | ||
|
bb84a43a7b | ||
|
20d917a307 | ||
|
77eb33d5f2 | ||
|
75cf5f55f9 | ||
|
fb615aaef1 | ||
|
7f7d01fb8d | ||
|
87b6f274a0 | ||
|
0b5584a334 | ||
|
f82455dd84 | ||
|
8717ffe07c | ||
|
b4768a3d1d | ||
|
f1f95425b6 | ||
|
49430082f5 | ||
|
22fd09efea | ||
|
e8c8111178 | ||
|
08213d8ead | ||
|
c3225afda1 | ||
|
dfbeec069c | ||
|
a54b9f05a7 | ||
|
1f0dc33875 | ||
|
8d1f924248 | ||
|
5694acf482 | ||
|
8f88dc5ac8 | ||
|
b1b053c205 | ||
|
c9e9ef905e | ||
|
8a720a7d6a | ||
|
d2d121619f | ||
|
9a2c586720 | ||
|
579a83c2a4 | ||
|
b4927bfb1f | ||
|
9a95fd9886 | ||
|
99ebd62653 | ||
|
0894027cb5 | ||
|
582df637ce | ||
|
c16bd47b30 | ||
|
c6c4e79b96 | ||
|
76e92ae3a1 | ||
|
80cf45d234 | ||
|
736efdb370 | ||
|
8c0f97d6bb | ||
|
e0ca2c967c | ||
|
879b061bc8 | ||
|
1a2dd9e7ea | ||
|
6e9947b64f | ||
|
76378fd5d0 | ||
|
189f16fcc4 | ||
|
56e8dcf3d5 | ||
|
8762b578ff | ||
|
9e2c76abdc | ||
|
c820db4dc7 | ||
|
1ddf199e71 | ||
|
46d1ef68bd | ||
|
9bcabfeb1f | ||
|
8aeefc3fca | ||
|
197db8c82b | ||
|
f822cc610f | ||
|
ce14df0c77 | ||
|
605d1a5b1e | ||
|
ac57ed5b44 | ||
|
6528677dcc | ||
|
0765dc8a0d | ||
|
eff74fe862 | ||
|
05b74111d3 | ||
|
0bfc65c635 | ||
|
a784a34561 | ||
|
faf7da4c2c | ||
|
9700caefae | ||
|
4ae31f6f26 | ||
|
57abc4a1c5 | ||
|
7062d210a7 | ||
|
a9ce39dee0 | ||
|
98ab26671c | ||
|
fba3d706fc | ||
|
5f5d6f1d5d | ||
|
975d877800 | ||
|
afbb3b88d7 | ||
|
92ebb6ef05 | ||
|
a87eb50441 | ||
|
cec42bdcae | ||
|
651745b1d4 | ||
|
fc337d12a4 | ||
|
387dc6a188 | ||
|
528fec1a29 | ||
|
339a27579d | ||
|
66e3fa6db2 | ||
|
42b351127d | ||
|
2559fcf00a | ||
|
7c4688f557 | ||
|
65df386d66 | ||
|
7b3646a012 | ||
|
5632420827 | ||
|
d6e71c8f4f | ||
|
d2e736b10a | ||
|
a69a015189 | ||
|
ac3e2f48d1 | ||
|
6d8975f9fc | ||
|
175d49293c | ||
|
7fe7cd746f | ||
|
5a2d940631 | ||
|
0689c664d7 | ||
|
779a4d9e59 | ||
|
97df408d51 | ||
|
361a6cc9e0 | ||
|
f96cb9a3b6 | ||
|
604ecbd31e | ||
|
feba821306 | ||
|
4fc58e6afd | ||
|
38008a8e03 | ||
|
ba58cb045f | ||
|
8e7eb94e50 | ||
|
ab854ec035 | ||
|
07c3d49cfa | ||
|
24e56d0476 | ||
|
1dc1f1b9c4 | ||
|
304e992942 | ||
|
4fcfc913d3 | ||
|
c6eb62ccbc | ||
|
6bd2f1feec | ||
|
aa9ec3f872 | ||
|
f7f86fb040 | ||
|
5ad72374cd | ||
|
b7cb555cee | ||
|
66cc8dcdaf | ||
|
c0011891e6 | ||
|
ac7de68ac7 | ||
|
df4e4949c8 | ||
|
7794f27dc2 | ||
|
1a56577f7a | ||
|
be3ae83c44 | ||
|
398983fc49 | ||
|
e9f501c250 | ||
|
123246cc84 | ||
|
2d049b7ff3 | ||
|
2863455185 | ||
|
ff488dd81f | ||
|
da80667fb0 | ||
|
9551c70c59 | ||
|
fa3d28872e | ||
|
d23d9b1ba8 | ||
|
55c9143b2b | ||
|
115916d753 | ||
|
1c3e8de57a | ||
|
b7773ba11f | ||
|
6a553122b1 | ||
|
7a7d0442aa | ||
|
3568fb8747 | ||
|
b973d24081 | ||
|
074af44ead | ||
|
828e74e6c3 | ||
|
3a73e12550 | ||
|
c27bfcd7fe | ||
|
38b8dc338d | ||
|
7bb1849968 | ||
|
ed672847f3 | ||
|
56210f3e96 | ||
|
5519dd0a14 | ||
|
7589c6c578 | ||
|
a7c3e34fbe | ||
|
f5e734f636 | ||
|
a30172f8a6 | ||
|
9b3839de70 | ||
|
faa9f6ea9f | ||
|
3e660011b2 | ||
|
e19f80cd3f | ||
|
6473118b24 | ||
|
615ecdf7f3 | ||
|
79d9fc530d | ||
|
e3ae451c09 | ||
|
4c8ef63383 | ||
|
e95099817b | ||
|
732a05dde0 | ||
|
a9557fe53d | ||
|
ea43a61094 | ||
|
e24b9548d4 | ||
|
b9997eb628 | ||
|
a53e7905db | ||
|
861011fa24 | ||
|
575d215c77 | ||
|
294066ca61 | ||
|
2099a88ddf | ||
|
1662b47f7e | ||
|
f3c58b7cd6 | ||
|
ce59a62f72 | ||
|
8658f722dd | ||
|
446a1a5108 | ||
|
2628ce8664 | ||
|
9054643fe8 | ||
|
09e49439bc | ||
|
af0afabfa0 | ||
|
ffa4e05708 | ||
|
ccf8026761 | ||
|
253dec94d1 | ||
|
53f9144fc3 | ||
|
d91144a10d | ||
|
aaa2934595 | ||
|
21c4886f90 | ||
|
5ad1efd698 | ||
|
0bb5d86c20 | ||
|
94599e9b4e | ||
|
fdebeab612 | ||
|
e6a2bc545c | ||
|
5a3f4be04e | ||
|
79a6dc9501 | ||
|
19dd940b22 | ||
|
7522403da8 | ||
|
aa2caacf4c | ||
|
ae4368a3ca | ||
|
4c7375555a | ||
|
28a0b0626b | ||
|
da2abb9c3b | ||
|
62a7fe0be5 | ||
|
c3a52b366e | ||
|
d4691bb799 | ||
|
494444a433 | ||
|
f981aa34dc | ||
|
c6024b93ce | ||
|
8d89104241 | ||
|
be06e2448b | ||
|
f2272ab4cb | ||
|
2c73268668 | ||
|
f8dd3c0efd | ||
|
141f5effa3 | ||
|
721cc0ec5e | ||
|
cb87fa12e1 | ||
|
c11d8f033e | ||
|
23080b7455 | ||
|
1d5fb4b9d1 | ||
|
1234528521 | ||
|
9fb72a896d | ||
|
9d68a5f4cc | ||
|
2a90fc0fe8 | ||
|
2928c622f9 | ||
|
696d842b07 | ||
|
b00ca9bb7a | ||
|
6b5d26c9ce | ||
|
f3ebe71dd1 | ||
|
07f87990ef | ||
|
86d34e9bc5 | ||
|
664c25bdac | ||
|
78619d3710 | ||
|
cba4c74f94 | ||
|
3c74e72242 | ||
|
0462ca02c8 | ||
|
209ff4d527 | ||
|
fa7391e814 | ||
|
fafa1f11f0 | ||
|
06290483da | ||
|
0e8d876c5d | ||
|
e502e12e07 | ||
|
60ebc444ab | ||
|
307dab47c8 | ||
|
a64dbe0268 | ||
|
89dda4879b | ||
|
240c81e626 | ||
|
33768740fa | ||
|
f1a2a00d38 | ||
|
e634e512c8 | ||
|
98fb03dd30 | ||
|
af0042b71d | ||
|
9df5bd708e | ||
|
5b54a24b4e | ||
|
4662109980 | ||
|
b85b37192e | ||
|
0af2c0e4c1 | ||
|
48d7a04c73 | ||
|
866339eff6 | ||
|
b0e5e8d331 | ||
|
17a31b75d7 | ||
|
f796df783c | ||
|
ac37f8053b | ||
|
01d703cdbb | ||
|
20959d1444 | ||
|
62a5c54a18 | ||
|
892f0519ad | ||
|
6a18f8007d | ||
|
8bb8aaa0db | ||
|
cc9f679a85 | ||
|
7cdc72f936 | ||
|
5c8c925e8a | ||
|
8ec6136a7c | ||
|
5b0191f691 | ||
|
0df3715894 | ||
|
6190582f16 | ||
|
4cea082303 | ||
|
578a2f9852 | ||
|
47f66a3d13 | ||
|
02ac6fa2d7 | ||
|
2971bb65fd | ||
|
91f02b145b | ||
|
42a09f8593 | ||
|
87b1833f73 | ||
|
664c85106f | ||
|
a445e806ea | ||
|
1ad01f4989 | ||
|
6d9fe60608 | ||
|
4abeac1231 | ||
|
72d3f21816 | ||
|
d08e1357dd | ||
|
eb0222455a | ||
|
b6910667a8 | ||
|
e87976bc09 | ||
|
ffe8b7761e | ||
|
2c5cc4289e | ||
|
75853dae60 | ||
|
23b0450938 | ||
|
600a15a57b | ||
|
60cdbeb219 | ||
|
cf2f753660 | ||
|
e6a2434887 | ||
|
c6628f22ee | ||
|
d3e5957215 | ||
|
eb9405bd97 | ||
|
49184c86a3 | ||
|
4333255571 | ||
|
1032fbdbd0 | ||
|
dc6f171f20 | ||
|
c07b269c94 | ||
|
02c1b20ed7 | ||
|
68f99bc2d5 | ||
|
df507a675b | ||
|
d9c7e72d4b | ||
|
234b537ad9 | ||
|
483ef98af3 | ||
|
f31e0e405f | ||
|
7db6e9355d | ||
|
b78c239395 | ||
|
b7be35618d | ||
|
42fb860077 | ||
|
e2e57d8347 | ||
|
85f03c4a06 | ||
|
915da57d32 | ||
|
b3e5e10473 | ||
|
2eeeb2997d | ||
|
9997c31703 | ||
|
cae7281def | ||
|
9bee1f7edf | ||
|
b65a0600ee | ||
|
6f301b5cea | ||
|
bf5fdc2b5c | ||
|
e52fc14114 | ||
|
429a4596c1 | ||
|
9980b7ac62 | ||
|
fd0f6cc429 | ||
|
c29eabec50 | ||
|
138b9e1510 | ||
|
f22dc769f4 | ||
|
f976861e21 | ||
|
2d910838a2 | ||
|
f811bab608 | ||
|
9a4731dd14 | ||
|
16f65663dc | ||
|
ac2bcb2d19 | ||
|
eaa330d745 | ||
|
b63e63cfcd | ||
|
5b3a5a0153 | ||
|
57a5004f4e | ||
|
190304f601 | ||
|
0005d1a6b5 | ||
|
224239f5a1 | ||
|
5b8bbddbc1 | ||
|
c5d4eb49d4 | ||
|
e4b635f5be | ||
|
f95f2032fc | ||
|
78b1154b8d | ||
|
1f3ba35140 | ||
|
1f3c7cf272 | ||
|
9a1dc5d179 | ||
|
f22185d646 | ||
|
517a08e134 | ||
|
a9b183612b | ||
|
ed4faf7c11 | ||
|
a9015d1d84 | ||
|
83a72a6e3a | ||
|
5f0b92f7c3 | ||
|
c270243b56 | ||
|
a6e587f0f0 | ||
|
a50b1e17d8 | ||
|
9a83db66f5 | ||
|
2fa53badd9 | ||
|
db14b0eae8 | ||
|
f4f4d966f3 | ||
|
7423ac6824 | ||
|
20201290e3 | ||
|
4563f56e77 | ||
|
c46e666907 | ||
|
10eb6b370a | ||
|
8f90f30b07 | ||
|
222b1c651b | ||
|
e0d80639b3 | ||
|
0baa7d47b6 | ||
|
c80d6e5284 | ||
|
ad63658f9e | ||
|
ffb9bc92d6 | ||
|
672c519378 | ||
|
cfd8526961 | ||
|
00de99b839 | ||
|
fb1189fd31 | ||
|
7dff2749ec | ||
|
4d3e31cf6c | ||
|
5987f389c6 | ||
|
6d7daf787d | ||
|
73e84e9963 | ||
|
8c0534a055 | ||
|
5c17b1c767 | ||
|
79bb453bb6 | ||
|
6b1650ae4f | ||
|
378d89af2f | ||
|
8c16331b69 | ||
|
fc4455d837 | ||
|
5f83f77b2e | ||
|
6d6a1c1ab0 | ||
|
aa5c340029 | ||
|
a35af02494 | ||
|
decde43371 | ||
|
2d583aa83a | ||
|
57037740fd | ||
|
8efa1ba067 | ||
|
2162059352 | ||
|
6b3b351c9a | ||
|
c6a3290c4f | ||
|
df5d935194 | ||
|
075ed7b7b4 | ||
|
109b3481a7 | ||
|
83bc3f518b | ||
|
717735311b | ||
|
e3489be0c0 | ||
|
9223989a01 | ||
|
4ed80b88de | ||
|
662fa61fc7 | ||
|
dcc2d91b14 | ||
|
86e33d0cb1 | ||
|
5d6f829624 | ||
|
1ed354890b | ||
|
939aad5cb9 | ||
|
8be119aa6a | ||
|
aedde87f42 | ||
|
63a0910f5b | ||
|
81f9a23d16 | ||
|
7842d0160b | ||
|
87d740b92a | ||
|
d9a9b7a74e | ||
|
27d6a0cc08 | ||
|
b82588f081 | ||
|
71c6ac8c2e | ||
|
2de1f9a33b | ||
|
f13461caee | ||
|
84c320d539 | ||
|
864e0b88eb | ||
|
6555ecf6b8 | ||
|
f3df286985 | ||
|
b8dd9d19dd | ||
|
fab9dbf294 | ||
|
c0b9b91a06 | ||
|
f7c4ed050f | ||
|
c775cfca73 | ||
|
b145b4c651 | ||
|
a68df8de7f | ||
|
de71cf469c | ||
|
cc12f0a0a4 | ||
|
3132e20fad | ||
|
dbc9c7e0da | ||
|
883c852897 | ||
|
989034bd41 | ||
|
139a2a082c | ||
|
f38c726faf | ||
|
b8cc1ac79d | ||
|
e98ab37806 | ||
|
846238fe99 | ||
|
14513e6f70 | ||
|
4b2ba10300 | ||
|
f46fc6c4e8 | ||
|
8633337bbd | ||
|
f68a53e46a | ||
|
30a97db735 | ||
|
28448c0fe1 | ||
|
391991bfce | ||
|
7059f5b3b9 | ||
|
3792e7dc20 | ||
|
934e0208bf | ||
|
26d0f3f2de | ||
|
4a58365b2c | ||
|
41dfdc7f59 | ||
|
f710188c86 | ||
|
ad23638913 | ||
|
b364506cbc | ||
|
b77c8e253b | ||
|
ffa12bfe54 | ||
|
e305009e9a | ||
|
af7a6e3c87 | ||
|
6620aa97a8 | ||
|
8b6d85eb78 | ||
|
dc73473394 | ||
|
7bf47f90d9 | ||
|
c24fbda302 | ||
|
702f784e44 | ||
|
679714c8be | ||
|
ff0ca9ba67 | ||
|
ee0bcc39f1 | ||
|
ebdd015aae | ||
|
3c1022af99 | ||
|
add4867d21 | ||
|
d69fddf8b4 | ||
|
218fb9c794 | ||
|
c531ad756d | ||
|
c5f6e26802 | ||
|
fbcbbd8421 | ||
|
00f9b62ffb | ||
|
59d8d2807f | ||
|
d9f792b712 | ||
|
42d80a666a | ||
|
abf7f1a41b | ||
|
fdb180e062 | ||
|
39cc240a4e | ||
|
79189c86ab | ||
|
9fd0f1c231 | ||
|
8172519389 | ||
|
cc11191e57 | ||
|
81e091e005 | ||
|
08d684a90f | ||
|
54223e9a99 | ||
|
871e14178b | ||
|
1c1b949648 | ||
|
b88841c6ef | ||
|
0bfc04bb14 | ||
|
10c0204b16 | ||
|
a35bc43cab | ||
|
044e6b22b2 | ||
|
0b2c33bcd2 | ||
|
081b683e03 | ||
|
2166c32047 | ||
|
1d57677426 | ||
|
9abe6cd8f6 | ||
|
9d4c02f7ca | ||
|
92c2c84617 | ||
|
d4bfebec22 | ||
|
db9421d0be | ||
|
a59b72f96a | ||
|
8831166705 | ||
|
bebe9f8e2e | ||
|
69d41b65d4 | ||
|
4d3c49f93b | ||
|
f44ec00133 | ||
|
b4b86113e4 | ||
|
52c73126e1 | ||
|
4d97a24dd8 | ||
|
b6febae2fa | ||
|
8f6b8588c1 | ||
|
ba11085ddc | ||
|
71ab8d560e | ||
|
a580c8c5e5 | ||
|
0eeb5942a1 | ||
|
6434c4db77 | ||
|
4f4e322ad4 | ||
|
553963295f | ||
|
d69ddc7234 | ||
|
c156c220c4 | ||
|
a182ca62c8 | ||
|
d397619939 | ||
|
5413c59bc7 | ||
|
4fbf4ee03d | ||
|
32e1908859 | ||
|
dd6ef4811c | ||
|
3d5a0c5a29 | ||
|
dbe79790dc | ||
|
fddebce313 | ||
|
e09f434ed8 | ||
|
54c978addb | ||
|
2204a83ec0 | ||
|
aa629a76e7 | ||
|
f83e7f0071 | ||
|
463de74865 | ||
|
c2a21bcaee | ||
|
24480a3782 | ||
|
0ccb99137a | ||
|
a25090de4b | ||
|
8b06e5bdcd | ||
|
a134a75572 | ||
|
446029e7cf | ||
|
48d6a3354a | ||
|
afc3cac54d | ||
|
acf910b64b | ||
|
aaafe0f3f2 | ||
|
c03bb3693e | ||
|
910c921d5d | ||
|
014120e73e | ||
|
73cf46ff45 | ||
|
f49c9c87d4 | ||
|
9542fce9c5 | ||
|
5f6756cb4d | ||
|
e60a2e9fcc | ||
|
a565e4a7b1 | ||
|
265e15116b | ||
|
85b7c26bb0 | ||
|
9bbeb1f578 | ||
|
47cd091879 | ||
|
6ac5211062 | ||
|
25b1fa6fe0 | ||
|
dcae6a8a20 | ||
|
1ebd9044ca | ||
|
181cbae74c | ||
|
205a0eb2da | ||
|
22c3d62dec | ||
|
a82f521633 | ||
|
bc9710e8f2 | ||
|
902cecb0c3 | ||
|
950f3f97c1 | ||
|
828d9971a4 | ||
|
50fea6be75 | ||
|
a1c5c20d7e | ||
|
ae86152282 | ||
|
9eb0eaf6a6 | ||
|
5f278eee7b | ||
|
362a7e61f9 | ||
|
379d9121b4 | ||
|
09ed8eb2b1 | ||
|
45b63c4394 | ||
|
c4497ff17d | ||
|
62413f6277 | ||
|
530d0bf570 | ||
|
80b01d3505 | ||
|
2b9e9c79b9 | ||
|
3fc438ffd1 | ||
|
3b16c6be92 | ||
|
78f577686a | ||
|
af6c6850ec | ||
|
38db4d3ae0 | ||
|
c071f53f2c | ||
|
5a7752a22e | ||
|
ddb1af89e9 | ||
|
7452317c10 | ||
|
120e5b94f9 | ||
|
4ec11496e6 | ||
|
c556bf9f68 | ||
|
fb28b2d416 | ||
|
e99a1c8b09 | ||
|
0b80c4367d | ||
|
e95d5ed43c | ||
|
553663c952 | ||
|
780ce669d0 | ||
|
47b5ff9a93 | ||
|
2bc6ced671 | ||
|
f4738600b4 | ||
|
83c0789246 | ||
|
0424aa7c19 | ||
|
3e6d806ce2 | ||
|
77762b9c2c | ||
|
34de3964e6 | ||
|
5241fdf673 | ||
|
51adb7385c | ||
|
21edabf07f | ||
|
7d6705345d | ||
|
2dc1982e11 | ||
|
041113dbc4 | ||
|
c93995a827 | ||
|
35eeb6036d | ||
|
9e5810e615 | ||
|
a51904b13f | ||
|
c4ec65bd5a | ||
|
604f227751 | ||
|
61063a54ef | ||
|
162171618c | ||
|
14f06ca1bb | ||
|
c47896232c | ||
|
91c4b5d708 | ||
|
e441908230 | ||
|
1b350b627b | ||
|
dd38ee103b | ||
|
53829a1270 | ||
|
14b072dd47 | ||
|
30ee4df0fa | ||
|
4ceb767022 | ||
|
b0543a111d | ||
|
7a3ee17093 | ||
|
e0426f10b2 | ||
|
6319331a33 | ||
|
c87d46ad5b | ||
|
7d084ee0bf | ||
|
cfc92ca3db | ||
|
1488b9747f | ||
|
2446ff49f2 | ||
|
98d4031b5c | ||
|
7e1911b13b | ||
|
1f304d55c4 | ||
|
9f93ff5168 | ||
|
839bb086b1 | ||
|
a5b5c7e9cd | ||
|
f8ec7f94a4 | ||
|
f8baef15ca | ||
|
187b187ef2 | ||
|
ac50f3ff34 | ||
|
e4a7e67783 | ||
|
1a5e1928ec | ||
|
d75b14d4af | ||
|
0bed55701f | ||
|
356a981164 | ||
|
8a241ed0fd | ||
|
cb0b9da51f | ||
|
8ebb7be36d | ||
|
a05d0df50e | ||
|
15ad1d2247 | ||
|
768fa2c3bc | ||
|
0db5963641 | ||
|
cdc7d550eb | ||
|
f973f5beb7 | ||
|
6619176a76 | ||
|
faeaf9259e | ||
|
34d91789c4 | ||
|
cdfd789f56 | ||
|
5ca0e5617d | ||
|
c197b58734 | ||
|
8072f90536 | ||
|
252f1919c2 | ||
|
2e64e9fd52 | ||
|
c3e0753455 | ||
|
03e426fc28 | ||
|
7f9d677f89 | ||
|
314f2ec568 | ||
|
f09f4a4c6c | ||
|
6703841c35 | ||
|
dd9975cd67 | ||
|
97369c5d6c | ||
|
328c3d7b8b | ||
|
16874378f1 | ||
|
a0cfa59e56 | ||
|
b4399f42da | ||
|
dfbc74dc5f | ||
|
539823f565 | ||
|
4a3fcdb937 | ||
|
0bc20edb5b | ||
|
bab760897b | ||
|
7f71cfaee7 | ||
|
2ffd4cb9fa | ||
|
de2796508f | ||
|
aa8170ecfd | ||
|
4fc2b4ed64 | ||
|
604200e905 | ||
|
a543db5dc6 | ||
|
9552049524 | ||
|
0c85f03f05 | ||
|
b883486308 | ||
|
e7e9994b73 | ||
|
47d6f849f2 | ||
|
59b7379db4 | ||
|
e042550ba4 | ||
|
15528c9583 | ||
|
f3dfc6e4c6 | ||
|
1df58d6231 | ||
|
c068eed19d | ||
|
ab4294f3ca | ||
|
f4a3d07b0e | ||
|
4b11a54345 | ||
|
78940b46a4 | ||
|
45bf43d76e | ||
|
6ba614d425 | ||
|
5e622aa69f | ||
|
a50f104fd3 | ||
|
8443a836aa | ||
|
f5e23903a2 | ||
|
291a33ce65 | ||
|
7c96c30be8 | ||
|
3594c11238 | ||
|
1977bf4d29 | ||
|
1146bcad2c | ||
|
1199863e47 | ||
|
590e6b1258 | ||
|
2bba5ce69a | ||
|
015e4f2f33 | ||
|
8951f80748 | ||
|
4ffd847b7a | ||
|
0dd638d0fd | ||
|
1a97b2cbe1 | ||
|
9b662bb0ca | ||
|
3775ac40ad | ||
|
666aaf013a | ||
|
63aff82dc8 | ||
|
21ae30b985 | ||
|
d5086f6a54 | ||
|
005b50de92 | ||
|
6e60b596d7 | ||
|
929d6255fc | ||
|
b451fbd1c8 | ||
|
419bdecc20 | ||
|
5f824d64da | ||
|
79479e40c6 | ||
|
cfcd6e9ac9 | ||
|
1bd022305f | ||
|
d0ab27092c | ||
|
850ae540a9 | ||
|
b2aa84ddbd | ||
|
9cf4564057 | ||
|
d8fc093fd8 | ||
|
3953db97cd | ||
|
d1c0b8fea6 | ||
|
7ced590cbc | ||
|
82cbc94f27 | ||
|
5d2b738ec1 | ||
|
59a1b018ed | ||
|
3615e717ca | ||
|
e08e140c3c | ||
|
aa963603ed | ||
|
3894e53cf6 | ||
|
94a4be95fe | ||
|
2db8156326 | ||
|
6bb9052261 | ||
|
c440929700 | ||
|
c2ee729380 | ||
|
4e343f65bd | ||
|
15b160e51a | ||
|
2a5fae43b8 | ||
|
59cb65f47a | ||
|
93d37a6366 | ||
|
6e183f3e64 | ||
|
3776650a38 | ||
|
7e9e2b7b58 | ||
|
6e525ea8fe | ||
|
8d4a1ca359 | ||
|
ea23bdb579 | ||
|
cff3ab867a | ||
|
8071b895d2 | ||
|
8b9c107a03 | ||
|
ee6285c79d | ||
|
54ab06493a | ||
|
97aac34dc9 | ||
|
2e1a7b56d8 | ||
|
41d7554efd | ||
|
d7911d8f3f | ||
|
7ba6f72825 | ||
|
9a9dd7a4ad | ||
|
2cc771371a | ||
|
0a4cd13622 | ||
|
91dfec4ef7 | ||
|
0237153ddd | ||
|
71f011c70d | ||
|
581f734099 | ||
|
8ea62d22cb | ||
|
f8b2d26a00 | ||
|
3b3e78d65b | ||
|
a8efe40293 | ||
|
35e661fdf9 | ||
|
e1206eb310 | ||
|
199b41af0a | ||
|
e7c7313f77 | ||
|
ae2699ca98 | ||
|
2bae36e8eb | ||
|
12c08ddcdb | ||
|
f1f2d9f98a | ||
|
47d2da259b | ||
|
e7452e00ce | ||
|
83873aa7f7 | ||
|
9a1b7b0a63 | ||
|
a350be335b | ||
|
a676d9ea52 | ||
|
598936be46 | ||
|
d0623e5ef7 | ||
|
bc5924a780 | ||
|
c1dca680f2 | ||
|
d4b0444d7a | ||
|
d9efe61030 | ||
|
a93886fb65 | ||
|
87774ae21f | ||
|
19e06100b2 | ||
|
e8acb93b99 | ||
|
4d0d865700 | ||
|
8bd81ee883 | ||
|
8b0a8737b8 | ||
|
c111f59825 | ||
|
f2ba295668 | ||
|
01dbd4093b | ||
|
152c984176 | ||
|
de85f2735e | ||
|
39cf32879d | ||
|
47413928c8 | ||
|
1463103cd7 | ||
|
f30c7a63b1 | ||
|
e46785a434 | ||
|
a873066466 | ||
|
f60b00ee71 | ||
|
a876962405 | ||
|
c2ca5d857d | ||
|
27825963f6 | ||
|
ca7b0ceadd | ||
|
32b546df69 | ||
|
cea2f598b2 | ||
|
d44eb7bf8d | ||
|
e1445316aa | ||
|
238e3707c8 | ||
|
16e5f54507 | ||
|
65c29cafa0 | ||
|
c4b233d094 | ||
|
cd189320e5 | ||
|
17114347d1 | ||
|
1866afd80b | ||
|
fcdeea683b | ||
|
92255bcdc3 | ||
|
b2442a2268 | ||
|
1b3b07d4d8 | ||
|
95f3b0d354 | ||
|
9b5c6bfff0 | ||
|
57b172072a | ||
|
3b2618f63b | ||
|
4f525b9150 | ||
|
325a746d90 | ||
|
6978e2dc4c | ||
|
520493fab1 | ||
|
09303625fb | ||
|
02b6d0a288 | ||
|
4d454b474c | ||
|
204004b90e | ||
|
ccf919c58c | ||
|
567fbcd517 | ||
|
7f25e28d01 | ||
|
9e0f946696 | ||
|
bd08cc5126 | ||
|
bf23890a34 | ||
|
9eedca0a98 | ||
|
68aec7eec0 | ||
|
76811b7b84 | ||
|
38d43e8fc9 | ||
|
9cd90838e1 | ||
|
e7d7de870a | ||
|
bcbf454255 | ||
|
4dd53b333f | ||
|
b1b47a6d4c | ||
|
518944c41e | ||
|
481e1528d6 | ||
|
33c0a676fd | ||
|
6bbc4c8dbd | ||
|
19f1c1a9ec | ||
|
5d9428f014 | ||
|
63774d75f3 | ||
|
f185eaa232 | ||
|
d49064b43e | ||
|
e6b8188480 | ||
|
ab81658471 | ||
|
8883624b2e | ||
|
62f6b25b63 | ||
|
e6c3d42eb8 | ||
|
3a43a41141 | ||
|
f886e69dfb | ||
|
46123d359f | ||
|
8f2aeed9da | ||
|
8890b2fd27 | ||
|
5ee794f9f4 | ||
|
2ab4a8a44a | ||
|
5ba0e3ec2a | ||
|
0fed80968b | ||
|
41f6932b68 | ||
|
1ae40316a8 | ||
|
3dace577fe | ||
|
1395b42692 | ||
|
c0a132e039 | ||
|
9b6110edc6 | ||
|
2b64ee21b3 | ||
|
a290f7d299 | ||
|
a8e6cfe5cf | ||
|
9d53d48552 | ||
|
3f6ad29f55 | ||
|
ab16be08f5 | ||
|
3ba84fb283 | ||
|
4f3d335ab4 | ||
|
4f776ee56b | ||
|
40313929eb | ||
|
c76509fe41 | ||
|
889ad7c3eb | ||
|
d59f4cf199 | ||
|
dc9c2897fd | ||
|
b17c624c81 | ||
|
9dee60934f | ||
|
bc856740f2 | ||
|
c497d478ce | ||
|
17683249fd | ||
|
2c146f564e | ||
|
fc1732e758 | ||
|
486fa99602 | ||
|
570c9cfc6b | ||
|
02bed88835 | ||
|
62eac5d91c | ||
|
b47aa6871d | ||
|
eeb4ecd109 | ||
|
c22bb12c1e | ||
|
b096f94ca4 | ||
|
a63042d961 | ||
|
8b42767b19 | ||
|
20a173d8a3 | ||
|
08315a4329 | ||
|
a7d94a4859 | ||
|
72b514cdde | ||
|
4231c5a6ae | ||
|
bbffcbf739 | ||
|
aa4e60ae27 | ||
|
6a24935777 | ||
|
c03271c856 | ||
|
8c591bf065 | ||
|
88b69ea8a1 | ||
|
1fb91dc02e | ||
|
69c46aff80 | ||
|
d3bc58d80b | ||
|
c72d130fde | ||
|
58b6f9f353 | ||
|
e9eaae4dd1 | ||
|
29eb4e4647 | ||
|
6b5387f428 | ||
|
a0852adf18 | ||
|
c1ed795196 | ||
|
6da2078067 | ||
|
9a0a52b7b2 | ||
|
8d2770f2f2 | ||
|
37e22dc22f | ||
|
fb4d05fd60 | ||
|
3369f6d115 | ||
|
4b652198f0 | ||
|
2d07189e38 | ||
|
b97093a778 | ||
|
287cc1a0e8 | ||
|
7317f1d233 | ||
|
037af0aec2 | ||
|
0cf5a2e12f | ||
|
9af7931a79 | ||
|
5fbc5c074d | ||
|
023c1e3baf | ||
|
3a232f1576 | ||
|
adde73123f | ||
|
178608c5f8 | ||
|
6babcafbec | ||
|
ec3ff1deb9 | ||
|
67bfe6bb36 | ||
|
17e0ab99e6 | ||
|
674600bab2 | ||
|
9885c926e9 | ||
|
52543481dd | ||
|
d2ed9e70cd | ||
|
210cba53b9 | ||
|
abaee9f4a3 | ||
|
fc19f53ea9 | ||
|
81d56dfdc0 | ||
|
6941e406f4 | ||
|
b439753ac5 | ||
|
c11f721ad4 | ||
|
b61ed9fa3e | ||
|
95bc1703a6 | ||
|
0d59209e4c | ||
|
7dd1ea3719 | ||
|
9d59de41a2 | ||
|
6916eb8613 | ||
|
94552e5503 | ||
|
936d4f4f6d | ||
|
526a70a6d7 | ||
|
58a64597e8 | ||
|
209f46a235 | ||
|
2659e63483 | ||
|
d9b20d7896 | ||
|
566596f7b4 | ||
|
c9ea68d1d3 | ||
|
10d5c8e9ad | ||
|
d60c94cbb1 | ||
|
9e9e3a9abd | ||
|
b2dd2661d0 | ||
|
d1122b982c | ||
|
9c08b11a75 | ||
|
4733155583 | ||
|
2a18a264d4 | ||
|
f787db1be5 | ||
|
d113b1b646 | ||
|
8be13a4ecc | ||
|
12775d0627 | ||
|
5ec6cc0d5e | ||
|
edeb44b0b8 | ||
|
bf30d1d3ce | ||
|
1fc2e8cc6f | ||
|
4be6ca834a | ||
|
7274beebed | ||
|
b7c205baf0 | ||
|
c41219ae79 | ||
|
96a8fc5700 | ||
|
caf0dbb341 | ||
|
82784a6169 | ||
|
b6103a1916 | ||
|
1cff91ced5 | ||
|
1bb54f839e | ||
|
63cf35b904 | ||
|
bc3808cb3f | ||
|
b5aef1856d | ||
|
f134ff9fdf | ||
|
c9316542be | ||
|
8ba288cfb1 | ||
|
9544364116 | ||
|
79f15d5621 | ||
|
45ea164270 | ||
|
82371fea3b | ||
|
69fc7eeabe | ||
|
c219878ac2 | ||
|
5aef27a3ab | ||
|
26d1449ac3 | ||
|
6bf21c5687 | ||
|
5ddd37eb77 | ||
|
30b0585447 | ||
|
fc48579776 | ||
|
69371d6d6d | ||
|
c068c0d0f4 | ||
|
102f88674b | ||
|
3b6726e0c7 | ||
|
f43570c964 | ||
|
b5fe5d29c9 | ||
|
3ac76914bd | ||
|
c3c5149fa0 | ||
|
e7b7506efa | ||
|
0bfcaa85b6 | ||
|
4ab559ceef | ||
|
5689be448c | ||
|
7aa895089a | ||
|
bbc83291ef | ||
|
5ef5f4b41f | ||
|
600e5dce97 | ||
|
47dc226393 | ||
|
eabafd4eed | ||
|
f5164a9c02 | ||
|
fc560a79d9 | ||
|
c255191a2a | ||
|
f1b2c802e6 | ||
|
8f6f49c9f3 | ||
|
a397dfffb7 | ||
|
dc9237c1d8 | ||
|
7248c5e731 | ||
|
4970aaf02d | ||
|
6da929dc95 | ||
|
2b1b400e37 | ||
|
6040dbfbb9 | ||
|
2b93228076 | ||
|
0de8ee48d0 | ||
|
f1e07caca4 | ||
|
0365676262 | ||
|
c084965cf1 | ||
|
b4365e3fb9 | ||
|
0e0d7ec9d5 | ||
|
4c1dac3cd5 | ||
|
ab46adc91c | ||
|
919af60ca9 | ||
|
437ce48f42 | ||
|
16d19097c5 | ||
|
fea209fa7f | ||
|
580eb24546 | ||
|
8d719e1191 | ||
|
d2595b8b92 | ||
|
fecf24ebfd | ||
|
d65cedf8c7 | ||
|
88042ce5a9 | ||
|
dff6dc53f4 | ||
|
87c0be470b | ||
|
3241e91e84 | ||
|
499b5a1ac8 | ||
|
f2b1d26da3 | ||
|
fae6c52082 | ||
|
a6f10efd03 | ||
|
5d85c0a965 | ||
|
60b1ec222e | ||
|
c5ba642630 | ||
|
b4d006438c | ||
|
ef1e1edea5 | ||
|
868be37007 | ||
|
57a1004c15 | ||
|
9d0ea883ff | ||
|
1c32e7284b | ||
|
1d17835e9a | ||
|
c97312ba41 | ||
|
e440663ea3 | ||
|
a77b946ce2 | ||
|
aa37e7f4e8 | ||
|
795131cd9f | ||
|
d4cdec6f11 | ||
|
6fbf08869c | ||
|
279a053dbe | ||
|
cfaf862249 | ||
|
dae467032b | ||
|
6ae11ed755 | ||
|
fec17e2bf5 | ||
|
42fa547cb4 | ||
|
0b7bc23a30 | ||
|
cf93ad50fa | ||
|
46c9535087 | ||
|
57d621ac14 | ||
|
59219d3825 | ||
|
8a6f6d7e36 | ||
|
477b61c5aa | ||
|
2930654c7d | ||
|
1f98a77ba0 | ||
|
9f513a755b | ||
|
8c46046fdb | ||
|
178516ac17 | ||
|
6b6a7bdc2b | ||
|
4346a59035 | ||
|
da90ed748b | ||
|
2fccafb3ca | ||
|
a2b564eaaa | ||
|
0347571ee9 | ||
|
da63bcb24b | ||
|
1fe80667a2 | ||
|
ee2ae84d7a | ||
|
7b96b4df22 | ||
|
07534edfcd | ||
|
e84653571c | ||
|
19c8b007b2 | ||
|
ee99ee93e4 | ||
|
8cef1af95d | ||
|
2c4e99fe8d | ||
|
1a633ec925 | ||
|
d7a74ebb94 | ||
|
3a5cb29e67 | ||
|
5aba776da5 | ||
|
1c9febfd22 | ||
|
b4359d0f53 | ||
|
a078064497 | ||
|
14f2a95205 | ||
|
dbe95c849b | ||
|
752f95e913 | ||
|
ce92ef745c | ||
|
0ec65bef5b | ||
|
7d69a78d06 | ||
|
5eaeaa8dc1 | ||
|
b2bb919c83 | ||
|
1262c197c4 | ||
|
face80aa3f | ||
|
4cbb9b0e64 | ||
|
7a46222758 | ||
|
8111eee1b2 | ||
|
9413eba2f6 | ||
|
17553c844a | ||
|
092535d653 | ||
|
82d7d23b86 | ||
|
62e4eb29eb | ||
|
a98df451cf | ||
|
9c84c17d5e | ||
|
939a724b1a | ||
|
ffb179c991 | ||
|
d53ce41a20 | ||
|
c0201a52a5 | ||
|
baef33c12d | ||
|
7d49398186 | ||
|
1dba9eaeb9 | ||
|
718e5efaf3 | ||
|
84404ec311 | ||
|
6d6d492c51 | ||
|
d0501a8314 | ||
|
ff39293537 | ||
|
e03b2f7183 | ||
|
b1ac1453e1 | ||
|
e71b20359c | ||
|
42fb23d6c3 | ||
|
9682abb095 | ||
|
d32457f9cf | ||
|
69651e6ebf | ||
|
132a7fd0fc | ||
|
14600c0980 | ||
|
965f479bad | ||
|
ab12ed6275 | ||
|
8e0609e3ad | ||
|
2d0479bb07 | ||
|
320eede0a4 | ||
|
f496dc5bff | ||
|
f0ce4e9a67 | ||
|
d31cc7adbb | ||
|
091a685d75 | ||
|
357258c46e | ||
|
c3eef5df05 | ||
|
e46b5fc132 | ||
|
982c3ae3bd | ||
|
b06baffb06 | ||
|
9be1e63080 | ||
|
e190309f4e | ||
|
bf210cd080 | ||
|
08968e2130 | ||
|
7e29c62e18 | ||
|
3ffd04b12d | ||
|
76d30f2e5b | ||
|
d196fcf32c | ||
|
41175ce3e9 | ||
|
d6acb22582 | ||
|
4a7c0bb9ea | ||
|
bb222d1f33 | ||
|
ba5a0fccbf | ||
|
9197fd38b1 | ||
|
34a8576eca | ||
|
699f324716 | ||
|
e53c30bacf | ||
|
287f471ac4 | ||
|
a44d20b26b | ||
|
ee4f6b8a89 | ||
|
08475bb0cc | ||
|
0714354f52 | ||
|
d4de0e6f1e | ||
|
d1153b8049 | ||
|
f9503cb98a | ||
|
201a3003d9 | ||
|
7a6e793813 | ||
|
c2c78f6724 | ||
|
7cb004c728 | ||
|
58774361bb | ||
|
6c4cb27d3e | ||
|
0728fee706 | ||
|
17f2006f38 | ||
|
18b91278db | ||
|
884c5e9643 | ||
|
0cf39307e0 | ||
|
6e50a0effd | ||
|
fe8e32155d | ||
|
ce75bcbf61 | ||
|
6d283a1599 | ||
|
de73007922 | ||
|
006e6e967a | ||
|
63322c9f2f | ||
|
c7bdddfda3 | ||
|
e166c37d22 | ||
|
8764321c8d | ||
|
fd144a6b5b | ||
|
363f1be4a5 | ||
|
55cb6d4b94 | ||
|
2e6dc308a8 | ||
|
9b1f4e01c7 | ||
|
2696f0af0e | ||
|
9558861cb7 | ||
|
bfdf734ac1 | ||
|
d3e8b9066c | ||
|
4c473451c9 | ||
|
e3e3d8a255 | ||
|
0be46af0c6 | ||
|
66281d81b3 | ||
|
0de8abc342 | ||
|
17b8858408 | ||
|
563e4fcdf4 | ||
|
bbd6cc7dcb | ||
|
ae9315ad48 | ||
|
a58c2b0f94 | ||
|
7167663160 | ||
|
95c2e82543 | ||
|
0375d6469a | ||
|
7b97896221 | ||
|
6ea15d1765 | ||
|
08378eed4b | ||
|
2595fbe764 | ||
|
d2f2748e9e | ||
|
f1e206fde6 | ||
|
0c1be7ca7b | ||
|
c96456503c | ||
|
423eb0499b | ||
|
3987085572 | ||
|
fe52f1eeac | ||
|
f08a4f5a66 | ||
|
a984c85ffc | ||
|
9d99863c7e | ||
|
f130a8ea89 | ||
|
38e2e3e393 | ||
|
e4ff6853dd | ||
|
d7b3b47aa4 | ||
|
1b514d6f23 | ||
|
f5a5d8f8e7 | ||
|
83c2b3ef62 | ||
|
90c4fc1db1 | ||
|
a828ee8fda | ||
|
dc3e68c507 | ||
|
a6ffae72f5 | ||
|
c91d67912b | ||
|
9b51137767 | ||
|
62cf10f0c3 | ||
|
f08e22db95 | ||
|
88c489d393 | ||
|
94e0021e78 | ||
|
1b4d0c7965 | ||
|
2ca61e2de2 | ||
|
aa67fae7b9 | ||
|
4d3e219d84 | ||
|
50fbf29b3b | ||
|
ff18b03250 | ||
|
3b87c428dc | ||
|
c8b7a09028 | ||
|
fa5336cade | ||
|
34337fb959 | ||
|
6a4c55de7d | ||
|
2e8ce87c23 | ||
|
cd7cb8c1a8 | ||
|
44b4ff6f05 | ||
|
d3bae33c64 | ||
|
914ae9e0d1 | ||
|
7ae802d736 | ||
|
d83ec1810a | ||
|
b3d1b49fab | ||
|
a6e3b57848 | ||
|
7007105150 | ||
|
9c93cd1283 | ||
|
d2f909981a | ||
|
aa00fc6f63 | ||
|
db001a6eb5 | ||
|
f69a8e66c6 | ||
|
072747b741 | ||
|
4fa8a90787 | ||
|
c0e3509e65 | ||
|
0edb16150a | ||
|
7e6812f64a | ||
|
1c13d0dd6b | ||
|
f58faf5f2c | ||
|
207b9aef96 | ||
|
c5c2721e60 | ||
|
db76fc7b66 | ||
|
c1cf9d8e67 | ||
|
5f210d3404 | ||
|
24328568ed | ||
|
f5921a3535 | ||
|
f691d2ed79 | ||
|
60f54ee691 | ||
|
db3933d150 | ||
|
d0b335dc6e | ||
|
25f507c5e3 | ||
|
2fb232ee68 | ||
|
90c4eed92e | ||
|
bf4ba091e4 | ||
|
c19b9d9d5d | ||
|
5143cada8e | ||
|
f630a8afc8 | ||
|
ccd0adb84d | ||
|
4afefa25d1 | ||
|
4de2bf21a3 | ||
|
136309ae6f | ||
|
12d2e49adf | ||
|
85bb592eeb | ||
|
164285b221 | ||
|
297ced77b9 | ||
|
3e1de6b014 | ||
|
2a2e2e2868 | ||
|
0c1931284e | ||
|
9ac3763267 | ||
|
b6cd247d12 | ||
|
f3bce9ecfd | ||
|
55456eaf17 | ||
|
12a8864532 | ||
|
d933783629 | ||
|
f3aee6d766 | ||
|
3b0ce189ea | ||
|
9a2bce66fd | ||
|
9c191949d8 | ||
|
d3f22d2089 | ||
|
6eb10a5f5a | ||
|
75822ec227 | ||
|
ce4ef6e272 | ||
|
a86ca1491f | ||
|
0519111528 | ||
|
2d4e3a6d25 | ||
|
c99a518ba4 | ||
|
512e3ff61c | ||
|
3d732bbbb6 | ||
|
19e160117f | ||
|
f78fda6d9c | ||
|
d6d4badbda | ||
|
0f890ce7f1 | ||
|
e81e7bee13 | ||
|
b3609a23fa | ||
|
8a1464ac41 | ||
|
5468e9745c | ||
|
4cd9d1df46 | ||
|
f097e01c3f | ||
|
ec101fc52b | ||
|
1a7daad657 | ||
|
9815050287 | ||
|
1503a6571f | ||
|
3501e8fa46 | ||
|
46fb7b310e | ||
|
64327b8ddb | ||
|
33cdfa644e | ||
|
5dc96ddf47 | ||
|
f520a39c89 | ||
|
bc97cc0bfb | ||
|
79af43b861 | ||
|
f1883fd773 | ||
|
d77e4a1470 | ||
|
4c2f4095d2 | ||
|
4a79099115 | ||
|
11d0b204f5 | ||
|
db466c56fa | ||
|
8a55f1db35 | ||
|
31654d2908 | ||
|
d61abc5a18 | ||
|
4df96b097d | ||
|
ea051bddfb | ||
|
3b2a005a92 | ||
|
fb186b6fab | ||
|
f453bca1c3 | ||
|
be4d91c105 | ||
|
60bea040d0 | ||
|
0f303eb999 | ||
|
94c864390d | ||
|
3772645fca | ||
|
e2855dee7d | ||
|
aa46469878 | ||
|
4125796569 | ||
|
44ebe2f09a | ||
|
d46d657190 | ||
|
e56cd58d70 | ||
|
426771deda | ||
|
f0f319a418 | ||
|
779e064a17 | ||
|
1f15fdd6cb | ||
|
a07cf853d7 | ||
|
59c3e271db | ||
|
922b4802f1 | ||
|
bd586d37e6 | ||
|
90b2860fd2 | ||
|
0748a05bf0 | ||
|
8f51d87826 | ||
|
e57845dd50 | ||
|
fdc804b7df | ||
|
ad36859607 | ||
|
c4e90ce865 | ||
|
bc57a4e74f | ||
|
878d68bb21 | ||
|
dc607846a3 | ||
|
568bec17fc | ||
|
2a458530b7 | ||
|
87d2a54638 | ||
|
9971541d78 | ||
|
3b6c207ea8 | ||
|
af0a1200ab | ||
|
ab6644c874 | ||
|
7f0c820566 | ||
|
de818ab5ec | ||
|
73b365e952 | ||
|
d9fb9bac09 | ||
|
6139d52a39 | ||
|
784f91e441 | ||
|
da30315556 | ||
|
419c8f6ee6 | ||
|
ddacdb0ab2 | ||
|
ec644cf1a4 | ||
|
b5572520c2 | ||
|
54cac3b051 | ||
|
9e4fe0d514 | ||
|
917c52ec96 | ||
|
86f5c9f031 | ||
|
0afe87be0a | ||
|
225494b559 | ||
|
dca0bbcbb1 | ||
|
7e11cb5cc1 | ||
|
5557124f05 | ||
|
a459f578fa | ||
|
98f8602c59 | ||
|
f3f29e4769 | ||
|
16b2721c2a | ||
|
2385dd3972 | ||
|
fd47b6e0c6 | ||
|
1bf18472c1 | ||
|
5a6d3fde61 | ||
|
71ac17464a | ||
|
735160157c | ||
|
4b717322d3 | ||
|
eb43b69e4d | ||
|
da6d417d5d | ||
|
3e1c70a887 | ||
|
bde7b8dd7f | ||
|
096c5e7509 | ||
|
2854e70c94 | ||
|
e4d74f199f | ||
|
2f964928ff | ||
|
0dd14eed43 | ||
|
f9954e5831 | ||
|
7498f84261 | ||
|
389eee472f | ||
|
93339d9be4 | ||
|
90e7aa65a1 | ||
|
6c2655c841 | ||
|
1e7a4d2727 | ||
|
0ddc00727d | ||
|
6912199ae0 | ||
|
83e70d7dd7 | ||
|
c0fcf06c96 | ||
|
21a00e00a2 | ||
|
1026edec6c | ||
|
15572e2d61 | ||
|
bf395c8ac1 | ||
|
e409a6cf23 | ||
|
14d986c87a | ||
|
873fb6924f | ||
|
1000fdc902 | ||
|
e3a380bbe4 | ||
|
89b28d5a4a | ||
|
17a8e7f56e | ||
|
38fb271c83 | ||
|
e5864c5abf | ||
|
139d68700b | ||
|
57dd24a2e0 | ||
|
4cfa4fa1ca | ||
|
525c45e9f5 | ||
|
a1306b8d96 | ||
|
f2fd18d803 | ||
|
6b6fe3c5d9 | ||
|
5cb07b900a | ||
|
d5ce84a9f5 | ||
|
f6ff4796b2 | ||
|
f606adfa69 | ||
|
4e81779adb | ||
|
de8257d7aa | ||
|
f608ae76ed | ||
|
950ef59319 | ||
|
d010b126cd | ||
|
369ed2adb7 | ||
|
2d74ae8f53 | ||
|
1f69ffd2bc | ||
|
f53ab14afc | ||
|
5f4524e385 | ||
|
5f132b0f1c | ||
|
6d1d20cbcb | ||
|
ba4c28ca41 | ||
|
d64fa7cb7b | ||
|
f6bbb15e75 | ||
|
ec9ae29be8 | ||
|
3a65722bff | ||
|
c8ae274845 | ||
|
e54e1af413 | ||
|
73ef98ca60 | ||
|
360477f209 | ||
|
7e64cbf543 | ||
|
2c2de2169f | ||
|
52178abe4d | ||
|
ad46732e12 | ||
|
7718aac519 | ||
|
ed1d061aa4 | ||
|
2a6486b78f | ||
|
e5c92a2c30 | ||
|
d8ddbb0687 | ||
|
e414ede098 | ||
|
e3d750597a | ||
|
fe2e9dbfc2 | ||
|
13db8fdf70 | ||
|
bd65a373ec | ||
|
14b1716be8 | ||
|
a73ae02b7e | ||
|
0ffd9caaed | ||
|
5c380e2310 | ||
|
7e7209d29a | ||
|
afd0acd4a7 | ||
|
07aaf3713c | ||
|
1b908eeb9e | ||
|
3db718799f | ||
|
146d77f819 | ||
|
06a9241bcf | ||
|
ce4b23b41a | ||
|
3184d1466e | ||
|
8793d8f8d5 | ||
|
a26a98cb98 | ||
|
5e69db511c | ||
|
468aaba79e | ||
|
a3aa086375 | ||
|
82ad133d91 | ||
|
250cb89479 | ||
|
121dc75451 | ||
|
69c06545ce | ||
|
9e5b5683af | ||
|
f01357aa7a | ||
|
7f13ae3e4f | ||
|
e5b990b8e0 | ||
|
99411af951 | ||
|
b318509687 | ||
|
37f7975416 | ||
|
40c1fee55a | ||
|
b0fe6c83e2 | ||
|
59fc122986 | ||
|
3ec6bbc2ce | ||
|
a431cb420b | ||
|
5a6c4ea408 | ||
|
7d9376a64b | ||
|
6e4f09366e | ||
|
6c22cb171d | ||
|
77e900585a | ||
|
86bfeec554 | ||
|
45343e6e27 | ||
|
944f608f09 | ||
|
ad960a64e2 | ||
|
e2a687d96d | ||
|
53e43b8f31 | ||
|
da2eb8ea66 | ||
|
088f109a64 | ||
|
9d65198786 | ||
|
49e3b748c3 | ||
|
5324c7c620 | ||
|
26d2a4f877 | ||
|
76d407b45a | ||
|
e783c4bfcb | ||
|
afc663a51a | ||
|
cb500636cc | ||
|
e6f4dfbfe2 | ||
|
1bfdda7e71 | ||
|
330fd1c2ae | ||
|
56b676eafb | ||
|
73e3e52057 | ||
|
56b53584d1 | ||
|
f43fcd6670 | ||
|
5984f0d442 | ||
|
1b75b0ba92 | ||
|
52f5723f4e | ||
|
eb6ab857fc | ||
|
24bfff9cf1 | ||
|
1d3f91be43 | ||
|
824d9953d9 | ||
|
b706108ed6 | ||
|
adab9c93a0 | ||
|
0f8c61c1e1 | ||
|
0b4f28fecf | ||
|
d97ab913cf | ||
|
2249f1e70c | ||
|
0f4ee9d91d | ||
|
5cc5ea4006 | ||
|
2145823971 | ||
|
cdf3807955 | ||
|
10ff8c11fd | ||
|
81af863496 | ||
|
3e8c921b9f | ||
|
f201592ddb | ||
|
72bebf9af8 | ||
|
73ea754640 | ||
|
ce9728af93 | ||
|
6486c56a15 | ||
|
1d95fb3dcd | ||
|
c07d8f3d93 | ||
|
adaf207b58 | ||
|
0dc6a4a5dd | ||
|
626bfe5240 | ||
|
e4a3647b88 | ||
|
f942a857d0 | ||
|
633a81f864 | ||
|
1b5dc0d567 | ||
|
21b8f905ae | ||
|
36a15919ca | ||
|
24ff7c3a01 | ||
|
7beef260f2 | ||
|
36db059672 | ||
|
01f3d729de | ||
|
0a38ef831f | ||
|
55d18da46c | ||
|
a7d6352a22 | ||
|
240c92e20f | ||
|
f410ea743d | ||
|
9100ec753c | ||
|
1d7cbd4203 | ||
|
4049a0c3be | ||
|
86ea50dfdd | ||
|
6a4318f4d1 | ||
|
6d03b29963 | ||
|
44e078c7c0 | ||
|
e1dd514f15 | ||
|
c52943b03c | ||
|
b33d2f559b | ||
|
53ed817183 | ||
|
683f453b6f | ||
|
145ff45876 | ||
|
e3e64233ec | ||
|
313044fe89 | ||
|
074fd60f3c | ||
|
b608305c79 | ||
|
bbf7593e43 | ||
|
e373ee1165 | ||
|
375d6aa0da | ||
|
4c4fde8bf3 | ||
|
5e9e119c76 | ||
|
2a383feef6 | ||
|
a726b796db | ||
|
9348f9931e | ||
|
4c79232f17 | ||
|
16720a2f70 | ||
|
69a8a86ff6 | ||
|
b0286c9c4d | ||
|
660e97c764 | ||
|
df522ebe6f | ||
|
be35cc9912 | ||
|
9801c4166f | ||
|
80db0ed0b3 | ||
|
b9d98ede39 | ||
|
e6c8afa5de | ||
|
60b3f30ab3 | ||
|
cfd2011e80 | ||
|
5ed4c27732 | ||
|
afd1072583 | ||
|
64ad54aa51 | ||
|
3df060cad6 | ||
|
1497d58e41 | ||
|
fd028ca1e7 | ||
|
a1d812398b | ||
|
df96a81a75 | ||
|
656d30be83 | ||
|
6e8a164e67 | ||
|
521288dae0 | ||
|
4c464390ac | ||
|
408e69c41c | ||
|
cc99d6d1fb | ||
|
3030302952 | ||
|
f281a24274 | ||
|
efbba0a909 | ||
|
3750788893 | ||
|
993b6e6c74 | ||
|
7f51048438 | ||
|
212697b950 | ||
|
6a567f3c77 | ||
|
36241e2905 | ||
|
b630ffe28f | ||
|
f6276db4d0 | ||
|
a2e3f8682f | ||
|
dbf6143747 | ||
|
4aafcc50a0 | ||
|
a86b1c5097 | ||
|
2d737970d0 | ||
|
b7f8503655 | ||
|
ca3d15c27e | ||
|
468e6fb9dd | ||
|
50bbefa3ba | ||
|
c635638fd1 | ||
|
b2b2c1d961 | ||
|
748d000c02 | ||
|
c1791361da | ||
|
6a483cfcae | ||
|
fcdd17480c | ||
|
21ad8ba71b | ||
|
dd55716f15 | ||
|
bd3b7fc70c | ||
|
26f1c8dec7 | ||
|
a749aad1b4 | ||
|
58c7239b48 | ||
|
e616bd523e | ||
|
d163ead2ac | ||
|
00838065ae | ||
|
8298158f08 | ||
|
824ed30872 | ||
|
2b15c30ad1 | ||
|
643ddc18be | ||
|
639db5846e | ||
|
0bb430b3eb | ||
|
550dbae0c7 | ||
|
f0ee52f892 | ||
|
84b146d74a | ||
|
3f1226e504 | ||
|
186519dc92 | ||
|
51ce96ac3c | ||
|
16f6048d74 | ||
|
e2c1bad224 | ||
|
e6663991a7 | ||
|
62c41fbd03 | ||
|
0b581b1506 | ||
|
76a7cafe50 | ||
|
12ab387be5 | ||
|
cfc9c1dd02 | ||
|
544d2dedef | ||
|
1721383237 | ||
|
68961a91e2 | ||
|
435766b2ef | ||
|
750247e8a6 | ||
|
a81d6f3271 | ||
|
cb62613501 | ||
|
2efc82ea59 | ||
|
a95658bd2d | ||
|
5f10cc1ebc | ||
|
226d188d19 | ||
|
9e0f3f01a7 | ||
|
06b461acd7 | ||
|
ffb8fc683b | ||
|
aa2cac0f0c | ||
|
2bc6d965f6 | ||
|
c5e36a4e3c | ||
|
bbc6af247b | ||
|
164780363b | ||
|
807e6a0f9a | ||
|
605bef0482 | ||
|
2e3c652996 | ||
|
a8652dd91b | ||
|
2379aa3108 | ||
|
ed3f5dfd4b | ||
|
747d326ed5 | ||
|
b4ff754e29 | ||
|
67ac030c56 | ||
|
15b62648c9 | ||
|
b09bf4c532 | ||
|
e045e2fdb6 | ||
|
36dc8da47c | ||
|
25d95f1115 | ||
|
e254ef6b15 | ||
|
7038305812 | ||
|
c77176a4ce | ||
|
c604eefde0 | ||
|
48022d3c5c | ||
|
cf36abf7e6 | ||
|
ed84900ab6 | ||
|
83c82387e3 | ||
|
9ce9b142e7 | ||
|
ced56c79b6 | ||
|
d836aeb716 | ||
|
7c642fbf6e | ||
|
a28a80e45f | ||
|
2cbf7fca08 | ||
|
4b02ffa920 | ||
|
8316318c31 | ||
|
7b6d4ce699 | ||
|
6f590c85f6 | ||
|
f86dad801f | ||
|
ee5dccfc0f | ||
|
16c17cff63 | ||
|
ce526ac432 | ||
|
a3342213b5 | ||
|
ef41393bc3 | ||
|
a45d98efea | ||
|
e23f3747ba | ||
|
3f268e5f2e | ||
|
b3e61b1d75 | ||
|
6865b984e0 | ||
|
7c4dccac8c | ||
|
6c0300801f | ||
|
069c293aba | ||
|
7690f1a099 | ||
|
add02dc55e | ||
|
961114c260 | ||
|
ff3def3d00 | ||
|
39f759368f | ||
|
4cdd43b29b | ||
|
0c82e09df1 | ||
|
1129f09660 | ||
|
079606c143 | ||
|
66feed1d2b | ||
|
65748001f0 | ||
|
4504875df9 | ||
|
cd023c30d9 | ||
|
7bb562182f | ||
|
77ca104a8d | ||
|
b660df8df6 | ||
|
b1a086ee93 | ||
|
504ddb4c2f | ||
|
d38d2f56e1 | ||
|
9b0ed67c9c | ||
|
1081e84981 | ||
|
ee64440fef | ||
|
0c56e2803e | ||
|
5fc89085d6 | ||
|
f747acdc7c | ||
|
4e2493759e | ||
|
1f1ecfa590 | ||
|
bd2ad31f5e | ||
|
fb5e7dbfdb | ||
|
0ac5ce46a7 | ||
|
1073a42409 | ||
|
66d7d39bee | ||
|
46bd9127fb | ||
|
5309189602 | ||
|
006396bc92 | ||
|
dc4c9f0258 | ||
|
3b737ab87b | ||
|
6170cbc95a | ||
|
78f18de61a | ||
|
e34120803d | ||
|
fdb094045e | ||
|
8c45216cfd | ||
|
897ed0cb10 | ||
|
fd8489d088 | ||
|
710cd548a9 | ||
|
525eb65e1c | ||
|
580e52bd2c | ||
|
2f6bfca68e | ||
|
0377715cdc | ||
|
e3240214a3 | ||
|
fc2b220c38 | ||
|
74c6290dc0 | ||
|
a93ef02efa | ||
|
68d2b03e48 | ||
|
d682375d7d | ||
|
3b80342a02 | ||
|
8f49cddd7d | ||
|
d679885985 | ||
|
82c3807bd5 | ||
|
58ad23186b | ||
|
c957a9db0f | ||
|
359b7e25dd | ||
|
5d6d0282b0 | ||
|
33e01af955 | ||
|
0d5531a090 | ||
|
2659c906fb | ||
|
d563ecb060 | ||
|
bfe1ff6e15 | ||
|
adfc2ab451 | ||
|
ea912f794c | ||
|
8e1f54465d | ||
|
2c2259ea15 | ||
|
be4fdb1776 | ||
|
76158b031d | ||
|
599029b68e | ||
|
201d65749e | ||
|
17d8197e72 | ||
|
1ed1d0005c | ||
|
51f8d7f84e | ||
|
1ec4d9cc7d | ||
|
b90bc3a3e4 | ||
|
de530e2ca3 | ||
|
5d4669d52e | ||
|
8dc310f1bb | ||
|
9cca961024 | ||
|
7b4283bf4a | ||
|
1f423dc39f | ||
|
ab6fea5767 | ||
|
3328b570d4 | ||
|
63427b2ad0 | ||
|
61052c41a1 | ||
|
5c68df7ac7 | ||
|
8872d98dd6 | ||
|
03bae80ed2 | ||
|
1161b5ee7e | ||
|
b49bf1b13c | ||
|
81994ecf58 | ||
|
4682cec1cb | ||
|
b9a0ffacc4 | ||
|
ae46e3f6ab | ||
|
68beb4b1a3 | ||
|
118b002ee8 | ||
|
a004e906dd | ||
|
eaa4122c5a | ||
|
e326ab1593 | ||
|
5252e06c2a | ||
|
e61809496d | ||
|
edaf960407 | ||
|
e3217964c4 | ||
|
397479cd77 | ||
|
d151ee0b58 | ||
|
ce88004900 | ||
|
1e8d0e10e6 | ||
|
bb641688ee | ||
|
ab53914351 | ||
|
54186736c8 | ||
|
b66fea0fbc | ||
|
bf2c9620f3 | ||
|
af96229d5d | ||
|
be323039d1 | ||
|
c71be87a3a | ||
|
e4b01bc066 | ||
|
3ac076e098 | ||
|
e6120fdcd6 | ||
|
4dc4616933 | ||
|
46a3929365 | ||
|
4597868d30 | ||
|
cf716c4049 | ||
|
cc6b9d3d81 | ||
|
a34279b971 | ||
|
5cac87c99f | ||
|
309bc2dcaa | ||
|
7124f8bd2c | ||
|
c9b19c76a5 | ||
|
8939c3076a | ||
|
71065a65dd | ||
|
7adc49c541 | ||
|
baba221dd9 | ||
|
829485ef2a | ||
|
b793b80360 | ||
|
ea34c2c78a | ||
|
722e97fef2 | ||
|
bd412d7204 | ||
|
39e6d958bf | ||
|
bb54b37399 | ||
|
88dd3b021e | ||
|
ef4d19378d | ||
|
7f1ea1490d | ||
|
041fb4e37f | ||
|
193e59df90 | ||
|
d4703f045d | ||
|
109b1e45b5 | ||
|
1f1edef98d | ||
|
83631e95aa | ||
|
6eb1242600 | ||
|
77e7ea161b | ||
|
09f271e5d0 | ||
|
e35a8326d5 | ||
|
09d46aa025 | ||
|
615e097c68 | ||
|
ade56b62e9 | ||
|
b3d7f04b5e | ||
|
4f81c50a3e | ||
|
d45c3aeb96 | ||
|
fff603635a | ||
|
06f01ea7dc | ||
|
2395abcf7e | ||
|
d33f9ba2d4 | ||
|
aec28542ac | ||
|
73219c45dd | ||
|
39d6cb7840 | ||
|
bfd4e345dd | ||
|
aded0f9c1c | ||
|
811265e28b | ||
|
0caffa2b82 | ||
|
4dfb01bb1d | ||
|
862ed243be | ||
|
39f1fa6045 | ||
|
f26939e2cc | ||
|
9d53451933 | ||
|
4ae54eeb2a | ||
|
d62ae07b75 | ||
|
0f22a7fa06 | ||
|
7f3c2d00ac | ||
|
b324e8ed9d | ||
|
8420823713 | ||
|
1d1b50ce0c | ||
|
35fcca8a66 | ||
|
7a01503478 | ||
|
dd8f138892 | ||
|
8341e41f04 | ||
|
a682ec6b7a | ||
|
451b648c7f | ||
|
2d1c43c937 | ||
|
17adb214f2 | ||
|
3a2839c6c9 | ||
|
f96f95c4ff | ||
|
609fdae508 | ||
|
580305ce92 | ||
|
cbfd12e0f1 | ||
|
c5ccf7d2c8 | ||
|
d1c42751cd |
24
.gitattributes
vendored
Normal file
24
.gitattributes
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Tell GitHub that these files are SourcePawn
|
||||
*.inc text linguist-language=sourcepawn
|
||||
*.sma text linguist-language=sourcepawn
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Sources
|
||||
*.C text
|
||||
*.cc text
|
||||
*.cxx text
|
||||
*.cpp text
|
||||
*.c++ text
|
||||
*.hpp text
|
||||
*.h text
|
||||
*.h++ text
|
||||
*.hh text
|
||||
|
||||
# Compiled Object files
|
||||
*.o binary
|
||||
*.obj binary
|
74
.github/CONTRIBUTING.md
vendored
Normal file
74
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
# Contributing to AMX Mod X
|
||||
|
||||
## Issue reports
|
||||
|
||||
Please consider the following guidelines when reporting an issue.
|
||||
|
||||
#### Not for general support
|
||||
This is not the right place to get help with using or installing AMX Mod X, or for issues with specific, third-party AMX Mod X plugins or extensions.
|
||||
|
||||
For help with AMX Mod X, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=3). Similarly, for assistance with, or to report issues with, third-party AMX Mod X plugins or extensions, you should post in the existing thread for that plugin or extension on the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=3).
|
||||
|
||||
#### Details, details, details
|
||||
Provide as much detail as possible when reporting an issue.
|
||||
|
||||
For bugs or other undesired behavior, answers to the following questions are a great start:
|
||||
* What is the issue?
|
||||
* What behavior are you expecting instead?
|
||||
* On what operating system is the game server running?
|
||||
* What game is the game server running?
|
||||
* What exact versions (full x.y.z.a version number) of Metamod and AMX Mod X are installed on the game server?
|
||||
* What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem.
|
||||
|
||||
If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation.
|
||||
* What is your end goal, or what are you trying to accomplish?
|
||||
* Why is this necessary, or what benefit do you see with it?
|
||||
* Will this be useful to others?
|
||||
|
||||
#### Issues with security implications
|
||||
Please report any security bugs to [security@alliedmods.net](mailto:security@alliedmods.net) rather than to this public issue tracker.
|
||||
|
||||
#### We're only human
|
||||
Please keep in mind that we maintain this project in our spare time, at no cost. There is no SLA, and you are not owed a response or a fix.
|
||||
|
||||
#### Conduct
|
||||
Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules)
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Firstly, thank you for considering contributing changes to the project!
|
||||
|
||||
However, if this is anything more than a small fix such as a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
|
||||
|
||||
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel like you wasted your time writing something only for us to shoot it down.
|
||||
|
||||
#### Rejection
|
||||
*Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.*
|
||||
|
||||
> If you send us a patch without coordinating it with us first, it will probably be immediately rejected, or sit in limbo for a long time and eventually be rejected. The reasons we do this vary from patch to patch, but some of the most common reasons are:
|
||||
>
|
||||
> **Unjustifiable Costs**: We support code in the upstream forever. Support is enormously expensive and takes up a huge amount of our time. The cost to support a change over its lifetime is often 10x or 100x or 1000x greater than the cost to write the first version of it. Many uncoordinated patches we receive are "white elephants", which would cost much more to maintain than the value they provide.
|
||||
>
|
||||
> As an author, it may look like you're giving us free work and we're rejecting it as too expensive, but this viewpoint doesn't align with the reality of a large project which is actively supported by a small, experienced team. Writing code is cheap; maintaining it is expensive.
|
||||
>
|
||||
> By coordinating with us first, you can make sure the patch is something we consider valuable enough to put long-term support resources behind, and that you're building it in a way that we're comfortable taking over.
|
||||
>
|
||||
> **Not a Good Fit**: Many patches aren't good fits for the upstream: they implement features we simply don't want. You can find more information in Contributing Feature Requests. Coordinating with us first helps make sure we're on the same page and interested in a feature.
|
||||
>
|
||||
> The most common type of patch along these lines is a patch which adds new configuration options. We consider additional configuration options to have an exceptionally high lifetime support cost and are very unlikely to accept them. Coordinate with us first.
|
||||
>
|
||||
> **Not a Priority**: If you send us a patch against something which isn't a priority, we probably won't have time to look at it. We don't give special treatment to low-priority issues just because there's code written: we'd still be spending time on something lower-priority when we could be spending it on something higher-priority instead.
|
||||
>
|
||||
> If you coordinate with us first, you can make sure your patch is in an area of the codebase that we can prioritize.
|
||||
>
|
||||
> **Overly Ambitious Patches**: Sometimes we'll get huge patches from new contributors. These can have a lot of fundamental problems and require a huge amount of our time to review and correct. If you're interested in contributing, you'll have more success if you start small and learn as you go.
|
||||
>
|
||||
> We can help you break a large change into smaller pieces and learn how the codebase works as you proceed through the implementation, but only if you coordinate with us first.
|
||||
>
|
||||
> **Generality**: We often receive several feature requests which ask for similar features, and can come up with a general approach which covers all of the use cases. If you send us a patch for your use case only, the approach may be too specific. When a cleaner and more general approach is available, we usually prefer to pursue it.
|
||||
>
|
||||
> By coordinating with us first, we can make you aware of similar use cases and opportunities to generalize an approach. These changes are often small, but can have a big impact on how useful a piece of code is.
|
||||
>
|
||||
> **Infrastructure and Sequencing**: Sometimes patches are written against a piece of infrastructure with major planned changes. We don't want to accept these because they'll make the infrastructure changes more difficult to implement.
|
||||
>
|
||||
> Coordinate with us first to make sure a change doesn't need to wait on other pieces of infrastructure. We can help you identify technical blockers and possibly guide you through resolving them if you're interested.
|
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://www.sourcemod.net/donate.php
|
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Help us help you
|
||||
- [ ] I have checked that my issue [doesn't exist yet](https://github.com/alliedmodders/amxmodx/issues).
|
||||
- [ ] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
|
||||
- [ ] I can always reproduce the issue with the provided description below.
|
||||
|
||||
# Environment
|
||||
* Operating System version:
|
||||
* Game/AppID (with version if applicable):
|
||||
* Current AMX Mod X version:
|
||||
* Current Metamod version:
|
||||
- [ ] I have updated AMX Mod X to the [latest version](https://www.amxmodx.org/downloads.php) and it still happens.
|
||||
- [ ] I have updated AMX Mod X to the [latest snapshot](https://www.amxmodx.org/snapshots.php) and it still happens.
|
||||
- [ ] I have updated Metamod to the [latest version](https://www.amxmodx.org/downloads.php) and it still happens.
|
||||
|
||||
# Description
|
||||
|
||||
|
||||
# Problematic Code (or Steps to Reproduce)
|
||||
```PAWN
|
||||
// TODO(you): code here to reproduce the problem
|
||||
```
|
||||
|
||||
# Logs
|
||||
* Please attach in separate files: game output, library logs, kernel logs, and any other supporting information.
|
||||
* In case of a crash, please attach minidump or dump analyze output.
|
137
.github/workflows/ci.yml
vendored
Normal file
137
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
name: Continuous Integration
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 1.9-dev
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 1.9-dev
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
os_short: linux
|
||||
compiler_cc: gcc
|
||||
compiler_cxx: g++
|
||||
- os: ubuntu-latest
|
||||
os_short: linux
|
||||
compiler_cc: clang
|
||||
compiler_cxx: clang++
|
||||
- os: ubuntu-18.04
|
||||
os_short: linux
|
||||
compiler_cc: clang-3.9
|
||||
compiler_cxx: clang++-3.9
|
||||
- os: ubuntu-18.04
|
||||
os_short: linux
|
||||
compiler_cc: gcc-6
|
||||
compiler_cxx: g++-6
|
||||
compiler_install: 'g++6 g++-6-multilib'
|
||||
- os: windows-latest
|
||||
os_short: windows
|
||||
compiler_cc: msvc
|
||||
- os: windows-2016
|
||||
os_short: windows
|
||||
compiler_cc: msvc++14.16-vs2017-cl
|
||||
# MacOS 32 Bins seem not supported
|
||||
# - os: macos-latest
|
||||
# os_short: mac
|
||||
# compiler_cc: clang
|
||||
# compiler_cxx: clang++
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os_short }}-${{ matrix.os }}-${{ matrix.compiler_cc }}
|
||||
env:
|
||||
DEPENDENCIES_FOLDER: dependencies
|
||||
DEPENDENCIES_ROOT: ${{ github.workspace }}/dependencies
|
||||
DEPENDENCIES_ROOT_WIN: ${{ github.workspace }}\dependencies
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
path: amxmodx
|
||||
# Setup Python for AMBuild
|
||||
- uses: actions/setup-python@v2
|
||||
name: Setup Python 3.8
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip setuptools wheel
|
||||
python3 --version
|
||||
- name: Install AMXModX dependencies (Linux)
|
||||
if: startsWith(runner.os, 'Linux') || startsWith(runner.os, 'macOS')
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ env.DEPENDENCIES_FOLDER }}
|
||||
cd ${{ env.DEPENDENCIES_FOLDER }}
|
||||
|
||||
# Satisfy checkout-deps requirement for a "amxmodx" folder.
|
||||
mkdir -p amxmodx
|
||||
../amxmodx/support/checkout-deps.sh
|
||||
- name: Install AMXModX dependencies (Windows)
|
||||
if: startsWith(runner.os, 'Windows')
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir %DEPENDENCIES_ROOT_WIN%\nasm
|
||||
curl -L -o "%DEPENDENCIES_ROOT_WIN%\nasm\nasm.zip" https://www.nasm.us/pub/nasm/releasebuilds/2.13.03/win32/nasm-2.13.03-win32.zip
|
||||
chdir %DEPENDENCIES_ROOT_WIN%\nasm
|
||||
7z x nasm.zip
|
||||
|
||||
chdir %DEPENDENCIES_ROOT_WIN%
|
||||
git clone https://github.com/alliedmodders/ambuild
|
||||
git clone https://github.com/alliedmodders/metamod-hl1 metamod-am
|
||||
git clone https://github.com/alliedmodders/hlsdk
|
||||
|
||||
curl -L -o "mysql-connector-c-6.1.1-win32.zip" https://downloads.mysql.com/archives/get/p/19/file/mysql-connector-c-6.1.1-win32.zip
|
||||
7z x mysql-connector-c-6.1.1-win32.zip -o"mysql"
|
||||
cd mysql
|
||||
dir
|
||||
ren mysql-connector-c-6.1.1-win32 mysql-5.5
|
||||
move /Y mysql-5.5 ..\
|
||||
|
||||
cd ..\ambuild
|
||||
python3 setup.py install
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
gcc-multilib g++-multilib libstdc++6 lib32stdc++6 \
|
||||
libc6-dev libc6-dev-i386 linux-libc-dev \
|
||||
linux-libc-dev:i386 lib32z1-dev nasm ${{ matrix.compiler_cc }} ${{ matrix.compiler_install }}
|
||||
- name: Select compiler
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
run: |
|
||||
echo "CC=${{ matrix.compiler_cc }}" >> $GITHUB_ENV
|
||||
echo "CXX=${{ matrix.compiler_cxx }}" >> $GITHUB_ENV
|
||||
${{ matrix.compiler_cc }} --version
|
||||
${{ matrix.compiler_cxx }} --version
|
||||
- uses: ilammy/setup-nasm@v1
|
||||
- name: Build Linux/macOS
|
||||
if: startsWith(runner.os, 'Linux') || startsWith(runner.os, 'macOS')
|
||||
working-directory: amxmodx
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
python3 ../configure.py --enable-optimize --metamod=${{ env.DEPENDENCIES_ROOT }}/metamod-am --hlsdk=${{ env.DEPENDENCIES_ROOT }}/hlsdk --mysql=${{ env.DEPENDENCIES_ROOT }}/mysql-5.5
|
||||
ambuild
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x86
|
||||
- name: Build Windows
|
||||
if: startsWith(runner.os, 'Windows')
|
||||
working-directory: amxmodx
|
||||
shell: cmd
|
||||
run: |
|
||||
cl.exe
|
||||
mkdir build
|
||||
cd build
|
||||
python3 ../configure.py --enable-optimize --metamod=${{ env.DEPENDENCIES_ROOT_WIN }}\metamod-am --hlsdk=${{ env.DEPENDENCIES_ROOT_WIN }}\hlsdk --mysql=${{ env.DEPENDENCIES_ROOT_WIN }}\mysql-5.5
|
||||
ambuild
|
||||
|
90
.gitignore
vendored
Normal file
90
.gitignore
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
# Binaries
|
||||
*.dll
|
||||
*.exe
|
||||
*.so
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
JITDebug/
|
||||
JITRelease/
|
||||
JITDebugBinLog/
|
||||
JITReleaseBinLog/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
build/
|
||||
obj-*/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# Files generated by Mac OS X Finder
|
||||
.DS_Store
|
||||
|
||||
# Files generated by Windows Explorer
|
||||
Desktop.ini
|
||||
Thumbs.db
|
||||
|
||||
# AMXX plugin build related files
|
||||
plugins/compile.dat
|
||||
plugins/compiled/
|
||||
*.amx
|
||||
*.amxx
|
||||
|
||||
build_deps/
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "public/amtl"]
|
||||
path = public/amtl
|
||||
url = https://github.com/alliedmodders/amtl
|
30
.travis.yml
Normal file
30
.travis.yml
Normal file
@ -0,0 +1,30 @@
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
- lib32stdc++6
|
||||
- lib32z1-dev
|
||||
- libc6-dev-i386
|
||||
- linux-libc-dev
|
||||
- gcc-multilib
|
||||
- g++-multilib
|
||||
- nasm
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
language: cpp
|
||||
sudo: false
|
||||
compiler:
|
||||
- clang
|
||||
install:
|
||||
- pyenv install 3.6.3
|
||||
- pyenv global 3.6.3
|
||||
before_script:
|
||||
- CHECKOUT_DIR=$PWD && cd ..
|
||||
- chmod a+x $CHECKOUT_DIR/support/checkout-deps.sh
|
||||
- $CHECKOUT_DIR/support/checkout-deps.sh && cd $CHECKOUT_DIR
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- PATH="~/.local/bin:$PATH"
|
||||
- CC=clang-3.7 CXX=clang-3.7 python3 ../configure.py --enable-optimize
|
||||
- ambuild
|
514
AMBuildScript
Normal file
514
AMBuildScript
Normal file
@ -0,0 +1,514 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python :
|
||||
import os
|
||||
import subprocess
|
||||
import locale
|
||||
|
||||
class AMXXConfig(object):
|
||||
def __init__(self):
|
||||
self.binaries = []
|
||||
self.modules = []
|
||||
self.plugins = {}
|
||||
self.libpc300 = None
|
||||
self.amxxpc = None
|
||||
self.metamod_path = None
|
||||
self.hlsdk_path = None
|
||||
self.mysql_path = None
|
||||
self.generated_headers = []
|
||||
self.versionlib = None
|
||||
self.zlib = None
|
||||
self.hashing = None
|
||||
self.utf8rewind = None
|
||||
self.csx_app = None
|
||||
self.stdcxx_path = None
|
||||
self.nasm_path = None
|
||||
|
||||
def use_auto_versioning(self):
|
||||
if builder.backend != 'amb2':
|
||||
return False
|
||||
return not getattr(builder.options, 'disable_auto_versioning', False)
|
||||
|
||||
def detectProductVersion(self):
|
||||
builder.AddConfigureFile('product.version')
|
||||
|
||||
# For OS X dylib versioning
|
||||
import re
|
||||
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
|
||||
productContents = fp.read()
|
||||
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
|
||||
if m == None:
|
||||
self.productVersion = '1.0.0'
|
||||
else:
|
||||
major, minor, release = m.groups()
|
||||
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
|
||||
|
||||
def detectMetamod(self):
|
||||
metamod_path = builder.options.metamod_path
|
||||
if not len(metamod_path):
|
||||
metamod_path = os.getenv('METAMOD', '')
|
||||
|
||||
if len(metamod_path):
|
||||
self.metamod_path = os.path.join(builder.originalCwd, metamod_path)
|
||||
if not os.path.exists(os.path.join(self.metamod_path, 'metamod')):
|
||||
raise Exception('Metamod path does not exist: {0}'.format(metamod_path))
|
||||
else:
|
||||
try_paths = [
|
||||
os.path.join(builder.sourcePath, '..', 'metamod'),
|
||||
os.path.join(builder.sourcePath, '..', 'metamod-am'),
|
||||
os.path.join(builder.sourcePath, '..', 'metamod-hl1'),
|
||||
]
|
||||
for try_path in try_paths:
|
||||
if os.path.exists(os.path.join(try_path, 'metamod')):
|
||||
self.metamod_path = os.path.normpath(try_path)
|
||||
break
|
||||
if not self.metamod_path:
|
||||
raise Exception('Could not find the source code to Metamod! Try passing --metamod to configure.py.')
|
||||
|
||||
def detectHlsdk(self):
|
||||
hlsdk_path = builder.options.hlsdk_path
|
||||
if not len(hlsdk_path):
|
||||
hlsdk_path = os.getenv('HLSDK', '')
|
||||
|
||||
if len(hlsdk_path):
|
||||
self.hlsdk_path = os.path.join(builder.originalCwd, hlsdk_path)
|
||||
if not os.path.exists(self.hlsdk_path):
|
||||
raise Exception('HLSDK path does not exist: {0}'.format(hlsdk_path))
|
||||
else:
|
||||
try_paths = [
|
||||
os.path.join(builder.sourcePath, '..', 'hlsdk'),
|
||||
]
|
||||
for try_path in try_paths:
|
||||
if os.path.exists(try_path):
|
||||
self.hlsdk_path = os.path.normpath(try_path)
|
||||
break
|
||||
if not self.hlsdk_path:
|
||||
raise Exception('Could not find the HLSDK! Try passing --hlsdk to configure.py.')
|
||||
|
||||
def detectMysql(self):
|
||||
if builder.options.disable_mysql:
|
||||
return
|
||||
|
||||
mysql_path = builder.options.mysql_path
|
||||
if not len(mysql_path):
|
||||
mysql_path = os.getenv('MYSQL55', '')
|
||||
|
||||
if len(mysql_path):
|
||||
self.mysql_path = os.path.join(builder.originalCwd, mysql_path)
|
||||
if not os.path.exists(self.mysql_path):
|
||||
raise Exception('MySQL path does not exist: {0}'.format(mysql_path))
|
||||
else:
|
||||
try_paths = [
|
||||
os.path.join(builder.sourcePath, '..', 'mysql-5.5'),
|
||||
]
|
||||
for try_path in try_paths:
|
||||
if os.path.exists(try_path):
|
||||
self.mysql_path = os.path.normpath(try_path)
|
||||
break
|
||||
if not self.mysql_path:
|
||||
raise Exception('Could not find MySQL! Try passing --mysql to configure.py.')
|
||||
|
||||
def detectNASM(self):
|
||||
import subprocess
|
||||
|
||||
nasm_paths = [
|
||||
getattr(builder.options, 'nasm_path', 'nasm'),
|
||||
]
|
||||
if builder.target_platform == 'windows':
|
||||
nasm_paths += [os.path.join(
|
||||
builder.sourcePath,
|
||||
'build_deps',
|
||||
'nasm',
|
||||
'nasm.exe')
|
||||
]
|
||||
|
||||
for nasm_path in nasm_paths:
|
||||
try:
|
||||
subprocess.check_output([nasm_path, '-v'])
|
||||
self.nasm_path = nasm_path
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if self.nasm_path is None:
|
||||
raise Exception('Could not find a suitable path for nasm')
|
||||
|
||||
# Returns list of lines of output from the compiler
|
||||
@staticmethod
|
||||
def invokeCompiler(args):
|
||||
if builder.compiler:
|
||||
p = subprocess.Popen(builder.compiler.argv + args, stdout=subprocess.PIPE)
|
||||
output = p.communicate()[0]
|
||||
if hasattr(output,'encoding') and output.encoding is not None:
|
||||
encoding = output.encoding
|
||||
else:
|
||||
encoding = locale.getpreferredencoding()
|
||||
return output.decode(encoding, 'replace').split('\n')
|
||||
return None
|
||||
|
||||
def configure(self):
|
||||
builder.AddConfigureFile('pushbuild.txt')
|
||||
|
||||
cxx = builder.DetectCompilers()
|
||||
|
||||
if cxx.like('gcc'):
|
||||
self.configure_gcc(cxx)
|
||||
elif cxx.like('msvc'):
|
||||
self.configure_msvc(cxx)
|
||||
|
||||
# Optimization
|
||||
if builder.options.opt == '1':
|
||||
cxx.defines += ['NDEBUG']
|
||||
|
||||
# Debugging
|
||||
if builder.options.debug == '1':
|
||||
cxx.defines += ['DEBUG', '_DEBUG']
|
||||
|
||||
# Platform-specifics
|
||||
if builder.target_platform == 'linux':
|
||||
self.configure_linux(cxx)
|
||||
elif builder.target_platform == 'mac':
|
||||
self.configure_mac(cxx)
|
||||
elif builder.target_platform == 'windows':
|
||||
self.configure_windows(cxx)
|
||||
|
||||
# Finish up.
|
||||
cxx.defines += [
|
||||
'AMX_NOPROPLIST',
|
||||
'PAWN_CELL_SIZE=32',
|
||||
'AMXMODX_BUILD',
|
||||
'AMXX_USE_VERSIONLIB',
|
||||
]
|
||||
|
||||
if self.use_auto_versioning():
|
||||
cxx.defines += ['AMXX_GENERATED_BUILD']
|
||||
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'support', 'versionlib')]
|
||||
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'public')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'sdk')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'amtl')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'memtools')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'third_party')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'hashing')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'zlib')]
|
||||
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'utf8rewind')]
|
||||
|
||||
def configure_gcc(self, cxx):
|
||||
cxx.cflags += [
|
||||
'-pipe',
|
||||
'-fno-strict-aliasing',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-Wno-uninitialized',
|
||||
'-Wno-unused',
|
||||
'-Wno-switch',
|
||||
'-Wno-format',
|
||||
'-Wno-format-security',
|
||||
'-m32',
|
||||
]
|
||||
cxx.cxxflags += [
|
||||
'-Wno-invalid-offsetof',
|
||||
'-std=c++11',
|
||||
]
|
||||
|
||||
cxx.linkflags += ['-m32']
|
||||
|
||||
have_gcc = cxx.vendor == 'gcc'
|
||||
have_clang = cxx.vendor == 'clang'
|
||||
|
||||
if have_clang or (have_gcc and cxx.version >= '4'):
|
||||
cxx.cflags += ['-fvisibility=hidden']
|
||||
cxx.cxxflags += ['-fvisibility-inlines-hidden']
|
||||
if have_clang or (have_gcc and cxx.version >= '4.6'):
|
||||
cxx.cflags += ['-Wno-narrowing']
|
||||
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
|
||||
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||
if have_gcc and cxx.version >= '4.8':
|
||||
cxx.cflags += ['-Wno-unused-result', '-Wno-error=sign-compare']
|
||||
if have_gcc and cxx.version >= '8.0':
|
||||
cxx.cflags += ['-Wno-stringop-truncation']
|
||||
if have_gcc and cxx.version >= '9.0':
|
||||
cxx.cflags += ['-Wno-address-of-packed-member']
|
||||
if have_clang:
|
||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||
if cxx.version >= '10.0':
|
||||
cxx.cxxflags += ['-Wno-tautological-compare']
|
||||
if cxx.version >= 'apple-clang-10.0':
|
||||
cxx.cxxflags += [
|
||||
'-Wno-inconsistent-missing-override',
|
||||
'-Wno-varargs',
|
||||
]
|
||||
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
||||
cxx.cxxflags += ['-Wno-deprecated-register']
|
||||
else:
|
||||
cxx.cxxflags += ['-Wno-deprecated']
|
||||
cxx.cflags += ['-Wno-sometimes-uninitialized']
|
||||
if builder.target_platform == 'linux' and cxx.version >= '3.6':
|
||||
cxx.cxxflags += ['-Wno-inconsistent-missing-override']
|
||||
if builder.target_platform == 'linux' and cxx.version >= '3.9':
|
||||
cxx.cxxflags += ['-Wno-varargs']
|
||||
if builder.target_platform == 'linux' and cxx.version >= '4.0':
|
||||
cxx.cxxflags += ['-Wno-address-of-packed-member']
|
||||
|
||||
if have_gcc:
|
||||
cxx.cflags += ['-Wno-parentheses']
|
||||
cxx.c_only_flags += ['-std=c99']
|
||||
elif have_clang:
|
||||
cxx.cflags += ['-Wno-logical-op-parentheses']
|
||||
|
||||
cxx.cxxflags += [
|
||||
'-fno-exceptions',
|
||||
'-fno-rtti',
|
||||
]
|
||||
|
||||
if builder.options.opt == '1':
|
||||
cxx.cflags += ['-O2']
|
||||
|
||||
def configure_msvc(self, cxx):
|
||||
if builder.options.debug == '1':
|
||||
cxx.cflags += ['/MTd']
|
||||
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
||||
else:
|
||||
cxx.cflags += ['/MT']
|
||||
|
||||
cxx.defines += [
|
||||
'_CRT_SECURE_NO_DEPRECATE',
|
||||
'_CRT_SECURE_NO_WARNINGS',
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
'_ITERATOR_DEBUG_LEVEL=0',
|
||||
]
|
||||
cxx.cflags += [
|
||||
'/W3',
|
||||
]
|
||||
cxx.cxxflags += [
|
||||
'/EHsc',
|
||||
'/GR-',
|
||||
'/TP',
|
||||
]
|
||||
cxx.linkflags += [
|
||||
'/MACHINE:X86',
|
||||
'/SUBSYSTEM:WINDOWS',
|
||||
'kernel32.lib',
|
||||
'user32.lib',
|
||||
'gdi32.lib',
|
||||
'winspool.lib',
|
||||
'comdlg32.lib',
|
||||
'advapi32.lib',
|
||||
'shell32.lib',
|
||||
'ole32.lib',
|
||||
'oleaut32.lib',
|
||||
'uuid.lib',
|
||||
'odbc32.lib',
|
||||
'odbccp32.lib',
|
||||
]
|
||||
|
||||
if cxx.version >= 1900:
|
||||
cxx.linkflags += ['legacy_stdio_definitions.lib', 'legacy_stdio_wide_specifiers.lib']
|
||||
|
||||
if builder.options.opt == '1':
|
||||
cxx.cflags += ['/Ox']
|
||||
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
||||
|
||||
if builder.options.debug == '1':
|
||||
cxx.cflags += ['/Od', '/RTC1']
|
||||
|
||||
# This needs to be after our optimization flags which could otherwise disable it.
|
||||
# Don't omit the frame pointer.
|
||||
cxx.cflags += ['/Oy-']
|
||||
|
||||
def configure_linux(self, cxx):
|
||||
cxx.defines += ['_LINUX', 'POSIX', 'LINUX']
|
||||
cxx.linkflags += ['-ldl', '-lm']
|
||||
if cxx.vendor == 'gcc':
|
||||
cxx.linkflags += ['-static-libgcc']
|
||||
elif cxx.vendor == 'clang':
|
||||
cxx.linkflags += ['-lgcc_eh']
|
||||
if cxx.like('gcc'):
|
||||
self.stdcxx_path = self.invokeCompiler(['-m32', '-print-file-name=' + 'libstdc++.a'])[0]
|
||||
|
||||
def configure_mac(self, cxx):
|
||||
cxx.defines += ['OSX', '_OSX', 'POSIX']
|
||||
cxx.cflags += [
|
||||
'-mmacosx-version-min=10.7',
|
||||
'-Wno-address-of-packed-member',
|
||||
]
|
||||
cxx.linkflags += [
|
||||
'-mmacosx-version-min=10.7',
|
||||
'-arch', 'i386',
|
||||
'-lstdc++',
|
||||
'-stdlib=libc++',
|
||||
'-framework', 'CoreServices',
|
||||
]
|
||||
cxx.cxxflags += ['-stdlib=libc++']
|
||||
|
||||
def configure_windows(self, cxx):
|
||||
cxx.defines += ['WIN32', '_WINDOWS']
|
||||
|
||||
#
|
||||
# Low-level compiler and binary construction.
|
||||
#
|
||||
|
||||
def ConfigureForModule(self, context, compiler):
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(context.currentSourcePath),
|
||||
os.path.join(context.currentSourcePath, 'sdk'),
|
||||
os.path.join(self.metamod_path, 'metamod'),
|
||||
os.path.join(self.hlsdk_path, 'common'),
|
||||
os.path.join(self.hlsdk_path, 'dlls'),
|
||||
os.path.join(self.hlsdk_path, 'engine'),
|
||||
os.path.join(self.hlsdk_path, 'game_shared'),
|
||||
os.path.join(self.hlsdk_path, 'public'),
|
||||
os.path.join(self.hlsdk_path, 'pm_shared'),
|
||||
]
|
||||
return compiler
|
||||
|
||||
def AddVersioning(self, binary):
|
||||
if builder.target_platform == 'windows':
|
||||
binary.compiler.rcdefines += [
|
||||
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
||||
'RC_COMPILE',
|
||||
]
|
||||
if self.use_auto_versioning():
|
||||
binary.compiler.rcdefines += ['AMXX_GENERATED_BUILD']
|
||||
elif builder.target_platform == 'mac':
|
||||
if binary.type == 'library':
|
||||
binary.compiler.postlink += [
|
||||
'-compatibility_version', '1.0.0',
|
||||
'-current_version', self.productVersion
|
||||
]
|
||||
if self.use_auto_versioning():
|
||||
binary.compiler.linkflags += [self.versionlib]
|
||||
binary.compiler.sourcedeps += AMXX.generated_headers
|
||||
return binary
|
||||
|
||||
#
|
||||
# High level job construction for libraries, metamod plugins, modules, and
|
||||
# executables.
|
||||
#
|
||||
|
||||
def Library(self, context, name):
|
||||
binary = context.compiler.Library(name)
|
||||
return self.AddVersioning(binary)
|
||||
|
||||
def MetaPlugin(self, context, name):
|
||||
if builder.target_platform == 'mac' or builder.target_platform == 'windows':
|
||||
name = name + '_mm'
|
||||
elif builder.target_platform == 'linux':
|
||||
name = name + '_mm_i386'
|
||||
binary = context.compiler.Library(name)
|
||||
self.ConfigureForModule(context, binary.compiler)
|
||||
return self.AddVersioning(binary)
|
||||
|
||||
def MetaModule(self, context, name):
|
||||
if builder.target_platform == 'mac' or builder.target_platform == 'windows':
|
||||
name = name + '_amxx'
|
||||
elif builder.target_platform == 'linux':
|
||||
name = name + '_amxx_i386'
|
||||
binary = context.compiler.Library(name)
|
||||
self.ConfigureForModule(context, binary.compiler)
|
||||
return self.AddVersioning(binary)
|
||||
|
||||
def Program(self, context, name):
|
||||
binary = context.compiler.Program(name)
|
||||
return self.AddVersioning(binary)
|
||||
|
||||
def AddAssembly(self, context, binary, input_file, output_file, includes=[], extra_argv=[]):
|
||||
if builder.target_platform == 'windows':
|
||||
obj_type = 'win32'
|
||||
elif builder.target_platform == 'linux':
|
||||
obj_type = 'elf32'
|
||||
elif builder.target_platform == 'mac':
|
||||
obj_type = 'macho32'
|
||||
|
||||
input_path = os.path.join(context.currentSourcePath, input_file)
|
||||
output_path = output_file
|
||||
|
||||
argv = [
|
||||
self.nasm_path,
|
||||
'-I{0}{1}'.format(context.currentSourcePath, os.sep),
|
||||
input_path,
|
||||
'-f', obj_type,
|
||||
'-o', output_path,
|
||||
] + extra_argv
|
||||
|
||||
extra_includes = []
|
||||
for include_file in includes:
|
||||
extra_includes.append(os.path.join(context.currentSourcePath, include_file))
|
||||
|
||||
cmd_node, output_nodes = context.AddCommand(
|
||||
inputs = [input_path] + extra_includes,
|
||||
argv = argv,
|
||||
outputs = [output_path])
|
||||
|
||||
binary.compiler.linkflags += [output_nodes[0]]
|
||||
|
||||
AMXX = AMXXConfig()
|
||||
AMXX.detectProductVersion()
|
||||
AMXX.detectMetamod()
|
||||
AMXX.detectHlsdk()
|
||||
AMXX.detectMysql()
|
||||
AMXX.detectNASM()
|
||||
AMXX.configure()
|
||||
|
||||
if AMXX.use_auto_versioning():
|
||||
AMXX.generated_headers = builder.RunScript(
|
||||
'support/Versioning',
|
||||
{ 'AMXX': AMXX }
|
||||
)
|
||||
AMXX.versionlib = builder.RunScript(
|
||||
'support/versionlib/AMBuilder',
|
||||
{ 'AMXX': AMXX }
|
||||
)
|
||||
|
||||
AMXX.zlib = builder.RunScript(
|
||||
'third_party/zlib/AMBuilder'
|
||||
)
|
||||
|
||||
AMXX.hashing = builder.RunScript(
|
||||
'third_party/hashing/AMBuilder'
|
||||
)
|
||||
|
||||
AMXX.utf8rewind = builder.RunScript(
|
||||
'third_party/utf8rewind/AMBuilder'
|
||||
)
|
||||
|
||||
builder.RunBuildScripts(
|
||||
[
|
||||
'amxmodx/AMBuilder',
|
||||
'compiler/amxxpc/AMBuilder',
|
||||
'compiler/libpc300/AMBuilder',
|
||||
'modules/cstrike/cstrike/AMBuilder',
|
||||
'modules/cstrike/csx/AMBuilder',
|
||||
'modules/dod/dodfun/AMBuilder',
|
||||
'modules/dod/dodx/AMBuilder',
|
||||
'modules/engine/AMBuilder',
|
||||
'modules/fakemeta/AMBuilder',
|
||||
'modules/fun/AMBuilder',
|
||||
'modules/geoip/AMBuilder',
|
||||
'modules/hamsandwich/AMBuilder',
|
||||
'modules/json/AMBuilder',
|
||||
'modules/mysqlx/AMBuilder',
|
||||
'modules/ns/AMBuilder',
|
||||
'modules/nvault/AMBuilder',
|
||||
'modules/regex/AMBuilder',
|
||||
'modules/sockets/AMBuilder',
|
||||
'modules/sqlite/AMBuilder',
|
||||
'modules/tfcx/AMBuilder',
|
||||
'modules/ts/tsfun/AMBuilder',
|
||||
'modules/ts/tsx/AMBuilder',
|
||||
],
|
||||
{ 'AMXX': AMXX }
|
||||
)
|
||||
|
||||
# The csstats.dat reader is Windows-only.
|
||||
if builder.target_platform == 'windows':
|
||||
builder.RunScript('modules/cstrike/csx/WinCSX/AMBuilder', { 'AMXX': AMXX })
|
||||
|
||||
if builder.backend == 'amb2':
|
||||
builder.RunBuildScripts([
|
||||
'plugins/AMBuilder',
|
||||
'support/PackageScript',
|
||||
],
|
||||
{ 'AMXX': AMXX }
|
||||
)
|
||||
|
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/alliedmodders/amxmodx/blob/master/editor/studio/AMXXLarge.bmp"/>
|
||||
</p>
|
||||
|
||||
**AMX Mod X** is a [Metamod](https://github.com/jkivilin/metamod-p) plugin for [Half-Life 1](https://github.com/ValveSoftware/halflife). It provides comprehensive scripting for the game engine and its mods. Scripts can intercept network messages, log events, commands, client commands, set cvars, modify entities, and more. AMX Mod X also has a system for extending native scripting through modules, leading to outside support for things like MySQL and Sockets.
|
||||
|
||||
General
|
||||
-------
|
||||
- [AMXX website](https://amxmodx.org/)
|
||||
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=3): Discussion forum including plugin/extension development
|
||||
- [General documentation](https://wiki.alliedmods.net/Category:Documentation_%28AMX_Mod_X%29): Miscellaneous information about AMXX
|
||||
- [Latest release](https://amxmodx.org/downloads.php): The latest stable AMXX release
|
||||
- [Build snapshots](https://www.amxmodx.org/downloads-new.php): Builds of recent development versions
|
||||
|
||||
Development
|
||||
-----------
|
||||
- [Issue tracker](https://github.com/alliedmodders/amxmodx/issues): Issues that require back and forth communication
|
||||
- [Issue archive](https://bugs.alliedmods.net/describecomponents.cgi?product=AMX%20Mod%20X): Old issue tracker (read-only)
|
||||
- [Building AMXX](https://wiki.alliedmods.net/Building_AMX_Mod_X): Instructions on how to build AMXX itself using [AMBuild](https://github.com/alliedmodders/ambuild)
|
||||
- [AMX Mod X API](https://amxmodx.org/api/): AMX Mod X API reference generated from include files
|
||||
- [AMXX scripting](https://wiki.alliedmods.net/Category:Scripting_(AMX_Mod_X)): Pawn examples and introduction to the language
|
101
amxmodx/AMBuilder
Normal file
101
amxmodx/AMBuilder
Normal file
@ -0,0 +1,101 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os.path
|
||||
|
||||
binary = AMXX.MetaPlugin(builder, 'amxmodx')
|
||||
|
||||
binary.compiler.defines += [
|
||||
'JIT',
|
||||
'ASM32',
|
||||
'HAVE_STDINT_H',
|
||||
]
|
||||
|
||||
AMXX.AddAssembly(builder, binary, 'helpers-x86.asm', 'helpers-asm.obj')
|
||||
AMXX.AddAssembly(builder, binary, 'natives-x86.asm', 'natives-asm.obj')
|
||||
AMXX.AddAssembly(builder, binary, 'amxexecn.asm', 'amxexecn-asm.obj',
|
||||
includes=['amxdefn.asm'])
|
||||
AMXX.AddAssembly(builder, binary, 'amxjitsn.asm', 'amxjitsn-asm.obj',
|
||||
includes=['amxdefn.asm'],
|
||||
# Opcode sizes must be maximum width for patching to work.
|
||||
extra_argv=['-O0'])
|
||||
|
||||
if builder.target_platform == 'mac':
|
||||
binary.compiler.postlink += [
|
||||
'-Wl,-read_only_relocs,suppress'
|
||||
]
|
||||
elif builder.target_platform == 'windows':
|
||||
binary.compiler.linkflags += [
|
||||
'/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1',
|
||||
'/SECTION:.data,RW',
|
||||
]
|
||||
elif builder.target_platform == 'linux':
|
||||
binary.compiler.postlink += [
|
||||
binary.Dep(AMXX.stdcxx_path),
|
||||
]
|
||||
|
||||
binary.compiler.linkflags += [AMXX.zlib.binary, AMXX.hashing.binary, AMXX.utf8rewind.binary]
|
||||
|
||||
binary.sources = [
|
||||
'meta_api.cpp',
|
||||
'CVault.cpp',
|
||||
'vault.cpp',
|
||||
'float.cpp',
|
||||
'file.cpp',
|
||||
'modules.cpp',
|
||||
'CMisc.cpp',
|
||||
'CTask.cpp',
|
||||
'string.cpp',
|
||||
'amxmodx.cpp',
|
||||
'CEvent.cpp',
|
||||
'CCmd.cpp',
|
||||
'CLogEvent.cpp',
|
||||
'srvcmd.cpp',
|
||||
'strptime.cpp',
|
||||
'amxcore.cpp',
|
||||
'amxtime.cpp',
|
||||
'power.cpp',
|
||||
'amxxlog.cpp',
|
||||
'fakemeta.cpp',
|
||||
'amxxfile.cpp',
|
||||
'CLang.cpp',
|
||||
'emsg.cpp',
|
||||
'CForward.cpp',
|
||||
'CPlugin.cpp',
|
||||
'CModule.cpp',
|
||||
'CMenu.cpp',
|
||||
'util.cpp',
|
||||
'amx.cpp',
|
||||
'amxdbg.cpp',
|
||||
'natives.cpp',
|
||||
'newmenus.cpp',
|
||||
'debugger.cpp',
|
||||
'optimizer.cpp',
|
||||
'format.cpp',
|
||||
'messages.cpp',
|
||||
'libraries.cpp',
|
||||
'vector.cpp',
|
||||
'sorting.cpp',
|
||||
'nongpl_matches.cpp',
|
||||
'CFlagManager.cpp',
|
||||
'datastructs.cpp',
|
||||
'trie_natives.cpp',
|
||||
'CDataPack.cpp',
|
||||
'datapacks.cpp',
|
||||
'stackstructs.cpp',
|
||||
'CTextParsers.cpp',
|
||||
'textparse.cpp',
|
||||
'CvarManager.cpp',
|
||||
'cvars.cpp',
|
||||
'../public/memtools/MemoryUtils.cpp',
|
||||
'../public/memtools/CDetour/detours.cpp',
|
||||
'../public/memtools/CDetour/asm/asm.c',
|
||||
'../public/resdk/mod_rehlds_api.cpp',
|
||||
'CLibrarySys.cpp',
|
||||
'CGameConfigs.cpp',
|
||||
'gameconfigs.cpp',
|
||||
'CoreConfig.cpp',
|
||||
]
|
||||
|
||||
if builder.target_platform == 'windows':
|
||||
binary.sources += ['version.rc']
|
||||
|
||||
AMXX.binaries += [builder.Add(binary)]
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CCmd.h"
|
||||
@ -52,19 +30,20 @@ CmdMngr::CmdMngr()
|
||||
}
|
||||
|
||||
CmdMngr::Command::Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags,
|
||||
int pfunc, bool pviewable, CmdMngr* pparent) : commandline(pcmd), info(pinfo)
|
||||
int pfunc, bool pviewable, bool pinfo_ml, CmdMngr* pparent) : commandline(pcmd), info(pinfo)
|
||||
{
|
||||
char szCmd[64], szArg[64];
|
||||
*szCmd = 0; *szArg = 0;
|
||||
sscanf(pcmd, "%s %s", szCmd, szArg);
|
||||
command.assign(szCmd);
|
||||
argument.assign(szArg);
|
||||
command = szCmd;
|
||||
argument = szArg;
|
||||
plugin = pplugin;
|
||||
flags = pflags;
|
||||
cmdtype = 0;
|
||||
prefix = 0;
|
||||
function = pfunc;
|
||||
listable = pviewable;
|
||||
info_ml = pinfo_ml;
|
||||
parent = pparent;
|
||||
id = --uniqueid;
|
||||
}
|
||||
@ -74,9 +53,9 @@ CmdMngr::Command::~Command()
|
||||
++uniqueid;
|
||||
}
|
||||
|
||||
CmdMngr::Command* CmdMngr::registerCommand(CPluginMngr::CPlugin* plugin, int func, char* cmd, char* info, int level, bool listable)
|
||||
CmdMngr::Command* CmdMngr::registerCommand(CPluginMngr::CPlugin* plugin, int func, const char* cmd, const char* info, int level, bool listable, bool info_ml)
|
||||
{
|
||||
Command* b = new Command(plugin, cmd, info, level, func, listable, this);
|
||||
Command* b = new Command(plugin, cmd, info, level, func, listable, info_ml, this);
|
||||
if (b == 0) return 0;
|
||||
setCmdLink(&sortedlists[0], b);
|
||||
|
||||
@ -124,8 +103,6 @@ CmdMngr::Command* CmdMngr::getCmd(long int id, int type, int access)
|
||||
|
||||
int CmdMngr::getCmdNum(int type, int access)
|
||||
{
|
||||
if ((access == buf_access) && (type == buf_type))
|
||||
return buf_num; // once calculated don't have to be done again
|
||||
|
||||
buf_access = access;
|
||||
buf_type = type;
|
||||
@ -155,7 +132,7 @@ void CmdMngr::setCmdLink(CmdLink** a, Command* c, bool sorted)
|
||||
{
|
||||
int i = strcmp(c->getCommand(), (*a)->cmd->getCommand());
|
||||
|
||||
if ((i < 0) || (i == 0) && (strcmp(c->getArgument(), (*a)->cmd->getArgument()) < 0))
|
||||
if ((i < 0) || ((i == 0) && (strcmp(c->getArgument(), (*a)->cmd->getArgument()) < 0)))
|
||||
break;
|
||||
|
||||
a = &(*a)->next;
|
||||
@ -224,7 +201,7 @@ bool CmdMngr::registerCmdPrefix(Command* cc)
|
||||
if (*b)
|
||||
{
|
||||
setCmdLink(&(*b)->list, cc, false);
|
||||
cc->prefix = (*b)->name.size();
|
||||
cc->prefix = (*b)->name.length();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -246,7 +223,7 @@ CmdMngr::CmdPrefix** CmdMngr::findPrefix(const char* nn)
|
||||
|
||||
while (*aa)
|
||||
{
|
||||
if (!strncmp((*aa)->name.c_str(), nn, (*aa)->name.size()))
|
||||
if (!strncmp((*aa)->name.chars(), nn, (*aa)->name.length()))
|
||||
break;
|
||||
aa = &(*aa)->next;
|
||||
}
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
@ -55,11 +33,12 @@ public:
|
||||
|
||||
CPluginMngr::CPlugin* plugin;
|
||||
CmdMngr* parent;
|
||||
String command;
|
||||
String argument;
|
||||
String commandline;
|
||||
String info;
|
||||
ke::AString command;
|
||||
ke::AString argument;
|
||||
ke::AString commandline;
|
||||
ke::AString info;
|
||||
|
||||
bool info_ml;
|
||||
bool listable;
|
||||
int function;
|
||||
int flags;
|
||||
@ -68,19 +47,20 @@ public:
|
||||
int prefix;
|
||||
static int uniqueid;
|
||||
|
||||
Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags, int pfunc, bool pviewable, CmdMngr* pparent);
|
||||
Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags, int pfunc, bool pviewable, bool pinfo_ml, CmdMngr* pparent);
|
||||
~Command();
|
||||
public:
|
||||
inline const char* getCommand() { return command.c_str(); }
|
||||
inline const char* getArgument() { return argument.c_str(); }
|
||||
inline const char* getCmdInfo() { return info.c_str(); }
|
||||
inline const char* getCmdLine() { return commandline.c_str(); }
|
||||
inline bool matchCommandLine(const char* cmd, const char* arg) { return (!stricmp(command.c_str() + prefix, cmd + prefix) && (argument.empty() || !stricmp(argument.c_str(), arg))); }
|
||||
inline bool matchCommand(const char* cmd) { return (!strcmp(command.c_str(), cmd)); }
|
||||
inline const char* getCommand() { return command.chars(); }
|
||||
inline const char* getArgument() { return argument.chars(); }
|
||||
inline const char* getCmdInfo() { return info.chars(); }
|
||||
inline const char* getCmdLine() { return commandline.chars(); }
|
||||
inline bool matchCommandLine(const char* cmd, const char* arg) {return (!stricmp(command.chars() + prefix, cmd + prefix) && (!argument.length() || !stricmp(argument.chars(), arg)));}
|
||||
inline bool matchCommand(const char* cmd) { return (!stricmp(command.chars(), cmd)); }
|
||||
inline int getFunction() const { return function; }
|
||||
inline bool gotAccess(int f) const { return (!flags || ((flags & f) == flags)); }
|
||||
inline bool gotAccess(int f) const { return (!flags || ((flags & f) != 0)); }
|
||||
inline CPluginMngr::CPlugin* getPlugin() { return plugin; }
|
||||
inline bool isViewable() const { return listable; }
|
||||
inline bool isInfoML() const { return info_ml; }
|
||||
inline int getFlags() const { return flags; }
|
||||
inline long int getId() const { return (long int)id; }
|
||||
|
||||
@ -105,7 +85,7 @@ private:
|
||||
|
||||
struct CmdPrefix
|
||||
{
|
||||
String name;
|
||||
ke::AString name;
|
||||
CmdMngr* parent;
|
||||
CmdLink* list;
|
||||
CmdPrefix* next;
|
||||
@ -128,7 +108,7 @@ public:
|
||||
|
||||
void registerPrefix(const char* nn);
|
||||
|
||||
Command* registerCommand(CPluginMngr::CPlugin* plugin, int func, char* cmd, char* info, int level, bool listable);
|
||||
Command* registerCommand(CPluginMngr::CPlugin* plugin, int func, const char* cmd, const char* info, int level, bool listable, bool info_ml);
|
||||
Command* getCmd(long int id, int type, int access);
|
||||
int getCmdNum(int type, int access);
|
||||
|
||||
|
340
amxmodx/CDataPack.cpp
Normal file
340
amxmodx/CDataPack.cpp
Normal file
@ -0,0 +1,340 @@
|
||||
/**
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "CDataPack.h"
|
||||
|
||||
#define DATAPACK_INITIAL_SIZE 64
|
||||
|
||||
CDataPack::CDataPack()
|
||||
{
|
||||
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
|
||||
m_capacity = DATAPACK_INITIAL_SIZE;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CDataPack::~CDataPack()
|
||||
{
|
||||
free(m_pBase);
|
||||
}
|
||||
|
||||
void CDataPack::Initialize()
|
||||
{
|
||||
m_curptr = m_pBase;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void CDataPack::CheckSize(size_t typesize)
|
||||
{
|
||||
if (m_curptr - m_pBase + typesize <= m_capacity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
do
|
||||
{
|
||||
m_capacity *= 2;
|
||||
} while (pos + typesize > m_capacity);
|
||||
|
||||
m_pBase = (char *)realloc(m_pBase, m_capacity);
|
||||
m_curptr = m_pBase + pos;
|
||||
}
|
||||
|
||||
void CDataPack::ResetSize()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
{
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + size);
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
|
||||
*(char *)m_curptr = Raw;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = size;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
if (addr)
|
||||
{
|
||||
*addr = m_curptr;
|
||||
}
|
||||
|
||||
m_curptr += size;
|
||||
m_size += sizeof(char) + sizeof(size_t) + size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void CDataPack::PackCell(cell cells)
|
||||
{
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell));
|
||||
|
||||
*(char *)m_curptr = DataPackType::Cell;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(cell *)m_curptr = cells;
|
||||
m_curptr += sizeof(cell);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell);
|
||||
}
|
||||
|
||||
void CDataPack::PackFloat(float val)
|
||||
{
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
|
||||
|
||||
*(char *)m_curptr = DataPackType::Float;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(float);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(float *)m_curptr = val;
|
||||
m_curptr += sizeof(float);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
|
||||
}
|
||||
|
||||
void CDataPack::PackString(const char *string)
|
||||
{
|
||||
size_t len = strlen(string);
|
||||
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
|
||||
CheckSize(maxsize);
|
||||
|
||||
*(char *)m_curptr = DataPackType::String;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
// Pack the string length first for buffer overrun checking.
|
||||
*(size_t *)m_curptr = len;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
// Now pack the string.
|
||||
memcpy(m_curptr, string, len);
|
||||
m_curptr[len] = '\0';
|
||||
m_curptr += len + 1;
|
||||
|
||||
m_size += maxsize;
|
||||
}
|
||||
|
||||
void CDataPack::Reset() const
|
||||
{
|
||||
m_curptr = m_pBase;
|
||||
}
|
||||
|
||||
size_t CDataPack::GetPosition() const
|
||||
{
|
||||
return static_cast<size_t>(m_curptr - m_pBase);
|
||||
}
|
||||
|
||||
bool CDataPack::SetPosition(size_t pos) const
|
||||
{
|
||||
if (pos > m_size-1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_curptr = m_pBase + pos;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDataPack::CanReadCell() const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Cell)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<size_t *>(m_curptr + sizeof(char)) != sizeof(cell))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cell CDataPack::ReadCell() const
|
||||
{
|
||||
if (!CanReadCell())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(char);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
cell val = *reinterpret_cast<cell *>(m_curptr);
|
||||
m_curptr += sizeof(cell);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool CDataPack::CanReadFloat() const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Float)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<size_t *>(m_curptr + sizeof(char)) != sizeof(float))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float CDataPack::ReadFloat() const
|
||||
{
|
||||
if (!CanReadFloat())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(char);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
float val = *reinterpret_cast<float *>(m_curptr);
|
||||
m_curptr += sizeof(float);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool CDataPack::IsReadable(size_t bytes) const
|
||||
{
|
||||
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
|
||||
}
|
||||
|
||||
bool CDataPack::CanReadString(size_t *len) const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::String)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t real_len = *(size_t *)(m_curptr + sizeof(char));
|
||||
char *str = (char *)(m_curptr + sizeof(char) + sizeof(size_t));
|
||||
|
||||
if ((strlen(str) != real_len) || !(IsReadable(sizeof(char) + sizeof(size_t) + real_len + 1)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
*len = real_len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *CDataPack::ReadString(size_t *len) const
|
||||
{
|
||||
size_t real_len;
|
||||
if (!CanReadString(&real_len))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(char);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
char *str = (char *)m_curptr;
|
||||
m_curptr += real_len + 1;
|
||||
|
||||
if (len)
|
||||
{
|
||||
*len = real_len;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void *CDataPack::GetMemory() const
|
||||
{
|
||||
return m_curptr;
|
||||
}
|
||||
|
||||
bool CDataPack::CanReadMemory(size_t *size) const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Raw)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t bytecount = *(size_t *)(m_curptr + sizeof(char));
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + bytecount))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = bytecount;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *CDataPack::ReadMemory(size_t *size) const
|
||||
{
|
||||
size_t bytecount;
|
||||
if (!CanReadMemory(&bytecount))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(char);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
void *ptr = m_curptr;
|
||||
m_curptr += bytecount;
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = bytecount;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
181
amxmodx/CDataPack.h
Normal file
181
amxmodx/CDataPack.h
Normal file
@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "natives_handles.h"
|
||||
|
||||
/**
|
||||
* @brief Contains functions for packing data abstractly to/from plugins.
|
||||
*/
|
||||
class CDataPack
|
||||
{
|
||||
public:
|
||||
CDataPack();
|
||||
~CDataPack();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Resets the position in the data stream to the beginning.
|
||||
*/
|
||||
void Reset() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the current stream position.
|
||||
*
|
||||
* @return Index into the stream.
|
||||
*/
|
||||
size_t GetPosition() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the current stream position.
|
||||
*
|
||||
* @param pos Index to set the stream at.
|
||||
* @return True if succeeded, false if out of bounds.
|
||||
*/
|
||||
bool SetPosition(size_t pos) const;
|
||||
|
||||
/**
|
||||
* @brief Reads one cell from the data stream.
|
||||
*
|
||||
* @return A cell read from the current position.
|
||||
*/
|
||||
cell ReadCell() const;
|
||||
|
||||
/**
|
||||
* @brief Reads one float from the data stream.
|
||||
*
|
||||
* @return A float read from the current position.
|
||||
*/
|
||||
float ReadFloat() const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether or not a specified number of bytes from the current stream
|
||||
* position to the end can be read.
|
||||
*
|
||||
* @param bytes Number of bytes to simulate reading.
|
||||
* @return True if can be read, false otherwise.
|
||||
*/
|
||||
bool IsReadable(size_t bytes) const;
|
||||
|
||||
/**
|
||||
* @brief Reads a string from the data stream.
|
||||
*
|
||||
* @param len Optional pointer to store the string length.
|
||||
* @return Pointer to the string, or NULL if out of bounds.
|
||||
*/
|
||||
const char *ReadString(size_t *len) const;
|
||||
|
||||
/**
|
||||
* @brief Reads the current position as a generic address.
|
||||
*
|
||||
* @return Pointer to the memory.
|
||||
*/
|
||||
void *GetMemory() const;
|
||||
|
||||
/**
|
||||
* @brief Reads the current position as a generic data type.
|
||||
*
|
||||
* @param size Optional pointer to store the size of the data type.
|
||||
* @return Pointer to the data, or NULL if out of bounds.
|
||||
*/
|
||||
void *ReadMemory(size_t *size) const;
|
||||
|
||||
bool CanReadCell() const;
|
||||
bool CanReadFloat() const;
|
||||
bool CanReadString(size_t *len) const;
|
||||
bool CanReadMemory(size_t *size) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Resets the used size of the stream back to zero.
|
||||
*/
|
||||
void ResetSize();
|
||||
|
||||
/**
|
||||
* @brief Packs one cell into the data stream.
|
||||
*
|
||||
* @param cell Cell value to write.
|
||||
*/
|
||||
void PackCell(cell cells);
|
||||
|
||||
/**
|
||||
* @brief Packs one float into the data stream.
|
||||
*
|
||||
* @param val Float value to write.
|
||||
*/
|
||||
void PackFloat(float val);
|
||||
|
||||
/**
|
||||
* @brief Packs one string into the data stream.
|
||||
* The length is recorded as well for buffer overrun protection.
|
||||
*
|
||||
* @param string String to write.
|
||||
*/
|
||||
void PackString(const char *string);
|
||||
|
||||
/**
|
||||
* @brief Creates a generic block of memory in the stream.
|
||||
*
|
||||
* Note that the pointer it returns can be invalidated on further
|
||||
* writing, since the stream size may grow. You may need to double back
|
||||
* and fetch the pointer again.
|
||||
*
|
||||
* @param size Size of the memory to create in the stream.
|
||||
* @param addr Optional pointer to store the relocated memory address.
|
||||
* @return Current position of the stream beforehand.
|
||||
*/
|
||||
size_t CreateMemory(size_t size, void **addr);
|
||||
|
||||
public:
|
||||
void Initialize();
|
||||
|
||||
private:
|
||||
void CheckSize(size_t sizetype);
|
||||
|
||||
private:
|
||||
char *m_pBase;
|
||||
mutable char *m_curptr;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
|
||||
enum DataPackType {
|
||||
Raw,
|
||||
Cell,
|
||||
Float,
|
||||
String,
|
||||
};
|
||||
};
|
||||
|
||||
extern NativeHandle<CDataPack> DataPackHandles;
|
||||
extern AMX_NATIVE_INFO g_DatapackNatives[];
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CEvent.h"
|
||||
@ -36,6 +14,8 @@
|
||||
// class ClEvent
|
||||
// *****************************************************
|
||||
|
||||
NativeHandle<EventHook> EventHandles;
|
||||
|
||||
EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
|
||||
{
|
||||
m_Plugin = plugin;
|
||||
@ -46,7 +26,7 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
|
||||
m_FlagDead = true;
|
||||
|
||||
m_FlagWorld = (flags & 1) ? true : false; // flag a
|
||||
m_FlagPlayer = (flags & 2) ? true : false; // flag b
|
||||
m_FlagClient = (flags & 2) ? true : false; // flag b
|
||||
m_FlagOnce = (flags & 4) ? true : false; // flag c
|
||||
|
||||
if (flags & 24)
|
||||
@ -55,8 +35,21 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
|
||||
m_FlagDead = (flags & 8) ? true : false; // flag d
|
||||
}
|
||||
|
||||
if (m_FlagClient)
|
||||
{
|
||||
m_FlagPlayer = true;
|
||||
m_FlagBot = true;
|
||||
|
||||
if (flags & 96)
|
||||
{
|
||||
m_FlagPlayer = (flags & 32) ? true : false; // flag f
|
||||
m_FlagBot = (flags & 64) ? true : false; // flag g
|
||||
}
|
||||
}
|
||||
|
||||
m_Stamp = 0.0f;
|
||||
m_Done = false;
|
||||
m_State = FSTATE_ACTIVE;
|
||||
|
||||
m_Conditions = NULL;
|
||||
}
|
||||
@ -126,7 +119,11 @@ EventsMngr::EventsMngr()
|
||||
{
|
||||
m_ParseVault = NULL;
|
||||
m_ParseVaultSize = 0;
|
||||
m_CurrentMsgType = -1;
|
||||
m_ParseMsgType = -1;
|
||||
m_ReadVault = NULL;
|
||||
m_ReadVaultSize = 0;
|
||||
m_ReadPos = -1;
|
||||
m_ReadMsgType = -1;
|
||||
clearEvents();
|
||||
}
|
||||
|
||||
@ -175,7 +172,7 @@ void EventsMngr::ClEvent::registerFilter(char *filter)
|
||||
tmpCond->paramId = atoi(filter);
|
||||
|
||||
// rest of line
|
||||
tmpCond->sValue.assign(value);
|
||||
tmpCond->sValue = value;
|
||||
tmpCond->fValue = static_cast<float>(atof(value));
|
||||
tmpCond->iValue = atoi(value);
|
||||
|
||||
@ -194,20 +191,31 @@ void EventsMngr::ClEvent::registerFilter(char *filter)
|
||||
m_Conditions = tmpCond;
|
||||
}
|
||||
|
||||
EventsMngr::ClEvent* EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid)
|
||||
void EventsMngr::ClEvent::setForwardState(ForwardState state)
|
||||
{
|
||||
m_State = state;
|
||||
}
|
||||
|
||||
|
||||
int EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid)
|
||||
{
|
||||
// validate parameter
|
||||
if (msgid < 0 || msgid >= MAX_AMX_REG_MSG)
|
||||
return NULL;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClEvent *event = new ClEvent(plugin, func, flags);
|
||||
auto event = ke::AutoPtr<ClEvent>(new ClEvent(plugin, func, flags));
|
||||
|
||||
int handle = EventHandles.create(event.get());
|
||||
|
||||
if (!event)
|
||||
return NULL;
|
||||
if (!handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_Events[msgid].put(event);
|
||||
m_Events[msgid].append(ke::Move(event));
|
||||
|
||||
return event;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index)
|
||||
@ -215,43 +223,43 @@ void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int in
|
||||
if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG)
|
||||
return;
|
||||
|
||||
m_CurrentMsgType = msg_type;
|
||||
|
||||
m_ParseNotDone = false;
|
||||
m_Timer = timer;
|
||||
|
||||
// don't parse if nothing to do
|
||||
if (!m_Events[msg_type].size())
|
||||
if (!m_Events[msg_type].length())
|
||||
return;
|
||||
|
||||
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
|
||||
m_ParseMsgType = msg_type;
|
||||
m_Timer = timer;
|
||||
|
||||
for (auto &event : m_Events[msg_type])
|
||||
{
|
||||
if ((*iter).m_Done)
|
||||
if (event->m_Done)
|
||||
continue;
|
||||
|
||||
if (!(*iter).m_Plugin->isExecutable((*iter).m_Func))
|
||||
if (!event->m_Plugin->isExecutable(event->m_Func))
|
||||
{
|
||||
(*iter).m_Done = true;
|
||||
event->m_Done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pPlayer)
|
||||
{
|
||||
if (!(*iter).m_FlagPlayer || (pPlayer->IsAlive() ? !(*iter).m_FlagAlive : !(*iter).m_FlagDead))
|
||||
if (!event->m_FlagClient || (pPlayer->IsBot() ? !event->m_FlagBot : !event->m_FlagPlayer) || (pPlayer->IsAlive() ? !event->m_FlagAlive : !event->m_FlagDead))
|
||||
{
|
||||
(*iter).m_Done = true;
|
||||
event->m_Done = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!(*iter).m_FlagWorld)
|
||||
else if (!event->m_FlagWorld)
|
||||
{
|
||||
(*iter).m_Done = true;
|
||||
event->m_Done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*iter).m_FlagOnce && (*iter).m_Stamp == (float)(*timer))
|
||||
if (event->m_FlagOnce && event->m_Stamp == *timer)
|
||||
{
|
||||
(*iter).m_Done = true;
|
||||
event->m_Done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -284,16 +292,16 @@ void EventsMngr::parseValue(int iValue)
|
||||
|
||||
// loop through the registered funcs, and decide whether they have to be called or not
|
||||
// if they shouldnt, their m_Done is set to true
|
||||
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
|
||||
for (auto &event : *m_ParseFun)
|
||||
{
|
||||
if ((*iter).m_Done)
|
||||
if (event->m_Done)
|
||||
continue; // already skipped; don't bother with parsing
|
||||
|
||||
// loop through conditions
|
||||
bool execute = false;
|
||||
bool anyConditions = false;
|
||||
|
||||
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
|
||||
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
|
||||
{
|
||||
if (condIter->paramId == m_ParsePos)
|
||||
{
|
||||
@ -312,7 +320,7 @@ void EventsMngr::parseValue(int iValue)
|
||||
}
|
||||
|
||||
if (anyConditions && !execute)
|
||||
(*iter).m_Done = true; // don't execute
|
||||
event->m_Done = true; // don't execute
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,16 +339,16 @@ void EventsMngr::parseValue(float fValue)
|
||||
|
||||
// loop through the registered funcs, and decide whether they have to be called or not
|
||||
// if they shouldnt, their m_Done is set to true
|
||||
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
|
||||
for (auto &event : *m_ParseFun)
|
||||
{
|
||||
if ((*iter).m_Done)
|
||||
if (event->m_Done)
|
||||
continue; // already skipped; don't bother with parsing
|
||||
|
||||
// loop through conditions
|
||||
bool execute = false;
|
||||
bool anyConditions = false;
|
||||
|
||||
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
|
||||
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
|
||||
{
|
||||
if (condIter->paramId == m_ParsePos)
|
||||
{
|
||||
@ -359,7 +367,7 @@ void EventsMngr::parseValue(float fValue)
|
||||
}
|
||||
|
||||
if (anyConditions && !execute)
|
||||
(*iter).m_Done = true; // don't execute
|
||||
event->m_Done = true; // don't execute
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,25 +386,25 @@ void EventsMngr::parseValue(const char *sz)
|
||||
|
||||
// loop through the registered funcs, and decide whether they have to be called or not
|
||||
// if they shouldnt, their m_Done is set to true
|
||||
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
|
||||
for (auto &event : *m_ParseFun)
|
||||
{
|
||||
if ((*iter).m_Done)
|
||||
if (event->m_Done)
|
||||
continue; // already skipped; don't bother with parsing
|
||||
|
||||
// loop through conditions
|
||||
bool execute = false;
|
||||
bool anyConditions = false;
|
||||
|
||||
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
|
||||
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
|
||||
{
|
||||
if (condIter->paramId == m_ParsePos)
|
||||
{
|
||||
anyConditions = true;
|
||||
switch (condIter->type)
|
||||
{
|
||||
case '=': if (!strcmp(sz, condIter->sValue.c_str())) execute = true; break;
|
||||
case '!': if (strcmp(sz, condIter->sValue.c_str())) execute = true; break;
|
||||
case '&': if (strstr(sz, condIter->sValue.c_str())) execute = true; break;
|
||||
case '=': if (!strcmp(sz, condIter->sValue.chars())) execute = true; break;
|
||||
case '!': if (strcmp(sz, condIter->sValue.chars())) execute = true; break;
|
||||
case '&': if (strstr(sz, condIter->sValue.chars())) execute = true; break;
|
||||
}
|
||||
|
||||
if (execute)
|
||||
@ -405,87 +413,134 @@ void EventsMngr::parseValue(const char *sz)
|
||||
}
|
||||
|
||||
if (anyConditions && !execute)
|
||||
(*iter).m_Done = true; // don't execute
|
||||
event->m_Done = true; // don't execute
|
||||
}
|
||||
}
|
||||
|
||||
void EventsMngr::executeEvents()
|
||||
{
|
||||
static unsigned int reentrant = 0;
|
||||
if (!m_ParseFun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
|
||||
// Store old read data, which are either default values or previous event data
|
||||
int oldMsgType = m_ReadMsgType, oldReadPos = m_ReadPos;
|
||||
MsgDataEntry *oldReadVault = m_ReadVault, *readVault = NULL;
|
||||
|
||||
// We have a re-entrant call
|
||||
if (reentrant++)
|
||||
{
|
||||
if ((*iter).m_Done)
|
||||
// Create temporary read vault
|
||||
readVault = new MsgDataEntry[m_ParsePos + 1];
|
||||
m_ReadVault = readVault;
|
||||
} else if (m_ReadVaultSize != m_ParseVaultSize) {
|
||||
// Extend read vault size if necessary
|
||||
delete [] m_ReadVault;
|
||||
m_ReadVault = new MsgDataEntry[m_ParseVaultSize];
|
||||
m_ReadVaultSize = m_ParseVaultSize;
|
||||
|
||||
// Update old read vault so we don't restore to a wrong pointer
|
||||
oldReadVault = m_ReadVault;
|
||||
}
|
||||
|
||||
// Copy data over to readvault
|
||||
m_ReadPos = m_ParsePos;
|
||||
m_ReadMsgType = m_ParseMsgType;
|
||||
|
||||
if (m_ParseVault)
|
||||
{
|
||||
memcpy(m_ReadVault, m_ParseVault, (m_ParsePos + 1) * sizeof(MsgDataEntry));
|
||||
}
|
||||
|
||||
// Reset this here so we don't trigger re-entrancy for unregistered messages
|
||||
auto parseFun = m_ParseFun;
|
||||
m_ParseFun = nullptr;
|
||||
|
||||
auto lastSize = parseFun->length();
|
||||
for(auto i = 0u; i < lastSize; i++)
|
||||
{
|
||||
auto &event = parseFun->at(i);
|
||||
|
||||
if (event->m_Done)
|
||||
{
|
||||
(*iter).m_Done = false;
|
||||
event->m_Done = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
(*iter).m_Stamp = (float)*m_Timer;
|
||||
executeForwards((*iter).m_Func, static_cast<cell>(m_ParseVault ? m_ParseVault[0].iValue : 0));
|
||||
}
|
||||
event->m_Stamp = *m_Timer;
|
||||
|
||||
m_CurrentMsgType = -1;
|
||||
m_ParseFun = NULL;
|
||||
if (event->m_State == FSTATE_ACTIVE)
|
||||
{
|
||||
executeForwards(event->m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
|
||||
}
|
||||
}
|
||||
|
||||
// Restore old read data, either resetting to default or to previous event data
|
||||
m_ReadMsgType = oldMsgType;
|
||||
m_ReadPos = oldReadPos;
|
||||
m_ReadVault = oldReadVault;
|
||||
|
||||
delete [] readVault;
|
||||
|
||||
--reentrant;
|
||||
}
|
||||
|
||||
int EventsMngr::getArgNum() const
|
||||
{
|
||||
return m_ParsePos + 1;
|
||||
return m_ReadPos + 1;
|
||||
}
|
||||
|
||||
const char* EventsMngr::getArgString(int a) const
|
||||
{
|
||||
if (a < 0 || a > m_ParsePos)
|
||||
if (a < 0 || a > m_ReadPos)
|
||||
return "";
|
||||
|
||||
static char var[32];
|
||||
|
||||
switch (m_ParseVault[a].type)
|
||||
switch (m_ReadVault[a].type)
|
||||
{
|
||||
case MSG_INTEGER:
|
||||
sprintf(var, "%d", m_ParseVault[a].iValue);
|
||||
sprintf(var, "%d", m_ReadVault[a].iValue);
|
||||
return var;
|
||||
case MSG_STRING:
|
||||
return m_ParseVault[a].sValue;
|
||||
return m_ReadVault[a].sValue;
|
||||
default:
|
||||
sprintf(var, "%g", m_ParseVault[a].fValue);
|
||||
sprintf(var, "%g", m_ReadVault[a].fValue);
|
||||
return var;
|
||||
}
|
||||
}
|
||||
|
||||
int EventsMngr::getArgInteger(int a) const
|
||||
{
|
||||
if (a < 0 || a > m_ParsePos)
|
||||
if (a < 0 || a > m_ReadPos)
|
||||
return 0;
|
||||
|
||||
switch (m_ParseVault[a].type)
|
||||
switch (m_ReadVault[a].type)
|
||||
{
|
||||
case MSG_INTEGER:
|
||||
return m_ParseVault[a].iValue;
|
||||
return m_ReadVault[a].iValue;
|
||||
case MSG_STRING:
|
||||
return atoi(m_ParseVault[a].sValue);
|
||||
return atoi(m_ReadVault[a].sValue);
|
||||
default:
|
||||
return (int)m_ParseVault[a].fValue;
|
||||
return (int)m_ReadVault[a].fValue;
|
||||
}
|
||||
}
|
||||
|
||||
float EventsMngr::getArgFloat(int a) const
|
||||
{
|
||||
if (a < 0 || a > m_ParsePos)
|
||||
if (a < 0 || a > m_ReadPos)
|
||||
return 0.0f;
|
||||
|
||||
switch (m_ParseVault[a].type)
|
||||
switch (m_ReadVault[a].type)
|
||||
{
|
||||
case MSG_INTEGER:
|
||||
return static_cast<float>(m_ParseVault[a].iValue);
|
||||
return static_cast<float>(m_ReadVault[a].iValue);
|
||||
case MSG_STRING:
|
||||
return static_cast<float>(atof(m_ParseVault[a].sValue));
|
||||
return static_cast<float>(atof(m_ReadVault[a].sValue));
|
||||
default:
|
||||
return m_ParseVault[a].fValue;
|
||||
return m_ReadVault[a].fValue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +550,9 @@ void EventsMngr::clearEvents(void)
|
||||
{
|
||||
m_Events[i].clear();
|
||||
}
|
||||
|
||||
|
||||
EventHandles.clear();
|
||||
|
||||
// delete parsevault
|
||||
if (m_ParseVault)
|
||||
{
|
||||
@ -503,6 +560,14 @@ void EventsMngr::clearEvents(void)
|
||||
m_ParseVault = NULL;
|
||||
m_ParseVaultSize = 0;
|
||||
}
|
||||
|
||||
if (m_ReadVault)
|
||||
{
|
||||
delete [] m_ReadVault;
|
||||
m_ReadVault = NULL;
|
||||
m_ReadVaultSize = 0;
|
||||
m_ReadPos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int EventsMngr::getEventId(const char* msg)
|
||||
@ -538,5 +603,5 @@ int EventsMngr::getEventId(const char* msg)
|
||||
|
||||
int EventsMngr::getCurrentMsgType()
|
||||
{
|
||||
return m_CurrentMsgType;
|
||||
return m_ReadMsgType;
|
||||
}
|
||||
|
@ -1,37 +1,17 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef __CEVENTS_H__
|
||||
#define __CEVENTS_H__
|
||||
|
||||
#include "natives_handles.h"
|
||||
|
||||
#define MAX_AMX_REG_MSG MAX_REG_MSGS + 16
|
||||
|
||||
enum
|
||||
@ -74,22 +54,25 @@ public:
|
||||
CPluginMngr::CPlugin *m_Plugin; // the plugin this ClEvent class is assigned to
|
||||
|
||||
// flags
|
||||
bool m_FlagPlayer;
|
||||
bool m_FlagClient;
|
||||
bool m_FlagWorld;
|
||||
bool m_FlagOnce;
|
||||
bool m_FlagDead;
|
||||
bool m_FlagAlive;
|
||||
bool m_FlagPlayer;
|
||||
bool m_FlagBot;
|
||||
|
||||
float m_Stamp; // for 'once' flag
|
||||
|
||||
bool m_Done;
|
||||
ForwardState m_State;
|
||||
|
||||
// conditions
|
||||
struct cond_t
|
||||
{
|
||||
int paramId; // the message parameter id
|
||||
|
||||
String sValue; // value (string)
|
||||
ke::AString sValue; // value (string)
|
||||
float fValue; // value (float)
|
||||
int iValue; // value (int)
|
||||
int type; // type (can be int, float, string)
|
||||
@ -107,6 +90,7 @@ public:
|
||||
inline CPluginMngr::CPlugin* getPlugin();
|
||||
inline int getFunction();
|
||||
void registerFilter(char* filter); // add a condition
|
||||
void setForwardState(ForwardState value);
|
||||
};
|
||||
|
||||
private:
|
||||
@ -119,30 +103,31 @@ private:
|
||||
};
|
||||
|
||||
MsgDataEntry *m_ParseVault;
|
||||
MsgDataEntry *m_ReadVault;
|
||||
int m_ParseVaultSize;
|
||||
int m_ReadVaultSize;
|
||||
void NextParam(); // make sure a new parameter can be added
|
||||
|
||||
typedef CList<ClEvent> ClEventVec;
|
||||
typedef ClEventVec::iterator ClEventVecIter;
|
||||
|
||||
ClEventVec m_Events[MAX_AMX_REG_MSG];
|
||||
ClEventVec *m_ParseFun; // current Event vector
|
||||
ke::Vector<ke::AutoPtr<ClEvent>> m_Events[MAX_AMX_REG_MSG];
|
||||
ke::Vector<ke::AutoPtr<ClEvent>> *m_ParseFun; // current Event vector
|
||||
|
||||
bool m_ParseNotDone;
|
||||
int m_ParsePos; // is args. num. - 1
|
||||
int m_ReadPos;
|
||||
float* m_Timer;
|
||||
|
||||
ClEvent* getValidEvent(ClEvent* a);
|
||||
|
||||
int m_CurrentMsgType;
|
||||
int m_ParseMsgType;
|
||||
int m_ReadMsgType;
|
||||
public:
|
||||
EventsMngr();
|
||||
~EventsMngr();
|
||||
|
||||
// Interface
|
||||
|
||||
ClEvent* registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid);
|
||||
|
||||
int registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid);
|
||||
|
||||
void parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index);
|
||||
void parseValue(int iValue);
|
||||
void parseValue(float fValue);
|
||||
@ -158,4 +143,12 @@ public:
|
||||
int getCurrentMsgType();
|
||||
};
|
||||
|
||||
struct EventHook
|
||||
{
|
||||
explicit EventHook(EventsMngr::ClEvent *event) : m_event(event) {}
|
||||
EventsMngr::ClEvent *m_event;
|
||||
};
|
||||
|
||||
extern NativeHandle<EventHook> EventHandles;
|
||||
|
||||
#endif //__CEVENTS_H__
|
||||
|
@ -1,126 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "amxmodx.h"
|
||||
#include "CFile.h"
|
||||
|
||||
// *****************************************************
|
||||
// class File
|
||||
// *****************************************************
|
||||
|
||||
File::File(const char* n, const char* m)
|
||||
{
|
||||
fp = fopen(n, m);
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
File::operator bool () const
|
||||
{
|
||||
return fp && !feof(fp);
|
||||
}
|
||||
|
||||
File& operator<<(File& f, const String& n)
|
||||
{
|
||||
if (f) fputs(n.c_str(), f.fp);
|
||||
return f;
|
||||
}
|
||||
|
||||
File& operator<<(File& f, const char* n)
|
||||
{
|
||||
if (f) fputs(n, f.fp);
|
||||
return f;
|
||||
}
|
||||
|
||||
File& operator<<(File& f, int n)
|
||||
{
|
||||
if (f) fprintf(f.fp, "%d", n);
|
||||
return f;
|
||||
}
|
||||
|
||||
File& operator<<(File& f, const char& c)
|
||||
{
|
||||
if (f) fputc(c, f.fp);
|
||||
return f;
|
||||
}
|
||||
|
||||
File& operator>>(File& f, String& n)
|
||||
{
|
||||
if (!f) return f;
|
||||
char temp[1024];
|
||||
fscanf(f.fp, "%s", temp);
|
||||
n.assign(temp);
|
||||
return f;
|
||||
}
|
||||
|
||||
File& operator>>(File& f, char* n)
|
||||
{
|
||||
if (f) fscanf(f.fp, "%s", n);
|
||||
return f;
|
||||
}
|
||||
|
||||
int File::getline(char* buf, int sz)
|
||||
{
|
||||
int a = sz;
|
||||
char *origBuf = buf;
|
||||
|
||||
if (*this)
|
||||
{
|
||||
int c;
|
||||
while (sz-- && (c = getc((*this).fp)) && c != EOF && c != '\n')
|
||||
*buf++ = c;
|
||||
*buf = 0;
|
||||
}
|
||||
|
||||
// trim 0x0a and 0x0d characters at the end
|
||||
while (buf != origBuf)
|
||||
{
|
||||
if (*buf == 0x0a || *buf == 0x0d)
|
||||
*buf = 0;
|
||||
--buf;
|
||||
}
|
||||
|
||||
return a - sz;
|
||||
}
|
||||
|
||||
File& File::skipWs()
|
||||
{
|
||||
if (!*this) return *this;
|
||||
int c;
|
||||
while (isspace(c = getc(fp))) {};
|
||||
ungetc(c, fp);
|
||||
return *this;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "CString.h"
|
||||
|
||||
// *****************************************************
|
||||
// class File
|
||||
// *****************************************************
|
||||
|
||||
class File
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
public:
|
||||
File(const char* n, const char* m);
|
||||
~File();
|
||||
|
||||
operator bool () const;
|
||||
|
||||
friend File& operator<<(File& f, const String& n);
|
||||
friend File& operator<<(File& f, const char* n);
|
||||
friend File& operator<<(File& f, const char& c);
|
||||
friend File& operator<<(File& f, int n);
|
||||
friend File& operator>>(File& f, String& n);
|
||||
friend File& operator>>(File& f, char* n);
|
||||
|
||||
int getline(char* buf, int sz);
|
||||
|
||||
File& skipWs();
|
||||
};
|
255
amxmodx/CFileSystem.h
Normal file
255
amxmodx/CFileSystem.h
Normal file
@ -0,0 +1,255 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_CFILESYSTEM_H_
|
||||
#define _INCLUDE_CFILESYSTEM_H_
|
||||
|
||||
#include <FileSystem.h> // IFileSystem, FileSystemSeek_t, FileHandle_t (HLSDK)
|
||||
#include <stdio.h> // FILE*
|
||||
|
||||
extern IFileSystem* g_FileSystem;
|
||||
|
||||
class ValveFile;
|
||||
class SystemFile;
|
||||
|
||||
class FileObject
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~FileObject() {};
|
||||
|
||||
virtual size_t Read(void* pOut, size_t size) = 0;
|
||||
virtual char* ReadLine(char* pOut, size_t size) = 0;
|
||||
virtual size_t Write(const void* pData, size_t size) = 0;
|
||||
|
||||
virtual bool Seek(int pos, int seek_type) = 0;
|
||||
virtual int Tell() = 0;
|
||||
virtual int Flush() = 0;
|
||||
|
||||
virtual bool HasError() = 0;
|
||||
|
||||
virtual bool EndOfFile() = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual ValveFile *AsValveFile()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual SystemFile *AsSystemFile()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class ValveFile : public FileObject
|
||||
{
|
||||
public:
|
||||
|
||||
ValveFile(FileHandle_t handle) : handle_(handle) {}
|
||||
|
||||
~ValveFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
static bool Exists(const char* file)
|
||||
{
|
||||
return g_FileSystem->FileExists(file);
|
||||
}
|
||||
|
||||
static ValveFile* Open(const char* filename, const char* mode, const char* pathID)
|
||||
{
|
||||
FileHandle_t handle = g_FileSystem->OpenFromCacheForRead(filename, mode, pathID);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new ValveFile(handle);
|
||||
}
|
||||
|
||||
static bool Delete(const char* filename, const char* pathID)
|
||||
{
|
||||
if (!Exists(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
g_FileSystem->RemoveFile(filename, pathID);
|
||||
|
||||
if (Exists(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t Read(void* pOut, size_t size) override
|
||||
{
|
||||
return static_cast<size_t>(g_FileSystem->Read(pOut, size, handle_));
|
||||
}
|
||||
|
||||
char* ReadLine(char* pOut, size_t size) override
|
||||
{
|
||||
return g_FileSystem->ReadLine(pOut, size, handle_);
|
||||
}
|
||||
|
||||
size_t Write(const void* pData, size_t size) override
|
||||
{
|
||||
return static_cast<size_t>(g_FileSystem->Write(pData, size, handle_));
|
||||
}
|
||||
|
||||
bool Seek(int pos, int seek_type) override
|
||||
{
|
||||
g_FileSystem->Seek(handle_, pos, static_cast<FileSystemSeek_t>(seek_type));
|
||||
return !HasError();
|
||||
}
|
||||
|
||||
int Tell() override
|
||||
{
|
||||
return g_FileSystem->Tell(handle_);
|
||||
}
|
||||
|
||||
bool HasError() override
|
||||
{
|
||||
return !handle_ || !g_FileSystem->IsOk(handle_);
|
||||
}
|
||||
|
||||
int Flush() override
|
||||
{
|
||||
g_FileSystem->Flush(handle_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EndOfFile() override
|
||||
{
|
||||
return g_FileSystem->EndOfFile(handle_);
|
||||
}
|
||||
|
||||
void Close() override
|
||||
{
|
||||
if (handle_)
|
||||
{
|
||||
g_FileSystem->Close(handle_);
|
||||
handle_ = nullptr;;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ValveFile* AsValveFile()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
FileHandle_t handle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FileHandle_t handle_;
|
||||
};
|
||||
|
||||
|
||||
class SystemFile : public FileObject
|
||||
{
|
||||
public:
|
||||
|
||||
SystemFile(FILE* fp) : fp_(fp) {}
|
||||
|
||||
~SystemFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
static SystemFile* Open(const char* path, const char* mode)
|
||||
{
|
||||
FILE* fp = fopen(path, mode);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new SystemFile(fp);
|
||||
}
|
||||
|
||||
static bool Delete(const char* path)
|
||||
{
|
||||
return unlink(path) == 0;
|
||||
}
|
||||
|
||||
size_t Read(void* pOut, size_t size) override
|
||||
{
|
||||
return fread(pOut, 1, size, fp_);
|
||||
}
|
||||
|
||||
char* ReadLine(char* pOut, size_t size) override
|
||||
{
|
||||
return fgets(pOut, size, fp_);
|
||||
}
|
||||
|
||||
size_t Write(const void* pData, size_t size) override
|
||||
{
|
||||
return fwrite(pData, 1, size, fp_);
|
||||
}
|
||||
|
||||
bool Seek(int pos, int seek_type) override
|
||||
{
|
||||
return fseek(fp_, pos, seek_type) == 0;
|
||||
}
|
||||
|
||||
int Tell() override
|
||||
{
|
||||
return ftell(fp_);
|
||||
}
|
||||
|
||||
bool HasError() override
|
||||
{
|
||||
return ferror(fp_) != 0;
|
||||
}
|
||||
|
||||
int Flush() override
|
||||
{
|
||||
return fflush(fp_);
|
||||
}
|
||||
|
||||
bool EndOfFile() override
|
||||
{
|
||||
return feof(fp_) != 0;
|
||||
}
|
||||
|
||||
void Close() override
|
||||
{
|
||||
if (fp_)
|
||||
{
|
||||
fclose(fp_);
|
||||
fp_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual SystemFile* AsSystemFile()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
FILE* handle() const
|
||||
{
|
||||
return fp_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FILE* fp_;
|
||||
};
|
||||
|
||||
#endif // _INCLUDE_CFILESYSTEM_H_
|
410
amxmodx/CFlagManager.cpp
Normal file
410
amxmodx/CFlagManager.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "sh_list.h"
|
||||
#include "amxmodx.h"
|
||||
|
||||
#include "CFlagManager.h"
|
||||
|
||||
void CFlagManager::SetFile(const char *Filename)
|
||||
{
|
||||
m_strConfigFile = build_pathname("%s/%s", get_localinfo("amxx_configsdir", "addons/amxmodx/configs"), Filename);
|
||||
|
||||
CreateIfNotExist();
|
||||
}
|
||||
|
||||
const int CFlagManager::LoadFile(const int force)
|
||||
{
|
||||
CheckIfDisabled();
|
||||
// If we're disabled get the hell out. now.
|
||||
if (m_iDisabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// if we're not forcing this, and NeedToLoad says we dont have to
|
||||
// then just stop
|
||||
if (!force && !NeedToLoad())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->Clear();
|
||||
|
||||
|
||||
// We need to load the file
|
||||
|
||||
FILE *File;
|
||||
|
||||
File=fopen(GetFile(),"r");
|
||||
|
||||
if (!File)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] FlagManager: Cannot open file \"%s\" (FILE pointer null!)", GetFile());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Trying to copy this almost exactly as other configs are read...
|
||||
char Line[512];
|
||||
char TempLine[512];
|
||||
|
||||
char Command[256];
|
||||
char Flags[256];
|
||||
|
||||
|
||||
while (!feof(File) && fgets(Line, sizeof(Line), File))
|
||||
{
|
||||
char *nonconst= Line;
|
||||
|
||||
// Strip out comments
|
||||
while (*nonconst)
|
||||
{
|
||||
if (*nonconst==';') // End the line at comments
|
||||
{
|
||||
*nonconst='\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
nonconst++;
|
||||
}
|
||||
}
|
||||
|
||||
Command[0]='\0';
|
||||
Flags[0]='\0';
|
||||
|
||||
// Extract the command
|
||||
strncopy(TempLine, Line, sizeof(TempLine));
|
||||
|
||||
nonconst = TempLine;
|
||||
|
||||
char *start=NULL;
|
||||
char *end=NULL;
|
||||
|
||||
// move up line until the first ", mark this down as the start
|
||||
// then find the second " and mark it down as the end
|
||||
while (*nonconst!='\0')
|
||||
{
|
||||
if (*nonconst=='"')
|
||||
{
|
||||
if (start==NULL)
|
||||
{
|
||||
start=nonconst+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
end=nonconst;
|
||||
goto done_with_command;
|
||||
}
|
||||
}
|
||||
nonconst++;
|
||||
}
|
||||
done_with_command:
|
||||
|
||||
// invalid line?
|
||||
if (start==NULL || end==NULL)
|
||||
{
|
||||
// TODO: maybe warn for an invalid non-commented line?
|
||||
continue;
|
||||
}
|
||||
|
||||
*end='\0';
|
||||
|
||||
strncpy(Command,start,sizeof(Command)-1);
|
||||
|
||||
// Now do the same thing for the flags
|
||||
nonconst=++end;
|
||||
|
||||
start=NULL;
|
||||
end=NULL;
|
||||
|
||||
// move up line until the first ", mark this down as the start
|
||||
// then find the second " and mark it down as the end
|
||||
while (*nonconst!='\0')
|
||||
{
|
||||
if (*nonconst=='"')
|
||||
{
|
||||
if (start==NULL)
|
||||
{
|
||||
start=nonconst+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
end=nonconst;
|
||||
goto done_with_flags;
|
||||
}
|
||||
}
|
||||
nonconst++;
|
||||
}
|
||||
done_with_flags:
|
||||
// invalid line?
|
||||
if (start==NULL || end==NULL)
|
||||
{
|
||||
// TODO: maybe warn for an invalid non-commented line?
|
||||
continue;
|
||||
}
|
||||
|
||||
*end='\0';
|
||||
|
||||
strncpy(Flags,start,sizeof(Flags)-1);
|
||||
|
||||
//if (!isalnum(*Command))
|
||||
if (*Command == '"' || *Command == '\0')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Done sucking the command and flags out of the line
|
||||
// now insert this command into the linked list
|
||||
|
||||
AddFromFile(const_cast<const char*>(&Command[0]),&Flags[0]);
|
||||
|
||||
nonconst = Line;
|
||||
*nonconst = '\0';
|
||||
}
|
||||
|
||||
fclose(File);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called from LoadFile
|
||||
* Do NOT flag the entries as NeedToWrite
|
||||
* No comment is passed from the file because
|
||||
* this should never get written
|
||||
*/
|
||||
void CFlagManager::AddFromFile(const char *Command, const char *Flags)
|
||||
{
|
||||
CFlagEntry *Entry=new CFlagEntry;
|
||||
|
||||
Entry->SetName(Command);
|
||||
Entry->SetFlags(Flags);
|
||||
|
||||
// Link it
|
||||
m_FlagList.push_back(Entry);
|
||||
|
||||
}
|
||||
|
||||
void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
||||
{
|
||||
if (m_iDisabled) // if disabled in core.ini stop
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int TempFlags=Flags;
|
||||
if (TempFlags==-1)
|
||||
{
|
||||
TempFlags=0;
|
||||
}
|
||||
|
||||
List<CFlagEntry *>::iterator iter;
|
||||
List<CFlagEntry *>::iterator end;
|
||||
|
||||
iter=m_FlagList.begin();
|
||||
end=m_FlagList.end();
|
||||
|
||||
while (iter!=end)
|
||||
{
|
||||
if (strcmp((*iter)->GetName()->chars(),Command)==0)
|
||||
{
|
||||
CFlagEntry *Entry=(*iter);
|
||||
|
||||
if (Entry->IsHidden()) // "!" flag, exclude this function
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Found, byref the new flags
|
||||
Flags=Entry->Flags();
|
||||
|
||||
// Move it to the back of the list for faster lookup for the rest
|
||||
m_FlagList.erase(iter);
|
||||
|
||||
m_FlagList.push_back(Entry);
|
||||
return;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
// was not found, add it
|
||||
|
||||
CFlagEntry *Entry=new CFlagEntry;
|
||||
|
||||
Entry->SetName(Command);
|
||||
Entry->SetFlags(TempFlags);
|
||||
|
||||
if (Plugin)
|
||||
{
|
||||
CPluginMngr::CPlugin* a = g_plugins.findPluginFast(Plugin);
|
||||
|
||||
if (a)
|
||||
{
|
||||
Entry->SetComment(a->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// This entry was added from a register_* native
|
||||
// it needs to be written during map change
|
||||
Entry->SetNeedWritten(1);
|
||||
|
||||
// Link it
|
||||
m_FlagList.push_back(Entry);
|
||||
|
||||
}
|
||||
|
||||
void CFlagManager::WriteCommands(void)
|
||||
{
|
||||
if (m_iDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<CFlagEntry *>::iterator iter;
|
||||
List<CFlagEntry *>::iterator end;
|
||||
FILE *File;
|
||||
int NeedToRead=0;
|
||||
|
||||
// First off check the modified time of this file
|
||||
// if it matches the stored modified time, then update
|
||||
// after we write so we do not re-read next map
|
||||
struct stat TempStat;
|
||||
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
|
||||
|
||||
if (TempStat.st_mtime != m_Stat.st_mtime)
|
||||
{
|
||||
NeedToRead=1;
|
||||
};
|
||||
|
||||
|
||||
File = fopen(GetFile(), "a");
|
||||
|
||||
if (!File)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
iter=m_FlagList.begin();
|
||||
end=m_FlagList.end();
|
||||
|
||||
|
||||
|
||||
while (iter!=end)
|
||||
{
|
||||
if ((*iter)->NeedWritten())
|
||||
{
|
||||
if ((*iter)->GetComment()->length())
|
||||
{
|
||||
fprintf(File,"\"%s\" \t\"%s\" ; %s\n",(*iter)->GetName()->chars(),(*iter)->GetFlags()->chars(),(*iter)->GetComment()->chars());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(File,"\"%s\" \t\"%s\"\n",(*iter)->GetName()->chars(),(*iter)->GetFlags()->chars());
|
||||
}
|
||||
(*iter)->SetNeedWritten(0);
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
fclose(File);
|
||||
|
||||
|
||||
// If NeedToRead was 0, then update the timestamp
|
||||
// that was saved so we do not re-read this file
|
||||
// next map
|
||||
if (!NeedToRead)
|
||||
{
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
m_Stat.st_mtime=TempStat.st_mtime;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const
|
||||
{
|
||||
// If flagmanager is disabled then ignore this
|
||||
if (m_iDisabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// If 5th param exists it was compiled after this change was made
|
||||
// if it does not exist, try our logic at the end of this function
|
||||
// 5th param being > 0 means explicit yes
|
||||
// < 0 means auto detect (default is -1), treat it like there was no 5th param
|
||||
// 0 means explicit no
|
||||
|
||||
if ((params[0] / sizeof(cell)) >= 5)
|
||||
{
|
||||
if (params[5]>0) // This command was explicitly told to be included
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (params[5]==0) // this command was explicitly told to NOT be used
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// auto detect if we should use this command
|
||||
|
||||
// if command access is -1 (default, not set to ADMIN_ALL or any other access), then no
|
||||
if (params[3]==-1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// if command is (or starts with) "say", then no
|
||||
if (strncmp(cmdname,"say",3)==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// else use it
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CFlagManager::Clear(void)
|
||||
{
|
||||
List<CFlagEntry *>::iterator iter;
|
||||
List<CFlagEntry *>::iterator end;
|
||||
|
||||
iter=m_FlagList.begin();
|
||||
end=m_FlagList.end();
|
||||
|
||||
while (iter!=end)
|
||||
{
|
||||
delete (*iter);
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
m_FlagList.clear();
|
||||
}
|
||||
|
||||
void CFlagManager::CheckIfDisabled(void)
|
||||
{
|
||||
if (atoi(get_localinfo("disableflagman","0"))==0)
|
||||
{
|
||||
m_iDisabled=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iDisabled=1;
|
||||
}
|
||||
}
|
231
amxmodx/CFlagManager.h
Normal file
231
amxmodx/CFlagManager.h
Normal file
@ -0,0 +1,231 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef CFLAGMANAGER_H
|
||||
#define CFLAGMANAGER_H
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sh_list.h"
|
||||
#include "amxmodx.h"
|
||||
#include "CLibrarySys.h"
|
||||
|
||||
class CFlagEntry
|
||||
{
|
||||
private:
|
||||
ke::AString m_strName; // command name ("amx_slap")
|
||||
ke::AString m_strFlags; // string flags ("a","b")
|
||||
ke::AString m_strComment; // comment to write ("; admincmd.amxx")
|
||||
int m_iFlags; // bitmask flags
|
||||
int m_iNeedWritten; // write this command on map change?
|
||||
int m_iHidden; // set to 1 when the command is set to "!" access in
|
||||
// the .ini file: this means do not process this command
|
||||
|
||||
public:
|
||||
|
||||
CFlagEntry()
|
||||
{
|
||||
m_iNeedWritten=0;
|
||||
m_iFlags=0;
|
||||
m_iHidden=0;
|
||||
};
|
||||
const int NeedWritten(void) const
|
||||
{
|
||||
return m_iNeedWritten;
|
||||
};
|
||||
|
||||
void SetNeedWritten(const int i=1)
|
||||
{
|
||||
m_iNeedWritten=i;
|
||||
};
|
||||
|
||||
const ke::AString *GetName(void) const
|
||||
{
|
||||
return &m_strName;
|
||||
};
|
||||
|
||||
const ke::AString *GetFlags(void) const
|
||||
{
|
||||
return &m_strFlags;
|
||||
};
|
||||
|
||||
const ke::AString *GetComment(void) const
|
||||
{
|
||||
return &m_strComment;
|
||||
};
|
||||
|
||||
const int Flags(void) const
|
||||
{
|
||||
return m_iFlags;
|
||||
};
|
||||
|
||||
void SetName(const char *data)
|
||||
{
|
||||
m_strName = data;
|
||||
};
|
||||
void SetFlags(const char *flags)
|
||||
{
|
||||
// If this is a "!" entry then stop
|
||||
if (flags && flags[0]=='!')
|
||||
{
|
||||
SetHidden(1);
|
||||
return;
|
||||
}
|
||||
|
||||
m_strFlags = flags;
|
||||
m_iFlags=UTIL_ReadFlags(flags);
|
||||
};
|
||||
void SetFlags(const int flags)
|
||||
{
|
||||
m_iFlags=flags;
|
||||
|
||||
char FlagsString[32];
|
||||
UTIL_GetFlags(FlagsString, flags);
|
||||
|
||||
m_strFlags = FlagsString;
|
||||
};
|
||||
void SetComment(const char *comment)
|
||||
{
|
||||
m_strComment = comment;
|
||||
};
|
||||
void SetHidden(int i=1)
|
||||
{
|
||||
m_iHidden=i;
|
||||
};
|
||||
int IsHidden(void) const
|
||||
{
|
||||
return m_iHidden;
|
||||
};
|
||||
};
|
||||
class CFlagManager
|
||||
{
|
||||
private:
|
||||
List<CFlagEntry *> m_FlagList;
|
||||
ke::AString m_strConfigFile;
|
||||
struct stat m_Stat;
|
||||
int m_iForceRead;
|
||||
int m_iDisabled;
|
||||
|
||||
|
||||
void CreateIfNotExist(void) const
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(GetFile(), "r");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
// File does not exist, create the header
|
||||
fp = fopen(GetFile(), "a");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp,"; This file will store the commands used by plugins, and their access level\n");
|
||||
fprintf(fp,"; To change the access of a command, edit the flags beside it and then\n");
|
||||
fprintf(fp,"; change the server's map.\n;\n");
|
||||
fprintf(fp,"; Example: If I wanted to change the amx_slap access to require\n");
|
||||
fprintf(fp,"; RCON access (flag \"l\") I would change this:\n");
|
||||
fprintf(fp,"; \"amx_slap\" \"e\" ; admincmd.amxx\n");
|
||||
fprintf(fp,"; To this:\n");
|
||||
fprintf(fp,"; \"amx_slap\" \"l\" ; admincmd.amxx\n;\n");
|
||||
fprintf(fp,"; To disable a specific command from being used with the command manager\n");
|
||||
fprintf(fp,"; and to only use the plugin-specified access set the flag to \"!\"\n;\n");
|
||||
fprintf(fp,"; NOTE: The plugin name at the end is just for reference to what plugin\n");
|
||||
fprintf(fp,"; uses what commands. It is ignored.\n\n");
|
||||
fclose(fp);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Returns 1 if the timestamp for the file is different than the one we have loaded
|
||||
* 0 otherwise
|
||||
*/
|
||||
inline int NeedToLoad(void)
|
||||
{
|
||||
struct stat TempStat;
|
||||
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
// If the modified timestamp does not match the stored
|
||||
// timestamp than we need to re-read this file.
|
||||
// Otherwise, ignore the file.
|
||||
if (TempStat.st_mtime != m_Stat.st_mtime)
|
||||
{
|
||||
// Save down the modified timestamp
|
||||
m_Stat.st_mtime=TempStat.st_mtime;
|
||||
return 1;
|
||||
};
|
||||
|
||||
return 0;
|
||||
|
||||
};
|
||||
public:
|
||||
|
||||
CFlagManager()
|
||||
{
|
||||
memset(&m_Stat,0x0,sizeof(struct stat));
|
||||
m_iDisabled=0;
|
||||
m_iForceRead=0;
|
||||
};
|
||||
~CFlagManager()
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the filename in relation to amxmodx/configs
|
||||
*/
|
||||
void SetFile(const char *Filename="cmdaccess.ini");
|
||||
|
||||
const char *GetFile(void) const { return m_strConfigFile.chars(); };
|
||||
|
||||
/**
|
||||
* Parse the file, and load all entries
|
||||
* Returns 1 on success, 0 on refusal (no need to), and -1 on error
|
||||
*/
|
||||
const int LoadFile(const int force=0);
|
||||
|
||||
/**
|
||||
* Checks if the command exists in the list
|
||||
* If it does, it byrefs the flags for it
|
||||
* If it does not, it adds it to the list
|
||||
* These are added from register_*cmd calls
|
||||
*/
|
||||
void LookupOrAdd(const char *Command, int &Flags, AMX *Plugin);
|
||||
|
||||
|
||||
/**
|
||||
* Write the commands back to the file
|
||||
*/
|
||||
void WriteCommands(void);
|
||||
|
||||
/**
|
||||
* Add this straight from the cmdaccess.ini file
|
||||
*/
|
||||
void AddFromFile(const char *Command, const char *Flags);
|
||||
|
||||
/**
|
||||
* Checks if this command should be added to flagman or not
|
||||
* This is only checked when adding commands from the register_* natives
|
||||
* If an admin manually adds a command to cmdaccess.ini it will be used
|
||||
* regardless of whatever this function would say should be done with it
|
||||
*/
|
||||
int ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const;
|
||||
|
||||
void Clear(void);
|
||||
|
||||
void CheckIfDisabled(void);
|
||||
};
|
||||
|
||||
#endif // CFLAGMANAGER_H
|
@ -1,39 +1,17 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "debugger.h"
|
||||
#include "binlog.h"
|
||||
|
||||
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes, int fwd_type)
|
||||
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes)
|
||||
{
|
||||
m_FuncName = name;
|
||||
m_ExecType = et;
|
||||
@ -47,23 +25,16 @@ CForward::CForward(const char *name, ForwardExecType et, int numParams, const Fo
|
||||
|
||||
for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter)
|
||||
{
|
||||
if ((fwd_type != FORWARD_ALL) &&
|
||||
((fwd_type == FORWARD_ONLY_NEW && ((*iter).getAMX()->flags & AMX_FLAG_OLDFILE))
|
||||
|| (fwd_type == FORWARD_ONLY_OLD && !((*iter).getAMX()->flags & AMX_FLAG_OLDFILE))
|
||||
))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((*iter).isValid() && amx_FindPublic((*iter).getAMX(), name, &func) == AMX_ERR_NONE)
|
||||
{
|
||||
AMXForward tmp;
|
||||
tmp.pPlugin = &(*iter);
|
||||
tmp.func = func;
|
||||
m_Funcs.push_back(tmp);
|
||||
m_Funcs.append(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
m_Name.assign(name);
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
@ -75,20 +46,20 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
|
||||
cell globRetVal = 0;
|
||||
|
||||
AMXForwardList::iterator iter;
|
||||
|
||||
for (iter = m_Funcs.begin(); iter != m_Funcs.end(); iter++)
|
||||
for (size_t i = 0; i < m_Funcs.length(); ++i)
|
||||
{
|
||||
auto iter = &m_Funcs[i];
|
||||
|
||||
if (iter->pPlugin->isExecutable(iter->func))
|
||||
{
|
||||
// Get debug info
|
||||
AMX *amx = (*iter).pPlugin->getAMX();
|
||||
AMX *amx = iter->pPlugin->getAMX();
|
||||
Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
|
||||
|
||||
if (pDebugger)
|
||||
pDebugger->BeginExec();
|
||||
|
||||
// handle strings & arrays
|
||||
// handle strings & arrays & values by reference
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m_NumParams; ++i)
|
||||
@ -99,7 +70,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
cell *tmp;
|
||||
if (!str)
|
||||
str = "";
|
||||
amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp);
|
||||
amx_Allot(amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp);
|
||||
amx_SetStringOld(tmp, str, 0, 0);
|
||||
physAddrs[i] = tmp;
|
||||
}
|
||||
@ -118,7 +89,24 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
|
||||
*tmp++ = (static_cast<cell>(*data++)) & 0xFF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
|
||||
{
|
||||
cell *tmp;
|
||||
amx_Allot(amx, 1, &realParams[i], &tmp);
|
||||
physAddrs[i] = tmp;
|
||||
|
||||
if (m_ParamTypes[i] == FP_CELL_BYREF)
|
||||
{
|
||||
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
realParams[i] = params[i];
|
||||
}
|
||||
}
|
||||
@ -130,12 +118,12 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
}
|
||||
|
||||
// exec
|
||||
cell retVal;
|
||||
cell retVal = 0;
|
||||
#if defined BINLOG_ENABLED
|
||||
g_BinLog.WriteOp(BinLog_CallPubFunc, (*iter).pPlugin->getId(), iter->func);
|
||||
g_BinLog.WriteOp(BinLog_CallPubFunc, iter->pPlugin->getId(), iter->func);
|
||||
#endif
|
||||
int err = amx_Exec(amx, &retVal, iter->func);
|
||||
|
||||
|
||||
int err = amx_ExecPerf(amx, &retVal, iter->func);
|
||||
// log runtime error, if any
|
||||
if (err != AMX_ERR_NONE)
|
||||
{
|
||||
@ -156,18 +144,18 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
if (pDebugger)
|
||||
pDebugger->EndExec();
|
||||
|
||||
// cleanup strings & arrays
|
||||
// cleanup strings & arrays & values by reference
|
||||
for (i = 0; i < m_NumParams; ++i)
|
||||
{
|
||||
if (m_ParamTypes[i] == FP_STRING)
|
||||
{
|
||||
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
|
||||
amx_Release(amx, realParams[i]);
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_STRINGEX)
|
||||
{
|
||||
// copy back
|
||||
amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
|
||||
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
|
||||
amx_Release(amx, realParams[i]);
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_ARRAY)
|
||||
{
|
||||
@ -185,7 +173,21 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
*data++ = static_cast<char>(*tmp++ & 0xFF);
|
||||
}
|
||||
}
|
||||
amx_Release(iter->pPlugin->getAMX(), realParams[i]);
|
||||
amx_Release(amx, realParams[i]);
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
|
||||
{
|
||||
//copy back
|
||||
cell *tmp = physAddrs[i];
|
||||
if (m_ParamTypes[i] == FP_CELL_BYREF)
|
||||
{
|
||||
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
|
||||
}
|
||||
amx_Release(amx, realParams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +227,7 @@ void CSPForward::Set(int func, AMX *amx, int numParams, const ForwardParam *para
|
||||
isFree = false;
|
||||
name[0] = '\0';
|
||||
amx_GetPublic(amx, func, name);
|
||||
m_Name.assign(name);
|
||||
m_Name = name;
|
||||
m_ToDelete = false;
|
||||
m_InExec = false;
|
||||
}
|
||||
@ -237,7 +239,7 @@ void CSPForward::Set(const char *funcName, AMX *amx, int numParams, const Forwar
|
||||
memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam));
|
||||
m_HasFunc = (amx_FindPublic(amx, funcName, &m_Func) == AMX_ERR_NONE);
|
||||
isFree = false;
|
||||
m_Name.assign(funcName);
|
||||
m_Name = funcName;
|
||||
m_ToDelete = false;
|
||||
m_InExec = false;
|
||||
}
|
||||
@ -265,7 +267,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
if (pDebugger)
|
||||
pDebugger->BeginExec();
|
||||
|
||||
// handle strings & arrays
|
||||
// handle strings & arrays & values by reference
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m_NumParams; ++i)
|
||||
@ -295,7 +297,24 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
|
||||
*tmp++ = (static_cast<cell>(*data++)) & 0xFF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
|
||||
{
|
||||
cell *tmp;
|
||||
amx_Allot(m_Amx, 1, &realParams[i], &tmp);
|
||||
physAddrs[i] = tmp;
|
||||
|
||||
if (m_ParamTypes[i] == FP_CELL_BYREF)
|
||||
{
|
||||
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
realParams[i] = params[i];
|
||||
}
|
||||
}
|
||||
@ -304,12 +323,11 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
amx_Push(m_Amx, realParams[i]);
|
||||
|
||||
// exec
|
||||
cell retVal;
|
||||
cell retVal = 0;
|
||||
#if defined BINLOG_ENABLED
|
||||
g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func);
|
||||
#endif
|
||||
int err = amx_Exec(m_Amx, &retVal, m_Func);
|
||||
|
||||
int err = amx_ExecPerf(m_Amx, &retVal, m_Func);
|
||||
if (err != AMX_ERR_NONE)
|
||||
{
|
||||
//Did something else set an error?
|
||||
@ -329,7 +347,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
|
||||
m_Amx->error = AMX_ERR_NONE;
|
||||
|
||||
// cleanup strings & arrays
|
||||
// cleanup strings & arrays & values by reference
|
||||
for (i = 0; i < m_NumParams; ++i)
|
||||
{
|
||||
if (m_ParamTypes[i] == FP_STRING)
|
||||
@ -360,6 +378,20 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
}
|
||||
amx_Release(m_Amx, realParams[i]);
|
||||
}
|
||||
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
|
||||
{
|
||||
//copy back
|
||||
cell *tmp = physAddrs[i];
|
||||
if (m_ParamTypes[i] == FP_CELL_BYREF)
|
||||
{
|
||||
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
|
||||
}
|
||||
amx_Release(m_Amx, realParams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_InExec = false;
|
||||
@ -367,17 +399,17 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes, int fwd_type)
|
||||
int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes)
|
||||
{
|
||||
int retVal = m_Forwards.size() << 1;
|
||||
CForward *tmp = new CForward(funcName, et, numParams, paramTypes, fwd_type);
|
||||
int retVal = m_Forwards.length() << 1;
|
||||
CForward *tmp = new CForward(funcName, et, numParams, paramTypes);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
return -1; // should be invalid
|
||||
}
|
||||
|
||||
m_Forwards.push_back(tmp);
|
||||
m_Forwards.append(tmp);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
@ -398,7 +430,7 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
|
||||
|
||||
m_FreeSPForwards.pop();
|
||||
} else {
|
||||
retVal = (m_SPForwards.size() << 1) | 1;
|
||||
retVal = (m_SPForwards.length() << 1) | 1;
|
||||
pForward = new CSPForward();
|
||||
|
||||
if (!pForward)
|
||||
@ -408,11 +440,11 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
|
||||
|
||||
if (pForward->getFuncsNum() == 0)
|
||||
{
|
||||
return -1;
|
||||
delete pForward;
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_SPForwards.push_back(pForward);
|
||||
m_SPForwards.append(pForward);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@ -420,7 +452,7 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
|
||||
|
||||
int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParams, const ForwardParam *paramTypes)
|
||||
{
|
||||
int retVal = (m_SPForwards.size() << 1) | 1;
|
||||
int retVal = (m_SPForwards.length() << 1) | 1;
|
||||
CSPForward *pForward;
|
||||
|
||||
if (!m_FreeSPForwards.empty())
|
||||
@ -447,7 +479,7 @@ int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParam
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_SPForwards.push_back(pForward);
|
||||
m_SPForwards.append(pForward);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@ -455,7 +487,7 @@ int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParam
|
||||
|
||||
bool CForwardMngr::isIdValid(int id) const
|
||||
{
|
||||
return (id >= 0) && ((id & 1) ? (static_cast<size_t>(id >> 1) < m_SPForwards.size()) : (static_cast<size_t>(id >> 1) < m_Forwards.size()));
|
||||
return (id >= 0) && ((id & 1) ? (static_cast<size_t>(id >> 1) < m_SPForwards.length()) : (static_cast<size_t>(id >> 1) < m_Forwards.length()));
|
||||
}
|
||||
|
||||
cell CForwardMngr::executeForwards(int id, cell *params)
|
||||
@ -513,24 +545,26 @@ ForwardParam CForwardMngr::getParamType(int id, int paramNum) const
|
||||
|
||||
void CForwardMngr::clear()
|
||||
{
|
||||
for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter)
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < m_Forwards.length(); ++i)
|
||||
{
|
||||
delete *iter;
|
||||
delete m_Forwards[i];
|
||||
}
|
||||
|
||||
SPForwardVec::iterator spIter;
|
||||
|
||||
for (spIter = m_SPForwards.begin(); spIter != m_SPForwards.end(); ++spIter)
|
||||
|
||||
for (i = 0; i < m_SPForwards.length(); ++i)
|
||||
{
|
||||
delete (*spIter);
|
||||
delete m_SPForwards[i];
|
||||
}
|
||||
|
||||
m_Forwards.clear();
|
||||
m_SPForwards.clear();
|
||||
|
||||
while (!m_FreeSPForwards.empty())
|
||||
{
|
||||
m_FreeSPForwards.pop();
|
||||
|
||||
}
|
||||
|
||||
m_TmpArraysNum = 0;
|
||||
}
|
||||
|
||||
@ -543,7 +577,9 @@ void CForwardMngr::unregisterSPForward(int id)
|
||||
{
|
||||
//make sure the id is valid
|
||||
if (!isIdValid(id) || m_SPForwards.at(id >> 1)->isFree)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CSPForward *fwd = m_SPForwards.at(id >> 1);
|
||||
|
||||
@ -556,7 +592,39 @@ void CForwardMngr::unregisterSPForward(int id)
|
||||
}
|
||||
}
|
||||
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num, int fwd_type)
|
||||
int CForwardMngr::duplicateSPForward(int id)
|
||||
{
|
||||
if (!isIdValid(id) || m_SPForwards.at(id >> 1)->isFree)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
CSPForward *fwd = m_SPForwards.at(id >> 1);
|
||||
|
||||
return registerSPForward(fwd->m_Func, fwd->m_Amx, fwd->m_NumParams, fwd->m_ParamTypes);
|
||||
}
|
||||
|
||||
int CForwardMngr::isSameSPForward(int id1, int id2)
|
||||
{
|
||||
if (!isIdValid(id1) || !isIdValid(id2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CSPForward *fwd1 = m_SPForwards.at(id1 >> 1);
|
||||
CSPForward *fwd2 = m_SPForwards.at(id2 >> 1);
|
||||
|
||||
if (fwd1->isFree || fwd2->isFree)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((fwd1->m_Amx == fwd2->m_Amx)
|
||||
&& (fwd1->m_Func == fwd2->m_Func)
|
||||
&& (fwd1->m_NumParams == fwd2->m_NumParams));
|
||||
}
|
||||
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num)
|
||||
{
|
||||
ForwardParam params[FORWARD_MAX_PARAMS];
|
||||
|
||||
@ -565,7 +633,7 @@ int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_
|
||||
params[i] = static_cast<ForwardParam>(list[i]);
|
||||
}
|
||||
|
||||
return g_forwards.registerForward(funcName, et, num, params, fwd_type);
|
||||
return g_forwards.registerForward(funcName, et, num, params);
|
||||
}
|
||||
|
||||
int registerForward(const char *funcName, ForwardExecType et, ...)
|
||||
@ -676,13 +744,26 @@ cell executeForwards(int id, ...)
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, id);
|
||||
|
||||
ForwardParam param_type;
|
||||
|
||||
for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i)
|
||||
{
|
||||
if (g_forwards.getParamType(id, i) == FP_FLOAT)
|
||||
param_type = g_forwards.getParamType(id, i);
|
||||
if (param_type == FP_FLOAT)
|
||||
{
|
||||
REAL tmp = (REAL)va_arg(argptr, double); // floats get converted to doubles
|
||||
params[i] = *(cell*)&tmp;
|
||||
params[i] = amx_ftoc(tmp);
|
||||
}
|
||||
else if(param_type == FP_FLOAT_BYREF)
|
||||
{
|
||||
REAL *tmp = reinterpret_cast<REAL *>(va_arg(argptr, double*));
|
||||
params[i] = reinterpret_cast<cell>(tmp);
|
||||
}
|
||||
else if(param_type == FP_CELL_BYREF)
|
||||
{
|
||||
cell *tmp = reinterpret_cast<cell *>(va_arg(argptr, cell*));
|
||||
params[i] = reinterpret_cast<cell>(tmp);
|
||||
}
|
||||
else
|
||||
params[i] = (cell)va_arg(argptr, cell);
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
/*
|
||||
CForward.h
|
||||
@ -51,10 +29,6 @@
|
||||
|
||||
const int FORWARD_MAX_PARAMS = 32;
|
||||
|
||||
#define FORWARD_ONLY_OLD 1
|
||||
#define FORWARD_ONLY_NEW 2
|
||||
#define FORWARD_ALL 3
|
||||
|
||||
enum ForwardExecType
|
||||
{
|
||||
ET_IGNORE = 0, // Ignore return vaue
|
||||
@ -72,6 +46,8 @@ enum ForwardParam
|
||||
FP_STRING, // string
|
||||
FP_STRINGEX, // string; will be updated to the last function's value
|
||||
FP_ARRAY, // array; use the return value of prepareArray.
|
||||
FP_CELL_BYREF, // cell; pass by reference
|
||||
FP_FLOAT_BYREF, // float; pass by reference
|
||||
};
|
||||
|
||||
// for prepareArray
|
||||
@ -97,7 +73,7 @@ class CForward
|
||||
const char *m_FuncName;
|
||||
ForwardExecType m_ExecType;
|
||||
int m_NumParams;
|
||||
String m_Name;
|
||||
ke::AString m_Name;
|
||||
|
||||
struct AMXForward
|
||||
{
|
||||
@ -105,13 +81,13 @@ class CForward
|
||||
int func;
|
||||
};
|
||||
|
||||
typedef CVector<AMXForward> AMXForwardList;
|
||||
typedef ke::Vector<AMXForward> AMXForwardList;
|
||||
|
||||
AMXForwardList m_Funcs;
|
||||
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
|
||||
|
||||
public:
|
||||
CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam * paramTypes, int fwd_type=FORWARD_ALL);
|
||||
CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam * paramTypes);
|
||||
CForward() {} // leaves everything unitialized'
|
||||
|
||||
cell execute(cell *params, ForwardPreparedArray *preparedArrays);
|
||||
@ -123,12 +99,12 @@ public:
|
||||
|
||||
int getFuncsNum() const
|
||||
{
|
||||
return m_Funcs.size();
|
||||
return m_Funcs.length();
|
||||
}
|
||||
|
||||
const char *getFuncName() const
|
||||
{
|
||||
return m_Name.c_str();
|
||||
return m_Name.chars();
|
||||
}
|
||||
|
||||
ForwardParam getParamType(int paramId) const
|
||||
@ -144,7 +120,6 @@ public:
|
||||
class CSPForward
|
||||
{
|
||||
friend class CForwardMngr;
|
||||
const char *m_FuncName;
|
||||
int m_NumParams;
|
||||
|
||||
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
|
||||
@ -152,7 +127,7 @@ class CSPForward
|
||||
|
||||
int m_Func;
|
||||
bool m_HasFunc;
|
||||
String m_Name;
|
||||
ke::AString m_Name;
|
||||
bool m_InExec;
|
||||
bool m_ToDelete;
|
||||
|
||||
@ -177,7 +152,7 @@ public:
|
||||
|
||||
const char *getFuncName() const
|
||||
{
|
||||
return m_Name.c_str();
|
||||
return m_Name.chars();
|
||||
}
|
||||
|
||||
ForwardParam getParamType(int paramId) const
|
||||
@ -191,8 +166,8 @@ public:
|
||||
|
||||
class CForwardMngr
|
||||
{
|
||||
typedef CVector<CForward*> ForwardVec;
|
||||
typedef CVector<CSPForward*> SPForwardVec;
|
||||
typedef ke::Vector<CForward*> ForwardVec;
|
||||
typedef ke::Vector<CSPForward*> SPForwardVec;
|
||||
typedef CStack<int> FreeSPVec; // Free SP Forwards
|
||||
|
||||
ForwardVec m_Forwards;
|
||||
@ -210,13 +185,15 @@ public:
|
||||
|
||||
// Interface
|
||||
// Register normal forward
|
||||
int registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam *paramTypes, int fwd_type=FORWARD_ALL);
|
||||
int registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam *paramTypes);
|
||||
// Register single plugin forward
|
||||
int registerSPForward(const char *funcName, AMX *amx, int numParams, const ForwardParam * paramTypes);
|
||||
int registerSPForward(int func, AMX *amx, int numParams, const ForwardParam * paramTypes);
|
||||
|
||||
// Unregister single plugin forward
|
||||
void unregisterSPForward(int id);
|
||||
int duplicateSPForward(int id);
|
||||
int isSameSPForward(int id1, int id2);
|
||||
|
||||
// execute forward
|
||||
cell executeForwards(int id, cell *params);
|
||||
@ -234,7 +211,7 @@ public:
|
||||
|
||||
// (un)register forward
|
||||
int registerForward(const char *funcName, ForwardExecType et, ...);
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num, int fwd_type=FORWARD_ALL);
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num);
|
||||
int registerSPForwardByName(AMX *amx, const char *funcName, ...);
|
||||
int registerSPForwardByNameC(AMX *amx, const char *funcName, cell *list, size_t num);
|
||||
int registerSPForward(AMX *amx, int func, ...);
|
||||
|
61
amxmodx/CFrameAction.h
Normal file
61
amxmodx/CFrameAction.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef FRAMEACTION_H
|
||||
#define FRAMEACTION_H
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include <amtl/am-deque.h>
|
||||
#include <amtl/am-autoptr.h>
|
||||
|
||||
class CFrameActionMngr
|
||||
{
|
||||
public:
|
||||
|
||||
class CFrameAction
|
||||
{
|
||||
public:
|
||||
CFrameAction(int callbackForward, cell callbackData) :
|
||||
m_callbackForward(callbackForward),
|
||||
m_callbackData(callbackData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~CFrameAction()
|
||||
{
|
||||
unregisterSPForward(m_callbackForward);
|
||||
}
|
||||
|
||||
void Execute()
|
||||
{
|
||||
executeForwards(m_callbackForward, m_callbackData);
|
||||
}
|
||||
|
||||
public:
|
||||
int m_callbackForward;
|
||||
cell m_callbackData;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
void AddFrameAction(int callbackForward, cell callbackData)
|
||||
{
|
||||
m_requestedFrames.append(new CFrameAction(callbackForward, callbackData));
|
||||
}
|
||||
|
||||
void ExecuteFrameCallbacks()
|
||||
{
|
||||
// In case a frame callback requests another frame, newly added frames won't be executed this way
|
||||
int callbacksToRun = m_requestedFrames.length();
|
||||
while (callbacksToRun--)
|
||||
{
|
||||
ke::AutoPtr<CFrameAction> action = ke::Move(m_requestedFrames.front());
|
||||
m_requestedFrames.popFront();
|
||||
action->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ke::Deque<ke::AutoPtr<CFrameAction>> m_requestedFrames;
|
||||
|
||||
};
|
||||
|
||||
#endif // FRAMEACTION_H
|
1050
amxmodx/CGameConfigs.cpp
Normal file
1050
amxmodx/CGameConfigs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
198
amxmodx/CGameConfigs.h
Normal file
198
amxmodx/CGameConfigs.h
Normal file
@ -0,0 +1,198 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_GAMECONFIG_H_
|
||||
#define _INCLUDE_GAMECONFIG_H_
|
||||
|
||||
#include <IGameConfigs.h>
|
||||
#include "CLibrarySys.h"
|
||||
#include <amtl/am-autoptr.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <amtl/am-refcounting.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
#include <sm_namehashset.h>
|
||||
|
||||
class CGameConfig
|
||||
:
|
||||
public ITextListener_SMC,
|
||||
public IGameConfig,
|
||||
public ke::Refcounted <CGameConfig>
|
||||
{
|
||||
friend class CGameConfigManager;
|
||||
|
||||
public:
|
||||
|
||||
CGameConfig(const char *file);
|
||||
~CGameConfig();
|
||||
|
||||
public:
|
||||
|
||||
bool Reparse(char *error, size_t maxlength);
|
||||
bool EnterFile(const char *file, char *error, size_t maxlength);
|
||||
|
||||
public: // ITextListener_SMC
|
||||
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
|
||||
public: // IGameConfig
|
||||
|
||||
const char* GetKeyValue(const char *key);
|
||||
bool GetOffset(const char *key, TypeDescription *value);
|
||||
bool GetOffsetByClass(const char *classname, const char *key, TypeDescription *value);
|
||||
bool GetMemSig(const char *key, void **addr);
|
||||
bool GetAddress(const char *key, void **addr);
|
||||
|
||||
public: // NameHashSet
|
||||
|
||||
static inline bool matches(const char *key, const CGameConfig *value)
|
||||
{
|
||||
return strcmp(key, value->m_File) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct OffsetClass
|
||||
{
|
||||
StringHashMap<TypeDescription> list;
|
||||
};
|
||||
|
||||
typedef StringHashMap<ke::AutoPtr<OffsetClass>> OffsetClassMap;
|
||||
typedef StringHashMap<TypeDescription> OffsetMap;
|
||||
|
||||
char m_File[PLATFORM_MAX_PATH];
|
||||
char m_CurrentPath[PLATFORM_MAX_PATH];
|
||||
|
||||
OffsetMap m_Offsets;
|
||||
OffsetClassMap m_OffsetsByClass;
|
||||
StringHashMap<ke::AString> m_Keys;
|
||||
StringHashMap<void*> m_Sigs;
|
||||
|
||||
int m_ParseState;
|
||||
unsigned int m_IgnoreLevel;
|
||||
|
||||
char m_Class[64];
|
||||
char m_Offset[64];
|
||||
char m_Game[256];
|
||||
|
||||
bool m_FoundOffset;
|
||||
bool m_MatchedClasses;
|
||||
bool m_ShouldBeReadingDefault;
|
||||
bool m_HadGame;
|
||||
bool m_MatchedGame;
|
||||
bool m_HadEngine;
|
||||
bool m_MatchedEngine;
|
||||
bool m_MatchedPlatform;
|
||||
|
||||
unsigned int m_CustomLevel;
|
||||
ITextListener_SMC* m_CustomHandler;
|
||||
|
||||
struct AddressConf
|
||||
{
|
||||
char m_SignatureName[64];
|
||||
size_t m_ReadCount;
|
||||
int m_ReadBytes[8];
|
||||
|
||||
AddressConf(const char *sigName, size_t sigLength, size_t readCount, int *read);
|
||||
AddressConf() {}
|
||||
};
|
||||
|
||||
char m_Address[64];
|
||||
char m_AddressSignature[64];
|
||||
int m_AddressReadCount;
|
||||
int m_AddressRead[8];
|
||||
StringHashMap<AddressConf> m_Addresses;
|
||||
|
||||
char m_pEngine[64];
|
||||
};
|
||||
|
||||
class CGameMasterReader : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
|
||||
void ReadSMC_ParseStart();
|
||||
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
|
||||
public:
|
||||
|
||||
ke::Vector<ke::AString>* m_FileList;
|
||||
|
||||
unsigned int m_State;
|
||||
unsigned int m_IgnoreLevel;
|
||||
|
||||
char m_CurrentPath[PLATFORM_MAX_PATH];
|
||||
|
||||
bool m_HadEngine;
|
||||
bool m_MatchedEngine;
|
||||
bool m_HadGame;
|
||||
bool m_MatchedGame;
|
||||
};
|
||||
|
||||
class CGameConfigManager : public IGameConfigManager
|
||||
{
|
||||
public:
|
||||
|
||||
CGameConfigManager();
|
||||
~CGameConfigManager();
|
||||
|
||||
public: // IGameConfigManager
|
||||
|
||||
bool LoadGameConfigFile(const char *file, IGameConfig **pConfig, char *error, size_t maxlength);
|
||||
void CloseGameConfigFile(IGameConfig *cfg);
|
||||
void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||
void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||
|
||||
public:
|
||||
|
||||
void OnAmxxStartup();
|
||||
void RemoveCachedConfig(CGameConfig *config);
|
||||
|
||||
private:
|
||||
|
||||
NameHashSet<CGameConfig*> m_Lookup;
|
||||
|
||||
public:
|
||||
|
||||
StringHashMap<ITextListener_SMC*> m_customHandlers;
|
||||
};
|
||||
|
||||
#define GET_OFFSET(classname, member) \
|
||||
static int member = -1; \
|
||||
if (member == -1) \
|
||||
{ \
|
||||
TypeDescription type; \
|
||||
if (!CommonConfig->GetOffsetByClass(classname, #member, &type) || type.fieldOffset < 0)\
|
||||
{ \
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid %s offset. Native %s is disabled", #member, __FUNCTION__);\
|
||||
return 0; \
|
||||
} \
|
||||
member = type.fieldOffset; \
|
||||
}
|
||||
|
||||
#define GET_OFFSET_NO_ERROR(classname, member) \
|
||||
static int member = -1; \
|
||||
if (member == -1) \
|
||||
{ \
|
||||
TypeDescription type; \
|
||||
if (!CommonConfig->GetOffsetByClass(classname, #member, &type) || type.fieldOffset < 0)\
|
||||
{ \
|
||||
return; \
|
||||
} \
|
||||
member = type.fieldOffset; \
|
||||
}
|
||||
|
||||
extern CGameConfigManager ConfigManager;
|
||||
extern IGameConfig *CommonConfig;
|
||||
|
||||
#endif // _INCLUDE_GAMECONFIG_H_
|
@ -1,43 +1,17 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "amxmodx.h"
|
||||
#include "CLang.h"
|
||||
#include "format.h"
|
||||
#include "amxmod_compat.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#define _snprintf snprintf
|
||||
#endif
|
||||
#include "ITextParsers.h"
|
||||
|
||||
#define LITIDX_NONE 0
|
||||
#define LITIDX_BRACKET 1
|
||||
@ -49,24 +23,29 @@
|
||||
#define INSERT_NEWLINE 4
|
||||
|
||||
template<>
|
||||
int Compare<String>(const String &k1, const String &k2)
|
||||
int Compare<ke::AString>(const ke::AString &k1, const ke::AString &k2)
|
||||
{
|
||||
return k1.compare(k2.c_str());
|
||||
return k1.compare(k2);
|
||||
}
|
||||
|
||||
template<>
|
||||
int CompareAlt<char const *, String>(char const * const &k1, String const &k2)
|
||||
int CompareAlt<char const *, ke::AString>(char const * const &k1, ke::AString const &k2)
|
||||
{
|
||||
return strcmp(k1, k2.c_str());
|
||||
return k2.compare(k1);
|
||||
}
|
||||
template<>
|
||||
int CompareAlt<ke::AString, ke::AString>(ke::AString const &k1, ke::AString const &k2)
|
||||
{
|
||||
return k1.compare(k2);
|
||||
}
|
||||
|
||||
template<>
|
||||
int HashFunction<String>(const String &k)
|
||||
int HashFunction<ke::AString>(const ke::AString &k)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k.c_str();
|
||||
register const char *str = k.chars();
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
@ -79,13 +58,27 @@ int HashAlt<const char *>(char const * const &k)
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k;
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<>
|
||||
int HashAlt<ke::AString>(ke::AString const &k)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k.chars();
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
int HashFunction<int>(const int &k)
|
||||
{
|
||||
@ -95,7 +88,7 @@ int HashFunction<int>(const int &k)
|
||||
template<>
|
||||
int Compare<int>(const int &k1, const int &k2)
|
||||
{
|
||||
return (k1-k2);
|
||||
return (k1 - k2);
|
||||
}
|
||||
|
||||
// strip the whitespaces at the beginning and the end of a string
|
||||
@ -108,7 +101,7 @@ size_t CLangMngr::strip(char *str, char *newstr, bool makelower)
|
||||
int flag = 0;
|
||||
size_t strln = strlen(str);
|
||||
|
||||
for (i = strln - 1; i >= 0; i--)
|
||||
for (i = strln - 1; i < strln; i--)
|
||||
{
|
||||
if (str[i] == '\n' || str[i] == ' ' || str[i] == '\t')
|
||||
{
|
||||
@ -167,7 +160,7 @@ void CLangMngr::CLang::AddEntry(int key, const char *definition)
|
||||
m_entries++;
|
||||
}
|
||||
|
||||
d.definition = new String(definition);
|
||||
d.definition = new ke::AString(definition);
|
||||
}
|
||||
|
||||
CLangMngr::CLang::~CLang()
|
||||
@ -190,21 +183,21 @@ void CLangMngr::CLang::Clear()
|
||||
m_entries = 0;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::MergeDefinitions(CQueue<sKeyDef> &vec)
|
||||
void CLangMngr::CLang::MergeDefinitions(ke::Vector<sKeyDef> &vec)
|
||||
{
|
||||
String *pDef;
|
||||
ke::AutoString *pDef;
|
||||
int key = -1;
|
||||
|
||||
while (!vec.empty())
|
||||
{
|
||||
key = vec.front().key;
|
||||
pDef = vec.front().definition;
|
||||
auto keydef = vec.popCopy();
|
||||
|
||||
AddEntry(key, pDef->c_str());
|
||||
key = keydef.key;
|
||||
pDef = keydef.definition;
|
||||
|
||||
delete vec.front().definition;
|
||||
|
||||
vec.pop();
|
||||
AddEntry(key, pDef->ptr());
|
||||
|
||||
delete pDef;
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +211,8 @@ const char * CLangMngr::CLang::GetDef(int key, int &status)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return def.definition->c_str();
|
||||
status = 0;
|
||||
return def.definition->chars();
|
||||
}
|
||||
|
||||
int CLangMngr::CLang::Entries()
|
||||
@ -228,15 +222,6 @@ int CLangMngr::CLang::Entries()
|
||||
|
||||
/******** CLangMngr *********/
|
||||
|
||||
inline String &make_string(const char *str)
|
||||
{
|
||||
static String g_temp;
|
||||
|
||||
g_temp.assign(str);
|
||||
|
||||
return g_temp;
|
||||
}
|
||||
|
||||
CLangMngr::CLangMngr()
|
||||
{
|
||||
Clear();
|
||||
@ -244,15 +229,15 @@ CLangMngr::CLangMngr()
|
||||
|
||||
const char * CLangMngr::GetKey(int key)
|
||||
{
|
||||
if (key < 0 || key >= (int)KeyList.size())
|
||||
if (key < 0 || key >= (int)KeyList.length())
|
||||
return NULL;
|
||||
|
||||
return KeyList[key]->c_str();
|
||||
return KeyList[key]->chars();
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(const char *key)
|
||||
{
|
||||
keytbl_val &val = KeyTable[key];
|
||||
keytbl_val &val = KeyTable[ke::AString(key)];
|
||||
|
||||
return val.index;
|
||||
}
|
||||
@ -260,22 +245,21 @@ int CLangMngr::GetKeyEntry(const char *key)
|
||||
int CLangMngr::AddKeyEntry(const char *key)
|
||||
{
|
||||
keytbl_val val;
|
||||
val.index = static_cast<int>(KeyList.size());
|
||||
val.index = static_cast<int>(KeyList.length());
|
||||
|
||||
String *pString = new String(key);
|
||||
KeyList.push_back(pString);
|
||||
KeyList.append(new ke::AString(key));
|
||||
|
||||
KeyTable[key] = val;
|
||||
KeyTable[ke::AString(key)] = val;
|
||||
|
||||
return val.index;
|
||||
}
|
||||
|
||||
int CLangMngr::AddKeyEntry(String &key)
|
||||
int CLangMngr::AddKeyEntry(ke::AString &key)
|
||||
{
|
||||
return AddKeyEntry(key.c_str());
|
||||
return AddKeyEntry(key.chars());
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(String &key)
|
||||
int CLangMngr::GetKeyEntry(ke::AString &key)
|
||||
{
|
||||
keytbl_val &val = KeyTable[key];
|
||||
|
||||
@ -288,232 +272,271 @@ char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len)
|
||||
static char outbuf[4096];
|
||||
cell *addr = get_amxaddr(amx, params[parm++]);
|
||||
|
||||
if (amx->flags & AMX_FLAG_OLDFILE)
|
||||
{
|
||||
if (*addr & BCOMPAT_TRANSLATE_BITS)
|
||||
{
|
||||
const char *key, *def;
|
||||
if (!translate_bcompat(amx, addr, &key, &def))
|
||||
{
|
||||
goto normal_string;
|
||||
}
|
||||
len = atcprintf(outbuf, sizeof(outbuf)-1, def, amx, params, &parm);
|
||||
} else {
|
||||
goto normal_string;
|
||||
}
|
||||
} else {
|
||||
normal_string:
|
||||
len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm);
|
||||
}
|
||||
len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm);
|
||||
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
void CLangMngr::MergeDefinitions(const char *lang, CQueue<sKeyDef> &tmpVec)
|
||||
void CLangMngr::MergeDefinitions(const char *lang, ke::Vector<sKeyDef> &tmpVec)
|
||||
{
|
||||
CLang * language = GetLang(lang);
|
||||
if (language)
|
||||
language->MergeDefinitions(tmpVec);
|
||||
}
|
||||
|
||||
void reparse_newlines_and_color(char* def)
|
||||
{
|
||||
size_t len = strlen(def);
|
||||
int offs = 0;
|
||||
int c;
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
c = def[i];
|
||||
|
||||
if (c == '^' && (i != len - 1))
|
||||
{
|
||||
c = def[++i];
|
||||
|
||||
if (c == 'n' || c == 't' || (c >= '1' && c <= '4'))
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': c = '\x01'; break;
|
||||
case '2': c = '\x02'; break;
|
||||
case '3': c = '\x03'; break;
|
||||
case '4': c = '\x04'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
}
|
||||
|
||||
if (!g_bmod_cstrike && (c >= '1' && c <= '4')) // remove completely these two characters if not under CS
|
||||
{
|
||||
offs += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
offs++;
|
||||
}
|
||||
}
|
||||
|
||||
def[i - offs] = c;
|
||||
}
|
||||
|
||||
def[len-offs] = '\0';
|
||||
}
|
||||
|
||||
struct LangFileData
|
||||
{
|
||||
void reset()
|
||||
{
|
||||
multiLine = false;
|
||||
|
||||
*language = '\0';
|
||||
*valueBuffer = '\0';
|
||||
|
||||
clearEntry();
|
||||
}
|
||||
|
||||
void clearEntry()
|
||||
{
|
||||
entry.key = -1;
|
||||
entry.definition = nullptr;
|
||||
}
|
||||
|
||||
bool multiLine;
|
||||
char language[3];
|
||||
char valueBuffer[512];
|
||||
ke::AString currentFile;
|
||||
ke::AString lastKey;
|
||||
ke::Vector<sKeyDef> defsQueue;
|
||||
sKeyDef entry;
|
||||
|
||||
} Data;
|
||||
|
||||
void CLangMngr::ReadINI_ParseStart()
|
||||
{
|
||||
Data.reset();
|
||||
}
|
||||
|
||||
bool CLangMngr::ReadINI_NewSection(const char *section, bool invalid_tokens, bool close_bracket, bool extra_tokens, unsigned int *curtok)
|
||||
{
|
||||
if (Data.multiLine)
|
||||
{
|
||||
AMXXLOG_Log("New section, unterminated block (file \"%s\" key \"%s\" lang \"%s\")", Data.currentFile.chars(), Data.lastKey.chars(), Data.language);
|
||||
|
||||
Data.clearEntry();
|
||||
}
|
||||
|
||||
if (!Data.defsQueue.empty())
|
||||
{
|
||||
MergeDefinitions(Data.language, Data.defsQueue);
|
||||
}
|
||||
|
||||
Data.reset();
|
||||
|
||||
Data.language[0] = section[0];
|
||||
Data.language[1] = section[1];
|
||||
Data.language[2] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLangMngr::ReadINI_KeyValue(const char *key, const char *value, bool invalid_tokens, bool equal_token, bool quotes, unsigned int *curtok)
|
||||
{
|
||||
bool colons_token = (key[strlen(key) - 1] == ':');
|
||||
|
||||
if (!Data.multiLine)
|
||||
{
|
||||
Data.lastKey = key;
|
||||
|
||||
if (colons_token || equal_token)
|
||||
{
|
||||
int iKey = GetKeyEntry(key);
|
||||
|
||||
if (iKey == -1)
|
||||
{
|
||||
iKey = AddKeyEntry(key);
|
||||
}
|
||||
|
||||
if (equal_token)
|
||||
{
|
||||
if(value == nullptr) // Support empty value
|
||||
Data.valueBuffer[0] = '\0';
|
||||
else
|
||||
strncopy(Data.valueBuffer, value, sizeof(Data.valueBuffer));
|
||||
|
||||
reparse_newlines_and_color(Data.valueBuffer);
|
||||
|
||||
Data.entry.key = iKey;
|
||||
Data.entry.definition = new ke::AutoString;
|
||||
*Data.entry.definition = Data.valueBuffer;
|
||||
|
||||
Data.defsQueue.append(Data.entry);
|
||||
Data.clearEntry();
|
||||
}
|
||||
else if (!value && colons_token)
|
||||
{
|
||||
Data.entry.key = iKey;
|
||||
Data.entry.definition = new ke::AutoString;
|
||||
|
||||
Data.multiLine = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AMXXLOG_Log("Invalid multi-lingual line (file \"%s\" key \"%s\" lang \"%s\")", Data.currentFile.chars(), Data.lastKey.chars(), Data.language);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!value && colons_token)
|
||||
{
|
||||
strncopy(Data.valueBuffer, Data.entry.definition->ptr(), sizeof(Data.valueBuffer));
|
||||
reparse_newlines_and_color(Data.valueBuffer);
|
||||
|
||||
*Data.entry.definition = Data.valueBuffer;
|
||||
|
||||
Data.defsQueue.append(Data.entry);
|
||||
Data.clearEntry();
|
||||
|
||||
Data.multiLine = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Data.entry.definition)
|
||||
{
|
||||
Data.entry.definition = new ke::AutoString();
|
||||
}
|
||||
|
||||
*Data.entry.definition = *Data.entry.definition + key;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLangMngr::ReadINI_ParseEnd(bool halted)
|
||||
{
|
||||
if (!Data.defsQueue.empty())
|
||||
{
|
||||
MergeDefinitions(Data.language, Data.defsQueue);
|
||||
}
|
||||
}
|
||||
|
||||
//this is the file parser for dictionary text files
|
||||
// -- BAILOPAN
|
||||
int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
{
|
||||
FILE *fp = fopen(file, "rt");
|
||||
if (!fp)
|
||||
/** Tries to open the file. */
|
||||
struct stat fileStat;
|
||||
if (stat(file, &fileStat))
|
||||
{
|
||||
CVector<md5Pair *>::iterator iter;
|
||||
for (iter = FileList.begin(); iter != FileList.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->file.compare(file) == 0)
|
||||
{
|
||||
char buf[33] = {0};
|
||||
(*iter)->val.assign(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
FileList.remove(file);
|
||||
AMXXLOG_Log("[AMXX] Failed to open dictionary file: %s", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MD5 md5;
|
||||
md5.update(fp); // closes for us
|
||||
md5.finalize();
|
||||
char md5buffer[33];
|
||||
md5.hex_digest(md5buffer);
|
||||
bool foundFlag = false;
|
||||
|
||||
CVector<md5Pair *>::iterator iter;
|
||||
for (iter = FileList.begin(); iter != FileList.end(); ++iter)
|
||||
|
||||
/** Checks if there is an existing entry with same time stamp. */
|
||||
time_t timeStamp;
|
||||
if (FileList.retrieve(file, &timeStamp) && fileStat.st_mtime == timeStamp)
|
||||
{
|
||||
if ((*iter)->file.compare(file) == 0)
|
||||
{
|
||||
if ((*iter)->val.compare(md5buffer) == 0)
|
||||
{
|
||||
return -1;
|
||||
} else {
|
||||
(*iter)->val.assign(md5buffer);
|
||||
break;
|
||||
}
|
||||
foundFlag = true;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!foundFlag)
|
||||
{
|
||||
md5Pair *p = new md5Pair;
|
||||
p->file.assign(file);
|
||||
p->val.assign(md5buffer);
|
||||
FileList.push_back(p);
|
||||
}
|
||||
/** If yes, it either means that the entry doesn't exist or the existing entry needs to be updated. */
|
||||
FileList.replace(file, fileStat.st_mtime);
|
||||
|
||||
fp = fopen(file, "rt");
|
||||
if (!fp)
|
||||
Data.currentFile = file;
|
||||
|
||||
unsigned int line, col;
|
||||
bool result = textparsers->ParseFile_INI(file, static_cast<ITextListener_INI*>(this), &line, &col, false);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] Failed to re-open dictionary file: %s", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate enough memory to store everything
|
||||
bool multiline = 0;
|
||||
int pos = 0, line = 0;
|
||||
CQueue<sKeyDef> Defq;
|
||||
String buf;
|
||||
char language[3];
|
||||
sKeyDef tmpEntry = {NULL, 0};
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
line++;
|
||||
buf._fread(fp);
|
||||
buf.trim();
|
||||
if (buf[0] == 0)
|
||||
continue;
|
||||
if ((buf[0] == ';') || (buf[0] == '/' && buf[1] == '/'))
|
||||
continue;
|
||||
|
||||
if (buf[0] == '[' && buf.size() >= 3)
|
||||
{
|
||||
if (multiline)
|
||||
{
|
||||
AMXXLOG_Log("New section, multiline unterminated (file \"%s\" line %d)", file, line);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
}
|
||||
|
||||
if (!Defq.empty())
|
||||
{
|
||||
MergeDefinitions(language, Defq);
|
||||
}
|
||||
|
||||
language[0] = buf[1];
|
||||
language[1] = buf[2];
|
||||
language[2] = 0;
|
||||
} else {
|
||||
if (!multiline)
|
||||
{
|
||||
pos = buf.find('=');
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());
|
||||
String def;
|
||||
def.assign(buf.substr(pos + 1).c_str());
|
||||
key.trim();
|
||||
key.toLower();
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
tmpEntry.definition->assign(def.c_str());
|
||||
tmpEntry.definition->trim();
|
||||
tmpEntry.definition->reparse_newlines();
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
} else {
|
||||
pos = buf.find(':');
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());;
|
||||
key.trim();
|
||||
key.toLower();
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
multiline = true;
|
||||
} else {
|
||||
//user typed a line with no directives
|
||||
AMXXLOG_Log("Invalid multi-lingual line (file \"%s\" line %d)", file, line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (buf[0] == ':')
|
||||
{
|
||||
tmpEntry.definition->reparse_newlines();
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
multiline = false;
|
||||
} else {
|
||||
if (!tmpEntry.definition)
|
||||
tmpEntry.definition = new String();
|
||||
tmpEntry.definition->append(buf);
|
||||
}
|
||||
} // if !multiline
|
||||
} //if - main
|
||||
}
|
||||
|
||||
// merge last section
|
||||
if (!Defq.empty())
|
||||
{
|
||||
MergeDefinitions(language, Defq);
|
||||
}
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find a CLang by name, if not found, add it
|
||||
CLangMngr::CLang * CLangMngr::GetLang(const char *name)
|
||||
{
|
||||
LangVecIter iter;
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), name) == 0)
|
||||
return (*iter);
|
||||
if (strcmp(m_Languages[iter]->GetName(), name) == 0)
|
||||
return m_Languages[iter];
|
||||
}
|
||||
|
||||
CLang *p = new CLang(name);
|
||||
p->SetMngr(this);
|
||||
|
||||
m_Languages.push_back(p);
|
||||
m_Languages.append(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Find a CLang by name, if not found, return NULL
|
||||
CLangMngr::CLang * CLangMngr::GetLangR(const char *name)
|
||||
{
|
||||
LangVecIter iter;
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), name) == 0)
|
||||
return (*iter);
|
||||
if (strcmp(m_Languages[iter]->GetName(), name) == 0)
|
||||
return m_Languages[iter];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *CLangMngr::GetDef(const char *langName, const char *key, int &status)
|
||||
{
|
||||
CLang *lang = GetLangR(langName);
|
||||
keytbl_val &val = KeyTable.AltFindOrInsert(key); //KeyTable[make_string(key)];
|
||||
|
||||
keytbl_val &val = KeyTable.AltFindOrInsert(ke::AString(key)); //KeyTable[make_string(key)];
|
||||
if (lang == NULL)
|
||||
{
|
||||
status = ERR_BADLANG;
|
||||
@ -522,18 +545,13 @@ const char *CLangMngr::GetDef(const char *langName, const char *key, int &status
|
||||
status = ERR_BADKEY;
|
||||
return NULL;
|
||||
} else {
|
||||
status = 0;
|
||||
return lang->GetDef(val.index, status);
|
||||
}
|
||||
}
|
||||
|
||||
void CLangMngr::InvalidateCache()
|
||||
{
|
||||
for (size_t i = 0; i < FileList.size(); i++)
|
||||
{
|
||||
if (FileList[i])
|
||||
delete FileList[i];
|
||||
}
|
||||
|
||||
FileList.clear();
|
||||
}
|
||||
|
||||
@ -548,19 +566,13 @@ void CLangMngr::Clear()
|
||||
|
||||
KeyTable.clear();
|
||||
|
||||
for (i = 0; i < m_Languages.size(); i++)
|
||||
for (i = 0; i < m_Languages.length(); i++)
|
||||
{
|
||||
if (m_Languages[i])
|
||||
delete m_Languages[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < FileList.size(); i++)
|
||||
{
|
||||
if (FileList[i])
|
||||
delete FileList[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < KeyList.size(); i++)
|
||||
for (i = 0; i < KeyList.length(); i++)
|
||||
{
|
||||
if (KeyList[i])
|
||||
delete KeyList[i];
|
||||
@ -573,23 +585,19 @@ void CLangMngr::Clear()
|
||||
|
||||
int CLangMngr::GetLangsNum()
|
||||
{
|
||||
return m_Languages.size();
|
||||
return m_Languages.length();
|
||||
}
|
||||
|
||||
const char *CLangMngr::GetLangName(int langId)
|
||||
{
|
||||
int i = 0;
|
||||
LangVecIter iter;
|
||||
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (i == langId)
|
||||
if ((int)iter == langId)
|
||||
{
|
||||
return (*iter)->GetName();
|
||||
return m_Languages[iter]->GetName();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -604,14 +612,13 @@ bool CLangMngr::LangExists(const char *langName)
|
||||
break;
|
||||
}
|
||||
|
||||
LangVecIter iter;
|
||||
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), buf) == 0)
|
||||
if (strcmp(m_Languages[iter]->GetName(), buf) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,38 +1,18 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_CLANG_H
|
||||
#define _INCLUDE_CLANG_H
|
||||
|
||||
#include "sh_tinyhash.h"
|
||||
#include "sm_stringhashmap.h"
|
||||
#include <ITextParsers.h>
|
||||
|
||||
#define LANG_SERVER 0
|
||||
#define LANG_PLAYER -1
|
||||
@ -40,15 +20,9 @@
|
||||
#define ERR_BADKEY 1 // Lang key not found
|
||||
#define ERR_BADLANG 2 // Invalid lang
|
||||
|
||||
struct md5Pair
|
||||
{
|
||||
String file;
|
||||
String val;
|
||||
};
|
||||
|
||||
struct sKeyDef
|
||||
{
|
||||
String *definition;
|
||||
ke::AutoString* definition;
|
||||
int key;
|
||||
};
|
||||
|
||||
@ -73,7 +47,7 @@ public:
|
||||
~defentry()
|
||||
{
|
||||
}
|
||||
String *definition;
|
||||
ke::AString *definition;
|
||||
};
|
||||
|
||||
struct keytbl_val
|
||||
@ -84,7 +58,7 @@ struct keytbl_val
|
||||
int index;
|
||||
};
|
||||
|
||||
class CLangMngr
|
||||
class CLangMngr : public ITextListener_INI
|
||||
{
|
||||
class CLang
|
||||
{
|
||||
@ -99,7 +73,7 @@ class CLangMngr
|
||||
// Get the definition
|
||||
const char *GetDef(int key, int &status);
|
||||
// Add definitions to this language
|
||||
void MergeDefinitions(CQueue <sKeyDef> & vec);
|
||||
void MergeDefinitions(ke::Vector <sKeyDef> & vec);
|
||||
// Reset this language
|
||||
void Clear();
|
||||
|
||||
@ -129,20 +103,25 @@ class CLangMngr
|
||||
};
|
||||
public:
|
||||
// Merge definitions into a language
|
||||
void MergeDefinitions(const char *lang, CQueue <sKeyDef> &tmpVec);
|
||||
void MergeDefinitions(const char *lang, ke::Vector <sKeyDef> &tmpVec);
|
||||
|
||||
public: // ITextListener_INI
|
||||
void ReadINI_ParseStart();
|
||||
void ReadINI_ParseEnd(bool halted);
|
||||
bool ReadINI_NewSection(const char *section, bool invalid_tokens, bool close_bracket, bool extra_tokens, unsigned int *curtok);
|
||||
bool ReadINI_KeyValue(const char *key, const char *value, bool invalid_tokens, bool equal_token, bool quotes, unsigned int *curtok);
|
||||
|
||||
private:
|
||||
// strip lowercase; make lower if needed
|
||||
static size_t strip(char *str, char *newstr, bool makelower = false);
|
||||
|
||||
typedef CVector<CLang*> LangVec;
|
||||
typedef CVector<CLang*>::iterator LangVecIter;
|
||||
typedef ke::Vector<CLang*> LangVec;
|
||||
|
||||
LangVec m_Languages;
|
||||
|
||||
CVector<md5Pair *> FileList;
|
||||
CVector<String *> KeyList;
|
||||
THash<String, keytbl_val> KeyTable;
|
||||
StringHashMap<time_t> FileList;
|
||||
ke::Vector<ke::AString *> KeyList;
|
||||
THash<ke::AString, keytbl_val> KeyTable;
|
||||
|
||||
// Get a lang object (construct if needed)
|
||||
CLang * GetLang(const char *name);
|
||||
@ -160,12 +139,12 @@ public:
|
||||
char *FormatAmxString(AMX *amx, cell *params, int parm, int &len);
|
||||
void InvalidateCache();
|
||||
// Get index
|
||||
int GetKeyEntry(String &key);
|
||||
int GetKeyEntry(ke::AString &key);
|
||||
int GetKeyEntry(const char *key);
|
||||
// Get key from index
|
||||
const char *GetKey(int key);
|
||||
// Add key
|
||||
int AddKeyEntry(String &key);
|
||||
int AddKeyEntry(ke::AString &key);
|
||||
int AddKeyEntry(const char *key);
|
||||
|
||||
// Get the number of languages
|
||||
|
388
amxmodx/CLibrarySys.cpp
Normal file
388
amxmodx/CLibrarySys.cpp
Normal file
@ -0,0 +1,388 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "CLibrarySys.h"
|
||||
#include <amxmodx.h>
|
||||
#include <amtl/os/am-fsutil.h>
|
||||
#include <amtl/os/am-path.h>
|
||||
#include <amtl/os/am-system-errors.h>
|
||||
|
||||
LibrarySystem g_LibSys;
|
||||
|
||||
/******************/
|
||||
/* Directory Code */
|
||||
/******************/
|
||||
|
||||
CDirectory::CDirectory(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
char newpath[PLATFORM_MAX_PATH];
|
||||
ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
||||
|
||||
m_dir = FindFirstFile(newpath, &m_fd);
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
m_fd.cFileName[0] = '\0';
|
||||
}
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
m_dir = opendir(path);
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
m_ep = readdir(m_dir); // TODO: we need to read past "." and ".."!
|
||||
ke::SafeSprintf(m_origpath, sizeof(m_origpath), "%s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ep = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CDirectory::~CDirectory()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
FindClose(m_dir);
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
closedir(m_dir);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DirHandle CDirectory::GetHandle()
|
||||
{
|
||||
return m_dir;
|
||||
}
|
||||
|
||||
void CDirectory::NextEntry()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
if (FindNextFile(m_dir, &m_fd) == 0)
|
||||
{
|
||||
FindClose(m_dir);
|
||||
m_dir = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
if (!(m_ep = readdir(m_dir)))
|
||||
{
|
||||
closedir(m_dir);
|
||||
m_dir = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryValid()
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryDirectory()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
|
||||
return ke::file::IsDirectory(temppath);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryFile()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
|
||||
return ke::file::IsFile(temppath);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* CDirectory::GetEntryName()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
return m_fd.cFileName;
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
return m_ep ? m_ep->d_name : "";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::MoreFiles()
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
bool CDirectory::IsValid()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
return (m_dir != INVALID_HANDLE_VALUE);
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
return (m_dir != nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/****************/
|
||||
/* Library Code */
|
||||
/****************/
|
||||
|
||||
CLibrary::CLibrary(ke::RefPtr<ke::SharedLib> lib) : lib_(lib)
|
||||
{}
|
||||
|
||||
void CLibrary::CloseLibrary()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void *CLibrary::GetSymbolAddress(const char* symname)
|
||||
{
|
||||
return lib_->lookup(symname);
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* Library System Code */
|
||||
/***********************/
|
||||
|
||||
bool LibrarySystem::PathExists(const char *path)
|
||||
{
|
||||
return ke::file::PathExists(path);
|
||||
}
|
||||
|
||||
bool LibrarySystem::IsPathFile(const char* path)
|
||||
{
|
||||
return ke::file::IsFile(path);
|
||||
}
|
||||
|
||||
bool LibrarySystem::IsPathDirectory(const char* path)
|
||||
{
|
||||
return ke::file::IsDirectory(path);
|
||||
}
|
||||
|
||||
CDirectory *LibrarySystem::OpenDirectory(const char* path)
|
||||
{
|
||||
CDirectory* dir = new CDirectory(path);
|
||||
|
||||
if (!dir->IsValid())
|
||||
{
|
||||
delete dir;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
CLibrary* LibrarySystem::OpenLibrary(const char* path, char* error, size_t maxlength)
|
||||
{
|
||||
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(path, error, maxlength);
|
||||
|
||||
if (!lib)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new CLibrary(lib);
|
||||
}
|
||||
|
||||
void LibrarySystem::GetPlatformError(char* error, size_t maxlength)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
return GetPlatformErrorEx(GetLastError(), error, maxlength);
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
return GetPlatformErrorEx(errno, error, maxlength);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LibrarySystem::GetPlatformErrorEx(int code, char* error, size_t maxlength)
|
||||
{
|
||||
if (error && maxlength)
|
||||
{
|
||||
ke::FormatSystemErrorCode(code, error, maxlength);
|
||||
}
|
||||
}
|
||||
|
||||
void LibrarySystem::GetLoaderError(char* buffer, size_t maxlength)
|
||||
{
|
||||
ke::FormatSystemError(buffer, maxlength);
|
||||
}
|
||||
|
||||
void LibrarySystem::CloseDirectory(CDirectory *dir)
|
||||
{
|
||||
delete dir;
|
||||
}
|
||||
|
||||
size_t LibrarySystem::PathFormat(char* buffer, size_t len, const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
size_t mylen = ke::path::FormatVa(buffer, len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return mylen;
|
||||
}
|
||||
|
||||
char* LibrarySystem::PathFormat(const char* fmt, ...)
|
||||
{
|
||||
static char buffer[PLATFORM_MAX_PATH];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ke::path::FormatVa(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* LibrarySystem::GetFileExtension(const char* filename)
|
||||
{
|
||||
size_t len, end;
|
||||
|
||||
len = strlen(filename);
|
||||
|
||||
/* Minimum string length for filename with ext would be 3; example: a.a */
|
||||
if (len < 3)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
end = len - 1;
|
||||
|
||||
for (size_t i = end; i <= end; i--)
|
||||
{
|
||||
if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (filename[i] == '.' && i != end && i != 0)
|
||||
{
|
||||
return &filename[++i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool LibrarySystem::CreateFolder(const char* path)
|
||||
{
|
||||
return ke::file::CreateDirectory(path, 0775);
|
||||
}
|
||||
|
||||
size_t LibrarySystem::GetFileFromPath(char* buffer, size_t maxlength, const char* path)
|
||||
{
|
||||
size_t length = strlen(path);
|
||||
|
||||
for (size_t i = length - 1; i <= length - 1; i--)
|
||||
{
|
||||
if (path[i] == '/'
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|| path[i] == '\\'
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ke::SafeSprintf(buffer, maxlength, "%s", &path[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* We scanned and found no path separator */
|
||||
return ke::SafeSprintf(buffer, maxlength, "%s", path);
|
||||
}
|
||||
|
||||
bool LibrarySystem::FileTime(const char* path, FileTimeType type, time_t* pTime)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
if (stat(path, &s) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FileTime_LastAccess:
|
||||
{
|
||||
*pTime = s.st_atime;
|
||||
break;
|
||||
}
|
||||
case FileTime_Created:
|
||||
{
|
||||
*pTime = s.st_ctime;
|
||||
break;
|
||||
}
|
||||
case FileTime_LastChange:
|
||||
{
|
||||
*pTime = s.st_mtime;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibrarySystem::DoesPlatformMatch(const char *platform)
|
||||
{
|
||||
return strcmp(platform, PLATFORM_NAME) == 0;
|
||||
}
|
||||
|
||||
bool LibrarySystem::IsPlatformCompatible(const char *platform, bool *hadPrimaryMatch)
|
||||
{
|
||||
if (DoesPlatformMatch(platform))
|
||||
{
|
||||
#if defined PLATFORM_COMPAT_ALT
|
||||
*hadPrimaryMatch = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined PLATFORM_COMPAT_ALT
|
||||
/* If entry hasn't been found for the primary platform name, check for compatible alternate */
|
||||
if (!*hadPrimaryMatch)
|
||||
{
|
||||
return strcmp(platform, PLATFORM_COMPAT_ALT) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
107
amxmodx/CLibrarySys.h
Normal file
107
amxmodx/CLibrarySys.h
Normal file
@ -0,0 +1,107 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_LIBRARY_SYS_H_
|
||||
#define _INCLUDE_LIBRARY_SYS_H_
|
||||
|
||||
#include "amx.h" // cell
|
||||
#include <platform_helpers.h>
|
||||
#include <amtl/os/am-shared-library.h>
|
||||
|
||||
enum FileTimeType
|
||||
{
|
||||
FileTime_LastAccess = 0, /* Last access (not available on FAT) */
|
||||
FileTime_Created = 1, /* Creation (not available on FAT) */
|
||||
FileTime_LastChange = 2, /* Last modification */
|
||||
};
|
||||
|
||||
class CDirectory
|
||||
{
|
||||
public:
|
||||
|
||||
CDirectory(const char* path);
|
||||
~CDirectory();
|
||||
|
||||
public:
|
||||
|
||||
bool MoreFiles();
|
||||
void NextEntry();
|
||||
const char* GetEntryName();
|
||||
bool IsEntryDirectory();
|
||||
bool IsEntryFile();
|
||||
bool IsEntryValid();
|
||||
|
||||
public:
|
||||
|
||||
bool IsValid();
|
||||
DirHandle GetHandle();
|
||||
|
||||
private:
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
HANDLE m_dir;
|
||||
WIN32_FIND_DATAA m_fd;
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
DIR* m_dir;
|
||||
struct dirent* m_ep;
|
||||
char m_origpath[PLATFORM_MAX_PATH];
|
||||
#endif
|
||||
};
|
||||
|
||||
class CLibrary
|
||||
{
|
||||
public:
|
||||
|
||||
CLibrary(ke::RefPtr<ke::SharedLib> lib);
|
||||
|
||||
public:
|
||||
|
||||
void CloseLibrary();
|
||||
void *GetSymbolAddress(const char* symname);
|
||||
|
||||
private:
|
||||
|
||||
ke::RefPtr<ke::SharedLib> lib_;
|
||||
};
|
||||
|
||||
class LibrarySystem
|
||||
{
|
||||
public:
|
||||
|
||||
CLibrary* OpenLibrary(const char* path, char* error = nullptr, size_t maxlength = 0);
|
||||
CDirectory* OpenDirectory(const char* path);
|
||||
void CloseDirectory(CDirectory *dir);
|
||||
|
||||
bool PathExists(const char* path);
|
||||
bool IsPathFile(const char* path);
|
||||
bool IsPathDirectory(const char* path);
|
||||
|
||||
void GetPlatformError(char* error, size_t maxlength);
|
||||
void GetPlatformErrorEx(int code, char* error, size_t maxlength);
|
||||
|
||||
size_t PathFormat(char* buffer, size_t len, const char* fmt, ...);
|
||||
char* PathFormat(const char* fmt, ...);
|
||||
|
||||
const char* GetFileExtension(const char* filename);
|
||||
bool CreateFolder(const char* path);
|
||||
size_t GetFileFromPath(char* buffer, size_t maxlength, const char* path);
|
||||
|
||||
bool FileTime(const char* path, FileTimeType type, time_t* pTime);
|
||||
void GetLoaderError(char* buffer, size_t maxlength);
|
||||
|
||||
bool DoesPlatformMatch(const char* platform);
|
||||
bool IsPlatformCompatible(const char *platform, bool *hadPrimaryMatch);
|
||||
};
|
||||
|
||||
extern LibrarySystem g_LibSys;
|
||||
|
||||
#endif // _INCLUDE_LIBRARY_SYS_H_
|
329
amxmodx/CList.h
329
amxmodx/CList.h
@ -1,329 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#ifndef CLIST_H
|
||||
#define CLIST_H
|
||||
|
||||
// *****************************************************
|
||||
// class CList
|
||||
// *****************************************************
|
||||
|
||||
// Linked list
|
||||
template <typename T, typename F = char* >
|
||||
class CList
|
||||
{
|
||||
private:
|
||||
// One list element
|
||||
class CElement
|
||||
{
|
||||
T *m_pObject; // pointer to the object
|
||||
CElement *m_pNext; // pointer to the next element
|
||||
CElement *m_pPrev; // pointer to the previous element
|
||||
public:
|
||||
// dereference operator
|
||||
T& operator* ()
|
||||
{
|
||||
return *m_pObject;
|
||||
}
|
||||
|
||||
// constructor
|
||||
CElement(T *pObj)
|
||||
{
|
||||
m_pObject = pObj;
|
||||
m_pNext = NULL;
|
||||
m_pPrev = NULL;
|
||||
}
|
||||
|
||||
// destructor
|
||||
~CElement()
|
||||
{
|
||||
delete m_pObject;
|
||||
|
||||
if (m_pNext)
|
||||
m_pNext->m_pPrev = m_pPrev;
|
||||
|
||||
if (m_pPrev)
|
||||
m_pPrev->m_pNext = m_pNext;
|
||||
}
|
||||
|
||||
// returns object pointer
|
||||
T *GetObj()
|
||||
{
|
||||
return m_pObject;
|
||||
}
|
||||
|
||||
// returns next element pointer
|
||||
CElement *GetNext()
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
// sets next element
|
||||
void SetNext(CElement *newNext)
|
||||
{
|
||||
m_pNext = newNext;
|
||||
}
|
||||
|
||||
// returns previous element pointer
|
||||
CElement *GetPrev()
|
||||
{
|
||||
return m_pPrev;
|
||||
}
|
||||
|
||||
// sets previous element
|
||||
void SetPrev(CElement *newPrev)
|
||||
{
|
||||
m_pPrev = newPrev;
|
||||
}
|
||||
};
|
||||
|
||||
// CList<T, F> class
|
||||
CElement *m_pHead; // head of the linked list
|
||||
CElement *m_pTail; // tail of the linked list
|
||||
public:
|
||||
// iterator class
|
||||
class iterator
|
||||
{
|
||||
friend class CList<T, F>;
|
||||
|
||||
CList<T, F> *m_pList; // The list that created this iterator
|
||||
CElement *m_CurPos; // Current position in the list
|
||||
public:
|
||||
iterator()
|
||||
{
|
||||
m_pList = NULL;
|
||||
m_CurPos = NULL;
|
||||
}
|
||||
|
||||
// constructor based on list, element
|
||||
iterator(CList<T, F> *pList, CElement *startPos)
|
||||
{
|
||||
m_pList = pList;
|
||||
m_CurPos = startPos;
|
||||
}
|
||||
|
||||
// constructor based on other iterator
|
||||
iterator(const iterator &other)
|
||||
{
|
||||
m_pList = other.m_pList;
|
||||
m_CurPos = other.m_CurPos;
|
||||
}
|
||||
|
||||
// dereference operator
|
||||
T & operator* () const
|
||||
{
|
||||
return *m_CurPos->GetObj();
|
||||
}
|
||||
|
||||
T * operator-> () const
|
||||
{
|
||||
return m_CurPos->GetObj();
|
||||
}
|
||||
|
||||
// validity check operator
|
||||
inline operator bool () const
|
||||
{
|
||||
return m_pList != NULL && m_CurPos != NULL && m_CurPos->GetObj() != NULL;
|
||||
}
|
||||
|
||||
// pre increment operator
|
||||
inline iterator& operator ++ ()
|
||||
{
|
||||
m_CurPos = m_CurPos->GetNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// post increment operator
|
||||
inline iterator operator++(int)
|
||||
{
|
||||
iterator tmp(*this);
|
||||
m_CurPos = m_CurPos->next;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// returns iterator that points to next element
|
||||
iterator GetNext()
|
||||
{
|
||||
iterator tmp(*this);
|
||||
return ++tmp;
|
||||
}
|
||||
|
||||
iterator remove()
|
||||
{
|
||||
return m_pList->remove(*this);
|
||||
}
|
||||
|
||||
iterator put(T *obj)
|
||||
{
|
||||
return m_pList->put(obj, *this);
|
||||
}
|
||||
};
|
||||
|
||||
CList<T, F>()
|
||||
{
|
||||
m_pHead = NULL;
|
||||
m_pTail = NULL;
|
||||
}
|
||||
|
||||
~CList<T, F>()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// removes the object referenced by where
|
||||
// sets where to the next object
|
||||
// returns an iterator pointing to the next object
|
||||
iterator remove(iterator &where)
|
||||
{
|
||||
iterator tmp(where.GetNext());
|
||||
|
||||
if (where.m_CurPos == m_pHead)
|
||||
m_pHead = where.m_CurPos->GetNext();
|
||||
|
||||
if (where.m_CurPos == m_pTail)
|
||||
m_pTail = where.m_CurPos->GetPrev();
|
||||
|
||||
delete where.m_CurPos;
|
||||
where = tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// puts an element to the end of the list
|
||||
// returns an iterator pointing to it
|
||||
iterator put_back(T *pObj)
|
||||
{
|
||||
CElement *pTmp = new CElement(pObj);
|
||||
|
||||
if (!m_pHead)
|
||||
{
|
||||
m_pHead = pTmp;
|
||||
m_pTail = pTmp;
|
||||
} else {
|
||||
pTmp->SetNext(NULL);
|
||||
pTmp->SetPrev(m_pTail);
|
||||
m_pTail->SetNext(pTmp);
|
||||
m_pTail = pTmp;
|
||||
}
|
||||
|
||||
return iterator(this, pTmp);
|
||||
}
|
||||
|
||||
iterator put_front(T *pObj)
|
||||
{
|
||||
CElement *pTmp = new CElement(pObj);
|
||||
|
||||
if (!m_pHead)
|
||||
{
|
||||
m_pHead = pTmp;
|
||||
m_pTail = pTmp;
|
||||
} else {
|
||||
pTmp->SetNext(m_pHead);
|
||||
pTmp->SetPrev(NULL);
|
||||
m_pHead->SetPrev(pTmp);
|
||||
m_pHead = pTmp;
|
||||
}
|
||||
|
||||
return iterator(this, pTmp);
|
||||
}
|
||||
|
||||
// alias for put_back
|
||||
iterator put(T *pObj)
|
||||
{
|
||||
return put_back(pObj);
|
||||
}
|
||||
|
||||
// puts an element after where
|
||||
// alters where to point to the new element
|
||||
// returns an iterator pointing to the new element
|
||||
iterator put(T *pObj, iterator &where)
|
||||
{
|
||||
CElement *pTmp = new CElement(pObj);
|
||||
|
||||
if (where.m_CurPos->GetNext())
|
||||
where.m_CurPos->GetNext()->SetPrev(pTmp);
|
||||
else // where = tail
|
||||
m_pTail = pTmp;
|
||||
|
||||
pTmp->SetPrev(where.m_CurPos);
|
||||
pTmp->SetNext(where.m_CurPos->GetNext());
|
||||
|
||||
where.m_CurPos->SetNext(pTmp);
|
||||
|
||||
return ++where;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(this, m_pHead);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
iterator iter = begin();
|
||||
while (iter) iter.remove();
|
||||
}
|
||||
|
||||
iterator find(iterator startOn, const F &desc)
|
||||
{
|
||||
iterator iter = startOn;
|
||||
while (iter)
|
||||
{
|
||||
if (*iter == desc)
|
||||
break;
|
||||
++iter;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
iterator find(const F &desc)
|
||||
{
|
||||
return find(begin(), desc);
|
||||
}
|
||||
|
||||
int size()
|
||||
{
|
||||
iterator iter = begin();
|
||||
int i = 0;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
++i;
|
||||
++iter;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //CLIST_H
|
@ -1,37 +1,17 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CLogEvent.h"
|
||||
|
||||
NativeHandle<LogEventHook> LogEventHandles;
|
||||
|
||||
// *****************************************************
|
||||
// class LogEventsMngr
|
||||
// *****************************************************
|
||||
@ -57,9 +37,9 @@ int LogEventsMngr::CLogCmp::compareCondition(const char* string)
|
||||
logid = parent->logCounter;
|
||||
|
||||
if (in)
|
||||
return result = strstr(string, text.c_str()) ? 0 : 1;
|
||||
return result = strstr(string, text.chars()) ? 0 : 1;
|
||||
|
||||
return result = strcmp(string,text.c_str());
|
||||
return result = strcmp(string,text.chars());
|
||||
}
|
||||
|
||||
LogEventsMngr::CLogCmp* LogEventsMngr::registerCondition(char* filter)
|
||||
@ -81,7 +61,7 @@ LogEventsMngr::CLogCmp* LogEventsMngr::registerCondition(char* filter)
|
||||
|
||||
while (c)
|
||||
{
|
||||
if ((c->pos == pos) && (c->in == in) && !strcmp(c->text.c_str(), filter))
|
||||
if ((c->pos == pos) && (c->in == in) && !strcmp(c->text.chars(), filter))
|
||||
return c;
|
||||
c = c->next;
|
||||
}
|
||||
@ -111,7 +91,7 @@ void LogEventsMngr::CLogEvent::registerFilter(char* filter)
|
||||
filters = new LogCond(cmp->pos, aa, filters);
|
||||
}
|
||||
|
||||
void LogEventsMngr::setLogString(char* frmt, va_list& vaptr)
|
||||
void LogEventsMngr::setLogString(const char* frmt, va_list& vaptr)
|
||||
{
|
||||
++logCounter;
|
||||
int len = vsnprintf(logString, 255, frmt, vaptr);
|
||||
@ -128,7 +108,7 @@ void LogEventsMngr::setLogString(char* frmt, va_list& vaptr)
|
||||
logArgc = 0;
|
||||
}
|
||||
|
||||
void LogEventsMngr::setLogString(char* frmt, ...)
|
||||
void LogEventsMngr::setLogString(const char* frmt, ...)
|
||||
{
|
||||
++logCounter;
|
||||
va_list logArgPtr;
|
||||
@ -186,18 +166,37 @@ void LogEventsMngr::parseLogString()
|
||||
}
|
||||
}
|
||||
|
||||
LogEventsMngr::CLogEvent* LogEventsMngr::registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos)
|
||||
void LogEventsMngr::CLogEvent::setForwardState(ForwardState state)
|
||||
{
|
||||
m_State = state;
|
||||
}
|
||||
|
||||
int LogEventsMngr::registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos)
|
||||
{
|
||||
if (pos < 1 || pos > MAX_LOGARGS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
arelogevents = true;
|
||||
CLogEvent** d = &logevents[pos];
|
||||
|
||||
auto d = &logevents[pos];
|
||||
|
||||
while (*d)
|
||||
{
|
||||
d = &(*d)->next;
|
||||
|
||||
return *d = new CLogEvent(plugin, func, this);
|
||||
}
|
||||
|
||||
auto logevent = new CLogEvent(plugin, func, this);
|
||||
auto handle = LogEventHandles.create(logevent);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*d = logevent;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void LogEventsMngr::executeLogEvents()
|
||||
@ -206,8 +205,13 @@ void LogEventsMngr::executeLogEvents()
|
||||
|
||||
for (CLogEvent* a = logevents[logArgc]; a; a = a->next)
|
||||
{
|
||||
if (a->m_State != FSTATE_ACTIVE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
|
||||
|
||||
for (CLogEvent::LogCond* b = a->filters; b; b = b->next)
|
||||
{
|
||||
valid = false;
|
||||
@ -220,11 +224,11 @@ void LogEventsMngr::executeLogEvents()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
|
||||
if (!valid)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (valid)
|
||||
{
|
||||
executeForwards(a->func);
|
||||
@ -249,6 +253,8 @@ void LogEventsMngr::clearLogEvents()
|
||||
}
|
||||
|
||||
clearConditions();
|
||||
|
||||
LogEventHandles.clear();
|
||||
}
|
||||
|
||||
void LogEventsMngr::clearConditions()
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef LOGEVENTS_H
|
||||
#define LOGEVENTS_H
|
||||
@ -35,6 +13,7 @@
|
||||
#define MAX_LOGARGS 12
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "natives_handles.h"
|
||||
|
||||
// *****************************************************
|
||||
// class LogEventsMngr
|
||||
@ -63,7 +42,7 @@ public:
|
||||
friend class CLogEvent;
|
||||
|
||||
LogEventsMngr* parent;
|
||||
String text;
|
||||
ke::AString text;
|
||||
|
||||
int logid;
|
||||
int pos;
|
||||
@ -117,13 +96,16 @@ public:
|
||||
|
||||
LogCond *filters;
|
||||
LogEventsMngr* parent;
|
||||
|
||||
|
||||
ForwardState m_State;
|
||||
|
||||
CLogEvent *next;
|
||||
CLogEvent(CPluginMngr::CPlugin *p, int f, LogEventsMngr* ppp) : plugin(p), func(f), filters(0), parent(ppp), next(0) {}
|
||||
CLogEvent(CPluginMngr::CPlugin *p, int f, LogEventsMngr* ppp) : plugin(p), func(f), filters(nullptr), parent(ppp), m_State(FSTATE_ACTIVE), next(nullptr) {}
|
||||
~CLogEvent();
|
||||
public:
|
||||
inline CPluginMngr::CPlugin *getPlugin() { return plugin; }
|
||||
void registerFilter(char* filter);
|
||||
void setForwardState(ForwardState value);
|
||||
inline int getFunction() { return func; }
|
||||
};
|
||||
|
||||
@ -138,11 +120,11 @@ public:
|
||||
~LogEventsMngr();
|
||||
|
||||
// Interface
|
||||
CLogEvent* registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos);
|
||||
int registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos);
|
||||
inline bool logEventsExist() { return arelogevents; }
|
||||
|
||||
void setLogString(char* frmt, va_list& vaptr);
|
||||
void setLogString(char* frmt, ...);
|
||||
void setLogString(const char* frmt, va_list& vaptr);
|
||||
void setLogString(const char* frmt, ...);
|
||||
void parseLogString();
|
||||
void executeLogEvents();
|
||||
|
||||
@ -175,4 +157,12 @@ public:
|
||||
inline iterator end() { return iterator(0, this); }
|
||||
};
|
||||
|
||||
struct LogEventHook
|
||||
{
|
||||
explicit LogEventHook(LogEventsMngr::CLogEvent *logevent) : m_logevent(logevent) {}
|
||||
LogEventsMngr::CLogEvent *m_logevent;
|
||||
};
|
||||
|
||||
extern NativeHandle<LogEventHook> LogEventHandles;
|
||||
|
||||
#endif //LOGEVENTS_H
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CMenu.h"
|
||||
@ -35,13 +13,15 @@
|
||||
// *****************************************************
|
||||
// class MenuMngr
|
||||
// *****************************************************
|
||||
MenuMngr::MenuCommand::MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f)
|
||||
MenuMngr::MenuCommand::MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f, bool new_menu)
|
||||
{
|
||||
plugin = a;
|
||||
keys = k;
|
||||
menuid = mi;
|
||||
function = f;
|
||||
next = 0;
|
||||
is_new_menu = new_menu;
|
||||
|
||||
function = f;
|
||||
}
|
||||
|
||||
MenuMngr::~MenuMngr()
|
||||
@ -54,77 +34,54 @@ int MenuMngr::findMenuId(const char* name, AMX* amx)
|
||||
{
|
||||
for (MenuIdEle* b = headid; b; b = b->next)
|
||||
{
|
||||
if ((!amx || !b->amx || amx == b->amx) && strstr(name,b->name.c_str()))
|
||||
if ((!amx || !b->amx || amx == b->amx) && strstr(name,b->name.chars()))
|
||||
return b->id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MenuMngr::removeMenuId(int id)
|
||||
{
|
||||
MenuIdEle *n = headid;
|
||||
MenuIdEle *l = NULL;
|
||||
while (n)
|
||||
{
|
||||
if (n->id == id)
|
||||
{
|
||||
if (l)
|
||||
l->next = n->next;
|
||||
else
|
||||
headid = n->next;
|
||||
delete n;
|
||||
break;
|
||||
}
|
||||
l = n;
|
||||
n = n->next;
|
||||
}
|
||||
|
||||
MenuCommand *c = headcmd;
|
||||
MenuCommand *lc = NULL;
|
||||
MenuCommand *tmp;
|
||||
while (c)
|
||||
{
|
||||
if (c->menuid == id)
|
||||
{
|
||||
if (m_watch_iter.a == c)
|
||||
{
|
||||
++m_watch_iter;
|
||||
}
|
||||
if (lc)
|
||||
lc->next = c->next;
|
||||
else
|
||||
headcmd = c->next;
|
||||
tmp = c->next;
|
||||
delete c;
|
||||
c = tmp;
|
||||
} else {
|
||||
lc = c;
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int MenuMngr::registerMenuId(const char* n, AMX* a)
|
||||
{
|
||||
int id = findMenuId(n, a);
|
||||
|
||||
if (id)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
headid = new MenuIdEle(n, a, headid);
|
||||
|
||||
if (!headid)
|
||||
return 0; // :TODO: Better error report
|
||||
|
||||
return headid->id;
|
||||
}
|
||||
|
||||
void MenuMngr::registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f)
|
||||
void MenuMngr::registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f, bool from_new_menu)
|
||||
{
|
||||
MenuCommand** temp = &headcmd;
|
||||
while (*temp) temp = &(*temp)->next;
|
||||
*temp = new MenuCommand(a, mi, k, f);
|
||||
MenuCommand **temp = &headcmd;
|
||||
if (from_new_menu)
|
||||
{
|
||||
MenuCommand *ptr;
|
||||
while (*temp)
|
||||
{
|
||||
ptr = *temp;
|
||||
if (ptr->is_new_menu
|
||||
&& ptr->plugin == a
|
||||
&& ptr->menuid == mi)
|
||||
{
|
||||
if (g_forwards.isSameSPForward(ptr->function, f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
temp = &(*temp)->next;
|
||||
}
|
||||
} else {
|
||||
while (*temp)
|
||||
{
|
||||
temp = &(*temp)->next;
|
||||
}
|
||||
}
|
||||
*temp = new MenuCommand(a, mi, k, f, from_new_menu);
|
||||
}
|
||||
|
||||
void MenuMngr::clear()
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef MENUS_H
|
||||
#define MENUS_H
|
||||
@ -40,7 +18,7 @@ class MenuMngr
|
||||
{
|
||||
struct MenuIdEle
|
||||
{
|
||||
String name;
|
||||
ke::AString name;
|
||||
AMX* amx;
|
||||
MenuIdEle* next;
|
||||
|
||||
@ -66,13 +44,17 @@ private:
|
||||
int menuid;
|
||||
int keys;
|
||||
int function;
|
||||
int is_new_menu;
|
||||
|
||||
MenuCommand* next;
|
||||
MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f);
|
||||
MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f, bool new_menu=false);
|
||||
public:
|
||||
inline int getFunction() { return function; }
|
||||
inline CPluginMngr::CPlugin* getPlugin() { return plugin; }
|
||||
inline bool matchCommand(int m, int k) { return ((m == menuid) && (keys & k)); }
|
||||
inline bool matchCommand(int m, int k)
|
||||
{
|
||||
return ((m == menuid) && (keys & k));
|
||||
}
|
||||
} *headcmd;
|
||||
|
||||
public:
|
||||
@ -84,8 +66,7 @@ public:
|
||||
|
||||
int findMenuId(const char* name, AMX* a = 0);
|
||||
int registerMenuId(const char* n, AMX* a);
|
||||
void removeMenuId(int id);
|
||||
void registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f);
|
||||
void registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f, bool from_new_menu=false);
|
||||
void clear();
|
||||
|
||||
class iterator
|
||||
@ -110,4 +91,6 @@ private:
|
||||
MenuMngr::iterator m_watch_iter;
|
||||
};
|
||||
|
||||
extern MenuMngr g_menucmds;
|
||||
|
||||
#endif //MENUS_H
|
||||
|
@ -1,33 +1,12 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "newmenus.h"
|
||||
// *****************************************************
|
||||
@ -40,9 +19,9 @@ void CPlayer::Init(edict_t* e, int i)
|
||||
pEdict = e;
|
||||
initialized = false;
|
||||
ingame = false;
|
||||
bot_value = false;
|
||||
bot_cached = false;
|
||||
authorized = false;
|
||||
disconnecting = false;
|
||||
teamIdsInitialized = false;
|
||||
|
||||
current = 0;
|
||||
teamId = -1;
|
||||
@ -53,10 +32,10 @@ void CPlayer::Init(edict_t* e, int i)
|
||||
menuexpire = 0.0;
|
||||
newmenu = -1;
|
||||
|
||||
death_weapon.clear();
|
||||
name.clear();
|
||||
ip.clear();
|
||||
team.clear();
|
||||
death_weapon = nullptr;
|
||||
name = nullptr;
|
||||
ip = nullptr;
|
||||
team = nullptr;
|
||||
}
|
||||
|
||||
void CPlayer::Disconnect()
|
||||
@ -64,21 +43,11 @@ void CPlayer::Disconnect()
|
||||
ingame = false;
|
||||
initialized = false;
|
||||
authorized = false;
|
||||
disconnecting = false;
|
||||
teamIdsInitialized = false;
|
||||
|
||||
if (newmenu != -1)
|
||||
{
|
||||
Menu *pMenu = g_NewMenus[newmenu];
|
||||
if (pMenu)
|
||||
{
|
||||
//prevent recursion
|
||||
newmenu = -1;
|
||||
menu = 0;
|
||||
executeForwards(pMenu->func,
|
||||
static_cast<cell>(ENTINDEX(pEdict)),
|
||||
static_cast<cell>(pMenu->thisId),
|
||||
static_cast<cell>(MENU_EXIT));
|
||||
}
|
||||
}
|
||||
if (Menu *pMenu = get_menu_by_id(newmenu))
|
||||
pMenu->Close(index);
|
||||
|
||||
List<ClientCvarQuery_Info *>::iterator iter, end=queries.end();
|
||||
for (iter=queries.begin(); iter!=end; iter++)
|
||||
@ -89,8 +58,6 @@ void CPlayer::Disconnect()
|
||||
}
|
||||
queries.clear();
|
||||
|
||||
bot_value = false;
|
||||
bot_cached = false;
|
||||
menu = 0;
|
||||
newmenu = -1;
|
||||
}
|
||||
@ -116,10 +83,8 @@ int CPlayer::NextHUDChannel()
|
||||
|
||||
bool CPlayer::Connect(const char* connectname, const char* ipaddress)
|
||||
{
|
||||
bot_value = false;
|
||||
bot_cached = false;
|
||||
name.assign(connectname);
|
||||
ip.assign(ipaddress);
|
||||
name = connectname;
|
||||
ip = ipaddress;
|
||||
time = gpGlobals->time;
|
||||
death_killer = 0;
|
||||
menu = 0;
|
||||
@ -276,7 +241,7 @@ void TeamIds::registerTeam(const char* n, int s)
|
||||
|
||||
while (*a)
|
||||
{
|
||||
if (strcmp((*a)->name.c_str(),n) == 0)
|
||||
if (strcmp((*a)->name.chars(),n) == 0)
|
||||
{
|
||||
if (s != -1)
|
||||
{
|
||||
@ -303,7 +268,7 @@ int TeamIds::findTeamId(const char* n)
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (!stricmp(a->name.c_str(), n))
|
||||
if (!stricmp(a->name.chars(), n))
|
||||
return a->id;
|
||||
a = a->next;
|
||||
}
|
||||
@ -317,7 +282,7 @@ int TeamIds::findTeamIdCase(const char* n)
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (!strcmp(a->name.c_str(), n))
|
||||
if (!strcmp(a->name.chars(), n))
|
||||
return a->id;
|
||||
a = a->next;
|
||||
}
|
||||
|
196
amxmodx/CMisc.h
196
amxmodx/CMisc.h
@ -1,66 +1,17 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef CMISC_H
|
||||
#define CMISC_H
|
||||
|
||||
#include "CList.h"
|
||||
#include "sh_list.h"
|
||||
|
||||
// *****************************************************
|
||||
// class CCVar
|
||||
// *****************************************************
|
||||
|
||||
class CCVar
|
||||
{
|
||||
cvar_t cvar;
|
||||
String name;
|
||||
String plugin;
|
||||
|
||||
public:
|
||||
CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin)
|
||||
{
|
||||
cvar.name = (char*)name.c_str();
|
||||
cvar.flags = pflags;
|
||||
cvar.string = "";
|
||||
cvar.value = pvalue;
|
||||
}
|
||||
|
||||
inline cvar_t* getCvar() { return &cvar; }
|
||||
inline const char* getPluginName() { return plugin.c_str(); }
|
||||
inline const char* getName() { return name.c_str(); }
|
||||
inline bool operator == (const char* string) { return (strcmp(name.c_str(), string) == 0); }
|
||||
int plugin_id;
|
||||
};
|
||||
|
||||
// *****************************************************
|
||||
// class CPlayer
|
||||
// *****************************************************
|
||||
@ -78,16 +29,16 @@ class CPlayer
|
||||
public:
|
||||
edict_t* pEdict;
|
||||
|
||||
String name;
|
||||
String ip;
|
||||
String team;
|
||||
ke::AString name;
|
||||
ke::AString ip;
|
||||
ke::AString team;
|
||||
|
||||
bool initialized;
|
||||
bool ingame;
|
||||
bool bot_cached;
|
||||
bool bot_value;
|
||||
bool authorized;
|
||||
bool vgui;
|
||||
bool disconnecting;
|
||||
bool vgui;
|
||||
bool teamIdsInitialized;
|
||||
|
||||
float time;
|
||||
float playtime;
|
||||
@ -112,7 +63,7 @@ public:
|
||||
int death_killer;
|
||||
int death_victim;
|
||||
bool death_tk;
|
||||
String death_weapon;
|
||||
ke::AString death_weapon;
|
||||
int newmenu;
|
||||
int page;
|
||||
|
||||
@ -120,7 +71,6 @@ public:
|
||||
cell hudmap[5];
|
||||
|
||||
Vector lastTrace;
|
||||
Vector thisTrace;
|
||||
Vector lastHit;
|
||||
|
||||
List<ClientCvarQuery_Info *> queries;
|
||||
@ -133,24 +83,8 @@ public:
|
||||
|
||||
inline bool IsBot()
|
||||
{
|
||||
if (!bot_cached)
|
||||
{
|
||||
bot_value = false;
|
||||
if (pEdict->v.flags & FL_FAKECLIENT)
|
||||
{
|
||||
bot_value = true;
|
||||
bot_cached = true;
|
||||
} else {
|
||||
const char *auth = GETPLAYERAUTHID(pEdict);
|
||||
if (auth && (strcmp(auth, "BOT") == 0))
|
||||
{
|
||||
bot_value = true;
|
||||
bot_cached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bot_value;
|
||||
const char *auth = GETPLAYERAUTHID(pEdict);
|
||||
return auth && !strcmp(auth, "BOT");
|
||||
}
|
||||
|
||||
inline bool IsAlive()
|
||||
@ -194,7 +128,7 @@ public:
|
||||
|
||||
class ForceObject
|
||||
{
|
||||
String filename;
|
||||
ke::AString filename;
|
||||
FORCE_TYPE type;
|
||||
Vector mins;
|
||||
Vector maxs;
|
||||
@ -202,7 +136,7 @@ class ForceObject
|
||||
public:
|
||||
ForceObject(const char* n, FORCE_TYPE c, Vector& mi, Vector& ma, AMX* a) : filename(n), type(c), mins(mi), maxs(ma), amx(a) {}
|
||||
|
||||
inline const char* getFilename() { return filename.c_str(); }
|
||||
inline const char* getFilename() { return filename.chars(); }
|
||||
inline AMX* getAMX() { return amx; }
|
||||
|
||||
Vector& getMin() { return mins; }
|
||||
@ -257,17 +191,16 @@ public:
|
||||
// class CScript
|
||||
// *****************************************************
|
||||
|
||||
class CScript
|
||||
class CScript : public ke::InlineListNode<CScript>
|
||||
{
|
||||
String filename;
|
||||
ke::AString filename;
|
||||
AMX* amx;
|
||||
void* code;
|
||||
public:
|
||||
CScript(AMX* aa, void* cc, const char* ff) : filename(ff), amx(aa), code(cc) {}
|
||||
|
||||
inline AMX* getAMX() { return amx; }
|
||||
inline const char* getName() { return filename.c_str(); }
|
||||
inline bool operator==(void* a) { return (amx == (AMX*)a); }
|
||||
inline const char* getName() { return filename.chars(); }
|
||||
inline void* getCode() { return code; }
|
||||
};
|
||||
|
||||
@ -279,7 +212,7 @@ class TeamIds
|
||||
{
|
||||
struct TeamEle
|
||||
{
|
||||
String name;
|
||||
ke::AString name;
|
||||
int id;
|
||||
char tid;
|
||||
static char uid;
|
||||
@ -305,4 +238,87 @@ public:
|
||||
inline bool isNewTeam() { return newTeam ? true : false; }
|
||||
};
|
||||
|
||||
class CAdminData
|
||||
{
|
||||
private:
|
||||
cell m_AuthData[44];
|
||||
cell m_Password[32];
|
||||
cell m_Flags;
|
||||
cell m_Access;
|
||||
public:
|
||||
|
||||
CAdminData()
|
||||
{
|
||||
m_AuthData[0]=0;
|
||||
m_Password[0]=0;
|
||||
m_Flags=0;
|
||||
m_Access=0;
|
||||
};
|
||||
|
||||
void SetAccess(cell Access)
|
||||
{
|
||||
m_Access=Access;
|
||||
};
|
||||
cell GetAccess(void) const
|
||||
{
|
||||
return m_Access;
|
||||
};
|
||||
|
||||
void SetFlags(cell Flags)
|
||||
{
|
||||
m_Flags=Flags;
|
||||
};
|
||||
cell GetFlags(void) const
|
||||
{
|
||||
return m_Flags;
|
||||
};
|
||||
|
||||
void SetAuthID(const cell *Input)
|
||||
{
|
||||
unsigned int i=0;
|
||||
while (i<sizeof(m_AuthData)-1)
|
||||
{
|
||||
if ((m_AuthData[i++]=*Input++)==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_AuthData[arraysize(m_AuthData)-1]=0;
|
||||
|
||||
};
|
||||
const cell *GetAuthID(void) const
|
||||
{
|
||||
return &m_AuthData[0];
|
||||
};
|
||||
|
||||
void SetPass(const cell *Input)
|
||||
{
|
||||
unsigned int i=0;
|
||||
while (i<sizeof(m_Password)-1)
|
||||
{
|
||||
if ((m_Password[i++]=*Input++)==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_Password[arraysize(m_Password)-1]=0;
|
||||
|
||||
};
|
||||
const cell *GetPass(void) const
|
||||
{
|
||||
return &m_Password[0];
|
||||
};
|
||||
|
||||
CAdminData & operator = (const CAdminData &src)
|
||||
{
|
||||
this->SetAccess(src.GetAccess());
|
||||
this->SetFlags(src.GetFlags());
|
||||
this->SetAuthID(src.GetAuthID());
|
||||
this->SetPass(src.GetPass());
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
#endif //CMISC_H
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "libraries.h"
|
||||
@ -39,6 +17,7 @@
|
||||
// New
|
||||
typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/);
|
||||
typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/);
|
||||
typedef int (FAR *CHECKGAME_NEW)(const char *);
|
||||
typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/);
|
||||
typedef int (FAR *DETACHMOD_NEW)(void);
|
||||
typedef void (FAR *PLUGINSLOADED_NEW)(void);
|
||||
@ -51,7 +30,7 @@ typedef void (*PLUGINSUNLOADING_NEW)(void);
|
||||
|
||||
CModule::CModule(const char* fname)
|
||||
{
|
||||
m_Filename.assign(fname);
|
||||
m_Filename = fname;
|
||||
clear(false);
|
||||
}
|
||||
|
||||
@ -70,19 +49,20 @@ void CModule::clear(bool clearFilename)
|
||||
m_Metamod = false;
|
||||
m_Handle = NULL;
|
||||
m_Status = MODULE_NONE;
|
||||
|
||||
|
||||
if (clearFilename)
|
||||
m_Filename.assign("unknown");
|
||||
{
|
||||
m_Filename = "unknown";
|
||||
}
|
||||
|
||||
// new
|
||||
m_Amxx = false;
|
||||
m_InfoNew.author = "unknown";
|
||||
m_InfoNew.name = "unknown";
|
||||
m_InfoNew.version = "unknown";
|
||||
m_InfoNew.reload = 0;
|
||||
m_MissingFunc = NULL;
|
||||
|
||||
for (size_t i=0; i<m_DestroyableIndexes.size(); i++)
|
||||
for (size_t i=0; i<m_DestroyableIndexes.length(); i++)
|
||||
{
|
||||
delete [] m_Natives[m_DestroyableIndexes[i]];
|
||||
}
|
||||
@ -117,12 +97,12 @@ bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now)
|
||||
void CModule::rewriteNativeLists(AMX_NATIVE_INFO *list)
|
||||
{
|
||||
AMX_NATIVE_INFO *curlist;
|
||||
for (size_t i=0; i<m_Natives.size(); i++)
|
||||
for (size_t i=0; i<m_Natives.length(); i++)
|
||||
{
|
||||
curlist = m_Natives[i];
|
||||
bool changed = false;
|
||||
bool found = false;
|
||||
CVector<size_t> newlist;
|
||||
ke::Vector<size_t> newlist;
|
||||
for (size_t j=0; curlist[j].func != NULL; j++)
|
||||
{
|
||||
found = false;
|
||||
@ -139,22 +119,22 @@ void CModule::rewriteNativeLists(AMX_NATIVE_INFO *list)
|
||||
changed = true;
|
||||
//don't break, we have to search it all
|
||||
} else {
|
||||
newlist.push_back(j);
|
||||
newlist.append(j);
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
//now build the new list
|
||||
AMX_NATIVE_INFO *rlist = new AMX_NATIVE_INFO[newlist.size()+1];
|
||||
for (size_t j=0; j<newlist.size(); j++)
|
||||
AMX_NATIVE_INFO *rlist = new AMX_NATIVE_INFO[newlist.length()+1];
|
||||
for (size_t j=0; j<newlist.length(); j++)
|
||||
{
|
||||
rlist[j].func = curlist[newlist[j]].func;
|
||||
rlist[j].name = curlist[newlist[j]].name;
|
||||
}
|
||||
rlist[newlist.size()].func = NULL;
|
||||
rlist[newlist.size()].name = NULL;
|
||||
rlist[newlist.length()].func = NULL;
|
||||
rlist[newlist.length()].name = NULL;
|
||||
m_Natives[i] = rlist;
|
||||
m_DestroyableIndexes.push_back(i);
|
||||
m_DestroyableIndexes.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,40 +145,34 @@ bool CModule::attachModule()
|
||||
if (m_Status != MODULE_QUERY || !m_Handle)
|
||||
return false;
|
||||
|
||||
if (m_Amxx)
|
||||
ATTACHMOD_NEW AttachFunc_New = (ATTACHMOD_NEW)DLPROC(m_Handle, "AMXX_Attach");
|
||||
|
||||
if (!AttachFunc_New)
|
||||
return false;
|
||||
|
||||
g_ModuleCallReason = ModuleCall_Attach;
|
||||
g_CurrentlyCalledModule = this;
|
||||
int retVal = (*AttachFunc_New)(Module_ReqFnptr);
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
|
||||
switch (retVal)
|
||||
{
|
||||
// new
|
||||
ATTACHMOD_NEW AttachFunc_New = (ATTACHMOD_NEW)DLPROC(m_Handle, "AMXX_Attach");
|
||||
|
||||
if (!AttachFunc_New)
|
||||
case AMXX_OK:
|
||||
m_Status = MODULE_LOADED;
|
||||
break;
|
||||
case AMXX_PARAM:
|
||||
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") returned \"Invalid parameter\" from Attach func.", m_Filename.chars(), getVersion());
|
||||
m_Status = MODULE_INTERROR;
|
||||
return false;
|
||||
case AMXX_FUNC_NOT_PRESENT:
|
||||
m_Status = MODULE_FUNCNOTPRESENT;
|
||||
m_MissingFunc = g_LastRequestedFunc;
|
||||
return false;
|
||||
default:
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.chars(), getVersion());
|
||||
m_Status = MODULE_BADLOAD;
|
||||
return false;
|
||||
|
||||
g_ModuleCallReason = ModuleCall_Attach;
|
||||
g_CurrentlyCalledModule = this;
|
||||
int retVal = (*AttachFunc_New)(Module_ReqFnptr);
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
|
||||
switch (retVal)
|
||||
{
|
||||
case AMXX_OK:
|
||||
m_Status = MODULE_LOADED;
|
||||
break;
|
||||
case AMXX_PARAM:
|
||||
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") retured \"Invalid parameter\" from Attach func.", m_Filename.c_str(), getVersion());
|
||||
m_Status = MODULE_INTERROR;
|
||||
return false;
|
||||
case AMXX_FUNC_NOT_PRESENT:
|
||||
m_Status = MODULE_FUNCNOTPRESENT;
|
||||
m_MissingFunc = g_LastRequestedFunc;
|
||||
return false;
|
||||
default:
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.c_str(), getVersion());
|
||||
m_Status = MODULE_BADLOAD;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
m_Status = MODULE_BADLOAD;
|
||||
}
|
||||
|
||||
if (m_Status == MODULE_LOADED)
|
||||
@ -216,9 +190,12 @@ bool CModule::queryModule()
|
||||
if (m_Status != MODULE_NONE) // don't check if already queried
|
||||
return false;
|
||||
|
||||
m_Handle = DLLOAD(m_Filename.c_str()); // load file
|
||||
m_Handle = DLLOAD(m_Filename.chars()); // load file
|
||||
if (!m_Handle)
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" failed to load (%s)", m_Filename.chars(), dlerror());
|
||||
#endif
|
||||
m_Status = MODULE_BADLOAD;
|
||||
return false;
|
||||
}
|
||||
@ -229,21 +206,20 @@ bool CModule::queryModule()
|
||||
|
||||
// Try new interface first
|
||||
QUERYMOD_NEW queryFunc_New = (QUERYMOD_NEW)DLPROC(m_Handle, "AMXX_Query");
|
||||
|
||||
|
||||
if (queryFunc_New)
|
||||
{
|
||||
m_Amxx = true;
|
||||
int ifVers = AMXX_INTERFACE_VERSION;
|
||||
g_ModuleCallReason = ModuleCall_Query;
|
||||
g_CurrentlyCalledModule = this;
|
||||
int retVal = (*queryFunc_New)(&ifVers, &m_InfoNew);
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
|
||||
|
||||
switch (retVal)
|
||||
{
|
||||
case AMXX_PARAM:
|
||||
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") retured \"Invalid parameter\" from Attach func.", m_Filename.c_str(), getVersion());
|
||||
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") returned \"Invalid parameter\" from Attach func.", m_Filename.chars(), getVersion());
|
||||
m_Status = MODULE_INTERROR;
|
||||
return false;
|
||||
case AMXX_IFVERS:
|
||||
@ -255,12 +231,12 @@ bool CModule::queryModule()
|
||||
g_ModuleCallReason = ModuleCall_Query;
|
||||
g_CurrentlyCalledModule = this;
|
||||
retVal = (*queryFunc_New)(&ifVers, &m_InfoNew);
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
if (retVal == AMXX_OK)
|
||||
{
|
||||
m_InfoNew.library = m_InfoNew.logtag;
|
||||
if (StrCaseStr(m_InfoNew.library, "sql")
|
||||
if (StrCaseStr(m_InfoNew.library, "sql")
|
||||
|| StrCaseStr(m_InfoNew.library, "dbi"))
|
||||
{
|
||||
m_InfoNew.libclass = "DBI";
|
||||
@ -281,7 +257,7 @@ bool CModule::queryModule()
|
||||
case AMXX_OK:
|
||||
break;
|
||||
default:
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.c_str(), getVersion());
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.chars(), getVersion());
|
||||
m_Status = MODULE_BADLOAD;
|
||||
return false;
|
||||
}
|
||||
@ -293,11 +269,37 @@ bool CModule::queryModule()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Lastly, check to see if this module is able to load on this game mod
|
||||
CHECKGAME_NEW checkGame_New = (CHECKGAME_NEW)DLPROC(m_Handle, "AMXX_CheckGame");
|
||||
|
||||
if (checkGame_New)
|
||||
{
|
||||
// This is an optional check; do not fail modules that do not have it
|
||||
int ret = checkGame_New(g_mod_name.chars());
|
||||
|
||||
if (ret != AMXX_GAME_OK)
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case AMXX_GAME_BAD:
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") reported that it cannot load on game \"%s\"", m_Filename.chars(), getVersion(), g_mod_name.chars());
|
||||
m_Status = MODULE_BADGAME;
|
||||
break;
|
||||
default:
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an unknown CheckGame code (value: %d)", m_Filename.chars(), getVersion(), ret);
|
||||
m_Status = MODULE_BADLOAD;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_Status = MODULE_QUERY;
|
||||
return true;
|
||||
} else {
|
||||
m_Status = MODULE_NOQUERY;
|
||||
m_Amxx = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -309,30 +311,25 @@ bool CModule::detachModule()
|
||||
|
||||
RemoveLibraries(this);
|
||||
|
||||
if (m_Amxx)
|
||||
DETACHMOD_NEW detachFunc_New = (DETACHMOD_NEW)DLPROC(m_Handle, "AMXX_Detach");
|
||||
|
||||
if (detachFunc_New)
|
||||
{
|
||||
DETACHMOD_NEW detachFunc_New = (DETACHMOD_NEW)DLPROC(m_Handle, "AMXX_Detach");
|
||||
|
||||
if (detachFunc_New)
|
||||
{
|
||||
g_ModuleCallReason = ModuleCall_Detach;
|
||||
g_CurrentlyCalledModule = this;
|
||||
(*detachFunc_New)();
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
}
|
||||
g_ModuleCallReason = ModuleCall_Detach;
|
||||
g_CurrentlyCalledModule = this;
|
||||
(*detachFunc_New)();
|
||||
g_CurrentlyCalledModule = NULL;
|
||||
g_ModuleCallReason = ModuleCall_NotCalled;
|
||||
}
|
||||
|
||||
#ifndef FAKEMETA
|
||||
if (IsMetamod())
|
||||
{
|
||||
UnloadMetamodPlugin(m_Handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
DLFREE(m_Handle);
|
||||
clear();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -377,10 +374,10 @@ void CModule::CallPluginsLoaded()
|
||||
return;
|
||||
|
||||
PLUGINSLOADED_NEW func = (PLUGINSLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsLoaded");
|
||||
|
||||
|
||||
if (!func)
|
||||
return;
|
||||
|
||||
|
||||
func();
|
||||
}
|
||||
|
||||
@ -400,8 +397,9 @@ const char* CModule::getStatus() const
|
||||
case MODULE_NEWER: return "newer";
|
||||
case MODULE_INTERROR: return "internal err";
|
||||
case MODULE_NOT64BIT: return "not 64bit";
|
||||
case MODULE_BADGAME: return "bad game";
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
// *****************************************************
|
||||
// class CModule
|
||||
@ -49,7 +27,8 @@ enum MODULE_STATUS
|
||||
MODULE_NEWER, // newer interface
|
||||
MODULE_INTERROR, // Internal error
|
||||
MODULE_FUNCNOTPRESENT, // Function not present
|
||||
MODULE_NOT64BIT // Not 64 bit compatible
|
||||
MODULE_NOT64BIT, // Not 64 bit compatible
|
||||
MODULE_BADGAME, // Module cannot load on the current game mod
|
||||
};
|
||||
|
||||
struct amxx_module_info_s
|
||||
@ -68,15 +47,17 @@ struct amxx_module_info_s
|
||||
#define AMXX_PARAM 2 /* Invalid parameter */
|
||||
#define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */
|
||||
|
||||
#define AMXX_GAME_OK 0 /* Module can load on this game. */
|
||||
#define AMXX_GAME_BAD 1 /* Module cannot load on this game. */
|
||||
|
||||
#define AMXX_INTERFACE_VERSION 4
|
||||
|
||||
class CModule
|
||||
class CModule : public ke::InlineListNode<CModule>
|
||||
{
|
||||
String m_Filename; // Filename
|
||||
|
||||
ke::AString m_Filename; // Filename
|
||||
|
||||
bool m_Metamod; // Using metamod?
|
||||
bool m_Amxx; // Using new module interface?
|
||||
|
||||
|
||||
amxx_module_info_s m_InfoNew; // module info (new module interface)
|
||||
DLHANDLE m_Handle; // handle
|
||||
MODULE_STATUS m_Status; // status
|
||||
@ -88,37 +69,33 @@ public:
|
||||
~CModule();
|
||||
|
||||
// Interface
|
||||
|
||||
|
||||
bool attachModule();
|
||||
bool queryModule();
|
||||
bool detachModule();
|
||||
void rewriteNativeLists(AMX_NATIVE_INFO *list);
|
||||
|
||||
#ifndef FAKEMETA
|
||||
bool attachMetamod(const char *mmfile, PLUG_LOADTIME now);
|
||||
#endif
|
||||
|
||||
const char* getStatus() const;
|
||||
inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); }
|
||||
inline const char* getType() const { return m_Metamod ? "amxx&mm" : "amxx"; }
|
||||
inline const char* getAuthor() const { return m_InfoNew.author; }
|
||||
inline const char* getVersion() const { return m_InfoNew.version; }
|
||||
inline const char* getName() const { return m_InfoNew.name; }
|
||||
inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new
|
||||
inline int getStatusValue() { return m_Status; }
|
||||
inline bool operator==(const char* fname) { return !strcmp(m_Filename.c_str(), fname); }
|
||||
inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); }
|
||||
inline bool isAmxx() const { return m_Amxx; }
|
||||
inline const char *getMissingFunc() const { return m_MissingFunc; }
|
||||
inline const char *getFilename() { return m_Filename.c_str(); }
|
||||
inline const char *getFilename() { return m_Filename.chars(); }
|
||||
inline bool IsMetamod() { return m_Metamod; }
|
||||
|
||||
|
||||
void CallPluginsLoaded();
|
||||
void CallPluginsUnloaded();
|
||||
void CallPluginsUnloading();
|
||||
|
||||
CVector<AMX_NATIVE_INFO*> m_Natives;
|
||||
CVector<AMX_NATIVE_INFO*> m_NewNatives; // Natives for new (AMXX, not AMX) plugins only
|
||||
CVector<size_t> m_DestroyableIndexes;
|
||||
ke::Vector<AMX_NATIVE_INFO*> m_Natives;
|
||||
ke::Vector<AMX_NATIVE_INFO*> m_NewNatives; // Natives for new (AMXX, not AMX) plugins only
|
||||
ke::Vector<size_t> m_DestroyableIndexes;
|
||||
};
|
||||
|
||||
#endif //CMODULE_H
|
||||
|
340
amxmodx/COPYING
340
amxmodx/COPYING
@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1,54 +1,33 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CPlugin.h"
|
||||
#include "CForward.h"
|
||||
#include "CFile.h"
|
||||
#include "amx.h"
|
||||
#include "natives.h"
|
||||
#include "debugger.h"
|
||||
#include "libraries.h"
|
||||
#include <amxmodx_version.h>
|
||||
#include "engine_strucs.h"
|
||||
|
||||
extern const char *no_function;
|
||||
|
||||
CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug)
|
||||
{
|
||||
CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, size_t maxLength, int debug)
|
||||
{
|
||||
CPlugin** a = &head;
|
||||
|
||||
|
||||
while (*a)
|
||||
a = &(*a)->next;
|
||||
|
||||
*a = new CPlugin(pCounter++, path, name, error, debug);
|
||||
|
||||
|
||||
*a = new CPlugin(pCounter++, path, name, error, maxLength, debug);
|
||||
|
||||
return (*a);
|
||||
}
|
||||
|
||||
@ -64,10 +43,10 @@ void CPluginMngr::Finalize()
|
||||
{
|
||||
if (m_Finalized)
|
||||
return;
|
||||
|
||||
|
||||
pNatives = BuildNativeTable();
|
||||
CPlugin *a = head;
|
||||
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (a->getStatusCode() == ps_running)
|
||||
@ -77,44 +56,45 @@ void CPluginMngr::Finalize()
|
||||
}
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
|
||||
m_Finalized = true;
|
||||
}
|
||||
|
||||
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
{
|
||||
char file[256];
|
||||
FILE *fp = fopen(build_pathname_r(file, sizeof(file) - 1, "%s", filename), "rt");
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
FILE *fp = fopen(build_pathname_r(file, sizeof(file), "%s", filename), "rt");
|
||||
|
||||
if (!fp)
|
||||
if (!fp)
|
||||
{
|
||||
if (warn)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] Plugins list not found (file \"%s\")", filename);
|
||||
AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Find now folder
|
||||
char pluginName[256], error[256], debug[256];
|
||||
int debugFlag = 0;
|
||||
const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins");
|
||||
|
||||
String line;
|
||||
|
||||
List<String *>::iterator block_iter;
|
||||
char line[512];
|
||||
|
||||
while (!feof(fp))
|
||||
List<ke::AString *>::iterator block_iter;
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
pluginName[0] = '\0';
|
||||
|
||||
|
||||
debug[0] = '\0';
|
||||
debugFlag = 0;
|
||||
|
||||
line.clear();
|
||||
line._fread(fp);
|
||||
|
||||
line[0] = '\0';
|
||||
fgets(line, sizeof(line), fp);
|
||||
|
||||
/** quick hack */
|
||||
char *ptr = const_cast<char *>(line.c_str());
|
||||
char *ptr = line;
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == ';')
|
||||
@ -124,8 +104,8 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
sscanf(line.c_str(), "%s %s", pluginName, debug);
|
||||
|
||||
sscanf(line, "%s %s", pluginName, debug);
|
||||
|
||||
if (!isalnum(*pluginName))
|
||||
{
|
||||
continue;
|
||||
@ -153,14 +133,68 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
continue;
|
||||
}
|
||||
|
||||
CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, debugFlag);
|
||||
|
||||
if (findPlugin(pluginName) != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, sizeof(error), debugFlag);
|
||||
|
||||
if (plugin->getStatusCode() == ps_bad_load)
|
||||
{
|
||||
char errorMsg[255];
|
||||
sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName);
|
||||
plugin->setError(errorMsg);
|
||||
AMXXLOG_Log("[AMXX] %s", plugin->getError());
|
||||
AMXXLOG_Error("[AMXX] %s", plugin->getError());
|
||||
}
|
||||
else
|
||||
{
|
||||
cell addr;
|
||||
if (amx_FindPubVar(plugin->getAMX(), "MaxClients", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
*get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients;
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "MapName", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
set_amxstring(plugin->getAMX(), addr, STRING(gpGlobals->mapname), MAX_MAPNAME_LENGTH - 1);
|
||||
}
|
||||
|
||||
auto length = 0;
|
||||
if (amx_FindPubVar(plugin->getAMX(), "PluginName", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->setTitle(get_amxstring(plugin->getAMX(), addr, 0, length));
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "PluginVersion", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->setVersion(get_amxstring(plugin->getAMX(), addr, 0, length));
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "PluginAuthor", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->setAuthor(get_amxstring(plugin->getAMX(), addr, 0, length));
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "PluginURL", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->setUrl(get_amxstring(plugin->getAMX(), addr, 0, length));
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "PluginDescription", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->setDescription(get_amxstring(plugin->getAMX(), addr, 0, length));
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr);
|
||||
}
|
||||
|
||||
if (amx_FindPubVar(plugin->getAMX(), "NULL_VECTOR", &addr) != AMX_ERR_NOTFOUND)
|
||||
{
|
||||
plugin->m_pNullVectorOfs = get_amxaddr(plugin->getAMX(), addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,20 +205,20 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
|
||||
void CPluginMngr::clear()
|
||||
{
|
||||
CPlugin**a = &head;
|
||||
|
||||
CPlugin**a = &head;
|
||||
|
||||
while (*a)
|
||||
unloadPlugin(a);
|
||||
|
||||
|
||||
m_Finalized = false;
|
||||
|
||||
|
||||
if (pNatives)
|
||||
{
|
||||
delete [] pNatives;
|
||||
pNatives = NULL;
|
||||
}
|
||||
|
||||
List<String *>::iterator iter = m_BlockList.begin();
|
||||
List<ke::AString *>::iterator iter = m_BlockList.begin();
|
||||
while (iter != m_BlockList.end())
|
||||
{
|
||||
delete (*iter);
|
||||
@ -196,46 +230,57 @@ void CPluginMngr::clear()
|
||||
CPluginMngr::CPlugin* CPluginMngr::findPlugin(AMX *amx)
|
||||
{
|
||||
CPlugin*a = head;
|
||||
|
||||
|
||||
while (a && &a->amx != amx)
|
||||
a = a->next;
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
CPluginMngr::CPlugin* CPluginMngr::findPlugin(int index)
|
||||
{
|
||||
CPlugin*a = head;
|
||||
|
||||
|
||||
while (a && index--)
|
||||
a = a->next;
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
CPluginMngr::CPlugin* CPluginMngr::findPlugin(const char* name)
|
||||
{
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
|
||||
int len = strlen(name);
|
||||
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
|
||||
CPlugin*a = head;
|
||||
|
||||
while (a && strncmp(a->name.c_str(), name, len))
|
||||
|
||||
while (a && strncmp(a->name.chars(), name, len))
|
||||
a = a->next;
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::AddToFailCounter(unsigned int i)
|
||||
{
|
||||
failcounter += i;
|
||||
if ((failcounter >= 3)
|
||||
&& (status ))
|
||||
{
|
||||
errorMsg = "This plugin is non-GPL which violates AMX Mod X's license.";
|
||||
status = ps_bad_load;
|
||||
}
|
||||
}
|
||||
|
||||
const char* CPluginMngr::CPlugin::getStatus() const
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case ps_running:
|
||||
case ps_running:
|
||||
{
|
||||
if (m_Debug)
|
||||
{
|
||||
@ -250,41 +295,43 @@ const char* CPluginMngr::CPlugin::getStatus() const
|
||||
case ps_stopped: return "stopped";
|
||||
case ps_locked: return "locked";
|
||||
}
|
||||
|
||||
|
||||
return "error";
|
||||
}
|
||||
|
||||
CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n)
|
||||
CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, size_t m, int d) : name(n), title(n), m_pNullStringOfs(nullptr), m_pNullVectorOfs(nullptr)
|
||||
{
|
||||
const char* unk = "unknown";
|
||||
|
||||
title.assign(unk);
|
||||
author.assign(unk);
|
||||
version.assign(unk);
|
||||
|
||||
char file[256];
|
||||
char* path = build_pathname_r(file, sizeof(file) - 1, "%s/%s", p, n);
|
||||
|
||||
failcounter = 0;
|
||||
title = unk;
|
||||
author = unk;
|
||||
version = unk;
|
||||
url = unk;
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
char* path = build_pathname_r(file, sizeof(file), "%s/%s", p, n);
|
||||
code = 0;
|
||||
memset(&amx, 0, sizeof(AMX));
|
||||
int err = load_amxscript(&amx, &code, path, e, d);
|
||||
|
||||
int err = load_amxscript_ex(&amx, &code, path, e, m, d);
|
||||
|
||||
if (err == AMX_ERR_NONE)
|
||||
{
|
||||
status = ps_running;
|
||||
} else {
|
||||
status = ps_bad_load;
|
||||
}
|
||||
|
||||
|
||||
amx.userdata[UD_FINDPLUGIN] = this;
|
||||
paused_fun = 0;
|
||||
next = 0;
|
||||
id = i;
|
||||
|
||||
|
||||
if (status == ps_running)
|
||||
{
|
||||
m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause", FP_DONE);
|
||||
m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause", FP_DONE);
|
||||
|
||||
|
||||
if (amx.flags & AMX_FLAG_DEBUG)
|
||||
{
|
||||
m_Debug = true;
|
||||
@ -354,22 +401,22 @@ void CPluginMngr::CPlugin::Finalize()
|
||||
{
|
||||
char buffer[128];
|
||||
int old_status = status;
|
||||
|
||||
|
||||
if (CheckModules(&amx, buffer))
|
||||
{
|
||||
if (amx_Register(&amx, core_Natives, -1) != AMX_ERR_NONE)
|
||||
{
|
||||
Handler *pHandler = (Handler *)amx.userdata[UD_HANDLER];
|
||||
int res = 0;
|
||||
|
||||
|
||||
if (pHandler->IsNativeFiltering())
|
||||
res = amx_CheckNatives(&amx, native_handler);
|
||||
|
||||
|
||||
if (!res)
|
||||
{
|
||||
status = ps_bad_load;
|
||||
sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function);
|
||||
errorMsg.assign(buffer);
|
||||
errorMsg = buffer;
|
||||
amx.error = AMX_ERR_NOTFOUND;
|
||||
} else {
|
||||
amx_RegisterToAny(&amx, invalid_native);
|
||||
@ -377,18 +424,18 @@ void CPluginMngr::CPlugin::Finalize()
|
||||
}
|
||||
} else {
|
||||
status = ps_bad_load;
|
||||
errorMsg.assign(buffer);
|
||||
errorMsg = buffer;
|
||||
amx.error = AMX_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
if (old_status != status)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] Plugin \"%s\" failed to load: %s", name.c_str(), errorMsg.c_str());
|
||||
AMXXLOG_Log("[AMXX] Plugin \"%s\" failed to load: %s", name.chars(), errorMsg.chars());
|
||||
}
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::pauseFunction(int id)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::unpauseFunction(int id)
|
||||
@ -396,8 +443,8 @@ void CPluginMngr::CPlugin::unpauseFunction(int id)
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::setStatus(int a)
|
||||
{
|
||||
status = a;
|
||||
{
|
||||
status = a;
|
||||
g_commands.clearBufforedInfo(); // ugly way
|
||||
}
|
||||
|
||||
@ -409,7 +456,7 @@ void CPluginMngr::CPlugin::pausePlugin()
|
||||
// call plugin_pause if provided
|
||||
if (m_PauseFwd != -1)
|
||||
executeForwards(m_PauseFwd);
|
||||
|
||||
|
||||
setStatus(ps_paused);
|
||||
}
|
||||
}
|
||||
@ -421,7 +468,7 @@ void CPluginMngr::CPlugin::unpausePlugin()
|
||||
{
|
||||
// set status first so the function will be marked executable
|
||||
setStatus(ps_running);
|
||||
|
||||
|
||||
// call plugin_unpause if provided
|
||||
if (m_UnpauseFwd != -1)
|
||||
{
|
||||
@ -430,6 +477,49 @@ void CPluginMngr::CPlugin::unpausePlugin()
|
||||
}
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::AddConfig(bool create, const char *name, const char *folder)
|
||||
{
|
||||
// Do a check for duplicates to prevent double-execution
|
||||
for (size_t i = 0; i < m_configs.length(); ++i)
|
||||
{
|
||||
AutoConfig *config = m_configs[i];
|
||||
|
||||
if (config->autocfg.compare(name) == 0 && config->folder.compare(folder) == 0)
|
||||
{
|
||||
if (!config->create)
|
||||
{
|
||||
config->create = create;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto c = new AutoConfig;
|
||||
|
||||
c->autocfg = name;
|
||||
c->folder = folder;
|
||||
c->create = create;
|
||||
|
||||
m_configs.append(c);
|
||||
}
|
||||
|
||||
size_t CPluginMngr::CPlugin::GetConfigCount()
|
||||
{
|
||||
return m_configs.length();
|
||||
}
|
||||
|
||||
AutoConfig *CPluginMngr::CPlugin::GetConfig(size_t i)
|
||||
{
|
||||
if (i >= GetConfigCount())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_configs[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize)
|
||||
{
|
||||
List<plcache_entry *>::iterator iter;
|
||||
@ -449,8 +539,7 @@ char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize)
|
||||
|
||||
pl->file = new CAmxxReader(file, sizeof(cell));
|
||||
pl->buffer = NULL;
|
||||
if (pl->file->GetStatus() != CAmxxReader::Err_None ||
|
||||
pl->file->IsOldFile())
|
||||
if (pl->file->GetStatus() != CAmxxReader::Err_None)
|
||||
{
|
||||
delete pl->file;
|
||||
delete pl;
|
||||
@ -472,7 +561,7 @@ char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pl->path.assign(file);
|
||||
pl->path = file;
|
||||
|
||||
bufsize = pl->bufsize;
|
||||
|
||||
@ -541,7 +630,7 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((hdr.defsize != sizeof(AMX_FUNCSTUB)) &&
|
||||
if ((hdr.defsize != sizeof(AMX_FUNCSTUB)) &&
|
||||
(hdr.defsize != sizeof(AMX_FUNCSTUBNT)))
|
||||
{
|
||||
return;
|
||||
@ -554,7 +643,7 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (hdr.stp <= 0)
|
||||
{
|
||||
return;
|
||||
@ -583,8 +672,8 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
cell tag_id;
|
||||
amx_NumTags(&amx, &num);
|
||||
|
||||
CVector<LibDecoder *> expects;
|
||||
CVector<LibDecoder *> defaults;
|
||||
ke::Vector<LibDecoder *> expects;
|
||||
ke::Vector<LibDecoder *> defaults;
|
||||
CStack<LibDecoder *> delstack;
|
||||
for (int i=0; i<num; i++)
|
||||
{
|
||||
@ -599,21 +688,21 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
{
|
||||
RunLibCommand(dc);
|
||||
} else if ( (dc->cmd == LibCmd_ExpectClass) ||
|
||||
(dc->cmd == LibCmd_ExpectLib) )
|
||||
(dc->cmd == LibCmd_ExpectLib) )
|
||||
{
|
||||
expects.push_back(dc);
|
||||
expects.append(dc);
|
||||
} else if (dc->cmd == LibCmd_DefaultLib) {
|
||||
defaults.push_back(dc);
|
||||
defaults.append(dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i=0; i<expects.size(); i++)
|
||||
for (size_t i=0; i<expects.length(); i++)
|
||||
{
|
||||
RunLibCommand(expects[i]);
|
||||
}
|
||||
for (size_t i=0; i<defaults.size(); i++)
|
||||
for (size_t i=0; i<defaults.length(); i++)
|
||||
{
|
||||
RunLibCommand(defaults[i]);
|
||||
}
|
||||
@ -632,10 +721,10 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
|
||||
void CPluginMngr::CALMFromFile(const char *file)
|
||||
{
|
||||
char filename[256];
|
||||
FILE *fp = fopen(build_pathname_r(filename, sizeof(filename) - 1, "%s", file), "rt");
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
FILE *fp = fopen(build_pathname_r(filename, sizeof(filename), "%s", file), "rt");
|
||||
|
||||
if (!fp)
|
||||
if (!fp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -643,9 +732,9 @@ void CPluginMngr::CALMFromFile(const char *file)
|
||||
// Find now folder
|
||||
char pluginName[256];
|
||||
char line[256];
|
||||
String rline;
|
||||
char rline[256];
|
||||
|
||||
while (!feof(fp))
|
||||
while (!feof(fp))
|
||||
{
|
||||
fgets(line, sizeof(line)-1, fp);
|
||||
if (line[0] == ';' || line[0] == '\n' || line[0] == '\0')
|
||||
@ -665,24 +754,26 @@ void CPluginMngr::CALMFromFile(const char *file)
|
||||
}
|
||||
}
|
||||
|
||||
rline.assign(line);
|
||||
rline.trim();
|
||||
strncopy(rline, line, sizeof(rline));
|
||||
UTIL_TrimLeft(rline);
|
||||
UTIL_TrimRight(rline);
|
||||
|
||||
pluginName[0] = '\0';
|
||||
sscanf(rline.c_str(), "%s", pluginName);
|
||||
sscanf(rline, "%s", pluginName);
|
||||
|
||||
/* HACK: see if there's a 'disabled' coming up
|
||||
* new block for scopying flexibility
|
||||
*/
|
||||
if (1)
|
||||
{
|
||||
const char *_ptr = rline.c_str() + strlen(pluginName);
|
||||
const char *_ptr = rline + strlen(pluginName);
|
||||
while (*_ptr != '\0' && isspace(*_ptr))
|
||||
{
|
||||
_ptr++;
|
||||
}
|
||||
if ((*_ptr != '\0') && !strcmp(_ptr, "disabled"))
|
||||
{
|
||||
String *pString = new String(pluginName);
|
||||
ke::AString *pString = new ke::AString(pluginName);
|
||||
m_BlockList.push_back(pString);
|
||||
continue;
|
||||
}
|
||||
@ -693,7 +784,7 @@ void CPluginMngr::CALMFromFile(const char *file)
|
||||
continue;
|
||||
}
|
||||
|
||||
build_pathname_r(filename, sizeof(filename)-1, "%s/%s", get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"), pluginName);
|
||||
build_pathname_r(filename, sizeof(filename), "%s/%s", get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"), pluginName);
|
||||
|
||||
CacheAndLoadModules(filename);
|
||||
}
|
||||
|
@ -1,41 +1,21 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef PLUGIN_H
|
||||
#define PLUGIN_H
|
||||
|
||||
#include "CString.h"
|
||||
#include "sh_list.h"
|
||||
#include "amx.h"
|
||||
#include "amxxfile.h"
|
||||
#include <amtl/am-string.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <amtl/am-autoptr.h>
|
||||
|
||||
// *****************************************************
|
||||
// class CPluginMngr
|
||||
@ -51,6 +31,13 @@ enum
|
||||
ps_running, //Plugin is running
|
||||
};
|
||||
|
||||
struct AutoConfig
|
||||
{
|
||||
ke::AString autocfg;
|
||||
ke::AString folder;
|
||||
bool create;
|
||||
};
|
||||
|
||||
class CPluginMngr
|
||||
{
|
||||
public:
|
||||
@ -65,12 +52,15 @@ public:
|
||||
AMX amx;
|
||||
void* code;
|
||||
|
||||
String name;
|
||||
String version;
|
||||
String title;
|
||||
String author;
|
||||
String errorMsg;
|
||||
ke::AString name;
|
||||
ke::AString version;
|
||||
ke::AString title;
|
||||
ke::AString author;
|
||||
ke::AString url;
|
||||
ke::AString description;
|
||||
ke::AString errorMsg;
|
||||
|
||||
unsigned int failcounter;
|
||||
int m_PauseFwd;
|
||||
int m_UnpauseFwd;
|
||||
int paused_fun;
|
||||
@ -78,29 +68,38 @@ public:
|
||||
CPlugin* next;
|
||||
int id;
|
||||
|
||||
CPlugin(int i, const char* p, const char* n, char* e, int d);
|
||||
CPlugin(int i, const char* p, const char* n, char* e, size_t m, int d);
|
||||
~CPlugin();
|
||||
|
||||
bool m_Debug;
|
||||
cell* m_pNullStringOfs;
|
||||
cell* m_pNullVectorOfs;
|
||||
ke::Vector<ke::AutoPtr<AutoConfig>> m_configs;
|
||||
public:
|
||||
inline const char* getName() { return name.c_str();}
|
||||
inline const char* getVersion() { return version.c_str();}
|
||||
inline const char* getTitle() { return title.c_str();}
|
||||
inline const char* getAuthor() { return author.c_str();}
|
||||
inline const char* getError() { return errorMsg.c_str();}
|
||||
inline const char* getName() { return name.chars();}
|
||||
inline const char* getVersion() { return version.chars();}
|
||||
inline const char* getTitle() { return title.chars();}
|
||||
inline const char* getAuthor() { return author.chars();}
|
||||
inline const char* getUrl() { return url.chars(); }
|
||||
inline const char* getDescription() { return description.chars(); }
|
||||
inline const char* getError() { return errorMsg.chars();}
|
||||
inline int getStatusCode() { return status; }
|
||||
inline int getId() const { return id; }
|
||||
inline AMX* getAMX() { return &amx; }
|
||||
inline const AMX* getAMX() const { return &amx; }
|
||||
inline void setTitle(const char* n) { title.assign(n); }
|
||||
inline void setAuthor(const char* n) { author.assign(n); }
|
||||
inline void setVersion(const char* n) { version.assign(n); }
|
||||
inline void setError(const char* n) { errorMsg.assign(n); }
|
||||
inline void setTitle(const char* n) { title = n; }
|
||||
inline void setAuthor(const char* n) { author =n; }
|
||||
inline void setVersion(const char* n) { version = n; }
|
||||
inline void setUrl(const char* n) { url = n; }
|
||||
inline void setDescription(const char* n) { description = n; }
|
||||
inline void setError(const char* n) { errorMsg = n; }
|
||||
inline bool isValid() const { return (status >= ps_paused); }
|
||||
inline bool isPaused() const { return ((status == ps_paused) || (status == ps_stopped)); }
|
||||
inline bool isStopped() const { return (status == ps_stopped); }
|
||||
inline bool isExecutable(int id) const { return (isValid() && !isPaused()); }
|
||||
|
||||
void Finalize();
|
||||
void AddToFailCounter(unsigned int i);
|
||||
void pausePlugin();
|
||||
void unpausePlugin();
|
||||
void pauseFunction(int id);
|
||||
@ -109,6 +108,12 @@ public:
|
||||
|
||||
const char* getStatus() const;
|
||||
inline bool isDebug() const { return m_Debug; }
|
||||
inline cell* getNullStringOfs() const { return m_pNullStringOfs; }
|
||||
inline cell* getNullVectorOfs() const { return m_pNullVectorOfs; }
|
||||
public:
|
||||
void AddConfig(bool create, const char *name, const char *folder);
|
||||
size_t GetConfigCount();
|
||||
AutoConfig *GetConfig(size_t index);
|
||||
};
|
||||
|
||||
private:
|
||||
@ -123,7 +128,7 @@ public:
|
||||
|
||||
// Interface
|
||||
|
||||
CPlugin* loadPlugin(const char* path, const char* name, char* error, int debug);
|
||||
CPlugin* loadPlugin(const char* path, const char* name, char* error, size_t maxLength, int debug);
|
||||
void unloadPlugin(CPlugin** a);
|
||||
int loadPluginsFromFile(const char* filename, bool warn=true);
|
||||
|
||||
@ -156,7 +161,7 @@ public:
|
||||
CAmxxReader *file;
|
||||
size_t bufsize;
|
||||
char *buffer;
|
||||
String path;
|
||||
ke::AString path;
|
||||
};
|
||||
char *ReadIntoOrFromCache(const char *file, size_t &bufsize);
|
||||
void InvalidateCache();
|
||||
@ -165,7 +170,7 @@ public:
|
||||
void CALMFromFile(const char *file);
|
||||
private:
|
||||
List<plcache_entry *> m_plcache;
|
||||
List<String *> m_BlockList;
|
||||
List<ke::AString *> m_BlockList;
|
||||
};
|
||||
|
||||
#endif //PLUGIN_H
|
||||
|
129
amxmodx/CQueue.h
129
amxmodx/CQueue.h
@ -1,129 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
//by David "BAILOPAN" Anderson
|
||||
#ifndef _INCLUDE_CQUEUE_H
|
||||
#define _INCLUDE_CQUEUE_H
|
||||
|
||||
template <class T>
|
||||
class CQueue
|
||||
{
|
||||
public:
|
||||
class CQueueItem
|
||||
{
|
||||
public:
|
||||
CQueueItem(const T &i, CQueueItem *n)
|
||||
{
|
||||
item = i;
|
||||
next = n;
|
||||
}
|
||||
|
||||
CQueueItem *GetNext()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
T & GetItem()
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
void SetNext(CQueueItem *n)
|
||||
{
|
||||
next = n;
|
||||
}
|
||||
private:
|
||||
T item;
|
||||
CQueueItem *next;
|
||||
};
|
||||
public:
|
||||
CQueue()
|
||||
{
|
||||
mSize = 0;
|
||||
mFirst = NULL;
|
||||
mLast = NULL;
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return ((mSize == 0) ? true : false);
|
||||
}
|
||||
|
||||
void push(const T &v)
|
||||
{
|
||||
CQueueItem *p = new CQueueItem(v, NULL);
|
||||
if (empty())
|
||||
{
|
||||
mFirst = p;
|
||||
} else {
|
||||
mLast->SetNext(p);
|
||||
}
|
||||
mLast = p;
|
||||
mSize++;
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
if (mFirst == mLast)
|
||||
{
|
||||
delete mFirst;
|
||||
mFirst = NULL;
|
||||
mLast = NULL;
|
||||
} else {
|
||||
CQueueItem *p = mFirst->GetNext();
|
||||
delete mFirst;
|
||||
mFirst = p;
|
||||
}
|
||||
mSize--;
|
||||
}
|
||||
|
||||
T & front()
|
||||
{
|
||||
return mFirst->GetItem();
|
||||
}
|
||||
|
||||
T & back()
|
||||
{
|
||||
return mLast->GetItem();
|
||||
}
|
||||
|
||||
unsigned int size()
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
private:
|
||||
CQueueItem *mFirst;
|
||||
CQueueItem *mLast;
|
||||
|
||||
unsigned int mSize;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CQUEUE_H
|
@ -1,413 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CSTRING_H
|
||||
#define _INCLUDE_CSTRING_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//by David "BAILOPAN" Anderson
|
||||
class String
|
||||
{
|
||||
public:
|
||||
String()
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
//assign("");
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
if (v)
|
||||
delete [] v;
|
||||
}
|
||||
|
||||
String(const char *src)
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
assign(src);
|
||||
}
|
||||
|
||||
const char * _fread(FILE *fp)
|
||||
{
|
||||
Grow(512, false);
|
||||
char *ret = fgets(v, 511, fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
String(const String &src)
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
assign(src.c_str());
|
||||
}
|
||||
|
||||
const char *c_str() { return v?v:""; }
|
||||
|
||||
const char *c_str() const { return v?v:""; }
|
||||
|
||||
void append(const char *t)
|
||||
{
|
||||
Grow(size() + strlen(t) + 1);
|
||||
strcat(v, t);
|
||||
}
|
||||
|
||||
void append(const char c)
|
||||
{
|
||||
size_t len = size();
|
||||
Grow(len + 2);
|
||||
v[len] = c;
|
||||
v[len + 1] = '\0';
|
||||
}
|
||||
|
||||
void append(String &d)
|
||||
{
|
||||
append(d.c_str());
|
||||
}
|
||||
|
||||
void assign(const String &src)
|
||||
{
|
||||
assign(src.c_str());
|
||||
}
|
||||
|
||||
void assign(const char *d)
|
||||
{
|
||||
if (!d)
|
||||
{
|
||||
clear();
|
||||
} else {
|
||||
size_t len = strlen(d);
|
||||
Grow(len + 1, false);
|
||||
memcpy(v, d, len);
|
||||
v[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (v)
|
||||
v[0] = '\0';
|
||||
}
|
||||
|
||||
int compare (const char *d) const
|
||||
{
|
||||
if (!v)
|
||||
return strcmp("", d);
|
||||
else
|
||||
return strcmp(v, d);
|
||||
}
|
||||
|
||||
//Added this for amxx inclusion
|
||||
bool empty()
|
||||
{
|
||||
if (!v)
|
||||
return true;
|
||||
|
||||
if (v[0] == '\0')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size()
|
||||
{
|
||||
if (v)
|
||||
return strlen(v);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find(const char c, int index = 0)
|
||||
{
|
||||
int len = static_cast<int>(size());
|
||||
if (len < 1)
|
||||
return npos;
|
||||
if (index >= len || index < 0)
|
||||
return npos;
|
||||
int i = 0;
|
||||
for (i=index; i<len; i++)
|
||||
{
|
||||
if (v[i] == c)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
bool is_space(int c)
|
||||
{
|
||||
if (c == '\f' || c == '\n' ||
|
||||
c == '\t' || c == '\r' ||
|
||||
c == '\v' || c == ' ')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void reparse_newlines()
|
||||
{
|
||||
size_t len = size();
|
||||
int offs = 0;
|
||||
char c;
|
||||
if (!len)
|
||||
return;
|
||||
for (size_t i=0; i<len; i++)
|
||||
{
|
||||
c = v[i];
|
||||
if (c == '^' && (i != len-1))
|
||||
{
|
||||
c = v[++i];
|
||||
if (c == 'n')
|
||||
c = '\n';
|
||||
else if (c == 't')
|
||||
c = '\t';
|
||||
offs++;
|
||||
}
|
||||
v[i-offs] = c;
|
||||
}
|
||||
v[len-offs] = '\0';
|
||||
}
|
||||
|
||||
void trim()
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
size_t len = strlen(v);
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
if (is_space(v[i]))
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char c0 = v[0];
|
||||
|
||||
if (is_space(c0))
|
||||
{
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==len-1)))
|
||||
{
|
||||
erase(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(v);
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_space(v[len-1]))
|
||||
{
|
||||
for (i=len-1; i>=0; i--)
|
||||
{
|
||||
if (!is_space(v[i])
|
||||
|| (is_space(v[i]) && i==0))
|
||||
{
|
||||
erase(i+1, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
if (is_space(v[0]))
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase(unsigned int start, int num = npos)
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
unsigned int i = 0;
|
||||
size_t len = size();
|
||||
//check for bounds
|
||||
if (num == npos || start+num > len-start)
|
||||
num = len - start;
|
||||
//do the erasing
|
||||
bool copyflag = false;
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (i>=start && i<start+num)
|
||||
{
|
||||
if (i+num < len)
|
||||
{
|
||||
v[i] = v[i+num];
|
||||
} else {
|
||||
v[i] = 0;
|
||||
}
|
||||
copyflag = true;
|
||||
} else if (copyflag) {
|
||||
if (i+num < len)
|
||||
{
|
||||
v[i] = v[i+num];
|
||||
} else {
|
||||
v[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
len -= num;
|
||||
v[len] = 0;
|
||||
}
|
||||
|
||||
String substr(unsigned int index, int num = npos)
|
||||
{
|
||||
if (!v)
|
||||
{
|
||||
String b("");
|
||||
return b;
|
||||
}
|
||||
|
||||
String ns;
|
||||
|
||||
size_t len = size();
|
||||
|
||||
if (index >= len || !v)
|
||||
return ns;
|
||||
|
||||
if (num == npos)
|
||||
{
|
||||
num = len - index;
|
||||
} else if (index+num >= len) {
|
||||
num = len - index;
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int nslen = num + 2;
|
||||
|
||||
ns.Grow(nslen);
|
||||
|
||||
for (i=index; i<index+num; i++)
|
||||
ns.append(v[i]);
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
void toLower()
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
unsigned int i = 0;
|
||||
size_t len = strlen(v);
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (v[i] >= 65 && v[i] <= 90)
|
||||
v[i] &= ~(1<<5);
|
||||
}
|
||||
}
|
||||
|
||||
String & operator = (const String &src)
|
||||
{
|
||||
assign(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & operator = (const char *src)
|
||||
{
|
||||
assign(src);
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
char operator [] (unsigned int index)
|
||||
{
|
||||
if (index > size() || !v)
|
||||
{
|
||||
return -1;
|
||||
} else {
|
||||
return v[index];
|
||||
}
|
||||
}
|
||||
|
||||
int at(int a)
|
||||
{
|
||||
if (a < 0 || a >= (int)size() || !v)
|
||||
return -1;
|
||||
|
||||
return v[a];
|
||||
}
|
||||
|
||||
bool at(int at, char c)
|
||||
{
|
||||
if (at < 0 || at >= (int)size() || !v)
|
||||
return false;
|
||||
|
||||
v[at] = c;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void Grow(unsigned int d, bool copy=true)
|
||||
{
|
||||
if (d <= a_size)
|
||||
return;
|
||||
char *n = new char[d + 1];
|
||||
if (copy && v)
|
||||
strcpy(n, v);
|
||||
if (v)
|
||||
delete [] v;
|
||||
else
|
||||
strcpy(n, "");
|
||||
v = n;
|
||||
a_size = d + 1;
|
||||
}
|
||||
|
||||
char *v;
|
||||
unsigned int a_size;
|
||||
public:
|
||||
static const int npos = -1;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CSTRING_H
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CTask.h"
|
||||
@ -113,7 +91,9 @@ void CTaskMngr::CTask::changeBase(float fNewBase)
|
||||
|
||||
void CTaskMngr::CTask::resetNextExecTime(float fCurrentTime)
|
||||
{
|
||||
m_fNextExecTime = fCurrentTime + m_fBase;
|
||||
// If we're here while we're executing we would add m_fBase twice
|
||||
if (!m_bInExecute)
|
||||
m_fNextExecTime = fCurrentTime + m_fBase;
|
||||
}
|
||||
|
||||
void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft)
|
||||
@ -223,35 +203,36 @@ void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pT
|
||||
void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat)
|
||||
{
|
||||
// first, search for free tasks
|
||||
TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true));
|
||||
|
||||
if (iter)
|
||||
for (auto &task : m_Tasks)
|
||||
{
|
||||
// found: reuse it
|
||||
iter->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||
} else {
|
||||
// not found: make a new one
|
||||
CTask *pTmp = new CTask;
|
||||
|
||||
if (!pTmp)
|
||||
if (task->isFree() && !task->inExecute())
|
||||
{
|
||||
// found: reuse it
|
||||
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||
return;
|
||||
|
||||
pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||
m_Tasks.put(pTmp);
|
||||
}
|
||||
}
|
||||
// not found: make a new one
|
||||
auto task = ke::AutoPtr<CTask>(new CTask);
|
||||
|
||||
if (!task)
|
||||
return;
|
||||
|
||||
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||
m_Tasks.append(ke::Move(task));
|
||||
}
|
||||
|
||||
int CTaskMngr::removeTasks(int iId, AMX *pAmx)
|
||||
{
|
||||
CTaskDescriptor descriptor(iId, pAmx);
|
||||
TaskListIter iter = m_Tasks.find(descriptor);
|
||||
int i = 0;
|
||||
|
||||
while (iter)
|
||||
for (auto &task : m_Tasks)
|
||||
{
|
||||
iter->clear();
|
||||
++i;
|
||||
iter = m_Tasks.find(++iter, descriptor);
|
||||
if (task->match(iId, pAmx))
|
||||
{
|
||||
task->clear();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
@ -259,16 +240,16 @@ int CTaskMngr::removeTasks(int iId, AMX *pAmx)
|
||||
|
||||
int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
|
||||
{
|
||||
CTaskDescriptor descriptor(iId, pAmx);
|
||||
TaskListIter iter = m_Tasks.find(descriptor);
|
||||
int i = 0;
|
||||
|
||||
while (iter)
|
||||
for (auto &task : m_Tasks)
|
||||
{
|
||||
iter->changeBase(fNewBase);
|
||||
iter->resetNextExecTime(*m_pTmr_CurrentTime);
|
||||
++i;
|
||||
iter = m_Tasks.find(++iter, descriptor);
|
||||
if (task->match(iId, pAmx))
|
||||
{
|
||||
task->changeBase(fNewBase);
|
||||
task->resetNextExecTime(*m_pTmr_CurrentTime);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
@ -276,16 +257,26 @@ int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
|
||||
|
||||
bool CTaskMngr::taskExists(int iId, AMX *pAmx)
|
||||
{
|
||||
return m_Tasks.find(CTaskDescriptor(iId, pAmx));
|
||||
for (auto &task : m_Tasks)
|
||||
{
|
||||
if (task->match(iId, pAmx))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTaskMngr::startFrame()
|
||||
{
|
||||
for (TaskListIter iter = m_Tasks.begin(); iter; ++iter)
|
||||
auto lastSize = m_Tasks.length();
|
||||
for(auto i = 0u; i < lastSize; i++)
|
||||
{
|
||||
if (iter->isFree())
|
||||
auto &task = m_Tasks[i];
|
||||
|
||||
if (task->isFree())
|
||||
continue;
|
||||
iter->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
|
||||
task->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef CTASK_H
|
||||
#define CTASK_H
|
||||
@ -73,41 +51,18 @@ private:
|
||||
inline bool inExecute() const { return m_bInExecute; }
|
||||
|
||||
bool shouldRepeat();
|
||||
|
||||
inline bool match(int id, AMX *amx)
|
||||
{
|
||||
return (!m_bFree) && (amx ? getAMX() == amx : true) && (m_iId == id);
|
||||
}
|
||||
|
||||
CTask();
|
||||
~CTask();
|
||||
};
|
||||
|
||||
class CTaskDescriptor
|
||||
{
|
||||
public:
|
||||
cell m_iId;
|
||||
AMX *m_pAmx;
|
||||
bool m_bFree;
|
||||
|
||||
CTaskDescriptor(int iId, AMX *pAmx, bool bFree = false)
|
||||
{
|
||||
m_iId = iId;
|
||||
m_pAmx = pAmx;
|
||||
m_bFree = bFree;
|
||||
}
|
||||
|
||||
friend bool operator == (const CTask &left, const CTaskDescriptor &right)
|
||||
{
|
||||
if (right.m_bFree)
|
||||
return (left.isFree() && !left.inExecute());
|
||||
|
||||
return (!left.isFree()) &&
|
||||
(right.m_pAmx ? left.getAMX() == right.m_pAmx : true) &&
|
||||
(left.getTaskId() == right.m_iId);
|
||||
}
|
||||
};
|
||||
|
||||
/*** CTaskMngr priv members ***/
|
||||
typedef CList<CTask, CTaskDescriptor> TaskList;
|
||||
typedef TaskList::iterator TaskListIter;
|
||||
|
||||
TaskList m_Tasks;
|
||||
ke::Vector<ke::AutoPtr<CTask>> m_Tasks;
|
||||
|
||||
float *m_pTmr_CurrentTime;
|
||||
float *m_pTmr_TimeLimit;
|
||||
|
1133
amxmodx/CTextParsers.cpp
Normal file
1133
amxmodx/CTextParsers.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
amxmodx/CTextParsers.h
Normal file
89
amxmodx/CTextParsers.h
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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_TEXTPARSERS_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
|
||||
#include <ITextParsers.h>
|
||||
#include <amtl/am-vector.h>
|
||||
|
||||
/**
|
||||
* @param void * IN: Stream pointer
|
||||
* @param char * IN/OUT: Stream buffer
|
||||
* @param size_t IN: Maximum size of buffer
|
||||
* @param unsigned int * OUT: Number of bytes read (0 = end of stream)
|
||||
* @return True on success, false on failure
|
||||
*/
|
||||
typedef bool(*STREAMREADER)(void *, char *, size_t, unsigned int *);
|
||||
|
||||
class TextParsers : public ITextParsers
|
||||
{
|
||||
public:
|
||||
TextParsers();
|
||||
public:
|
||||
bool ParseFile_INI(const char *file,
|
||||
ITextListener_INI *ini_listener,
|
||||
unsigned int *line,
|
||||
unsigned int *col,
|
||||
bool inline_comment);
|
||||
|
||||
SMCError ParseFile_SMC(const char *file,
|
||||
ITextListener_SMC *smc_listener,
|
||||
SMCStates *states);
|
||||
|
||||
SMCError ParseSMCFile(const char *file,
|
||||
ITextListener_SMC *smc_listener,
|
||||
SMCStates *states,
|
||||
char *buffer,
|
||||
size_t maxsize);
|
||||
|
||||
SMCError ParseSMCStream(const char *stream,
|
||||
size_t length,
|
||||
ITextListener_SMC *smc_listener,
|
||||
SMCStates *states,
|
||||
char *buffer,
|
||||
size_t maxsize);
|
||||
|
||||
unsigned int GetUTF8CharBytes(const char *stream);
|
||||
|
||||
const char *GetSMCErrorString(SMCError err);
|
||||
bool IsWhitespace(const char *stream);
|
||||
private:
|
||||
SMCError ParseStream_SMC(void *stream,
|
||||
STREAMREADER srdr,
|
||||
ITextListener_SMC *smc,
|
||||
SMCStates *states);
|
||||
};
|
||||
|
||||
extern TextParsers g_TextParser;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
|
@ -1,40 +1,18 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "amxmodx.h"
|
||||
#include "CVault.h"
|
||||
#include "CFile.h"
|
||||
#include "CFileSystem.h"
|
||||
|
||||
// *****************************************************
|
||||
// class Vault
|
||||
@ -61,7 +39,7 @@ void Vault::put(const char* k, const char* v)
|
||||
|
||||
if (*a)
|
||||
{
|
||||
(*a)->value.assign(v);
|
||||
(*a)->value = v;
|
||||
(*a)->number = atoi(v);
|
||||
}
|
||||
else
|
||||
@ -79,7 +57,7 @@ Vault::Obj** Vault::find(const char* n)
|
||||
|
||||
while (*a)
|
||||
{
|
||||
if (strcmp((*a)->key.c_str(), n) == 0)
|
||||
if (strcmp((*a)->key.chars(), n) == 0)
|
||||
return a;
|
||||
|
||||
a = &(*a)->next;
|
||||
@ -108,7 +86,7 @@ const char* Vault::get(const char* n)
|
||||
|
||||
if (b == 0) return "";
|
||||
|
||||
return b->value.c_str();
|
||||
return b->value.chars();
|
||||
}
|
||||
|
||||
void Vault::clear()
|
||||
@ -134,45 +112,74 @@ void Vault::remove(const char* n)
|
||||
|
||||
void Vault::setSource(const char* n)
|
||||
{
|
||||
path.assign(n);
|
||||
path = n;
|
||||
}
|
||||
|
||||
bool Vault::loadVault()
|
||||
{
|
||||
if (path.empty()) return false;
|
||||
if (!path.length())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
File a(path.c_str(), "r");
|
||||
FILE *fp = fopen(path.chars(), "r");
|
||||
|
||||
if (!a) return false;
|
||||
|
||||
const int sz = 512;
|
||||
char value[sz + 1];
|
||||
char key[sz + 1];
|
||||
|
||||
while (a >> key && a.skipWs() && a.getline(value, sz))
|
||||
if (!fp)
|
||||
{
|
||||
if (isalpha(*key))
|
||||
put(key, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
char lineRead[512];
|
||||
char key[sizeof(lineRead) + 1];
|
||||
char value[sizeof(lineRead) + 1];
|
||||
|
||||
while (fgets(lineRead, sizeof(lineRead), fp))
|
||||
{
|
||||
UTIL_TrimLeft(lineRead);
|
||||
|
||||
if (!*lineRead || *lineRead == ';')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sscanf(lineRead, "%s%*[ \t]%[^\n]", key, value);
|
||||
|
||||
if (isalpha(*key))
|
||||
{
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool Vault::saveVault()
|
||||
{
|
||||
if (path.empty()) return false;
|
||||
if (!path.length())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
File a(path.c_str(), "w");
|
||||
FILE *fp = fopen(path.chars(), "w");
|
||||
|
||||
if (!a) return false;
|
||||
if (!fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
a << "; Don't modify!" << '\n';
|
||||
fputs("; Don't modify!\n", fp);
|
||||
|
||||
for (Obj* b = head; b; b = b->next)
|
||||
a << b->key << '\t' << b->value << '\n';
|
||||
{
|
||||
fprintf(fp, "%s\t%s\n", b->key.chars(), b->value.chars());
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,40 +1,15 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef VAULT_CUSTOM_H
|
||||
#define VAULT_CUSTOM_H
|
||||
|
||||
#include "CString.h"
|
||||
#include "CList.h"
|
||||
|
||||
// *****************************************************
|
||||
// class Vault
|
||||
// *****************************************************
|
||||
@ -43,15 +18,15 @@ class Vault
|
||||
{
|
||||
struct Obj
|
||||
{
|
||||
String key;
|
||||
String value;
|
||||
|
||||
ke::AString key;
|
||||
ke::AString value;
|
||||
|
||||
int number;
|
||||
Obj *next;
|
||||
Obj(const char* k, const char* v);
|
||||
} *head;
|
||||
|
||||
String path;
|
||||
ke::AString path;
|
||||
|
||||
Obj** find(const char* n);
|
||||
|
||||
@ -84,8 +59,8 @@ public:
|
||||
iterator& operator++() { if (a) a = a->next; return *this; }
|
||||
bool operator==(const iterator& b) const { return a == b.a; }
|
||||
bool operator!=(const iterator& b) const { return !operator==(b); }
|
||||
String& key() const { return a->key; }
|
||||
String& value() const { return a->value; }
|
||||
ke::AString& key() const { return a->key; }
|
||||
ke::AString& value() const { return a->value; }
|
||||
};
|
||||
|
||||
inline iterator begin() const { return iterator(head); }
|
||||
|
@ -1,491 +0,0 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#ifndef __CVECTOR_H__
|
||||
#define __CVECTOR_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// Vector
|
||||
template <class T> class CVector
|
||||
{
|
||||
bool Grow()
|
||||
{
|
||||
// automatic grow
|
||||
size_t newSize = m_Size * 2;
|
||||
if (newSize == 0)
|
||||
newSize = 8; // a good init value
|
||||
T *newData = new T[newSize];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
for (size_t i=0; i<m_CurrentUsedSize; i++)
|
||||
newData[i] = m_Data[i];
|
||||
delete [] m_Data;
|
||||
}
|
||||
m_Data = newData;
|
||||
m_Size = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrowIfNeeded()
|
||||
{
|
||||
if (m_CurrentUsedSize >= m_Size)
|
||||
return Grow();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeSize(size_t size)
|
||||
{
|
||||
// change size
|
||||
if (size == m_Size)
|
||||
return true;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
if (m_Data)
|
||||
{
|
||||
delete [] m_Data;
|
||||
m_Data = NULL;
|
||||
m_Size = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T *newData = new T[size];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
|
||||
for (size_t i=0; i<end; i++)
|
||||
newData[i] = m_Data[i];
|
||||
delete [] m_Data;
|
||||
}
|
||||
m_Data = newData;
|
||||
m_Size = size;
|
||||
if (m_CurrentUsedSize > m_Size)
|
||||
m_CurrentUsedSize = m_Size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeMemIfPossible()
|
||||
{
|
||||
if (!m_Data)
|
||||
return;
|
||||
|
||||
if (!m_CurrentUsedSize)
|
||||
{
|
||||
ChangeSize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t newSize = m_Size;
|
||||
while (m_CurrentUsedSize <= newSize / 2)
|
||||
newSize /= 2;
|
||||
|
||||
if (newSize != m_Size)
|
||||
ChangeSize(newSize);
|
||||
}
|
||||
protected:
|
||||
T *m_Data;
|
||||
size_t m_Size;
|
||||
size_t m_CurrentUsedSize;
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
protected:
|
||||
T *m_Ptr;
|
||||
public:
|
||||
// constructors / destructors
|
||||
iterator()
|
||||
{
|
||||
m_Ptr = NULL;
|
||||
}
|
||||
|
||||
iterator(T * ptr)
|
||||
{
|
||||
m_Ptr = ptr;
|
||||
}
|
||||
|
||||
// member functions
|
||||
T * base()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
const T * base() const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
// operators
|
||||
T & operator*()
|
||||
{
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
T * operator->()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
iterator & operator++() // preincrement
|
||||
{
|
||||
++m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator++(int) // postincrement
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator & operator--() // predecrement
|
||||
{
|
||||
--m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator--(int) // postdecrememnt
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(T * right) const
|
||||
{
|
||||
return (m_Ptr == right);
|
||||
}
|
||||
|
||||
bool operator==(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr == right.m_Ptr);
|
||||
}
|
||||
|
||||
bool operator!=(T * right) const
|
||||
{
|
||||
return (m_Ptr != right);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr != right.m_Ptr);
|
||||
}
|
||||
|
||||
iterator & operator+=(size_t offset)
|
||||
{
|
||||
m_Ptr += offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator & operator-=(size_t offset)
|
||||
{
|
||||
m_Ptr -= offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator+(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr += offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator operator-(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr -= offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T & operator[](size_t offset)
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
const T & operator[](size_t offset) const
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
bool operator<(const iterator & right) const
|
||||
{
|
||||
return m_Ptr < right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>(const iterator & right) const
|
||||
{
|
||||
return m_Ptr > right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator<=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr <= right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr >= right.m_Ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const iterator & right) const
|
||||
{
|
||||
return m_Ptr - right.m_Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// constructors / destructors
|
||||
CVector<T>()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
m_Data = NULL;
|
||||
}
|
||||
|
||||
CVector<T>(const CVector<T> & other)
|
||||
{
|
||||
// copy data
|
||||
m_Data = new T [other.m_CurrentUsedSize];
|
||||
m_Size = other.m_CurrentUsedSize;
|
||||
m_CurrentUsedSize = other.m_CurrentUsedSize;
|
||||
for (size_t i=0; i<other.m_CurrentUsedSize; i++)
|
||||
m_Data[i] = other.m_Data[i];
|
||||
}
|
||||
|
||||
~CVector<T>()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// interface
|
||||
size_t size() const
|
||||
{
|
||||
return m_CurrentUsedSize;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(m_Data);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(m_Data + m_CurrentUsedSize);
|
||||
}
|
||||
|
||||
iterator iterAt(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
assert(0);
|
||||
return iterator(m_Data + pos);
|
||||
}
|
||||
|
||||
bool reserve(size_t newSize)
|
||||
{
|
||||
if (newSize > m_Size)
|
||||
return ChangeSize(newSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push_back(const T & elem)
|
||||
{
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Data[m_CurrentUsedSize - 1] = elem;
|
||||
return true;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
if (m_CurrentUsedSize < 0)
|
||||
m_CurrentUsedSize = 0;
|
||||
|
||||
FreeMemIfPossible();
|
||||
}
|
||||
|
||||
bool resize(size_t newSize)
|
||||
{
|
||||
if (!ChangeSize(newSize))
|
||||
return false;
|
||||
m_CurrentUsedSize = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (m_CurrentUsedSize == 0);
|
||||
}
|
||||
|
||||
T & at(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
const T & at(size_t pos) const
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
T & operator[](size_t pos)
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
const T & operator[](size_t pos) const
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
T & front()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
const T & front() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
T & back()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
const T & back() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
iterator insert(iterator where, const T & value)
|
||||
{
|
||||
// validate iter
|
||||
if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
|
||||
return iterator(0);
|
||||
|
||||
size_t ofs = where - begin();
|
||||
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
where = begin() + ofs;
|
||||
|
||||
// Move subsequent entries
|
||||
for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
|
||||
*(ptr + 1) = *ptr;
|
||||
|
||||
*where.base() = value;
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
iterator erase(iterator where)
|
||||
{
|
||||
// validate iter
|
||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
||||
return iterator(0);
|
||||
|
||||
size_t ofs = where - begin();
|
||||
|
||||
if (m_CurrentUsedSize > 1)
|
||||
{
|
||||
// move
|
||||
T *theend = m_Data + m_CurrentUsedSize;
|
||||
for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
|
||||
*(ptr - 1) = *ptr;
|
||||
}
|
||||
|
||||
--m_CurrentUsedSize;
|
||||
|
||||
FreeMemIfPossible();
|
||||
|
||||
return begin() + ofs;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
if (m_Data)
|
||||
{
|
||||
delete [] m_Data;
|
||||
m_Data = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __CVECTOR_H__
|
||||
|
340
amxmodx/CoreConfig.cpp
Normal file
340
amxmodx/CoreConfig.cpp
Normal file
@ -0,0 +1,340 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "CLibrarySys.h"
|
||||
#include <amxmodx_version.h>
|
||||
|
||||
CoreConfig CoreCfg;
|
||||
|
||||
const char *MainConfigFile = "amxx.cfg";
|
||||
const char *AutoConfigDir = "/plugins";
|
||||
const char *MapConfigDir = "/maps";
|
||||
const char *CommandFormat = "exec %s\n";
|
||||
|
||||
CoreConfig::CoreConfig()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
CoreConfig::~CoreConfig()
|
||||
{
|
||||
}
|
||||
|
||||
void CoreConfig::OnAmxxInitialized()
|
||||
{
|
||||
m_ConfigsBufferedForward = registerForward("OnAutoConfigsBuffered", ET_IGNORE, FP_DONE);
|
||||
m_ConfigsExecutedForward = registerForward("OnConfigsExecuted", ET_IGNORE, FP_DONE);
|
||||
}
|
||||
|
||||
void CoreConfig::Clear()
|
||||
{
|
||||
m_ConfigsExecuted = false;
|
||||
m_PendingForwardPush = false;
|
||||
m_LegacyMainConfigExecuted = false;
|
||||
m_LegacyMapConfigsExecuted = false,
|
||||
m_legacyMapConfigNextTime = 0.0f;
|
||||
}
|
||||
|
||||
void CoreConfig::ExecuteMainConfig()
|
||||
{
|
||||
if (m_LegacyMainConfigExecuted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
|
||||
|
||||
ke::SafeSprintf(path, sizeof(path), "%s/%s/%s", g_mod_name.chars(), get_localinfo("amxx_configsdir", "addons/amxmodx/configs"), MainConfigFile);
|
||||
ke::SafeSprintf(command, sizeof(command), CommandFormat, path);
|
||||
|
||||
SERVER_COMMAND(command);
|
||||
}
|
||||
|
||||
void CoreConfig::ExecuteAutoConfigs()
|
||||
{
|
||||
for (size_t i = 0; i < static_cast<size_t>(g_plugins.getPluginsNum()); ++i)
|
||||
{
|
||||
auto plugin = g_plugins.findPlugin(i);
|
||||
|
||||
bool can_create = true;
|
||||
|
||||
for (size_t j = 0; j < plugin->GetConfigCount(); ++j)
|
||||
{
|
||||
can_create = ExecuteAutoConfig(plugin, plugin->GetConfig(j), can_create);
|
||||
}
|
||||
}
|
||||
|
||||
executeForwards(m_ConfigsBufferedForward);
|
||||
}
|
||||
|
||||
bool CoreConfig::ExecuteAutoConfig(CPluginMngr::CPlugin *plugin, AutoConfig *config, bool can_create)
|
||||
{
|
||||
bool will_create = false;
|
||||
|
||||
const char *configsDir = get_localinfo("amxx_configsdir", "addons/amxmodx/configs");
|
||||
|
||||
if (can_create && config->create)
|
||||
{
|
||||
will_create = true;
|
||||
|
||||
const char *folder = config->folder.chars();
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char build[PLATFORM_MAX_PATH];
|
||||
|
||||
build_pathname_r(path, sizeof(path), "%s%s/%s", configsDir, AutoConfigDir, folder);
|
||||
|
||||
if (!g_LibSys.IsPathDirectory(path))
|
||||
{
|
||||
char *cur_ptr = path;
|
||||
|
||||
g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
|
||||
build_pathname_r(build, sizeof(build), "%s%s", configsDir, AutoConfigDir);
|
||||
|
||||
size_t length = strlen(build);
|
||||
|
||||
do
|
||||
{
|
||||
char *next_ptr = cur_ptr;
|
||||
|
||||
while (*next_ptr != '\0')
|
||||
{
|
||||
if (*next_ptr == PLATFORM_SEP_CHAR)
|
||||
{
|
||||
*next_ptr = '\0';
|
||||
next_ptr++;
|
||||
break;
|
||||
}
|
||||
|
||||
next_ptr++;
|
||||
}
|
||||
|
||||
if (*next_ptr == '\0')
|
||||
{
|
||||
next_ptr = nullptr;
|
||||
}
|
||||
|
||||
length += g_LibSys.PathFormat(&build[length], sizeof(build) - length, "/%s", cur_ptr);
|
||||
|
||||
if (!g_LibSys.CreateFolder(build))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
cur_ptr = next_ptr;
|
||||
|
||||
} while (cur_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
|
||||
if (config->folder.length())
|
||||
{
|
||||
ke::SafeSprintf(file, sizeof(file), "%s/%s%s/%s/%s.cfg", g_mod_name.chars(), configsDir, AutoConfigDir, config->folder.chars(), config->autocfg.chars());
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeSprintf(file, sizeof(file), "%s/%s%s/%s.cfg", g_mod_name.chars(), configsDir, AutoConfigDir, config->autocfg.chars());
|
||||
}
|
||||
|
||||
bool file_exists = g_LibSys.IsPathFile(file);
|
||||
|
||||
if (!file_exists && will_create)
|
||||
{
|
||||
auto list = g_CvarManager.GetCvarsList();
|
||||
|
||||
if (list->empty())
|
||||
{
|
||||
return can_create;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(file, "wt");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "// This file was auto-generated by AMX Mod X (v%s)\n", AMXX_VERSION);
|
||||
|
||||
if (*plugin->getTitle() && *plugin->getAuthor() && *plugin->getVersion())
|
||||
{
|
||||
fprintf(fp, "// Cvars for plugin \"%s\" by \"%s\" (%s, v%s)\n", plugin->getTitle(), plugin->getAuthor(), plugin->getName(), plugin->getVersion());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp, "// Cvars for plugin \"%s\"\n", plugin->getName());
|
||||
}
|
||||
|
||||
fprintf(fp, "\n\n");
|
||||
|
||||
for (auto iter = list->begin(); iter != list->end(); iter++)
|
||||
{
|
||||
auto info = (*iter);
|
||||
|
||||
if (info->pluginId == plugin->getId())
|
||||
{
|
||||
char description[255];
|
||||
char *ptr = description;
|
||||
|
||||
// Print comments until there is no more
|
||||
strncopy(description, info->description.chars(), sizeof(description));
|
||||
|
||||
while (*ptr != '\0')
|
||||
{
|
||||
// Find the next line
|
||||
char *next_ptr = ptr;
|
||||
|
||||
while (*next_ptr != '\0')
|
||||
{
|
||||
if (*next_ptr == '\n')
|
||||
{
|
||||
*next_ptr = '\0';
|
||||
next_ptr++;
|
||||
break;
|
||||
}
|
||||
|
||||
next_ptr++;
|
||||
}
|
||||
|
||||
fprintf(fp, "// %s\n", ptr);
|
||||
|
||||
ptr = next_ptr;
|
||||
}
|
||||
|
||||
fprintf(fp, "// -\n");
|
||||
fprintf(fp, "// Default: \"%s\"\n", info->defaultval.chars());
|
||||
|
||||
if (info->bound.hasMin)
|
||||
{
|
||||
fprintf(fp, "// Minimum: \"%02f\"\n", info->bound.minVal);
|
||||
}
|
||||
|
||||
if (info->bound.hasMax)
|
||||
{
|
||||
fprintf(fp, "// Maximum: \"%02f\"\n", info->bound.maxVal);
|
||||
}
|
||||
|
||||
fprintf(fp, "%s \"%s\"\n", info->var->name, info->defaultval.chars());
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, "\n");
|
||||
|
||||
file_exists = true;
|
||||
can_create = false;
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMXXLOG_Error("Failed to auto generate config for %s, make sure the directory has write permission.", plugin->getName());
|
||||
return can_create;
|
||||
}
|
||||
}
|
||||
|
||||
if (file_exists)
|
||||
{
|
||||
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
|
||||
ke::SafeSprintf(command, sizeof(command), CommandFormat, file);
|
||||
|
||||
SERVER_COMMAND(command);
|
||||
}
|
||||
|
||||
return can_create;
|
||||
}
|
||||
|
||||
void CoreConfig::ExecuteMapConfig()
|
||||
{
|
||||
const char *configsDir = get_localinfo("amxx_configsdir", "addons/amxmodx/configs");
|
||||
|
||||
char cfgPath[PLATFORM_MAX_PATH];
|
||||
char mapName[PLATFORM_MAX_PATH];
|
||||
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
|
||||
|
||||
strncopy(mapName, STRING(gpGlobals->mapname), sizeof(mapName));
|
||||
|
||||
char *mapPrefix;
|
||||
|
||||
if ((mapPrefix = strtok(mapName, "_")))
|
||||
{
|
||||
ke::SafeSprintf(cfgPath, sizeof(cfgPath), "%s/%s%s/prefix_%s.cfg", g_mod_name.chars(), configsDir, MapConfigDir, mapPrefix);
|
||||
|
||||
if (g_LibSys.IsPathFile(cfgPath))
|
||||
{
|
||||
ke::SafeSprintf(command, sizeof(command), CommandFormat, cfgPath);
|
||||
SERVER_COMMAND(command);
|
||||
}
|
||||
}
|
||||
|
||||
strncopy(mapName, STRING(gpGlobals->mapname), sizeof(mapName));
|
||||
ke::SafeSprintf(cfgPath, sizeof(cfgPath), "%s/%s%s/%s.cfg", g_mod_name.chars(), configsDir, MapConfigDir, mapName);
|
||||
|
||||
if (g_LibSys.IsPathFile(cfgPath))
|
||||
{
|
||||
ke::SafeSprintf(command, sizeof(command), CommandFormat, cfgPath);
|
||||
SERVER_COMMAND(command);
|
||||
}
|
||||
|
||||
// Consider all configs be executed to the next frame.
|
||||
m_PendingForwardPush = true;
|
||||
}
|
||||
|
||||
|
||||
void CoreConfig::OnMapConfigTimer()
|
||||
{
|
||||
if (m_ConfigsExecuted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_legacyMapConfigNextTime <= gpGlobals->time)
|
||||
{
|
||||
if (m_PendingForwardPush)
|
||||
{
|
||||
m_PendingForwardPush = false;
|
||||
m_ConfigsExecuted = true;
|
||||
|
||||
executeForwards(m_ConfigsExecutedForward);
|
||||
}
|
||||
else if (!m_LegacyMapConfigsExecuted)
|
||||
{
|
||||
ExecuteMapConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoreConfig::CheckLegacyBufferedCommand(char *command)
|
||||
{
|
||||
if (m_ConfigsExecuted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!m_LegacyMainConfigExecuted && strstr(command, MainConfigFile))
|
||||
{
|
||||
m_LegacyMainConfigExecuted = true;
|
||||
}
|
||||
|
||||
if (!m_LegacyMapConfigsExecuted && strstr(command, MapConfigDir))
|
||||
{
|
||||
m_LegacyMapConfigsExecuted = true;
|
||||
|
||||
// Consider all configs be executed to m_legacyMapConfigNextTime time.
|
||||
m_PendingForwardPush = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CoreConfig::SetMapConfigTimer(float time)
|
||||
{
|
||||
m_legacyMapConfigNextTime = gpGlobals->time + time;
|
||||
}
|
51
amxmodx/CoreConfig.h
Normal file
51
amxmodx/CoreConfig.h
Normal file
@ -0,0 +1,51 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _CORE_CONFIG_H_
|
||||
#define _CORE_CONFIG_H_
|
||||
|
||||
#include "CPlugin.h"
|
||||
|
||||
class CoreConfig
|
||||
{
|
||||
public:
|
||||
|
||||
CoreConfig();
|
||||
~CoreConfig();
|
||||
|
||||
public:
|
||||
|
||||
void Clear();
|
||||
|
||||
void ExecuteMainConfig();
|
||||
void ExecuteAutoConfigs();
|
||||
bool ExecuteAutoConfig(CPluginMngr::CPlugin *plugin, AutoConfig *config, bool can_create);
|
||||
void ExecuteMapConfig();
|
||||
|
||||
void OnAmxxInitialized();
|
||||
void OnMapConfigTimer();
|
||||
|
||||
void CheckLegacyBufferedCommand(char *command);
|
||||
void SetMapConfigTimer(float time);
|
||||
|
||||
private:
|
||||
|
||||
bool m_ConfigsExecuted; // Whether all configs have been executed
|
||||
bool m_PendingForwardPush; // Whether OnConfigsExecuted forward should be triggered to the next frame
|
||||
bool m_LegacyMainConfigExecuted; // Whether the old admin.sma is used and amxx.cfg was executed from there
|
||||
bool m_LegacyMapConfigsExecuted; // Whether the old admin.sma is used and per-map config was executed from there
|
||||
float m_legacyMapConfigNextTime; // Sets the next time that per-map configs should be executed
|
||||
|
||||
int m_ConfigsBufferedForward;
|
||||
int m_ConfigsExecutedForward;
|
||||
};
|
||||
|
||||
extern CoreConfig CoreCfg;
|
||||
|
||||
#endif // _CORE_CONFIG_H_
|
669
amxmodx/CvarManager.cpp
Normal file
669
amxmodx/CvarManager.cpp
Normal file
@ -0,0 +1,669 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "CvarManager.h"
|
||||
#include "amxmodx.h"
|
||||
#include <CDetour/detours.h>
|
||||
#include <auto-string.h>
|
||||
#include <resdk/mod_rehlds_api.h>
|
||||
|
||||
CvarManager g_CvarManager;
|
||||
|
||||
void (*Cvar_DirectSet_Actual)(struct cvar_s* var, const char *value) = nullptr;
|
||||
|
||||
void Cvar_DirectSet_Custom(struct cvar_s *var, const char *value, IRehldsHook_Cvar_DirectSet *chain = nullptr)
|
||||
{
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!var || !value // Sanity checks against bogus pointers.
|
||||
|| strcmp(var->string, value) == 0 // Make sure old and new values are different to not trigger callbacks.
|
||||
|| !g_CvarManager.CacheLookup(var->name, &info)) // No data in cache, nothing to do.
|
||||
{
|
||||
chain ? chain->callNext(var, value) : Cvar_DirectSet_Actual(var, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here.
|
||||
{
|
||||
float fvalue = atof(value);
|
||||
bool oob = false;
|
||||
|
||||
if (info->bound.hasMin && fvalue < info->bound.minVal)
|
||||
{
|
||||
oob = true;
|
||||
fvalue = info->bound.minVal;
|
||||
}
|
||||
else if (info->bound.hasMax && fvalue > info->bound.maxVal)
|
||||
{
|
||||
oob = true;
|
||||
fvalue = info->bound.maxVal;
|
||||
}
|
||||
|
||||
if (oob) // Found value out of bound, set new value and block original call.
|
||||
{
|
||||
CVAR_SET_FLOAT(var->name, fvalue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ke::AString oldValue; // We save old value since it will be likely changed after original function called.
|
||||
|
||||
if (!info->hooks.empty())
|
||||
{
|
||||
oldValue = var->string;
|
||||
}
|
||||
|
||||
chain ? chain->callNext(var, value) : Cvar_DirectSet_Actual(var, value);
|
||||
|
||||
if (!info->binds.empty())
|
||||
{
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
switch (bind->type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
{
|
||||
*bind->varAddress = atoi(var->string);
|
||||
break;
|
||||
}
|
||||
case CvarBind::CvarType_Float:
|
||||
{
|
||||
float fvalue = atof(var->string);
|
||||
*bind->varAddress = amx_ftoc(fvalue);
|
||||
break;
|
||||
}
|
||||
case CvarBind::CvarType_String:
|
||||
{
|
||||
set_amxstring_simple(bind->varAddress, var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!info->hooks.empty())
|
||||
{
|
||||
for (size_t i = 0; i < info->hooks.length(); ++i)
|
||||
{
|
||||
CvarHook* hook = info->hooks[i];
|
||||
|
||||
if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives.
|
||||
{
|
||||
executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), oldValue.chars(), var->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cvar_DirectSet(struct cvar_s *var, const char *value)
|
||||
{
|
||||
Cvar_DirectSet_Custom(var, value);
|
||||
}
|
||||
|
||||
void Cvar_DirectSet_RH(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value)
|
||||
{
|
||||
Cvar_DirectSet_Custom(var, value, chain);
|
||||
}
|
||||
|
||||
|
||||
CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr), m_ReHookEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
CvarManager::~CvarManager()
|
||||
{
|
||||
OnAmxxShutdown();
|
||||
}
|
||||
|
||||
void CvarManager::CreateCvarHook(void)
|
||||
{
|
||||
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
|
||||
// {
|
||||
// Cvar_DirectSet(var, value); // <- We want to hook this.
|
||||
// }
|
||||
|
||||
if (!RehldsHookchains)
|
||||
{
|
||||
void *functionAddress = nullptr;
|
||||
|
||||
if (CommonConfig && CommonConfig->GetMemSig("Cvar_DirectSet", &functionAddress) && functionAddress)
|
||||
{
|
||||
// Disabled by default.
|
||||
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, functionAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMXXLOG_Log("Binding/Hooking cvars have been disabled - %s.", RehldsApi ? "update ReHLDS" : "check your gamedata files");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CvarManager::EnableHook()
|
||||
{
|
||||
if (RehldsHookchains)
|
||||
{
|
||||
if (!m_ReHookEnabled)
|
||||
{
|
||||
RehldsHookchains->Cvar_DirectSet()->registerHook(Cvar_DirectSet_RH);
|
||||
m_ReHookEnabled = true;
|
||||
}
|
||||
}
|
||||
else if (m_HookDetour)
|
||||
{
|
||||
m_HookDetour->EnableDetour();
|
||||
}
|
||||
}
|
||||
|
||||
void CvarManager::DisableHook()
|
||||
{
|
||||
if (RehldsHookchains)
|
||||
{
|
||||
if (m_ReHookEnabled)
|
||||
{
|
||||
RehldsHookchains->Cvar_DirectSet()->unregisterHook(Cvar_DirectSet_RH);
|
||||
m_ReHookEnabled = false;
|
||||
}
|
||||
}
|
||||
else if (m_HookDetour)
|
||||
{
|
||||
m_HookDetour->DisableDetour();
|
||||
}
|
||||
}
|
||||
|
||||
void CvarManager::DestroyHook()
|
||||
{
|
||||
DisableHook();
|
||||
|
||||
if (m_HookDetour)
|
||||
{
|
||||
m_HookDetour->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
CvarInfo* CvarManager::CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags,
|
||||
const char* helpText)
|
||||
{
|
||||
cvar_t* var = nullptr;
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!CacheLookup(name, &info))
|
||||
{
|
||||
// Not cached - Is cvar already exist?
|
||||
var = CVAR_GET_POINTER(name);
|
||||
|
||||
// Whether it exists, we need to prepare a new entry.
|
||||
info = new CvarInfo(name, helpText, plugin, pluginId);
|
||||
|
||||
if (var)
|
||||
{
|
||||
// Cvar already exists. Just copy.
|
||||
// "string" will be set after. "value" and "next" are automatically set.
|
||||
info->var = var;
|
||||
info->defaultval = var->string;
|
||||
info->amxmodx = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Registers a new cvar.
|
||||
static cvar_t cvar_reg_helper;
|
||||
|
||||
// "string" will be set after. "value" and "next" are automatically set.
|
||||
cvar_reg_helper.name = info->name.chars();
|
||||
cvar_reg_helper.string = "";
|
||||
cvar_reg_helper.flags = flags;
|
||||
|
||||
// Adds cvar to global list.
|
||||
CVAR_REGISTER(&cvar_reg_helper);
|
||||
|
||||
// Registering can fail if name is already a registered command.
|
||||
var = CVAR_GET_POINTER(name);
|
||||
|
||||
// If so, we can't go further.
|
||||
if (!var)
|
||||
{
|
||||
delete info;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If ok, we got a valid pointer, we can copy.
|
||||
info->var = var;
|
||||
info->defaultval = value;
|
||||
info->amxmodx = true;
|
||||
|
||||
// Keeps track count of cvars registered by AMXX.
|
||||
++m_AmxmodxCvars;
|
||||
}
|
||||
|
||||
// Add a new entry in the caches.
|
||||
m_Cvars.append(info);
|
||||
m_Cache.insert(name, info);
|
||||
|
||||
// Make sure that whether an existing or new cvar is set to the given value.
|
||||
CVAR_DIRECTSET(var, value);
|
||||
}
|
||||
else if (info->pluginId == -1)
|
||||
{
|
||||
// In situation where a plugin has been modified/recompiled
|
||||
// or new added plugins, and a change map occurs. We want to keep data up to date.
|
||||
info->bound.hasMin = false;
|
||||
info->bound.minVal = 0;
|
||||
info->bound.hasMax = false;
|
||||
info->bound.maxVal = 0;
|
||||
info->defaultval = value;
|
||||
info->description = helpText;
|
||||
info->pluginId = pluginId;
|
||||
}
|
||||
|
||||
// Detour is disabled on map change.
|
||||
// Don't enable it unless there are things to do.
|
||||
if ((info->bound.hasMin || info->bound.hasMax))
|
||||
{
|
||||
EnableHook();
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
CvarInfo* CvarManager::FindCvar(const char* name)
|
||||
{
|
||||
cvar_t* var = nullptr;
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
// Do we have already cvar in cache?
|
||||
if (CacheLookup(name, &info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
||||
// Cvar doesn't exist.
|
||||
if (!(var = CVAR_GET_POINTER(name)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a new entry.
|
||||
info = new CvarInfo(name);
|
||||
info->var = var;
|
||||
|
||||
// Add entry in the caches.
|
||||
m_Cvars.append(info);
|
||||
m_Cache.insert(name, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
CvarInfo* CvarManager::FindCvar(size_t index)
|
||||
{
|
||||
// Used by get_plugins_cvar native.
|
||||
// For compatibility, only cvars registered by AMXX are concerned.
|
||||
|
||||
size_t iter_id = 0;
|
||||
|
||||
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
||||
{
|
||||
if (iter->amxmodx && iter_id++ == index)
|
||||
{
|
||||
return *(iter);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CvarManager::CacheLookup(const char* name, CvarInfo** info)
|
||||
{
|
||||
return m_Cache.retrieve(name, info);
|
||||
}
|
||||
|
||||
AutoForward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback)
|
||||
{
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
// A cvar is guaranteed to be in cache if pointer is got from
|
||||
// get_cvar_pointer and register_cvar natives. Though it might be
|
||||
// provided by another way. If by any chance we run in such
|
||||
// situation, we create a new entry right now.
|
||||
|
||||
if (!CacheLookup(var->name, &info))
|
||||
{
|
||||
// Create a new entry.
|
||||
info = new CvarInfo(var->name);
|
||||
info->var = var;
|
||||
|
||||
// Add entry in the caches.
|
||||
m_Cvars.append(info);
|
||||
m_Cache.insert(info->name.chars(), info);
|
||||
}
|
||||
|
||||
int length;
|
||||
*callback = get_amxstring(amx, param, 0, length);
|
||||
|
||||
int forwardId = registerSPForwardByName(amx, *callback, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
||||
|
||||
// Invalid callback, it could be: not a public function, wrongly named, or simply missing.
|
||||
if (forwardId == -1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Hook is disabled on map change.
|
||||
EnableHook();
|
||||
|
||||
AutoForward* forward = new AutoForward(forwardId, *callback);
|
||||
info->hooks.append(new CvarHook(g_plugins.findPlugin(amx)->getId(), forward));
|
||||
|
||||
return forward;
|
||||
}
|
||||
|
||||
bool CvarManager::BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen)
|
||||
{
|
||||
if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it.
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Cvars can only be bound to global variables");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
cell* address = get_amxaddr(amx, varofs);
|
||||
|
||||
// To avoid unexpected behavior, probably better to error such situations.
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
if (bind->pluginId == pluginId)
|
||||
{
|
||||
if (bind->varAddress == address)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A global variable can not be bound to multiple Cvars");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen);
|
||||
|
||||
info->binds.append(bind);
|
||||
|
||||
// Update right away variable with current cvar value.
|
||||
switch (type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
*bind->varAddress = atoi(info->var->string);
|
||||
break;
|
||||
case CvarBind::CvarType_Float:
|
||||
*bind->varAddress = amx_ftoc(info->var->value);
|
||||
break;
|
||||
case CvarBind::CvarType_String:
|
||||
set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
|
||||
// Hook is disabled on map change.
|
||||
EnableHook();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CvarManager::SetCvarMin(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMin = set;
|
||||
info->bound.minPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
// Hook is disabled on map change.
|
||||
EnableHook();
|
||||
|
||||
info->bound.minVal = value;
|
||||
|
||||
// Current value is already in the allowed range.
|
||||
if (info->var->value >= value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
}
|
||||
|
||||
void CvarManager::SetCvarMax(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMax = set;
|
||||
info->bound.maxPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
// Hook is disabled on map change.
|
||||
EnableHook();
|
||||
|
||||
info->bound.maxVal = value;
|
||||
|
||||
// Current value is already in the allowed range.
|
||||
if (info->var->value <= value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
}
|
||||
|
||||
size_t CvarManager::GetRegCvarsCount()
|
||||
{
|
||||
return m_AmxmodxCvars;
|
||||
}
|
||||
|
||||
CvarsList* CvarManager::GetCvarsList()
|
||||
{
|
||||
return &m_Cvars;
|
||||
}
|
||||
|
||||
ke::AutoString convertFlagsToString(int flags)
|
||||
{
|
||||
ke::AutoString flagsName;
|
||||
|
||||
if (flags > 0)
|
||||
{
|
||||
if (flags & FCVAR_ARCHIVE) flagsName = flagsName + "FCVAR_ARCHIVE ";
|
||||
if (flags & FCVAR_USERINFO) flagsName = flagsName + "FCVAR_USERINFO ";
|
||||
if (flags & FCVAR_SERVER) flagsName = flagsName + "FCVAR_SERVER ";
|
||||
if (flags & FCVAR_EXTDLL) flagsName = flagsName + "FCVAR_EXTDLL ";
|
||||
if (flags & FCVAR_CLIENTDLL) flagsName = flagsName + "FCVAR_CLIENTDLL ";
|
||||
if (flags & FCVAR_PROTECTED) flagsName = flagsName + "FCVAR_PROTECTED ";
|
||||
if (flags & FCVAR_SPONLY) flagsName = flagsName + "FCVAR_SPONLY ";
|
||||
if (flags & FCVAR_PRINTABLEONLY) flagsName = flagsName + "FCVAR_PRINTABLEONLY ";
|
||||
if (flags & FCVAR_UNLOGGED) flagsName = flagsName + "FCVAR_UNLOGGED ";
|
||||
if (flags & FCVAR_NOEXTRAWHITEPACE) flagsName = flagsName + "FCVAR_NOEXTRAWHITEPACE ";
|
||||
}
|
||||
|
||||
if (!flagsName.length())
|
||||
{
|
||||
flagsName = "-";
|
||||
}
|
||||
|
||||
return flagsName;
|
||||
}
|
||||
|
||||
void CvarManager::OnConsoleCommand()
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t indexToSearch = 0;
|
||||
ke::AString partialName;
|
||||
|
||||
int argcount = CMD_ARGC();
|
||||
|
||||
// amxx cvars [partial plugin name] [index from listing]
|
||||
// E.g.:
|
||||
// amxx cvars test <- list all cvars from plugin name starting by "test"
|
||||
// amxx cvars 2 <- show informations about cvar in position 2 from "amxx cvars" list
|
||||
// amxx cvars test 2 <- show informations about cvar in position 2 from "amxx cvars test" list
|
||||
|
||||
if (argcount > 2)
|
||||
{
|
||||
const char* argument = CMD_ARGV(2);
|
||||
|
||||
indexToSearch = atoi(argument); // amxx cvars 2
|
||||
|
||||
if (!indexToSearch)
|
||||
{
|
||||
partialName = argument; // amxx cvars test
|
||||
|
||||
if (argcount > 3) // amxx cvars test 2
|
||||
{
|
||||
indexToSearch = atoi(CMD_ARGV(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!indexToSearch)
|
||||
{
|
||||
print_srvconsole("\nManaged cvars:\n");
|
||||
print_srvconsole(" %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", "NAME", "VALUE", "PLUGIN", "HOOKED", "MIN", "MAX");
|
||||
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
|
||||
}
|
||||
|
||||
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
||||
{
|
||||
CvarInfo* ci = (*iter);
|
||||
|
||||
// List any cvars having a status either created, hooked or bound by a plugin.
|
||||
bool in_list = ci->amxmodx || !ci->binds.empty() || !ci->hooks.empty() || ci->bound.hasMin || ci->bound.hasMax;
|
||||
|
||||
if (in_list && (!partialName.length() || strncmp(ci->plugin.chars(), partialName.chars(), partialName.length()) == 0))
|
||||
{
|
||||
if (!indexToSearch)
|
||||
{
|
||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-18.17s %-8.7s ", ++index, ci->name.chars(), ci->var->string,
|
||||
ci->plugin.length() ? ci->plugin.chars() : "-",
|
||||
ci->hooks.empty() ? "no" : "yes");
|
||||
|
||||
(ci->bound.hasMin) ? print_srvconsole("%-8.2f ", ci->bound.minVal) : print_srvconsole("%-8.7s ", "-");
|
||||
(ci->bound.hasMax) ? print_srvconsole("%-8.2f ", ci->bound.maxVal) : print_srvconsole("%-8.7s ", "-");
|
||||
print_srvconsole("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++index != indexToSearch)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
print_srvconsole("\nCvar details :\n\n");
|
||||
print_srvconsole(" Cvar name : %s\n", ci->var->name);
|
||||
print_srvconsole(" Value : %s\n", ci->var->string);
|
||||
print_srvconsole(" Def. value : %s\n", ci->defaultval.chars());
|
||||
print_srvconsole(" Description : %s\n", ci->description.chars());
|
||||
print_srvconsole(" Flags : %s\n\n", convertFlagsToString(ci->var->flags).ptr());
|
||||
|
||||
print_srvconsole(" %-12s %-26.25s %s\n", "STATUS", "PLUGIN", "INFOS");
|
||||
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
|
||||
|
||||
if (ci->amxmodx)
|
||||
{
|
||||
print_srvconsole(" Registered %-26.25s %s\n", ci->plugin.chars(), "-");
|
||||
}
|
||||
|
||||
if (ci->bound.hasMin)
|
||||
{
|
||||
print_srvconsole(" Min value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.minPluginId)->getName(), ci->bound.minVal);
|
||||
}
|
||||
|
||||
if (ci->bound.hasMax)
|
||||
{
|
||||
print_srvconsole(" Max value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.maxPluginId)->getName(), ci->bound.maxVal);
|
||||
}
|
||||
|
||||
if (!ci->binds.empty())
|
||||
{
|
||||
for (size_t i = 0; i < ci->binds.length(); ++i)
|
||||
{
|
||||
print_srvconsole(" Bound %-26.25s %s\n", g_plugins.findPlugin(ci->binds[i]->pluginId)->getName(), "-");
|
||||
}
|
||||
}
|
||||
|
||||
if (!ci->hooks.empty())
|
||||
{
|
||||
for (size_t i = 0; i < ci->hooks.length(); ++i)
|
||||
{
|
||||
CvarHook* hook = ci->hooks[i];
|
||||
|
||||
print_srvconsole(" Hooked %-26.25s %s (%s)\n", g_plugins.findPlugin(hook->pluginId)->getName(),
|
||||
hook->forward->callback.chars(),
|
||||
hook->forward->state == AutoForward::FSTATE_OK ? "active" : "inactive");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CvarManager::OnPluginUnloaded()
|
||||
{
|
||||
// Clear only plugin hooks list.
|
||||
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar++)
|
||||
{
|
||||
for (size_t i = 0; i < (*cvar)->binds.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->binds[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->hooks[i];
|
||||
}
|
||||
|
||||
if ((*cvar)->amxmodx) // Mark registered cvars so we can refresh default datas at next map.
|
||||
{
|
||||
(*cvar)->pluginId = -1;
|
||||
}
|
||||
|
||||
(*cvar)->binds.clear();
|
||||
(*cvar)->hooks.clear();
|
||||
}
|
||||
|
||||
// There is no point to enable hook if at next map change
|
||||
// no plugins hook cvars.
|
||||
DisableHook();
|
||||
}
|
||||
|
||||
void CvarManager::OnAmxxShutdown()
|
||||
{
|
||||
// Free everything.
|
||||
|
||||
CvarsList::iterator iter = m_Cvars.begin();
|
||||
|
||||
while (iter != m_Cvars.end())
|
||||
{
|
||||
CvarInfo* cvar = (*iter);
|
||||
|
||||
for (size_t i = 0; i < cvar->binds.length(); ++i)
|
||||
{
|
||||
delete cvar->binds[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < cvar->hooks.length(); ++i)
|
||||
{
|
||||
delete cvar->hooks[i];
|
||||
}
|
||||
|
||||
iter = m_Cvars.erase(iter);
|
||||
|
||||
delete cvar;
|
||||
}
|
||||
|
||||
m_Cache.clear();
|
||||
|
||||
DestroyHook();
|
||||
}
|
177
amxmodx/CvarManager.h
Normal file
177
amxmodx/CvarManager.h
Normal file
@ -0,0 +1,177 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef CVARS_H
|
||||
#define CVARS_H
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include <amtl/am-vector.h>
|
||||
#include <amtl/am-inlinelist.h>
|
||||
#include <sm_namehashset.h>
|
||||
#include "CGameConfigs.h"
|
||||
|
||||
class CDetour;
|
||||
|
||||
enum CvarBounds
|
||||
{
|
||||
CvarBound_Upper = 0,
|
||||
CvarBound_Lower
|
||||
};
|
||||
|
||||
struct AutoForward
|
||||
{
|
||||
enum fwdstate
|
||||
{
|
||||
FSTATE_INVALID = 0,
|
||||
FSTATE_OK,
|
||||
FSTATE_STOP,
|
||||
};
|
||||
|
||||
AutoForward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {};
|
||||
AutoForward() : id(-1) , state(FSTATE_INVALID) {};
|
||||
|
||||
~AutoForward()
|
||||
{
|
||||
unregisterSPForward(id);
|
||||
}
|
||||
|
||||
int id;
|
||||
fwdstate state;
|
||||
ke::AString callback;
|
||||
};
|
||||
|
||||
struct CvarHook
|
||||
{
|
||||
CvarHook(int id, AutoForward* fwd) : pluginId(id), forward(fwd) {};
|
||||
CvarHook(int id) : pluginId(id), forward(new AutoForward()) {};
|
||||
|
||||
int pluginId;
|
||||
ke::AutoPtr<AutoForward> forward;
|
||||
};
|
||||
|
||||
struct CvarBind
|
||||
{
|
||||
enum CvarType
|
||||
{
|
||||
CvarType_Int,
|
||||
CvarType_Float,
|
||||
CvarType_String,
|
||||
};
|
||||
|
||||
CvarBind(int id_, CvarType type_, cell* varAddress_, size_t varLength_)
|
||||
:
|
||||
pluginId(id_),
|
||||
type(type_),
|
||||
varAddress(varAddress_),
|
||||
varLength(varLength_) {};
|
||||
|
||||
int pluginId;
|
||||
CvarType type;
|
||||
cell* varAddress;
|
||||
size_t varLength;
|
||||
};
|
||||
|
||||
struct CvarBound
|
||||
{
|
||||
CvarBound()
|
||||
:
|
||||
hasMin(false), minVal(0),
|
||||
hasMax(false), maxVal(0),
|
||||
minPluginId(-1),
|
||||
maxPluginId(-1) {};
|
||||
|
||||
bool hasMin;
|
||||
float minVal;
|
||||
bool hasMax;
|
||||
float maxVal;
|
||||
int minPluginId;
|
||||
int maxPluginId;
|
||||
};
|
||||
|
||||
typedef ke::Vector<CvarHook*> CvarsHook;
|
||||
typedef ke::Vector<CvarBind*> CvarsBind;
|
||||
|
||||
struct CvarInfo : public ke::InlineListNode<CvarInfo>
|
||||
{
|
||||
CvarInfo(const char* name_, const char* helpText, const char* plugin_, int pluginId_)
|
||||
:
|
||||
name(name_), description(helpText),
|
||||
plugin(plugin_), pluginId(pluginId_), bound() {};
|
||||
|
||||
CvarInfo(const char* name_)
|
||||
:
|
||||
name(name_), defaultval(""), description(""),
|
||||
plugin(""), pluginId(-1), bound(), amxmodx(false) {};
|
||||
|
||||
cvar_t* var;
|
||||
ke::AString name;
|
||||
ke::AString defaultval;
|
||||
ke::AString description;
|
||||
|
||||
ke::AString plugin;
|
||||
int pluginId;
|
||||
|
||||
CvarBound bound;
|
||||
CvarsBind binds;
|
||||
CvarsHook hooks;
|
||||
|
||||
bool amxmodx;
|
||||
|
||||
static inline bool matches(const char *name, const CvarInfo* info)
|
||||
{
|
||||
return strcmp(name, info->var->name) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef NameHashSet<CvarInfo*> CvarsCache;
|
||||
typedef ke::InlineList<CvarInfo> CvarsList;
|
||||
|
||||
class CvarManager
|
||||
{
|
||||
public:
|
||||
|
||||
CvarManager();
|
||||
~CvarManager();
|
||||
|
||||
public:
|
||||
|
||||
void CreateCvarHook();
|
||||
void EnableHook();
|
||||
void DisableHook();
|
||||
void DestroyHook();
|
||||
|
||||
CvarInfo* CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags = 0, const char* helpText = "");
|
||||
CvarInfo* FindCvar(const char* name);
|
||||
CvarInfo* FindCvar(size_t index);
|
||||
bool CacheLookup(const char* name, CvarInfo** info);
|
||||
|
||||
AutoForward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback);
|
||||
bool BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen = 0);
|
||||
void SetCvarMin(CvarInfo* info, bool set, float value, int pluginId);
|
||||
void SetCvarMax(CvarInfo* info, bool set, float value, int pluginId);
|
||||
|
||||
size_t GetRegCvarsCount();
|
||||
CvarsList* GetCvarsList();
|
||||
|
||||
void OnConsoleCommand();
|
||||
void OnPluginUnloaded();
|
||||
void OnAmxxShutdown();
|
||||
|
||||
private:
|
||||
|
||||
CvarsCache m_Cache;
|
||||
CvarsList m_Cvars;
|
||||
size_t m_AmxmodxCvars;
|
||||
CDetour* m_HookDetour;
|
||||
bool m_ReHookEnabled;
|
||||
};
|
||||
|
||||
extern CvarManager g_CvarManager;
|
||||
|
||||
#endif // CVARS_H
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
118
amxmodx/Makefile
118
amxmodx/Makefile
@ -1,118 +0,0 @@
|
||||
#(C)2004-2005 AMX Mod X Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
HLSDK = ../../hlsdk
|
||||
MM_ROOT = ../metamod/metamod
|
||||
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
|
||||
OPT_FLAGS = -O2 -fno-strict-aliasing -funroll-loops -s -fomit-frame-pointer -pipe
|
||||
DEBUG_FLAGS = -g -ggdb3
|
||||
CPP = gcc-4.1
|
||||
NAME = amxmodx
|
||||
|
||||
BIN_SUFFIX_32 = mm_i386.so
|
||||
BIN_SUFFIX_64 = mm_amd64.so
|
||||
|
||||
OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules.cpp \
|
||||
CMisc.cpp CTask.cpp string.cpp amxmodx.cpp CEvent.cpp CCmd.cpp CLogEvent.cpp \
|
||||
srvcmd.cpp strptime.cpp amxcore.cpp amxtime.cpp power.cpp amxxlog.cpp fakemeta.cpp \
|
||||
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
|
||||
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
|
||||
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
||||
amxmod_compat.cpp
|
||||
|
||||
LINK = -lgcc -static-libgcc
|
||||
|
||||
INCLUDE = -I. -I$(HLSDK) -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared -I$(HLSDK)/game_shared \
|
||||
-I$(MM_ROOT) -Lzlib -I$(HLSDK)/common
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
OPT_FLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
endif
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS = $(DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS = $(OPT_FLAGS)
|
||||
endif
|
||||
|
||||
ifeq "$(BINLOG)" "true"
|
||||
NAME := $(NAME)_bl
|
||||
BIN_DIR := $(BIN_DIR)BinLog
|
||||
OBJECTS += binlog.cpp
|
||||
CFLAGS += -DBINLOG_ENABLED
|
||||
endif
|
||||
|
||||
CFLAGS += -DLINUX -DNDEBUG -DAMX_NOPROPLIST -fPIC -Wall -Werror -DHAVE_STDINT_H -static-libgcc -fno-rtti -fno-exceptions
|
||||
|
||||
ifeq "$(AMD64)" "true"
|
||||
BINARY = $(NAME)_$(BIN_SUFFIX_64)
|
||||
CFLAGS += -DPAWN_CELL_SIZE=64 -DHAVE_I64 -DAMD64 -m64
|
||||
LINK += -lz64
|
||||
OBJECTS += JIT/natives-amd64.o
|
||||
else
|
||||
BINARY = $(NAME)_$(BIN_SUFFIX_32)
|
||||
OBJECTS += JIT/amxexecn.o JIT/amxjitsn.o JIT/natives-x86.o
|
||||
OBJECTS += JIT/helpers-x86.o
|
||||
CFLAGS += -DPAWN_CELL_SIZE=32 -DJIT -DASM32
|
||||
LINK += -lz
|
||||
OPT_FLAGS += -march=i586
|
||||
endif
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
$(MAKE) amxmodx
|
||||
|
||||
amd64:
|
||||
rm -f zlib/libz.a
|
||||
$(MAKE) all AMD64=true
|
||||
|
||||
amd64_debug:
|
||||
rm -f zlib/libz.a
|
||||
$(MAKE) all AMD64=true DEBUG=true
|
||||
|
||||
amd64_binlog:
|
||||
rm -f zlib/libz.a
|
||||
$(MAKE) all AMD64=true BINLOG=true
|
||||
|
||||
amd64_binlog_debug:
|
||||
rm -f zlib/libz.a
|
||||
$(MAKE) all AMD64=true BINLOG=true DEBUG=true
|
||||
|
||||
binlog:
|
||||
$(MAKE) all BINLOG=true
|
||||
|
||||
binlog_debug:
|
||||
$(MAKE) all BINLOG=true DEBUG=true
|
||||
|
||||
amxmodx: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf Release/*.o
|
||||
rm -rf Release/$(NAME)_$(BIN_SUFFIX_32)
|
||||
rm -rf Release/$(NAME)_$(BIN_SUFFIX_64)
|
||||
rm -rf ReleaseBinLog/*.o
|
||||
rm -rf ReleaseBinLog/$(NAME)_bl_$(BIN_SUFFIX_32)
|
||||
rm -rf ReleaseBinLog/$(NAME)_bl_$(BIN_SUFFIX_64)
|
||||
rm -rf Debug/*.o
|
||||
rm -rf Debug/$(NAME)_$(BIN_SUFFIX_32)
|
||||
rm -rf Debug/$(NAME)_$(BIN_SUFFIX_64)
|
||||
rm -rf DebugBinLog/*.o
|
||||
rm -rf DebugBinLog/$(NAME)_bl_$(BIN_SUFFIX_32)
|
||||
rm -rf DebugBinLog/$(NAME)_bl_$(BIN_SUFFIX_64)
|
123
amxmodx/amx.cpp
123
amxmodx/amx.cpp
@ -17,8 +17,6 @@
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#define AMX_NODYNALOAD
|
||||
@ -48,7 +46,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "osdefs.h"
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#include <sclinux.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@ -68,6 +66,9 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
#include <amxmodx.h>
|
||||
#include <CPlugin.h>
|
||||
|
||||
/* When one or more of the AMX_funcname macris are defined, we want
|
||||
* to compile only those functions. However, when none of these macros
|
||||
@ -436,7 +437,7 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
|
||||
hdr=(AMX_HEADER *)amx->base;
|
||||
assert(hdr->natives<=hdr->libraries);
|
||||
#if defined AMX_NATIVETABLE
|
||||
if (index<NULL) {
|
||||
if (index<0) {
|
||||
assert(-(index+1)<(sizeof(AMX_NATIVETABLE)/sizeof(AMX_NATIVETABLE)[0]));
|
||||
f=(AMX_NATIVETABLE)[-(index+1)];
|
||||
} else {
|
||||
@ -803,7 +804,7 @@ static void expand(unsigned char *code, long codesize, long memsize)
|
||||
do {
|
||||
codesize--;
|
||||
/* no input byte should be shifted out completely */
|
||||
assert(shift<8*sizeof(cell));
|
||||
assert(shift<static_cast<int>(8*sizeof(cell)));
|
||||
/* we work from the end of a sequence backwards; the final code in
|
||||
* a sequence may not have the continuation bit set */
|
||||
assert(shift>0 || (code[(size_t)codesize] & 0x80)==0);
|
||||
@ -932,11 +933,11 @@ int AMXAPI amx_Init(AMX *amx, void *program)
|
||||
|
||||
#define ALIGN(addr) (addr)
|
||||
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
|
||||
/* Linux already has mprotect() */
|
||||
/* But wants the address aligned! */
|
||||
#define ALIGN(addr) (char *)(((long)addr + sysconf(_SC_PAGESIZE)-1) & ~(sysconf(_SC_PAGESIZE)-1))
|
||||
#define ALIGN(addr) ((void *)((intptr_t)addr & ~(sysconf(_SC_PAGESIZE)-1)))
|
||||
|
||||
#else
|
||||
|
||||
@ -973,27 +974,25 @@ int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code)
|
||||
memcpy(native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod);
|
||||
hdr = (AMX_HEADER *)native_code;
|
||||
|
||||
|
||||
|
||||
/* JIT rulz! (TM) */
|
||||
/* MP: added check for correct compilation */
|
||||
//Fixed bug (thanks T(+)rget)
|
||||
if ((res = asm_runJIT(amx->base, reloc_table, native_code)) == 0)
|
||||
{
|
||||
/* update the required memory size (the previous value was a
|
||||
* conservative estimate, now we know the exact size)
|
||||
*/
|
||||
amx->code_size = (hdr->dat + hdr->stp + 3) & ~3;
|
||||
/* The compiled code is relocatable, since only relative jumps are
|
||||
* used for destinations within the generated code and absoulute
|
||||
* addresses for jumps into the runtime, which is fixed in memory.
|
||||
*/
|
||||
amx->base = (unsigned char*) native_code;
|
||||
amx->cip = hdr->cip;
|
||||
amx->hea = hdr->hea;
|
||||
amx->stp = hdr->stp - sizeof(cell);
|
||||
amx->hlw = hdr->hea;
|
||||
/* also put a sentinel for strings at the top the stack */
|
||||
*(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0;
|
||||
amx->stk = amx->stp;
|
||||
/* also put a sentinel for strings at the top the stack */
|
||||
*(cell *)((char*)native_code + hdr->dat + amx->stp - sizeof(cell)) = 0;
|
||||
/* update the required memory size (the previous value was a
|
||||
* conservative estimate, now we know the exact size)
|
||||
*/
|
||||
amx->code_size = (hdr->dat + amx->stp + sizeof(cell)) & ~3;
|
||||
} /* if */
|
||||
|
||||
return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT;
|
||||
@ -1016,10 +1015,10 @@ int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table)
|
||||
#if defined AMX_CLEANUP
|
||||
int AMXAPI amx_Cleanup(AMX *amx)
|
||||
{
|
||||
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
|
||||
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__) && !defined AMX_NODYNALOAD
|
||||
#if defined _Windows
|
||||
typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx);
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
typedef int (*AMX_ENTRY)(AMX *amx);
|
||||
#endif
|
||||
AMX_HEADER *hdr;
|
||||
@ -1029,7 +1028,7 @@ int AMXAPI amx_Cleanup(AMX *amx)
|
||||
#endif
|
||||
|
||||
/* unload all extension modules */
|
||||
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
|
||||
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__) && !defined AMX_NODYNALOAD
|
||||
hdr=(AMX_HEADER *)amx->base;
|
||||
assert(hdr->magic==AMX_MAGIC);
|
||||
numlibraries=NUMENTRIES(hdr,libraries,pubvars);
|
||||
@ -1042,14 +1041,14 @@ int AMXAPI amx_Cleanup(AMX *amx)
|
||||
strcat(funcname,"Cleanup");
|
||||
#if defined _Windows
|
||||
libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname);
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname);
|
||||
#endif
|
||||
if (libcleanup!=NULL)
|
||||
libcleanup(amx);
|
||||
#if defined _Windows
|
||||
FreeLibrary((HINSTANCE)lib->address);
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
dlclose((void*)lib->address);
|
||||
#endif
|
||||
} /* if */
|
||||
@ -1177,12 +1176,12 @@ int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname)
|
||||
|
||||
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index)
|
||||
{
|
||||
int first,last,mid;
|
||||
int last,mid;
|
||||
char pname[sNAMEMAX+1];
|
||||
|
||||
amx_NumNatives(amx, &last);
|
||||
last--; /* last valid index is 1 less than the number of functions */
|
||||
first=0;
|
||||
|
||||
/* normal search */
|
||||
for (mid=0; mid<=last; mid++)
|
||||
{
|
||||
@ -1642,7 +1641,7 @@ int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char
|
||||
* fast "indirect threaded" interpreter.
|
||||
*/
|
||||
|
||||
#define NEXT(cip) goto **cip++
|
||||
#define NEXT(cip) goto *(const void *)*cip++
|
||||
|
||||
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index)
|
||||
{
|
||||
@ -1826,14 +1825,14 @@ static const void * const amx_opcodelist[] = {
|
||||
NEXT(cip);
|
||||
op_load_i:
|
||||
/* verify address */
|
||||
if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
|
||||
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
pri= * (cell *)(data+(int)pri);
|
||||
NEXT(cip);
|
||||
op_lodb_i:
|
||||
GETPARAM(offs);
|
||||
/* verify address */
|
||||
if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
|
||||
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
switch (offs) {
|
||||
case 1:
|
||||
@ -1899,14 +1898,14 @@ static const void * const amx_opcodelist[] = {
|
||||
NEXT(cip);
|
||||
op_stor_i:
|
||||
/* verify address */
|
||||
if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
|
||||
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
*(cell *)(data+(int)alt)=pri;
|
||||
NEXT(cip);
|
||||
op_strb_i:
|
||||
GETPARAM(offs);
|
||||
/* verify address */
|
||||
if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
|
||||
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
switch (offs) {
|
||||
case 1:
|
||||
@ -1923,7 +1922,7 @@ static const void * const amx_opcodelist[] = {
|
||||
op_lidx:
|
||||
offs=pri*sizeof(cell)+alt;
|
||||
/* verify address */
|
||||
if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
|
||||
if ((offs>=hea && offs<stk) || (ucell)offs>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
pri= * (cell *)(data+(int)offs);
|
||||
NEXT(cip);
|
||||
@ -1931,7 +1930,7 @@ static const void * const amx_opcodelist[] = {
|
||||
GETPARAM(offs);
|
||||
offs=(pri << (int)offs)+alt;
|
||||
/* verify address */
|
||||
if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
|
||||
if ((offs>=hea && offs<stk) || (ucell)offs>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
pri= * (cell *)(data+(int)offs);
|
||||
NEXT(cip);
|
||||
@ -2368,13 +2367,13 @@ static const void * const amx_opcodelist[] = {
|
||||
/* verify top & bottom memory addresses, for both source and destination
|
||||
* addresses
|
||||
*/
|
||||
if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
|
||||
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
|
||||
if (((pri+offs)>hea && (pri+offs)<stk) || (ucell)(pri+offs)>(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
|
||||
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
memcpy(data+(int)alt, data+(int)pri, (int)offs);
|
||||
NEXT(cip);
|
||||
@ -2383,22 +2382,22 @@ static const void * const amx_opcodelist[] = {
|
||||
/* verify top & bottom memory addresses, for both source and destination
|
||||
* addresses
|
||||
*/
|
||||
if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
|
||||
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
|
||||
if (((pri+offs)>hea && (pri+offs)<stk) || (ucell)(pri+offs)>(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
|
||||
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
pri=memcmp(data+(int)alt, data+(int)pri, (int)offs);
|
||||
NEXT(cip);
|
||||
op_fill:
|
||||
GETPARAM(offs);
|
||||
/* verify top & bottom memory addresses */
|
||||
if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
|
||||
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp)
|
||||
ABORT(amx,AMX_ERR_MEMACCESS);
|
||||
for (i=(int)alt; offs>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell))
|
||||
*(cell *)(data+i) = pri;
|
||||
@ -3697,7 +3696,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr)
|
||||
data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
|
||||
|
||||
assert(phys_addr!=NULL);
|
||||
if (amx_addr>=amx->hea && amx_addr<amx->stk || amx_addr<0 || amx_addr>=amx->stp) {
|
||||
if ((amx_addr>=amx->hea && amx_addr<amx->stk) || amx_addr<0 || amx_addr>=amx->stp) {
|
||||
*phys_addr=NULL;
|
||||
return AMX_ERR_MEMACCESS;
|
||||
} /* if */
|
||||
@ -4096,10 +4095,6 @@ int AMXAPI amx_GetLibraries(AMX *amx)
|
||||
return numLibraries;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#define _snprintf snprintf
|
||||
#endif
|
||||
|
||||
const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len)
|
||||
{
|
||||
AMX_HEADER *hdr = (AMX_HEADER *)amx->base;
|
||||
@ -4143,7 +4138,7 @@ int AMXAPI amx_SetStringOld(cell *dest,const char *source,int pack,int use_wchar
|
||||
dest[i]=(cell)(((wchar_t*)source)[i]);
|
||||
} else {
|
||||
for (i=0; i<len; i++)
|
||||
dest[i]=(cell)source[i];
|
||||
dest[i]=(unsigned char)source[i];
|
||||
} /* if */
|
||||
dest[len]=0;
|
||||
} /* if */
|
||||
@ -4181,3 +4176,37 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar)
|
||||
dest[len]='\0'; /* store terminator */
|
||||
return AMX_ERR_NONE;
|
||||
}
|
||||
|
||||
int AMXAPI amx_ExecPerf(AMX* amx, cell* retval, int index)
|
||||
{
|
||||
CPluginMngr::CPlugin* perf_Plug = g_plugins.findPluginFast(amx);
|
||||
if (amxmodx_perflog->value > 0.0f && perf_Plug && (perf_Plug->isDebug() || (int)amxmodx_debug->value == 2))
|
||||
{
|
||||
char perf_funcname[sNAMEMAX + 1];
|
||||
perf_funcname[0] = '\0';
|
||||
amx_GetPublic(perf_Plug->getAMX(), index, perf_funcname);
|
||||
if (perf_funcname[0] == '\0')
|
||||
sprintf(perf_funcname, "Unknown_ID%d", index);
|
||||
|
||||
const char* perf_plugname = perf_Plug->getName();
|
||||
if (!perf_plugname || perf_plugname[0] == '\0')
|
||||
perf_plugname = "Unknown_plugin";
|
||||
|
||||
using std::chrono::steady_clock;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::duration;
|
||||
using std::chrono::microseconds;
|
||||
|
||||
auto t1 = steady_clock::now();
|
||||
int err = amx_Exec(amx, retval, index);
|
||||
|
||||
auto ms_int = duration_cast<microseconds>(steady_clock::now() - t1);
|
||||
auto ms_float = (float)(ms_int.count() / 1000.0f);
|
||||
if (ms_float >= amxmodx_perflog->value)
|
||||
{
|
||||
AMXXLOG_Log("[%s] performance issue. Function %s executed more than %.*fms.", perf_plugname, perf_funcname, 1, ms_float);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
return amx_Exec(amx, retval, index);
|
||||
}
|
||||
|
@ -17,14 +17,12 @@
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#if defined FREEBSD && !defined __FreeBSD__
|
||||
#define __FreeBSD__
|
||||
#endif
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
@ -34,7 +32,7 @@
|
||||
#if defined HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#if defined __LCC__ || defined __DMC__ || defined LINUX
|
||||
#if defined __LCC__ || defined __DMC__ || defined LINUX || defined __APPLE__
|
||||
#if defined HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
@ -190,7 +188,7 @@ typedef int (AMXAPI *AMX_NATIVE_FILTER)(struct tagAMX *amx, int index);
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
@ -210,7 +208,7 @@ typedef struct tagAMX_NATIVE_INFO {
|
||||
|
||||
#define AMX_USERNUM 4
|
||||
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
|
||||
#define sNAMEMAX 31 /* maximum name length of symbol name */
|
||||
#define sNAMEMAX 63 /* maximum name length of symbol name */
|
||||
|
||||
typedef struct tagAMX_FUNCSTUB {
|
||||
ucell address PACKED;
|
||||
@ -322,7 +320,7 @@ enum {
|
||||
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */
|
||||
#define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */
|
||||
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */
|
||||
#define AMX_FLAG_OLDFILE 0x20 /* Old AMX Mod plugin */
|
||||
/* AMX_FLAG_OLDFILE 0x20 Old AMX Mod plugin */
|
||||
#define AMX_FLAG_PRENIT 0x100 /* pre-initialized, do not check natives */
|
||||
#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
|
||||
#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
|
||||
@ -384,6 +382,7 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
|
||||
int AMXAPI amx_CheckNatives(AMX *amx, AMX_NATIVE_FILTER nf);
|
||||
int AMXAPI amx_Cleanup(AMX *amx);
|
||||
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
|
||||
int AMXAPI amx_ExecPerf(AMX* amx, cell* retval, int index);
|
||||
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
|
||||
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
|
||||
int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
|
||||
@ -442,7 +441,7 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar);
|
||||
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
|
@ -17,9 +17,8 @@
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
# if !defined UNICODE /* for Windows */
|
||||
# define UNICODE
|
||||
@ -180,7 +179,7 @@ static cell AMX_NATIVE_CALL setarg(AMX *amx, cell *params)
|
||||
/* adjust the address in "value" in case of an array access */
|
||||
value+=params[2]*sizeof(cell);
|
||||
/* verify the address */
|
||||
if (value<0 || value>=amx->hea && value<amx->stk)
|
||||
if (value<0 || (value>=amx->hea && value<amx->stk))
|
||||
return 0;
|
||||
/* set the value indirectly */
|
||||
* (cell *)(data+(int)value) = params[3];
|
||||
|
@ -19,9 +19,8 @@
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -462,8 +461,8 @@ int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr
|
||||
break;
|
||||
/* check the range, keep a pointer to the symbol with the smallest range */
|
||||
if (strcmp(amxdbg->symboltbl[index]->name, symname) == 0
|
||||
&& (codestart == 0 && codeend == 0
|
||||
|| amxdbg->symboltbl[index]->codestart >= codestart && amxdbg->symboltbl[index]->codeend <= codeend))
|
||||
&& ((codestart == 0 && codeend == 0)
|
||||
|| (amxdbg->symboltbl[index]->codestart >= codestart && amxdbg->symboltbl[index]->codeend <= codeend)))
|
||||
{
|
||||
*sym = amxdbg->symboltbl[index];
|
||||
codestart = amxdbg->symboltbl[index]->codestart;
|
||||
|
@ -20,8 +20,6 @@
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef AMXDBG_H_INCLUDED
|
||||
@ -49,7 +47,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
@ -156,7 +154,7 @@ int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX
|
||||
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
|
@ -56,6 +56,9 @@
|
||||
;
|
||||
;History (list of changes)
|
||||
;-------------------------
|
||||
; 24 february 2013 by Scott Ehlert
|
||||
; Aligned stack to 16-byte boundary for native calls in case they make library
|
||||
; calls on Mac OS X or use SSE instructions.
|
||||
; 10 february 2006 by David Anderson
|
||||
; Addition of float opcodes
|
||||
; 17 february 2005 by Thiadmer Riemersms
|
||||
@ -189,6 +192,21 @@
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro _STK_ALIGN 1 ; align stack to 16-byte boundary and
|
||||
; allocate %1 bytes of stack space
|
||||
%if %1 % 16 != 0
|
||||
%error "expected 16-byte aligned value"
|
||||
%endif
|
||||
push edi
|
||||
mov edi, esp
|
||||
and esp, 0xFFFFFFF0
|
||||
sub esp, %1
|
||||
%endmacro
|
||||
|
||||
%macro _STK_RESTORE 0 ; restore stack pointer after 16-byte alignment
|
||||
mov esp, edi
|
||||
pop edi
|
||||
%endmacro
|
||||
|
||||
Start_CODE
|
||||
|
||||
@ -1265,13 +1283,15 @@ OP_SYSREQ_PRI:
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
_STK_ALIGN 16 ; align stack to 16-byte boundary and
|
||||
; allocate 16 bytes of stack space
|
||||
; push the parameters
|
||||
push ecx
|
||||
push ebx
|
||||
push edx
|
||||
push eax
|
||||
mov [esp+12], ecx
|
||||
mov [esp+08], ebx
|
||||
mov [esp+04], edx
|
||||
mov [esp], eax
|
||||
call [ebp+_callback]
|
||||
_DROPARGS 10h ; remove arguments from stack
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
pop edi ; restore saved registers
|
||||
pop esi
|
||||
pop ebp
|
||||
@ -1308,11 +1328,13 @@ OP_SYSREQ_D: ; (TR)
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
_STK_ALIGN 16 ; align stack to 16-byte boundary and
|
||||
; allocate 16 bytes of stack space
|
||||
; push the parameters
|
||||
push edx
|
||||
push eax
|
||||
mov [esp+04], edx
|
||||
mov [esp], eax
|
||||
call ebx ; direct call
|
||||
_DROPARGS 8 ; remove arguments from stack
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
pop edi ; restore saved registers
|
||||
pop esi
|
||||
pop ebp
|
||||
@ -1458,7 +1480,7 @@ OP_FLOAT_ROUND:
|
||||
push 0
|
||||
mov ebp,esp
|
||||
fstcw [ebp]
|
||||
mov eax,[ebp]
|
||||
mov eax,[ebp]
|
||||
push eax
|
||||
;clear the top bits
|
||||
xor ah,ah
|
||||
@ -1470,22 +1492,20 @@ OP_FLOAT_ROUND:
|
||||
;set the bits
|
||||
or ah,dl ;set bits 15,14 of FCW to rounding method
|
||||
or ah,3 ;set precision to 64bit
|
||||
mov [ebp], eax
|
||||
fldcw [ebp]
|
||||
|
||||
;calculate
|
||||
sub esp,4
|
||||
fld dword [edi+ecx+4]
|
||||
test edx,edx
|
||||
jz .correct
|
||||
jmp .skip_correct
|
||||
.correct:
|
||||
fadd st0
|
||||
jnz .skip_correct
|
||||
;nearest mode
|
||||
;correct so as to AVOID bankers rounding
|
||||
or ah, 4 ;set rounding mode to floor
|
||||
fadd dword [g_round_nearest]
|
||||
fistp dword [esp]
|
||||
pop eax
|
||||
sar eax,1
|
||||
jmp .done
|
||||
|
||||
.skip_correct:
|
||||
mov [ebp], eax
|
||||
fldcw [ebp]
|
||||
frndint
|
||||
fistp dword [esp]
|
||||
pop eax
|
||||
@ -1533,9 +1553,11 @@ OP_BREAK:
|
||||
; call the debug hook
|
||||
mov eax,ebp ; 1st parm: amx
|
||||
_SAVEREGS
|
||||
push eax
|
||||
_STK_ALIGN 16 ; align stack to 16-byte boundary and
|
||||
; allocate 16 bytes of stack space
|
||||
mov [esp], eax
|
||||
call [ebp+_debug] ; call debug function
|
||||
_DROPARGS 4 ; remove arguments from stack
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
cmp eax,AMX_ERR_NONE
|
||||
je short break_noabort; continue running
|
||||
mov [ebp+_error],eax ; save EAX (error code) before restoring all regs
|
||||
|
@ -6,6 +6,14 @@
|
||||
; (27 disks, no output, DOS4/GW under Win95) with this implementation of the
|
||||
; JIT compiler.
|
||||
|
||||
; BUILD NOTE: Use nasm 0.97.x or 0.98.x with the options below.
|
||||
; ----------------
|
||||
; Windows : nasm -O2 -f win32 -o amxjitsn.obj amxjitsn.asm
|
||||
; Linux : nasm -O2 -f elf -o amxjitsn.o amxjitsn.asm
|
||||
; OS X : nasm -O2 -f macho -o amxjitsn-darwin.o amxjitsn.asm
|
||||
; ----------------
|
||||
; If nasm 2.x must be used, replace -O2 with -O0.
|
||||
|
||||
; NOTE 1:
|
||||
; There is only one pass implemented in this version. This means there is no
|
||||
; way of knowing the size of the compiled code before it has actually been com-
|
||||
@ -90,6 +98,9 @@
|
||||
|
||||
; Revision History
|
||||
; ----------------
|
||||
; 24 february 2013 by Scott Ehlert
|
||||
; Aligned stack to 16-byte boundary for native calls in case they make library
|
||||
; calls on Mac OS X or use SSE instructions.
|
||||
; 16 august 2005 by David "BAILOPAN" Anderson (DA)
|
||||
; Changed JIT to not swap stack pointer during execution. This
|
||||
; is playing with fire, especially with pthreads and signals on linux,
|
||||
@ -303,13 +314,31 @@
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro _STK_ALIGN 1 ; align stack to 16-byte boundary and
|
||||
; allocate %1 bytes of stack space
|
||||
; top of stack allocation will hold original esp
|
||||
%if %1 % 16 != 0
|
||||
%error "expected 16-byte aligned value"
|
||||
%endif
|
||||
|
||||
%ifdef WIN32
|
||||
section .data exec
|
||||
%else
|
||||
section .text
|
||||
%endif
|
||||
%push stkalign
|
||||
%assign stkspace %1
|
||||
|
||||
mov ebp, esp
|
||||
and esp, 0xFFFFFFF0
|
||||
sub esp, %1
|
||||
mov [esp+%1-4], ebp
|
||||
%endmacro
|
||||
|
||||
%macro _STK_RESTORE 0 ; restore stack pointer after 16-byte alignment
|
||||
%ifnctx stkalign
|
||||
%fatal "expected _STK_ALIGN before _STK_RESTORE"
|
||||
%endif
|
||||
|
||||
mov esp, [esp+stkspace-4]
|
||||
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
global asm_runJIT, _asm_runJIT
|
||||
global amx_exec_jit, _amx_exec_jit
|
||||
@ -436,15 +465,6 @@ reloc_done:
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
; GWMV:
|
||||
; The code below modifies itself to store the arguments to the Pawn opcodes
|
||||
; in the compiled code. This is fine, but the .text section in an ELF executable
|
||||
; is usually marked read-only, that's why this code is in the .data section.
|
||||
|
||||
%ifndef WIN32
|
||||
section .data exec
|
||||
%endif
|
||||
|
||||
OP_LOAD_PRI:
|
||||
;nop;
|
||||
putval j_load_pri+2
|
||||
@ -1052,7 +1072,7 @@ OP_CALL:
|
||||
j_call:
|
||||
;call 12345678h ; tasm chokes on this out of a sudden
|
||||
_PUSH 0
|
||||
j_call_e8
|
||||
j_call_e8:
|
||||
db 0e8h, 0, 0, 0, 0
|
||||
CHECKCODESIZE j_call
|
||||
|
||||
@ -1959,22 +1979,20 @@ OP_FLOAT_ROUND:
|
||||
;set the bits
|
||||
or ah,dl ;set bits 15,14 of FCW to rounding method
|
||||
or ah,3 ;set precision to 64bit
|
||||
mov [ebp], eax
|
||||
fldcw [ebp]
|
||||
|
||||
;calculate
|
||||
sub esp,4
|
||||
fld dword [esi+4]
|
||||
test edx,edx
|
||||
jz .correct
|
||||
jmp .skip_correct
|
||||
.correct:
|
||||
fadd st0
|
||||
jnz .skip_correct
|
||||
;nearest mode
|
||||
;correct so as to AVOID bankers rounding
|
||||
or ah, 4 ;set rounding mode to floor
|
||||
fadd dword [g_round_nearest]
|
||||
fistp dword [esp]
|
||||
pop eax
|
||||
sar eax,1
|
||||
jmp .done
|
||||
|
||||
.skip_correct:
|
||||
mov [ebp], eax
|
||||
fldcw [ebp]
|
||||
frndint
|
||||
fistp dword [esp]
|
||||
pop eax
|
||||
@ -2255,8 +2273,10 @@ err_divide:
|
||||
jmp _return_popstack
|
||||
|
||||
JIT_OP_SYSREQ:
|
||||
push ecx
|
||||
push esi
|
||||
_STK_ALIGN 32 ; align stack to 16-byte boundary and
|
||||
; allocate 32 bytes of stack space
|
||||
mov [esp+16], ecx
|
||||
mov [esp+12], esi
|
||||
mov ebp,amx ; get amx into EBP
|
||||
|
||||
sub esi,edi ; correct STK
|
||||
@ -2271,14 +2291,15 @@ JIT_OP_SYSREQ:
|
||||
lea ebx,pri ; 3rd param: addr. of retval
|
||||
|
||||
;Our original esi is still pushed!
|
||||
push ebx
|
||||
push eax ; 2nd param: function number
|
||||
push ebp ; 1st param: amx
|
||||
mov [esp+08], ebx
|
||||
mov [esp+04], eax ; 2nd param: function number
|
||||
mov [esp], ebp ; 1st param: amx
|
||||
call [ebp+_callback]
|
||||
_DROPARGS 12 ; remove args from stack
|
||||
|
||||
pop esi
|
||||
pop ecx
|
||||
mov esi, [esp+12] ; restore esi
|
||||
mov ecx, [esp+16] ; restore ecx
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
|
||||
cmp eax,AMX_ERR_NONE
|
||||
jne _return_popstack
|
||||
.continue:
|
||||
@ -2290,8 +2311,10 @@ JIT_OP_SYSREQ:
|
||||
|
||||
|
||||
JIT_OP_SYSREQ_D: ; (TR)
|
||||
push ecx
|
||||
push esi
|
||||
_STK_ALIGN 16 ; align stack to 16-byte boundary and
|
||||
; allocate 16 bytes of stack space
|
||||
mov [esp+08], ecx
|
||||
mov [esp+04], esi
|
||||
mov ebp,amx ; get amx into EBP
|
||||
|
||||
sub esi,edi ; correct STK
|
||||
@ -2304,11 +2327,12 @@ JIT_OP_SYSREQ_D: ; (TR)
|
||||
mov [ebp+_frm],eax ; eax & ecx are invalid by now
|
||||
|
||||
;esi is still pushed!
|
||||
push ebp ; 1st param: amx
|
||||
mov [esp], ebp ; 1st param: amx
|
||||
call ebx ; direct call
|
||||
_DROPARGS 8 ; remove args from stack
|
||||
|
||||
pop ecx
|
||||
|
||||
mov ecx, [esp+08] ; restore ecx
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
|
||||
mov ebp,amx ; get amx into EBP
|
||||
cmp dword [ebp+_error],AMX_ERR_NONE
|
||||
jne _return_popstack; return error code, if any
|
||||
@ -2322,8 +2346,10 @@ JIT_OP_SYSREQ_D: ; (TR)
|
||||
|
||||
JIT_OP_BREAK:
|
||||
%ifdef DEBUGSUPPORT
|
||||
push ecx
|
||||
push esi
|
||||
_STK_ALIGN 16 ; align stack to 16-byte boundary and
|
||||
; allocate 16 bytes of stack space
|
||||
mov [esp+08], ecx
|
||||
mov [esp+04], esi
|
||||
mov ebp,amx ; get amx into EBP
|
||||
|
||||
sub esi,edi ; correct STK
|
||||
@ -2337,12 +2363,13 @@ JIT_OP_BREAK:
|
||||
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
|
||||
;??? storing CIP is not very useful, because the code changed (during JIT compile)
|
||||
|
||||
push ebp ; 1st param: amx
|
||||
mov [esp], ebp ; 1st param: amx
|
||||
call [ebp+_debug]
|
||||
_DROPARGS 4 ; remove args from stack
|
||||
|
||||
pop esi
|
||||
pop ecx
|
||||
mov esi, [esp+04] ; restore esi
|
||||
mov ecx, [esp+08] ; restore ecx
|
||||
_STK_RESTORE ; restore stack pointer
|
||||
|
||||
cmp eax,AMX_ERR_NONE
|
||||
jne _return_popstack; return error code, if any
|
||||
|
||||
@ -2591,4 +2618,4 @@ _amx_opcodelist_jit:
|
||||
DD OP_FLOAT_ROUND ; DA
|
||||
DD OP_FLOAT_CMP ; DA
|
||||
|
||||
END
|
||||
END:
|
||||
|
@ -1,117 +0,0 @@
|
||||
#include "amxmodx.h"
|
||||
#include "amxmod_compat.h"
|
||||
#include "format.h"
|
||||
|
||||
bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang)
|
||||
{
|
||||
key = (trans & BCOMPAT_TRANSLATE_KEYMASK);
|
||||
dest = (trans >> BCOMPAT_TRANSLATE_DESTRSH) & BCOMPAT_TRANSLATE_DESTMASK;
|
||||
lang = (trans >> BCOMPAT_TRANSLATE_LANGRSH) & BCOMPAT_TRANSLATE_LANGMASK;
|
||||
|
||||
if (dest == 0x3F)
|
||||
{
|
||||
dest = -1;
|
||||
}
|
||||
|
||||
if (lang == 0x1F)
|
||||
{
|
||||
lang = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def)
|
||||
{
|
||||
amxtrans_t trans = static_cast<amxtrans_t>(*source);
|
||||
int key, _dest, lang;
|
||||
if (!GetTranslation(trans, key, _dest, lang))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cell amx_addr, *phys_addr;
|
||||
if (amx_Allot(amx, 3, &amx_addr, &phys_addr) != AMX_ERR_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_dest == -1)
|
||||
{
|
||||
*phys_addr = LANG_PLAYER;
|
||||
} else if (_dest == 0) {
|
||||
*phys_addr = LANG_SERVER;
|
||||
} else if (lang >= 0 && lang < g_langMngr.GetLangsNum()) {
|
||||
const char *name = g_langMngr.GetLangName(lang);
|
||||
phys_addr[0] = static_cast<cell>(name[0]);
|
||||
phys_addr[1] = static_cast<cell>(name[1]);
|
||||
phys_addr[2] = static_cast<cell>('\0');
|
||||
} else {
|
||||
*phys_addr = LANG_SERVER;
|
||||
}
|
||||
|
||||
//not optimized but it works, eh
|
||||
//if someone cares they can make a translate() wrapper that takes the key # in directly
|
||||
const char *r_key = g_langMngr.GetKey(key);
|
||||
const char *def = translate(amx, amx_addr, r_key);
|
||||
if (!def)
|
||||
{
|
||||
def = r_key;
|
||||
}
|
||||
amx_Release(amx, amx_addr);
|
||||
|
||||
*_key = g_langMngr.GetKey(key);
|
||||
*_def = def;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL amx_translate(AMX *amx, cell *params)
|
||||
{
|
||||
int len;
|
||||
char *key = get_amxstring(amx, params[1], 0, len);
|
||||
|
||||
amxtrans_t trans;
|
||||
|
||||
int suki = g_langMngr.GetKeyEntry(key);
|
||||
//Some AMX Mod plugins do not register everything they need. Prevent a crash.
|
||||
if (suki == -1)
|
||||
{
|
||||
suki = g_langMngr.AddKeyEntry(key);
|
||||
}
|
||||
|
||||
if (suki > BCOMPAT_TRANSLATE_KEYMASK)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Not enough translation space, aborting!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
trans = suki & BCOMPAT_TRANSLATE_KEYMASK;
|
||||
int dest = static_cast<int>(params[2]);
|
||||
int lang = static_cast<int>(params[3]);
|
||||
if (dest == -1)
|
||||
{
|
||||
trans |= (0x3F << BCOMPAT_TRANSLATE_DESTRSH);
|
||||
} else {
|
||||
trans |= (dest & BCOMPAT_TRANSLATE_DESTMASK) << BCOMPAT_TRANSLATE_DESTRSH;
|
||||
}
|
||||
|
||||
if (lang == -1)
|
||||
{
|
||||
trans |= (0x1F << BCOMPAT_TRANSLATE_LANGRSH);
|
||||
} else {
|
||||
trans |= (lang & BCOMPAT_TRANSLATE_LANGMASK) << BCOMPAT_TRANSLATE_LANGRSH;
|
||||
}
|
||||
|
||||
trans |= BCOMPAT_TRANSLATE_BITS;
|
||||
|
||||
return static_cast<cell>(trans);
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO g_BcompatNatives[] =
|
||||
{
|
||||
{"translate", amx_translate},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
@ -1,28 +0,0 @@
|
||||
#ifndef _INCLUDE_AMXMOD_CORE_COMPAT_H
|
||||
#define _INCLUDE_AMXMOD_CORE_COMPAT_H
|
||||
|
||||
/**
|
||||
* New format for translation:
|
||||
* Note that we only support:
|
||||
* 4k keys
|
||||
* 32 languages
|
||||
* 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
* | key id |
|
||||
* | | <- dest id
|
||||
* | | <- lang id
|
||||
*/
|
||||
|
||||
#define BCOMPAT_TRANSLATE_BITS 0xFF000000
|
||||
#define BCOMPAT_TRANSLATE_KEYMASK 0xFFF
|
||||
#define BCOMPAT_TRANSLATE_DESTMASK 0x3F
|
||||
#define BCOMPAT_TRANSLATE_DESTRSH 12
|
||||
#define BCOMPAT_TRANSLATE_LANGMASK 0x1F
|
||||
#define BCOMPAT_TRANSLATE_LANGRSH 18
|
||||
|
||||
typedef unsigned int amxtrans_t;
|
||||
|
||||
bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang);
|
||||
|
||||
extern AMX_NATIVE_INFO g_BcompatNatives[];
|
||||
|
||||
#endif //_INCLUDE_AMXMOD_CORE_COMPAT_H
|
2934
amxmodx/amxmodx.cpp
2934
amxmodx/amxmodx.cpp
File diff suppressed because it is too large
Load Diff
@ -1,38 +1,16 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef AMXMODX_H
|
||||
#define AMXMODX_H
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined PLATFORM_POSIX
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "sclinux.h"
|
||||
@ -45,19 +23,20 @@
|
||||
#ifdef _MSC_VER
|
||||
// MSVC8 - replace POSIX functions with ISO C++ conformant ones as they are deprecated
|
||||
#if _MSC_VER >= 1400
|
||||
#define unlink _unlink
|
||||
#define unlink _unlink
|
||||
#define mkdir _mkdir
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "md5.h"
|
||||
#include "CVector.h"
|
||||
#include "CList.h"
|
||||
#include "CQueue.h"
|
||||
#include "hashing.h"
|
||||
#include "modules.h"
|
||||
#include "CString.h"
|
||||
#include "CPlugin.h"
|
||||
#include "CLibrarySys.h"
|
||||
#include <auto-string.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <amtl/am-inlinelist.h>
|
||||
#include "CMisc.h"
|
||||
#include "CVault.h"
|
||||
#include "CModule.h"
|
||||
@ -65,15 +44,18 @@
|
||||
#include "CLogEvent.h"
|
||||
#include "CForward.h"
|
||||
#include "CCmd.h"
|
||||
#include "CMenu.h"
|
||||
#include "CEvent.h"
|
||||
#include "CLang.h"
|
||||
#include "fakemeta.h"
|
||||
#include "amxxlog.h"
|
||||
#include "CvarManager.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "CFrameAction.h"
|
||||
#include <amxmodx_version.h>
|
||||
#include <HLTypeConversion.h>
|
||||
|
||||
#define AMXXLOG_Log g_log.Log
|
||||
#define AMXXLOG_Error g_log.LogError
|
||||
#define AMX_VERSION "1.76c"
|
||||
|
||||
extern AMX_NATIVE_INFO core_Natives[];
|
||||
extern AMX_NATIVE_INFO time_Natives[];
|
||||
@ -86,13 +68,18 @@ extern AMX_NATIVE_INFO vault_Natives[];
|
||||
extern AMX_NATIVE_INFO msg_Natives[];
|
||||
extern AMX_NATIVE_INFO vector_Natives[];
|
||||
extern AMX_NATIVE_INFO g_SortNatives[];
|
||||
extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||
extern AMX_NATIVE_INFO g_StackNatives[];
|
||||
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
||||
extern AMX_NATIVE_INFO g_CvarNatives[];
|
||||
extern AMX_NATIVE_INFO g_GameConfigNatives[];
|
||||
|
||||
#ifndef __linux__
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||
#define DLPROC(m, func) GetProcAddress(m, func)
|
||||
#define DLFREE(m) FreeLibrary(m)
|
||||
#else
|
||||
#define DLLOAD(path) (DLHANDLE)dlopen(path, RTLD_NOW)
|
||||
#define DLLOAD(path) (DLHANDLE)dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND)
|
||||
#define DLPROC(m, func) dlsym(m, func)
|
||||
#define DLFREE(m) dlclose(m)
|
||||
#endif
|
||||
@ -108,7 +95,7 @@ extern AMX_NATIVE_INFO g_SortNatives[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __linux__
|
||||
#if defined PLATFORM_WINDOWS
|
||||
typedef HINSTANCE DLHANDLE;
|
||||
#else
|
||||
typedef void* DLHANDLE;
|
||||
@ -126,19 +113,34 @@ extern AMX_NATIVE_INFO g_SortNatives[];
|
||||
#define SETCLIENTLISTENING (*g_engfuncs.pfnVoice_SetClientListening)
|
||||
#define SETCLIENTMAXSPEED (*g_engfuncs.pfnSetClientMaxspeed)
|
||||
|
||||
#define MAX_BUFFER_LENGTH 16384
|
||||
|
||||
char* UTIL_SplitHudMessage(register const char *src);
|
||||
int UTIL_ReadFlags(const char* c);
|
||||
|
||||
void UTIL_ClientPrint(edict_t *pEntity, int msg_dest, char *msg);
|
||||
void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1 = NULL, const char *arg2 = NULL);
|
||||
void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1 = NULL, const char *arg2 = NULL, bool fwd = false);
|
||||
void UTIL_GetFlags(char* flags, int flag);
|
||||
void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, char *pMessage);
|
||||
void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage);
|
||||
void UTIL_DHudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage, unsigned int length);
|
||||
void UTIL_IntToString(int value, char *output);
|
||||
void UTIL_ShowMOTD(edict_t *client, char *motd, int mlen, const char *name);
|
||||
void UTIL_ShowMenu(edict_t* pEntity, int slots, int time, char *menu, int mlen);
|
||||
void UTIL_ClientSayText(edict_t *pEntity, int sender, char *msg);
|
||||
void UTIL_TeamInfo(edict_t *pEntity, int playerIndex, const char *pszTeamName);
|
||||
|
||||
char *UTIL_VarArgs(const char *fmt, ...);
|
||||
template <typename D> int UTIL_CheckValidChar(D *c);
|
||||
template <typename D, typename S> unsigned int strncopy(D *dest, const S *src, size_t count);
|
||||
unsigned int UTIL_GetUTF8CharBytes(const char *stream);
|
||||
size_t UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive);
|
||||
size_t UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive);
|
||||
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive);
|
||||
void UTIL_TrimLeft(char *buffer);
|
||||
void UTIL_TrimRight(char *buffer);
|
||||
|
||||
char* utf8stristr(const char *string1, const char *string2);
|
||||
int utf8strncasecmp(const char *string1, const char *string2, size_t n);
|
||||
int utf8strcasecmp(const char *string1, const char *string2);
|
||||
|
||||
#define GET_PLAYER_POINTER(e) (&g_players[ENTINDEX(e)])
|
||||
//#define GET_PLAYER_POINTER(e) (&g_players[(((int)e-g_edict_point)/sizeof(edict_t))])
|
||||
@ -146,7 +148,7 @@ char *UTIL_VarArgs(const char *fmt, ...);
|
||||
|
||||
struct WeaponsVault
|
||||
{
|
||||
String fullName;
|
||||
ke::AString fullName;
|
||||
short int iId;
|
||||
short int ammoSlot;
|
||||
};
|
||||
@ -157,28 +159,28 @@ struct fakecmd_t
|
||||
const char *argv[3];
|
||||
int argc;
|
||||
bool fake;
|
||||
bool notify; // notify to plugins.
|
||||
};
|
||||
|
||||
extern CLog g_log;
|
||||
extern CPluginMngr g_plugins;
|
||||
extern CTaskMngr g_tasksMngr;
|
||||
extern CFrameActionMngr g_frameActionMngr;
|
||||
extern CPlayer g_players[33];
|
||||
extern CPlayer* mPlayer;
|
||||
extern CmdMngr g_commands;
|
||||
extern CList<CCVar> g_cvars;
|
||||
extern CList<ForceObject> g_forcemodels;
|
||||
extern CList<ForceObject> g_forcesounds;
|
||||
extern CList<ForceObject> g_forcegeneric;
|
||||
extern CList<CModule, const char *> g_modules;
|
||||
extern CList<CScript, AMX*> g_loadedscripts;
|
||||
extern CList<CPlayer*> g_auth;
|
||||
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcemodels;
|
||||
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcesounds;
|
||||
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcegeneric;
|
||||
extern ke::Vector<ke::AutoPtr<CPlayer *>> g_auth;
|
||||
extern ke::InlineList<CModule> g_modules;
|
||||
extern ke::InlineList<CScript> g_loadedscripts;
|
||||
extern EventsMngr g_events;
|
||||
extern Grenades g_grenades;
|
||||
extern LogEventsMngr g_logevents;
|
||||
extern MenuMngr g_menucmds;
|
||||
extern CLangMngr g_langMngr;
|
||||
extern String g_log_dir;
|
||||
extern String g_mod_name;
|
||||
extern ke::AString g_log_dir;
|
||||
extern ke::AString g_mod_name;
|
||||
extern TeamIds g_teamsIds;
|
||||
extern Vault g_vault;
|
||||
extern CForwardMngr g_forwards;
|
||||
@ -186,9 +188,17 @@ extern WeaponsVault g_weaponsData[MAX_WEAPONS];
|
||||
extern XVars g_xvars;
|
||||
extern bool g_bmod_cstrike;
|
||||
extern bool g_bmod_dod;
|
||||
extern bool g_bmod_dmc;
|
||||
extern bool g_bmod_ricochet;
|
||||
extern bool g_bmod_valve;
|
||||
extern bool g_bmod_gearbox;
|
||||
extern bool g_official_mod;
|
||||
extern bool g_dontprecache;
|
||||
extern int g_srvindex;
|
||||
extern cvar_t* amxmodx_version;
|
||||
extern cvar_t* amxmodx_debug;
|
||||
extern cvar_t* amxmodx_language;
|
||||
extern cvar_t* amxmodx_perflog;
|
||||
extern cvar_t* hostname;
|
||||
extern cvar_t* mp_timelimit;
|
||||
extern fakecmd_t g_fakecmd;
|
||||
@ -229,6 +239,8 @@ extern int gmsgWeaponList;
|
||||
extern int gmsgintermission;
|
||||
extern int gmsgResetHUD;
|
||||
extern int gmsgRoundTime;
|
||||
extern int gmsgSayText;
|
||||
extern int gmsgInitHUD;
|
||||
|
||||
void Client_AmmoPickup(void*);
|
||||
void Client_AmmoX(void*);
|
||||
@ -241,6 +253,7 @@ void Client_VGUIMenu(void*);
|
||||
void Client_WeaponList(void*);
|
||||
void Client_DamageEnd(void*);
|
||||
void Client_DeathMsg(void*);
|
||||
void Client_InitHUDEnd(void*);
|
||||
|
||||
void amx_command();
|
||||
void plugin_srvcmd();
|
||||
@ -252,10 +265,6 @@ int loadModules(const char* filename, PLUG_LOADTIME now);
|
||||
void detachModules();
|
||||
void detachReloadModules();
|
||||
|
||||
#ifdef FAKEMETA
|
||||
void attachModules();
|
||||
#endif
|
||||
|
||||
// Count modules
|
||||
enum CountModulesMode
|
||||
{
|
||||
@ -270,29 +279,33 @@ void modules_callPluginsUnloaded();
|
||||
void modules_callPluginsUnloading();
|
||||
|
||||
cell* get_amxaddr(AMX *amx, cell amx_addr);
|
||||
char* build_pathname(char *fmt, ...);
|
||||
char* build_pathname_r(char *buffer, size_t maxlen, char *fmt, ...);
|
||||
char* build_pathname(const char *fmt, ...);
|
||||
char* build_pathname_r(char *buffer, size_t maxlen, const char *fmt, ...);
|
||||
char* format_amxstring(AMX *amx, cell *params, int parm, int& len);
|
||||
AMX* get_amxscript(int, void**, const char**);
|
||||
const char* get_amxscriptname(AMX* amx);
|
||||
char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len);
|
||||
char* get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len);
|
||||
cell* get_amxvector_null(AMX *amx, cell amx_addr);
|
||||
extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, int maxlen);
|
||||
|
||||
int amxstring_len(cell* cstr);
|
||||
int load_amxscript(AMX* amx, void** program, const char* path, char error[64], int debug);
|
||||
int load_amxscript_ex(AMX* amx, void** program, const char* path, char *error, size_t maxLength, int debug);
|
||||
int set_amxnatives(AMX* amx, char error[64]);
|
||||
int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max);
|
||||
int set_amxstring_simple(cell *dest, const char *source, int max);
|
||||
template <typename T> int set_amxstring_utf8(AMX *amx, cell amx_addr, const T *source, size_t sourcelen, size_t maxlen);
|
||||
int set_amxstring_utf8_char(AMX *amx, cell amx_addr, const char *source, size_t sourcelen, size_t maxlen);
|
||||
int set_amxstring_utf8_cell(AMX *amx, cell amx_addr, const cell *source, size_t sourcelen, size_t maxlen);
|
||||
int unload_amxscript(AMX* amx, void** program);
|
||||
|
||||
void copy_amxmemory(cell* dest, cell* src, int len);
|
||||
void get_modname(char*);
|
||||
void print_srvconsole(char *fmt, ...);
|
||||
void report_error(int code, char* fmt, ...);
|
||||
void* alloc_amxmemory(void**, int size);
|
||||
void free_amxmemory(void **ptr);
|
||||
void print_srvconsole(const char *fmt, ...);
|
||||
void report_error(int code, const char* fmt, ...);
|
||||
// get_localinfo
|
||||
const char* get_localinfo(const char* name, const char* def);
|
||||
cell AMX_NATIVE_CALL require_module(AMX *amx, cell *params);
|
||||
extern "C" void LogError(AMX *amx, int err, const char *fmt, ...);
|
||||
|
||||
enum ModuleCallReason
|
||||
@ -327,6 +340,8 @@ extern int FF_PluginEnd;
|
||||
extern int FF_InconsistentFile;
|
||||
extern int FF_ClientAuthorized;
|
||||
extern int FF_ChangeLevel;
|
||||
extern int FF_ClientConnectEx;
|
||||
|
||||
extern bool g_coloredmenus;
|
||||
|
||||
typedef void (*AUTHORIZEFUNC)(int player, const char *authstring);
|
||||
@ -339,6 +354,23 @@ struct func_s
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
enum AdminProperty
|
||||
{
|
||||
Admin_Auth = 0,
|
||||
Admin_Password,
|
||||
Admin_Access,
|
||||
Admin_Flags
|
||||
};
|
||||
|
||||
enum PrintColor
|
||||
{
|
||||
print_team_default = 0,
|
||||
print_team_grey =-1,
|
||||
print_team_red = -2,
|
||||
print_team_blue = -3,
|
||||
};
|
||||
|
||||
extern enginefuncs_t *g_pEngTable;
|
||||
extern HLTypeConversion TypeConversion;
|
||||
|
||||
#endif // AMXMODX_H
|
||||
|
@ -2,8 +2,6 @@
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2001-2002
|
||||
* This file may be freely used. No warranties of any kind.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
@ -1,11 +0,0 @@
|
||||
; /usr/local/cross-tools/bin/i386-mingw32msvc-dlltool --base-file /tmp/cc4kB6s0.base --output-exp amx_mm.exp --dllname amx_mm.dll --output-def amx_mm.def --add-stdcall-alias --exclude-symbol=DllMainCRTStartup@12 --def /tmp/ccyI7I7K.def
|
||||
EXPORTS
|
||||
GetEngineFunctions @ 1 ;
|
||||
GetEngineFunctions_Post @ 2 ;
|
||||
GetEntityAPI2 @ 3 ;
|
||||
GetEntityAPI2_Post @ 4 ;
|
||||
GiveFnptrsToDll = GiveFnptrsToDll@8 @ 5 ;
|
||||
GiveFnptrsToDll@8 @ 6 ;
|
||||
Meta_Attach @ 7 ;
|
||||
Meta_Detach @ 8 ;
|
||||
Meta_Query @ 9 ;
|
@ -1,32 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "amxxfile.h"
|
||||
@ -42,7 +21,7 @@
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
#if defined __linux__
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#else
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
@ -127,7 +106,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
|
||||
|
||||
for (mint8_t i = 0; i < m_Bh.numPlugins; i++)
|
||||
{
|
||||
pe = &(m_Bh.plugins[i]);
|
||||
pe = &(m_Bh.plugins[(unsigned)i]);
|
||||
DATAREAD(&pe->cellsize, sizeof(mint8_t), 1);
|
||||
DATAREAD(&pe->disksize, sizeof(int32_t), 1);
|
||||
DATAREAD(&pe->imagesize, sizeof(int32_t), 1);
|
||||
@ -137,7 +116,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
|
||||
|
||||
for (mint8_t i = 0; i < m_Bh.numPlugins; i++)
|
||||
{
|
||||
pe = &(m_Bh.plugins[i]);
|
||||
pe = &(m_Bh.plugins[(unsigned)i]);
|
||||
|
||||
if (pe->cellsize == m_CellSize)
|
||||
{
|
||||
@ -310,7 +289,18 @@ size_t CAmxxReader::GetBufferSize()
|
||||
m_pFile = NULL; \
|
||||
return m_Status; \
|
||||
}
|
||||
|
||||
#define DATAREAD_RELEASE(addr, itemsize, itemcount) \
|
||||
if (fread(addr, itemsize, itemcount, m_pFile) != static_cast<size_t>(itemcount)) \
|
||||
{ \
|
||||
if (feof(m_pFile)) \
|
||||
m_Status = Err_FileInvalid; \
|
||||
else \
|
||||
m_Status = Err_FileRead; \
|
||||
fclose(m_pFile); \
|
||||
m_pFile = NULL; \
|
||||
delete[] tempBuffer;\
|
||||
return m_Status; \
|
||||
}
|
||||
CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
|
||||
{
|
||||
if (!m_pFile)
|
||||
@ -332,7 +322,7 @@ CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
|
||||
PluginEntry *pe = &(m_Bh.plugins[m_Entry]);
|
||||
char *tempBuffer = new char[m_SectionLength + 1];
|
||||
fseek(m_pFile, pe->offs, SEEK_SET);
|
||||
DATAREAD((void *)tempBuffer, 1, m_SectionLength);
|
||||
DATAREAD_RELEASE((void *)tempBuffer, 1, m_SectionLength);
|
||||
uLongf destLen = GetBufferSize();
|
||||
int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength);
|
||||
delete [] tempBuffer;
|
||||
@ -356,7 +346,7 @@ CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
|
||||
// read the data to a temporary buffer
|
||||
char *tempBuffer = new char[m_SectionLength + 1];
|
||||
//fread(tempBuffer, sizeof(char), m_SectionLength, m_pFile);
|
||||
DATAREAD((void*)tempBuffer, 1, m_SectionLength);
|
||||
DATAREAD_RELEASE((void*)tempBuffer, 1, m_SectionLength);
|
||||
// decompress
|
||||
int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength);
|
||||
delete [] tempBuffer;
|
||||
|
@ -1,33 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef __AMXXFILE_H__
|
||||
#define __AMXXFILE_H__
|
||||
|
@ -1,32 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
// amxx_logging localinfo:
|
||||
// 0 = no logging
|
||||
@ -35,19 +14,21 @@
|
||||
// 3 = HL Logs
|
||||
|
||||
#include <time.h>
|
||||
#ifndef __linux__
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "amxmodx.h"
|
||||
|
||||
#ifndef __linux__
|
||||
#if defined(_WIN32WIN32)
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#include <amxmodx_version.h>
|
||||
|
||||
CLog::CLog()
|
||||
{
|
||||
m_LogType = 0;
|
||||
m_LogFile.clear();
|
||||
m_LogFile = nullptr;
|
||||
m_FoundError = false;
|
||||
m_LoggedErrMap = false;
|
||||
}
|
||||
@ -60,14 +41,14 @@ CLog::~CLog()
|
||||
void CLog::CloseFile()
|
||||
{
|
||||
// log "log file closed" to old file, if any
|
||||
if (!m_LogFile.empty())
|
||||
if (m_LogFile.length())
|
||||
{
|
||||
FILE *fp = fopen(m_LogFile.c_str(), "r");
|
||||
|
||||
FILE *fp = fopen(m_LogFile.chars(), "r");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
fp = fopen(m_LogFile.c_str(), "a+");
|
||||
fp = fopen(m_LogFile.chars(), "a+");
|
||||
|
||||
// get time
|
||||
time_t td;
|
||||
@ -80,73 +61,81 @@ void CLog::CloseFile()
|
||||
fprintf(fp, "L %s: %s\n", date, "Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
m_LogFile.clear();
|
||||
|
||||
m_LogFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CLog::CreateNewFile()
|
||||
{
|
||||
CloseFile();
|
||||
|
||||
|
||||
// build filename
|
||||
time_t td;
|
||||
time(&td);
|
||||
tm *curTime = localtime(&td);
|
||||
|
||||
char file[256];
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
char name[256];
|
||||
int i = 0;
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
build_pathname_r(file, sizeof(file)-1, "%s/L%02d%02d%03d.log", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday, i);
|
||||
ke::SafeSprintf(name, sizeof(name), "%s/L%02d%02d%03d.log", g_log_dir.chars(), curTime->tm_mon + 1, curTime->tm_mday, i);
|
||||
build_pathname_r(file, sizeof(file), "%s", name);
|
||||
FILE *pTmpFile = fopen(file, "r"); // open for reading to check whether the file exists
|
||||
|
||||
|
||||
if (!pTmpFile)
|
||||
break;
|
||||
|
||||
|
||||
fclose(pTmpFile);
|
||||
++i;
|
||||
}
|
||||
m_LogFile.assign(file);
|
||||
|
||||
m_LogFile = file;
|
||||
|
||||
// Log logfile start
|
||||
FILE *fp = fopen(m_LogFile.c_str(), "w");
|
||||
|
||||
FILE *fp = fopen(m_LogFile.chars(), "w");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
ALERT(at_logged, "[AMXX] Unexpected fatal logging error. AMXX Logging disabled.\n");
|
||||
SET_LOCALINFO("amxx_logging", "0");
|
||||
} else {
|
||||
fprintf(fp, "AMX Mod X log file started (file \"%s/L%02d%02d%03d.log\") (version \"%s\")\n", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday, i, AMX_VERSION);
|
||||
fprintf(fp, "AMX Mod X log file started (file \"%s\") (version \"%s\")\n", name, AMXX_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void CLog::UseFile(const String &fileName)
|
||||
void CLog::UseFile(const ke::AString &fileName)
|
||||
{
|
||||
static char file[256];
|
||||
m_LogFile.assign(build_pathname_r(file, sizeof(file)-1, "%s/%s", g_log_dir.c_str(), fileName.c_str()));
|
||||
static char file[PLATFORM_MAX_PATH];
|
||||
m_LogFile = build_pathname_r(file, sizeof(file), "%s/%s", g_log_dir.chars(), fileName.chars());
|
||||
}
|
||||
|
||||
void CLog::SetLogType(const char* localInfo)
|
||||
{
|
||||
m_LogType = atoi(get_localinfo(localInfo, "1"));
|
||||
|
||||
if (m_LogType < 0 || m_LogType > 3)
|
||||
{
|
||||
SET_LOCALINFO(localInfo, "1");
|
||||
m_LogType = 1;
|
||||
|
||||
print_srvconsole("[AMXX] Invalid amxx_logging value; setting back to 1...");
|
||||
}
|
||||
}
|
||||
|
||||
void CLog::MapChange()
|
||||
{
|
||||
// create dir if not existing
|
||||
char file[256];
|
||||
#ifdef __linux
|
||||
mkdir(build_pathname_r(file, sizeof(file)-1, "%s", g_log_dir.c_str()), 0700);
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
mkdir(build_pathname_r(file, sizeof(file), "%s", g_log_dir.chars()), 0700);
|
||||
#else
|
||||
mkdir(build_pathname_r(file, sizeof(file)-1, "%s", g_log_dir.c_str()));
|
||||
mkdir(build_pathname_r(file, sizeof(file), "%s", g_log_dir.chars()));
|
||||
#endif
|
||||
|
||||
m_LogType = atoi(get_localinfo("amxx_logging", "1"));
|
||||
|
||||
if (m_LogType < 0 || m_LogType > 3)
|
||||
{
|
||||
SET_LOCALINFO("amxx_logging", "1");
|
||||
m_LogType = 1;
|
||||
print_srvconsole("[AMXX] Invalid amxx_logging value; setting back to 1...");
|
||||
}
|
||||
SetLogType("amxx_logging");
|
||||
|
||||
m_LoggedErrMap = false;
|
||||
|
||||
@ -163,8 +152,8 @@ void CLog::MapChange()
|
||||
|
||||
void CLog::Log(const char *fmt, ...)
|
||||
{
|
||||
static char file[256];
|
||||
|
||||
static char file[PLATFORM_MAX_PATH];
|
||||
|
||||
if (m_LogType == 1 || m_LogType == 2)
|
||||
{
|
||||
// get time
|
||||
@ -186,24 +175,24 @@ void CLog::Log(const char *fmt, ...)
|
||||
FILE *pF = NULL;
|
||||
if (m_LogType == 2)
|
||||
{
|
||||
pF = fopen(m_LogFile.c_str(), "a+");
|
||||
pF = fopen(m_LogFile.chars(), "a+");
|
||||
if (!pF)
|
||||
{
|
||||
CreateNewFile();
|
||||
pF = fopen(m_LogFile.c_str(), "a+");
|
||||
|
||||
pF = fopen(m_LogFile.chars(), "a+");
|
||||
|
||||
if (!pF)
|
||||
{
|
||||
ALERT(at_logged, "[AMXX] Unexpected fatal logging error (couldn't open %s for a+). AMXX Logging disabled for this map.\n", m_LogFile.c_str());
|
||||
ALERT(at_logged, "[AMXX] Unexpected fatal logging error (couldn't open %s for a+). AMXX Logging disabled for this map.\n", m_LogFile.chars());
|
||||
m_LogType = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
build_pathname_r(file, sizeof(file)-1, "%s/L%02d%02d.log", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday);
|
||||
build_pathname_r(file, sizeof(file), "%s/L%04d%02d%02d.log", g_log_dir.chars(), (curTime->tm_year + 1900), curTime->tm_mon + 1, curTime->tm_mday);
|
||||
pF = fopen(file, "a+");
|
||||
}
|
||||
|
||||
|
||||
if (pF)
|
||||
{
|
||||
fprintf(pF, "L %s: %s\n", date, msg);
|
||||
@ -229,7 +218,8 @@ void CLog::Log(const char *fmt, ...)
|
||||
|
||||
void CLog::LogError(const char *fmt, ...)
|
||||
{
|
||||
static char file[256];
|
||||
static char file[PLATFORM_MAX_PATH];
|
||||
static char name[256];
|
||||
|
||||
if (m_FoundError)
|
||||
{
|
||||
@ -253,7 +243,8 @@ void CLog::LogError(const char *fmt, ...)
|
||||
va_end(arglst);
|
||||
|
||||
FILE *pF = NULL;
|
||||
build_pathname_r(file, sizeof(file)-1, "%s/error_%02d%02d%02d.log", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday, curTime->tm_year - 100);
|
||||
ke::SafeSprintf(name, sizeof(name), "%s/error_%04d%02d%02d.log", g_log_dir.chars(), curTime->tm_year + 1900, curTime->tm_mon + 1, curTime->tm_mday);
|
||||
build_pathname_r(file, sizeof(file), "%s", name);
|
||||
pF = fopen(file, "a+");
|
||||
|
||||
if (pF)
|
||||
@ -261,7 +252,7 @@ void CLog::LogError(const char *fmt, ...)
|
||||
if (!m_LoggedErrMap)
|
||||
{
|
||||
fprintf(pF, "L %s: Start of error session.\n", date);
|
||||
fprintf(pF, "L %s: Info (map \"%s\") (logfile \"error_%02d%02d%02d.log\")\n", date, STRING(gpGlobals->mapname), curTime->tm_mon + 1, curTime->tm_mday, curTime->tm_year - 100);
|
||||
fprintf(pF, "L %s: Info (map \"%s\") (file \"%s\")\n", date, STRING(gpGlobals->mapname), name);
|
||||
m_LoggedErrMap = true;
|
||||
}
|
||||
fprintf(pF, "L %s: %s\n", date, msg);
|
||||
@ -275,4 +266,3 @@ void CLog::LogError(const char *fmt, ...)
|
||||
// print on server console
|
||||
print_srvconsole("L %s: %s\n", date, msg);
|
||||
}
|
||||
|
||||
|
@ -1,32 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef __AMXXLOG_H__
|
||||
#define __AMXXLOG_H__
|
||||
@ -34,19 +13,20 @@
|
||||
class CLog
|
||||
{
|
||||
private:
|
||||
String m_LogFile;
|
||||
ke::AString m_LogFile;
|
||||
int m_LogType;
|
||||
bool m_FoundError;
|
||||
bool m_LoggedErrMap;
|
||||
|
||||
void GetLastFile(int &outMonth, int &outDay, String &outFilename);
|
||||
void UseFile(const String &fileName);
|
||||
void GetLastFile(int &outMonth, int &outDay, ke::AString &outFilename);
|
||||
void UseFile(const ke::AString &fileName);
|
||||
public:
|
||||
CLog();
|
||||
~CLog();
|
||||
|
||||
void CreateNewFile();
|
||||
void CloseFile();
|
||||
void SetLogType(const char* localInfo);
|
||||
void MapChange();
|
||||
void Log(const char *fmt, ...);
|
||||
void LogError(const char *fmt, ...);
|
||||
|
@ -1,3 +1,12 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#if defined BINLOG_ENABLED
|
||||
|
||||
#include <time.h>
|
||||
@ -40,13 +49,13 @@ int LookupFile(AMX_DBG *amxdbg, ucell address)
|
||||
bool BinLog::Open()
|
||||
{
|
||||
const char *data = get_localinfo("amxmodx_datadir", "addons/amxmodx/data");
|
||||
char path[255];
|
||||
build_pathname_r(path, sizeof(path)-1, "%s/binlogs", data);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
build_pathname_r(path, sizeof(path), "%s/binlogs", data);
|
||||
|
||||
if (!DirExists(path))
|
||||
{
|
||||
mkdir(path
|
||||
#if defined __linux__
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
, 0755
|
||||
#endif
|
||||
);
|
||||
@ -54,8 +63,8 @@ bool BinLog::Open()
|
||||
return false;
|
||||
}
|
||||
|
||||
char file[255];
|
||||
build_pathname_r(file, sizeof(file)-1, "%s/binlogs/lastlog", data);
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
build_pathname_r(file, sizeof(file), "%s/binlogs/lastlog", data);
|
||||
|
||||
unsigned int lastcntr = 0;
|
||||
FILE *lastlog = fopen(file, "rb");
|
||||
@ -72,13 +81,13 @@ bool BinLog::Open()
|
||||
fwrite(&lastcntr, sizeof(int), 1, lastlog);
|
||||
fclose(lastlog);
|
||||
}
|
||||
build_pathname_r(file, sizeof(file)-1, "%s/binlogs/binlog%04d.blg", data, lastcntr);
|
||||
m_logfile.assign(file);
|
||||
build_pathname_r(file, sizeof(file), "%s/binlogs/binlog%04d.blg", data, lastcntr);
|
||||
m_logfile = file;
|
||||
|
||||
/**
|
||||
* it's now safe to create the binary log
|
||||
*/
|
||||
FILE *fp = fopen(m_logfile.c_str(), "wb");
|
||||
FILE *fp = fopen(m_logfile.chars(), "wb");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
@ -110,7 +119,7 @@ void BinLog::WriteOp(BinLogOp op, int plug, ...)
|
||||
if (!m_state)
|
||||
return;
|
||||
|
||||
FILE *fp = fopen(m_logfile.c_str(), "ab");
|
||||
FILE *fp = fopen(m_logfile.chars(), "ab");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
@ -122,7 +131,7 @@ void BinLog::WriteOp(BinLogOp op, int plug, ...)
|
||||
fclose(fp);
|
||||
Close();
|
||||
Open();
|
||||
fp = fopen(m_logfile.c_str(), "ab");
|
||||
fp = fopen(m_logfile.chars(), "ab");
|
||||
if (!fp)
|
||||
return;
|
||||
}
|
||||
|
@ -1,9 +1,18 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_BINLOG_H
|
||||
#define _INCLUDE_BINLOG_H
|
||||
|
||||
#if defined BINLOG_ENABLED
|
||||
|
||||
#include "CString.h"
|
||||
#include <amtl/am-string.h>
|
||||
|
||||
#define BINLOG_MAGIC 0x414D424C
|
||||
#define BINLOG_VERSION 0x0300
|
||||
@ -71,7 +80,7 @@ public:
|
||||
private:
|
||||
void WritePluginDB(FILE *fp);
|
||||
private:
|
||||
String m_logfile;
|
||||
ke::AString m_logfile;
|
||||
bool m_state;
|
||||
};
|
||||
|
||||
|
729
amxmodx/cvars.cpp
Normal file
729
amxmodx/cvars.cpp
Normal file
@ -0,0 +1,729 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "CvarManager.h"
|
||||
#include "amxmodx.h"
|
||||
#include "nongpl_matches.h"
|
||||
|
||||
char CVarTempBuffer[64];
|
||||
const char *invis_cvar_list[5] ={ "amxmodx_version", "amxmodx_modules", "amx_debug", "amx_mldebug", "amx_client_languages" };
|
||||
|
||||
// create_cvar(const name[], const default_value[], flags = 0, const description[] = "", bool:has_min = false, Float:min_val = 0.0, bool:has_max = false, Float:max_val = 0.0)
|
||||
static cell AMX_NATIVE_CALL create_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||
const char* helpText = get_amxstring(amx, params[4], 2, length);
|
||||
|
||||
int flags = params[3];
|
||||
|
||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||
|
||||
if (CheckBadConList(name, 0))
|
||||
{
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags, helpText);
|
||||
|
||||
if (info)
|
||||
{
|
||||
bool hasMin = params[5] != 0;
|
||||
bool hasMax = params[7] != 0;
|
||||
float minVal = amx_ctof(params[6]);
|
||||
float maxVal = amx_ctof(params[8]);
|
||||
|
||||
if (hasMin && hasMax)
|
||||
{
|
||||
if (minVal > maxVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
|
||||
return 0;
|
||||
}
|
||||
else if (maxVal < minVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
g_CvarManager.SetCvarMin(info, hasMin, minVal, plugin->getId());
|
||||
g_CvarManager.SetCvarMax(info, hasMax, maxVal, plugin->getId());
|
||||
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0)
|
||||
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||
|
||||
int flags = params[3];
|
||||
float fvalue = amx_ctof(params[4]);
|
||||
|
||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||
|
||||
if (CheckBadConList(name, 0))
|
||||
{
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags);
|
||||
|
||||
if (info)
|
||||
{
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cvar_exists(const cvar[])
|
||||
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params)
|
||||
{
|
||||
int ilen;
|
||||
return (g_CvarManager.FindCvar(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
|
||||
}
|
||||
|
||||
// get_cvar_pointer(const cvar[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
||||
{
|
||||
int len;
|
||||
const char *name = get_amxstring(amx, params[1], 0, len);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return reinterpret_cast<cell>(info ? info->var : 0);
|
||||
}
|
||||
|
||||
// hook_cvar_change(cvarHandle, const callback[])
|
||||
static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t* var = reinterpret_cast<cvar_t*>(params[1]);
|
||||
|
||||
if (!var)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar handle: %p", var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* callback;
|
||||
AutoForward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(forward);
|
||||
}
|
||||
|
||||
// enable_cvar_hook(cvarhook:handle);
|
||||
static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params)
|
||||
{
|
||||
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||
return 0;
|
||||
}
|
||||
|
||||
forward->state = AutoForward::FSTATE_OK;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// disable_cvar_hook(cvarhook:handle);
|
||||
static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params)
|
||||
{
|
||||
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||
return 0;
|
||||
}
|
||||
|
||||
forward->state = AutoForward::FSTATE_STOP;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_cvar_flags(const cvar[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
int ilen;
|
||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
return info ? info->var->flags : 0;
|
||||
}
|
||||
|
||||
// get_cvar_float(const cvarname[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return info ? amx_ftoc(info->var->value) : 0;
|
||||
}
|
||||
|
||||
// get_cvar_num(const cvarname[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return info ? (int)info->var->value : 0;
|
||||
}
|
||||
|
||||
// get_cvar_string(const cvarname[], output[], iLen)
|
||||
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
const char *value = info ? info->var->string : "";
|
||||
length = info ? strlen(value) : 0;
|
||||
|
||||
return set_amxstring_utf8(amx, params[2], value, length, params[3]);
|
||||
}
|
||||
|
||||
// set_cvar_flags(const cvar[], flags)
|
||||
static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
int ilen;
|
||||
const char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||
|
||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||
return 0;
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->var->flags |= (int)(params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set_cvar_float(const cvar[], Float:value)
|
||||
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%f", amx_ctof(params[2]));
|
||||
CVAR_DIRECTSET(info->var, &CVarTempBuffer[0]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_cvar_num(const cvarname[], value)
|
||||
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
int value = params[2];
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%d", value);
|
||||
CVAR_DIRECTSET(info->var, &CVarTempBuffer[0]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_cvar_string(const cvar[], const value[])
|
||||
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
CVAR_DIRECTSET(info->var, get_amxstring(amx, params[2], 1, length));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_pcvar_flags(pcvar)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ptr->flags;
|
||||
}
|
||||
|
||||
// Float:get_pcvar_float(pcvar)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return amx_ftoc(ptr->value);
|
||||
}
|
||||
|
||||
// get_pcvar_num(pcvar)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)ptr->value;
|
||||
}
|
||||
|
||||
// bool:get_pcvar_bool(pcvar)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_bool(AMX *amx, cell *params)
|
||||
{
|
||||
return !!get_pcvar_num(amx, params);
|
||||
}
|
||||
|
||||
// get_pcvar_string(pcvar, string[], maxlen)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3]);
|
||||
}
|
||||
|
||||
// get_pcvar_bounds(pcvar, CvarBounds:type, &Float:value)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hasBound = false;
|
||||
float bound;
|
||||
|
||||
switch (params[2])
|
||||
{
|
||||
case CvarBound_Lower:
|
||||
hasBound = info->bound.hasMin;
|
||||
bound = info->bound.minVal;
|
||||
break;
|
||||
case CvarBound_Upper:
|
||||
hasBound = info->bound.hasMax;
|
||||
bound = info->bound.maxVal;
|
||||
break;
|
||||
default:
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*get_amxaddr(amx, params[3]) = amx_ftoc(bound);
|
||||
|
||||
return hasBound;
|
||||
}
|
||||
|
||||
// bind_pcvar_float(pcvar, &Float:var)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Float, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_num(pcvar, &any:var)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Int, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_string(pcvar, any:var[], varlen)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_String, amx, params[2], params[3]);
|
||||
}
|
||||
|
||||
// set_pcvar_flags(pcvar, flags)
|
||||
static cell AMX_NATIVE_CALL set_pcvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr->flags = static_cast<int>(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_pcvar_float(pcvar, Float:num)
|
||||
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%f", amx_ctof(params[2]));
|
||||
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_pcvar_num(pcvar, num)
|
||||
static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%d", params[2]);
|
||||
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_pcvar_string(pcvar, const string[])
|
||||
static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
|
||||
CVAR_DIRECTSET(ptr, get_amxstring(amx, params[2], 0, len));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set_pcvar_bounds(pcvar, CvarBounds:type, bool:set, Float:value = 0.0)
|
||||
static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool set = params[3] != 0;
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
float value = amx_ctof(params[4]);
|
||||
|
||||
switch (params[2])
|
||||
{
|
||||
case CvarBound_Lower:
|
||||
{
|
||||
if (set && info->bound.hasMax && value > info->bound.maxVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_CvarManager.SetCvarMin(info, set, value, pluginId);
|
||||
break;
|
||||
}
|
||||
case CvarBound_Upper:
|
||||
{
|
||||
if (set && info->bound.hasMin && value < info->bound.minVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_CvarManager.SetCvarMax(info, set, value, pluginId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// remove_cvar_flags(const cvar[], flags=-1)
|
||||
static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
int ilen;
|
||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||
|
||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||
return 0;
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->var->flags &= ~((int)(params[2]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0, description[]="", desc_len=0)
|
||||
static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
|
||||
|
||||
if (info)
|
||||
{
|
||||
set_amxstring(amx, params[2], info->name.chars(), params[3]);
|
||||
*get_amxaddr(amx, params[4]) = info->var->flags;
|
||||
*get_amxaddr(amx, params[5]) = info->pluginId;
|
||||
*get_amxaddr(amx, params[6]) = reinterpret_cast<cell>(info->var);
|
||||
|
||||
if (*params / sizeof(cell) >= 7)
|
||||
{
|
||||
set_amxstring(amx, params[7], info->description.chars(), params[8]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_plugins_cvarsnum()
|
||||
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
||||
{
|
||||
return g_CvarManager.GetRegCvarsCount();
|
||||
}
|
||||
|
||||
#if defined AMD64
|
||||
static bool g_warned_ccqv = false;
|
||||
#endif
|
||||
// query_client_cvar(id, const cvar[], const resultfunc[])
|
||||
static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
int numParams = params[0] / sizeof(cell);
|
||||
|
||||
if (numParams != 3 && numParams != 5)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined AMD64
|
||||
if (!g_warned_ccqv)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "[AMXX] Client CVAR Querying is not available on AMD64 (one time warn)");
|
||||
g_warned_ccqv = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (!g_NewDLL_Available)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Client CVAR querying is not enabled - check MM version!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int id = params[1];
|
||||
|
||||
if (id < 1 || id > gpGlobals->maxClients)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CPlayer *pPlayer = GET_PLAYER_POINTER_I(id);
|
||||
|
||||
if (!pPlayer->initialized || pPlayer->IsBot())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Player %d is either not connected or a bot", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dummy;
|
||||
const char *cvarname = get_amxstring(amx, params[2], 0, dummy);
|
||||
const char *resultfuncname = get_amxstring(amx, params[3], 1, dummy);
|
||||
|
||||
// public clientcvarquery_result(id, const cvar[], const result[], [const param[]])
|
||||
int iFunc;
|
||||
|
||||
if (numParams == 5 && params[4] != 0)
|
||||
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE);
|
||||
else
|
||||
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
||||
|
||||
if (iFunc == -1)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", resultfuncname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClientCvarQuery_Info *queryObject = new ClientCvarQuery_Info;
|
||||
queryObject->resultFwd = iFunc;
|
||||
queryObject->requestId = MAKE_REQUESTID(PLID);
|
||||
|
||||
if (numParams == 5 && params[4] != 0)
|
||||
{
|
||||
queryObject->paramLen = params[4] + 1;
|
||||
queryObject->params = new cell[queryObject->paramLen];
|
||||
|
||||
if (!queryObject->params)
|
||||
{
|
||||
delete queryObject;
|
||||
unregisterSPForward(iFunc);
|
||||
LogError(amx, AMX_ERR_MEMORY, "Hmm. Out of memory?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(reinterpret_cast<void*>(queryObject->params), reinterpret_cast<const void *>(get_amxaddr(amx, params[5])), queryObject->paramLen * sizeof(cell));
|
||||
|
||||
queryObject->params[queryObject->paramLen - 1] = 0;
|
||||
}
|
||||
else {
|
||||
queryObject->params = NULL;
|
||||
queryObject->paramLen = 0;
|
||||
}
|
||||
|
||||
pPlayer->queries.push_back(queryObject);
|
||||
|
||||
QUERY_CLIENT_CVAR_VALUE2(pPlayer->pEdict, cvarname, queryObject->requestId);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO g_CvarNatives[] =
|
||||
{
|
||||
{"create_cvar", create_cvar},
|
||||
{"register_cvar", register_cvar},
|
||||
{"cvar_exists", cvar_exists},
|
||||
{"get_cvar_pointer", get_cvar_pointer},
|
||||
|
||||
{"hook_cvar_change", hook_cvar_change},
|
||||
{"enable_cvar_hook", enable_cvar_hook},
|
||||
{"disable_cvar_hook", disable_cvar_hook},
|
||||
|
||||
{"get_cvar_flags", get_cvar_flags},
|
||||
{"get_cvar_float", get_cvar_float},
|
||||
{"get_cvar_num", get_cvar_num},
|
||||
{"get_cvar_string", get_cvar_string},
|
||||
|
||||
{"set_cvar_flags", set_cvar_flags},
|
||||
{"set_cvar_float", set_cvar_float},
|
||||
{"set_cvar_num", set_cvar_num},
|
||||
{"set_cvar_string", set_cvar_string},
|
||||
|
||||
{"get_pcvar_flags", get_pcvar_flags},
|
||||
{"get_pcvar_float", get_pcvar_float},
|
||||
{"get_pcvar_num", get_pcvar_num},
|
||||
{"get_pcvar_bool", get_pcvar_bool},
|
||||
{"get_pcvar_string", get_pcvar_string},
|
||||
{"get_pcvar_bounds", get_pcvar_bounds},
|
||||
|
||||
{"set_pcvar_flags", set_pcvar_flags},
|
||||
{"set_pcvar_float", set_pcvar_float},
|
||||
{"set_pcvar_num", set_pcvar_num},
|
||||
{"set_pcvar_bool", set_pcvar_num},
|
||||
{"set_pcvar_string", set_pcvar_string},
|
||||
{"set_pcvar_bounds", set_pcvar_bounds},
|
||||
|
||||
{"remove_cvar_flags", remove_cvar_flags},
|
||||
|
||||
{"bind_pcvar_float", bind_pcvar_float},
|
||||
{"bind_pcvar_num", bind_pcvar_num},
|
||||
{"bind_pcvar_string", bind_pcvar_string},
|
||||
|
||||
{"get_plugins_cvar", get_plugins_cvar},
|
||||
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
|
||||
|
||||
{"query_client_cvar", query_client_cvar},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
250
amxmodx/datapacks.cpp
Normal file
250
amxmodx/datapacks.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
#include "CDataPack.h"
|
||||
|
||||
NativeHandle<CDataPack> DataPackHandles;
|
||||
|
||||
static cell AMX_NATIVE_CALL CreateDataPack(AMX* amx, cell* params)
|
||||
{
|
||||
return static_cast<cell>(DataPackHandles.create());
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL WritePackCell(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->PackCell(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL WritePackFloat(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->PackFloat(amx_ctof(params[2]));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL WritePackString(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
const char *str = get_amxstring(amx, params[2], 0, len);
|
||||
|
||||
d->PackString(str);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL ReadPackCell(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!d->CanReadCell())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return d->ReadCell();
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL ReadPackFloat(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!d->CanReadFloat())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
float value = d->ReadFloat();
|
||||
|
||||
return amx_ftoc(value);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL ReadPackString(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!d->CanReadString(NULL))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
const char *str = d->ReadString(&len);
|
||||
|
||||
return set_amxstring_utf8(amx, params[2], str, len, params[3]);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL ResetPack(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->Reset();
|
||||
|
||||
if (params[2])
|
||||
{
|
||||
d->ResetSize();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL GetPackPosition(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<cell>(d->GetPosition());
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL SetPackPosition(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!d->SetPosition(params[2]))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid DataPack position, %d is out of bounds", params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL IsPackEnded(AMX* amx, cell* params)
|
||||
{
|
||||
CDataPack *d = DataPackHandles.lookup(params[1]);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return d->IsReadable(1) ? false : true;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL DestroyDataPack(AMX* amx, cell* params)
|
||||
{
|
||||
cell *ptr = get_amxaddr(amx, params[1]);
|
||||
|
||||
CDataPack *d = DataPackHandles.lookup(*ptr);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (DataPackHandles.destroy(*ptr))
|
||||
{
|
||||
*ptr = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AMX_NATIVE_INFO g_DatapackNatives[] =
|
||||
{
|
||||
{ "CreateDataPack" , CreateDataPack },
|
||||
{ "WritePackCell" , WritePackCell },
|
||||
{ "WritePackFloat" , WritePackFloat },
|
||||
{ "WritePackString", WritePackString },
|
||||
{ "ReadPackCell" , ReadPackCell },
|
||||
{ "ReadPackFloat" , ReadPackFloat },
|
||||
{ "ReadPackString" , ReadPackString },
|
||||
{ "ResetPack" , ResetPack },
|
||||
{ "GetPackPosition", GetPackPosition },
|
||||
{ "SetPackPosition", SetPackPosition },
|
||||
{ "IsPackEnded" , IsPackEnded },
|
||||
{ "DestroyDataPack", DestroyDataPack },
|
||||
{ nullptr , nullptr}
|
||||
};
|
935
amxmodx/datastructs.cpp
Normal file
935
amxmodx/datastructs.cpp
Normal file
@ -0,0 +1,935 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "datastructs.h"
|
||||
#include <amtl/am-utility.h>
|
||||
|
||||
NativeHandle<CellArray> ArrayHandles;
|
||||
|
||||
// Array:ArrayCreate(cellsize=1, reserved=32);
|
||||
static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params)
|
||||
{
|
||||
// params[1] (cellsize) is how big in cells each element is.
|
||||
// this MUST be greater than 0!
|
||||
int cellsize = params[1];
|
||||
|
||||
// params[2] (reserved) is how many elements to allocate
|
||||
// immediately when the list is created.
|
||||
int reserved = params[2];
|
||||
|
||||
if (cellsize <= 0)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (reserved < 0)
|
||||
{
|
||||
reserved = 0;
|
||||
}
|
||||
|
||||
return ArrayHandles.create(cellsize, reserved);
|
||||
}
|
||||
|
||||
// native ArrayClear(Array:which);
|
||||
static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vec->clear();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArraySize(Array:which);
|
||||
static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vec->size();
|
||||
}
|
||||
|
||||
// native bool:ArrayResize(Array:which, newsize);
|
||||
static cell AMX_NATIVE_CALL ArrayResize(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vec->resize(params[2]))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Unable to resize array to \"%u\"", params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native Array:ArrayClone(Array:which);
|
||||
static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto data = vec->clone();
|
||||
|
||||
if (!data)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Failed to clone array. Out of memory.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ArrayHandles.clone(data);
|
||||
}
|
||||
|
||||
// native ArrayGetArray(Array:which, item, any:output[], size = -1);
|
||||
static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
size_t indexes = vec->blocksize();
|
||||
|
||||
if (*params / sizeof(cell) == 4)
|
||||
{
|
||||
if (params[4] != -1 && (size_t)params[4] <= vec->blocksize())
|
||||
{
|
||||
indexes = params[4];
|
||||
}
|
||||
}
|
||||
|
||||
cell *addr = get_amxaddr(amx, params[3]);
|
||||
|
||||
memcpy(addr, blk, sizeof(cell) * indexes);
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
// native any:ArrayGetCell(Array:which, item, block = 0, bool:asChar = false);
|
||||
static cell AMX_NATIVE_CALL ArrayGetCell(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
|
||||
if (*params / sizeof(cell) <= 2)
|
||||
{
|
||||
return *blk;
|
||||
}
|
||||
|
||||
idx = (size_t)params[3];
|
||||
|
||||
if (!params[4])
|
||||
{
|
||||
if (idx >= vec->blocksize())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return blk[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idx >= vec->blocksize() * 4)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (cell)*((char *)blk + idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// native ArrayGetString(Array:which, item, output[], size);
|
||||
static cell AMX_NATIVE_CALL ArrayGetString(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
return set_amxstring_utf8(amx, params[3], blk, amxstring_len(blk), params[4]);
|
||||
}
|
||||
|
||||
// native ArraySetArray(Array:which, item, const any:input[], size =-1);
|
||||
static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
size_t indexes = vec->blocksize();
|
||||
|
||||
if (*params / sizeof(cell) == 4)
|
||||
{
|
||||
if (params[4] != -1 && (size_t)params[4] <= vec->blocksize())
|
||||
{
|
||||
indexes = params[4];
|
||||
}
|
||||
}
|
||||
|
||||
cell *addr = get_amxaddr(amx, params[3]);
|
||||
|
||||
memcpy(blk, addr, sizeof(cell) * indexes);
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
// native ArraySetCell(Array:which, item, any:input, block = 0, bool:asChar = false);
|
||||
static cell AMX_NATIVE_CALL ArraySetCell(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
idx = (size_t)params[4];
|
||||
|
||||
if (*params / sizeof(cell) <= 3)
|
||||
{
|
||||
*blk = params[3];
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (params[5] == 0)
|
||||
{
|
||||
if (idx >= vec->blocksize())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize());
|
||||
return 0;
|
||||
}
|
||||
blk[idx] = params[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idx >= vec->blocksize() * 4)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4);
|
||||
return 0;
|
||||
}
|
||||
*((char *)blk + idx) = (char)params[3];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArraySetString(Array:which, item, const input[]);
|
||||
static cell AMX_NATIVE_CALL ArraySetString(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->at(idx);
|
||||
|
||||
int len;
|
||||
char *str = get_amxstring(amx, params[3], 0, len);
|
||||
|
||||
return strncopy(blk, str, ke::Min((size_t)len + 1, vec->blocksize()));
|
||||
}
|
||||
|
||||
// native ArrayPushArray(Array:which, const any:input[], size = -1);
|
||||
static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->push();
|
||||
|
||||
if (!blk)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *addr = get_amxaddr(amx, params[2]);
|
||||
size_t indexes = vec->blocksize();
|
||||
|
||||
if (*params / sizeof(cell) == 3)
|
||||
{
|
||||
if (params[3] != -1 && (size_t)params[3] <= vec->blocksize())
|
||||
{
|
||||
indexes = params[3];
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(blk, addr, sizeof(cell) * indexes);
|
||||
|
||||
return static_cast<cell>((vec->size() - 1));
|
||||
}
|
||||
|
||||
// native ArrayPushCell(Array:which, any:input);
|
||||
static cell AMX_NATIVE_CALL ArrayPushCell(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->push();
|
||||
|
||||
if (!blk)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*blk = params[2];
|
||||
|
||||
return static_cast<cell>((vec->size() - 1));
|
||||
}
|
||||
|
||||
// native ArrayPushString(Array:which, const input[]);
|
||||
static cell AMX_NATIVE_CALL ArrayPushString(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *blk = vec->push();
|
||||
if (!blk)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncopy(blk, get_amxaddr(amx, params[2]), vec->blocksize());
|
||||
|
||||
return static_cast<cell>((vec->size() - 1));
|
||||
}
|
||||
|
||||
// native DoNotUse : ArrayGetStringHandle(Array : which, item);
|
||||
static cell AMX_NATIVE_CALL ArrayGetStringHandle(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell* ptr = vec->at(idx);
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(ptr);
|
||||
}
|
||||
|
||||
// native ArrayInsertArrayAfter(Array:which, item, const any:input[]);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertArrayAfter(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2] + 1;
|
||||
|
||||
if (idx > vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayAfter (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *addr = get_amxaddr(amx, params[3]);
|
||||
|
||||
memcpy(vec->insert_at(idx), addr, sizeof(cell) * vec->blocksize());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArrayInsertCellAfter(Array:which, item, any:input);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertCellAfter(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2] + 1;
|
||||
|
||||
if (idx > vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellAfter (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
*vec->insert_at(idx) = params[3];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArrayInsertStringAfter(Array:which, item, const input[]);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertStringAfter(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2] + 1;
|
||||
|
||||
if (idx > vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringAfter (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
const char *str = get_amxstring(amx, params[3], 0, len);
|
||||
|
||||
return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize()));
|
||||
}
|
||||
|
||||
// native ArrayInsertArrayBefore(Array:which, item, const any:input[]);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertArrayBefore(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
cell *addr = get_amxaddr(amx, params[3]);
|
||||
|
||||
memcpy(vec->insert_at(idx), addr, vec->blocksize() * sizeof(cell));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArrayInsertCellBefore(Array:which, item, const any:input);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertCellBefore(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
*vec->insert_at(idx) = params[3];
|
||||
|
||||
return 1;
|
||||
}
|
||||
// native ArrayInsertStringBefore(Array:which, item, const input[]);
|
||||
static cell AMX_NATIVE_CALL ArrayInsertStringBefore(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
const char *str = get_amxstring(amx, params[3], 0, len);
|
||||
|
||||
return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize()));
|
||||
}
|
||||
|
||||
// native ArraySwap(Array:which, item1, item2);
|
||||
static cell AMX_NATIVE_CALL ArraySwap(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx1 = (size_t)params[2];
|
||||
size_t idx2 = (size_t)params[3];
|
||||
|
||||
if (idx1 >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx1, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (idx2 >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx2, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
vec->swap(idx1, idx2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArrayDeleteItem(Array:which, item);
|
||||
static cell AMX_NATIVE_CALL ArrayDeleteItem(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t idx = (size_t)params[2];
|
||||
|
||||
if (idx >= vec->size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
vec->remove(idx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native ArrayDestroy(&Array:which);
|
||||
static cell AMX_NATIVE_CALL ArrayDestroy(AMX* amx, cell* params)
|
||||
{
|
||||
cell *handle = get_amxaddr(amx, params[1]);
|
||||
|
||||
CellArray* vec = ArrayHandles.lookup(*handle);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ArrayHandles.destroy(*handle))
|
||||
{
|
||||
*handle = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct ArraySort_s
|
||||
{
|
||||
int func;
|
||||
cell array_hndl;
|
||||
cell* array_base;
|
||||
cell array_bsize;
|
||||
cell data;
|
||||
cell size;
|
||||
cell addr1;
|
||||
cell addr2;
|
||||
AMX *amx;
|
||||
};
|
||||
|
||||
ArraySort_s SortInfo;
|
||||
|
||||
int SortArrayList(const void *elem1, const void *elem2)
|
||||
{
|
||||
return executeForwards(
|
||||
SortInfo.func,
|
||||
SortInfo.array_hndl,
|
||||
((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize,
|
||||
((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize,
|
||||
SortInfo.data,
|
||||
SortInfo.size
|
||||
);
|
||||
}
|
||||
|
||||
// native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0);
|
||||
static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params)
|
||||
{
|
||||
cell handle = params[1];
|
||||
CellArray* vec = ArrayHandles.lookup(handle);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
char* funcName = get_amxstring(amx, params[2], 0, len);
|
||||
|
||||
// MySortFunc(Array:array, item1, item2, const data[], data_size)
|
||||
int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||
if (func < 0)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t arraysize = vec->size();
|
||||
size_t blocksize = vec->blocksize();
|
||||
cell *array = vec->base();
|
||||
|
||||
ArraySort_s oldinfo = SortInfo;
|
||||
|
||||
SortInfo.func = func;
|
||||
SortInfo.array_base = array;
|
||||
SortInfo.array_bsize = static_cast<cell>(blocksize);
|
||||
SortInfo.array_hndl = handle;
|
||||
SortInfo.data = params[3];
|
||||
SortInfo.size = params[4];
|
||||
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), SortArrayList);
|
||||
|
||||
SortInfo = oldinfo;
|
||||
|
||||
unregisterSPForward(func);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int SortArrayListExCell(const void *elem1, const void *elem2)
|
||||
{
|
||||
size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
|
||||
size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;
|
||||
|
||||
return executeForwards(
|
||||
SortInfo.func,
|
||||
SortInfo.array_hndl,
|
||||
*&SortInfo.array_base[index1 * SortInfo.array_bsize],
|
||||
*&SortInfo.array_base[index2 * SortInfo.array_bsize],
|
||||
SortInfo.data,
|
||||
SortInfo.size
|
||||
);
|
||||
}
|
||||
|
||||
int SortArrayListExArray(const void *elem1, const void *elem2)
|
||||
{
|
||||
size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
|
||||
size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;
|
||||
|
||||
cell *addr1 = get_amxaddr(SortInfo.amx, SortInfo.addr1);
|
||||
cell *addr2 = get_amxaddr(SortInfo.amx, SortInfo.addr2);
|
||||
|
||||
memcpy(addr1, &SortInfo.array_base[index1 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));
|
||||
memcpy(addr2, &SortInfo.array_base[index2 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));
|
||||
|
||||
return executeForwards(
|
||||
SortInfo.func,
|
||||
SortInfo.array_hndl,
|
||||
SortInfo.addr1,
|
||||
SortInfo.addr2,
|
||||
SortInfo.data,
|
||||
SortInfo.size
|
||||
);
|
||||
}
|
||||
|
||||
// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0);
|
||||
static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len;
|
||||
char* funcName = get_amxstring(amx, params[2], 0, len);
|
||||
|
||||
int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||
|
||||
if (!func)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t arraysize = vec->size();
|
||||
size_t blocksize = vec->blocksize();
|
||||
cell *array = vec->base();
|
||||
cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL;
|
||||
|
||||
if (blocksize > 1)
|
||||
{
|
||||
int err;
|
||||
if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE
|
||||
|| ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE)
|
||||
{
|
||||
LogError(amx, err, "Ran out of memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ArraySort_s oldinfo = SortInfo;
|
||||
|
||||
SortInfo.func = func;
|
||||
SortInfo.array_base = array;
|
||||
SortInfo.array_bsize = static_cast<cell>(blocksize);
|
||||
SortInfo.array_hndl = params[1];
|
||||
SortInfo.data = params[3];
|
||||
SortInfo.size = params[4];
|
||||
SortInfo.amx = amx;
|
||||
SortInfo.addr1 = amx_addr1;
|
||||
SortInfo.addr2 = amx_addr2;
|
||||
|
||||
qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell);
|
||||
|
||||
SortInfo = oldinfo;
|
||||
|
||||
if (blocksize > 1)
|
||||
{
|
||||
amx_Release(amx, amx_addr1);
|
||||
amx_Release(amx, amx_addr2);
|
||||
}
|
||||
|
||||
unregisterSPForward(func);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern bool fastcellcmp(cell *a, cell *b, cell len);
|
||||
extern int amxstring_len(cell* a);
|
||||
|
||||
// native ArrayFindString(Array:which, const item[]);
|
||||
static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cell *b, *a = get_amxaddr(amx, params[2]);
|
||||
size_t cellcount = vec->blocksize();
|
||||
size_t a_len = ke::Max(1, amxstring_len(a));
|
||||
size_t len = a_len > cellcount ? cellcount : a_len;
|
||||
|
||||
for (size_t i = 0; i < vec->size(); i++)
|
||||
{
|
||||
b = vec->at(i);
|
||||
|
||||
if (fastcellcmp(a, b, len))
|
||||
{
|
||||
return static_cast<cell>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// native ArrayFindValue(Array:which, any:item);
|
||||
static cell AMX_NATIVE_CALL ArrayFindValue(AMX* amx, cell* params)
|
||||
{
|
||||
CellArray* vec = ArrayHandles.lookup(params[1]);
|
||||
|
||||
if (!vec)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < vec->size(); i++)
|
||||
{
|
||||
if (params[2] == *vec->at(i))
|
||||
{
|
||||
return static_cast<cell>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO g_DataStructNatives[] =
|
||||
{
|
||||
{ "ArrayCreate" , ArrayCreate },
|
||||
{ "ArrayClear" , ArrayClear },
|
||||
{ "ArrayClone" , ArrayClone },
|
||||
{ "ArraySize" , ArraySize },
|
||||
{ "ArrayResize" , ArrayResize },
|
||||
{ "ArrayGetArray" , ArrayGetArray },
|
||||
{ "ArrayGetCell" , ArrayGetCell },
|
||||
{ "ArrayGetString" , ArrayGetString },
|
||||
{ "ArraySetArray" , ArraySetArray },
|
||||
{ "ArraySetCell" , ArraySetCell },
|
||||
{ "ArraySetString" , ArraySetString },
|
||||
{ "ArrayPushArray" , ArrayPushArray },
|
||||
{ "ArrayPushCell" , ArrayPushCell },
|
||||
{ "ArrayPushString" , ArrayPushString },
|
||||
{ "ArrayInsertArrayAfter" , ArrayInsertArrayAfter },
|
||||
{ "ArrayInsertCellAfter" , ArrayInsertCellAfter },
|
||||
{ "ArrayInsertStringAfter" , ArrayInsertStringAfter },
|
||||
{ "ArrayInsertArrayBefore" , ArrayInsertArrayBefore },
|
||||
{ "ArrayInsertCellBefore" , ArrayInsertCellBefore },
|
||||
{ "ArrayInsertStringBefore", ArrayInsertStringBefore },
|
||||
{ "ArraySwap" , ArraySwap },
|
||||
{ "ArrayDeleteItem" , ArrayDeleteItem },
|
||||
{ "ArrayGetStringHandle" , ArrayGetStringHandle },
|
||||
{ "ArrayDestroy" , ArrayDestroy },
|
||||
{ "ArraySort" , ArraySort },
|
||||
{ "ArraySortEx" , ArraySortEx },
|
||||
{ "ArrayFindString" , ArrayFindString },
|
||||
{ "ArrayFindValue" , ArrayFindValue },
|
||||
{ nullptr , nullptr }
|
||||
};
|
197
amxmodx/datastructs.h
Normal file
197
amxmodx/datastructs.h
Normal file
@ -0,0 +1,197 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef DATASTRUCTS_H
|
||||
#define DATASTRUCTS_H
|
||||
|
||||
#include "natives_handles.h"
|
||||
|
||||
class CellArray
|
||||
{
|
||||
public:
|
||||
CellArray(size_t blocksize, size_t basesize = 0) : m_Data(nullptr), m_BlockSize(blocksize), m_AllocSize(0), m_BaseSize(basesize > 0 ? basesize : 8), m_Size(0)
|
||||
{
|
||||
}
|
||||
|
||||
~CellArray()
|
||||
{
|
||||
free(m_Data);
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
cell *push()
|
||||
{
|
||||
if (!GrowIfNeeded(1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
cell *arr = &m_Data[m_Size * m_BlockSize];
|
||||
m_Size++;
|
||||
return arr;
|
||||
}
|
||||
|
||||
cell *at(size_t b) const
|
||||
{
|
||||
return &m_Data[b * m_BlockSize];
|
||||
}
|
||||
|
||||
size_t blocksize() const
|
||||
{
|
||||
return m_BlockSize;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
bool swap(size_t item1, size_t item2)
|
||||
{
|
||||
/* Make sure there is extra space available */
|
||||
if (!GrowIfNeeded(1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cell *pri = at(item1);
|
||||
cell *alt = at(item2);
|
||||
|
||||
/* Get our temporary array 1 after the limit */
|
||||
cell *temp = &m_Data[m_Size * m_BlockSize];
|
||||
|
||||
memcpy(temp, pri, sizeof(cell)* m_BlockSize);
|
||||
memcpy(pri, alt, sizeof(cell)* m_BlockSize);
|
||||
memcpy(alt, temp, sizeof(cell)* m_BlockSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void remove(size_t index)
|
||||
{
|
||||
/* If we're at the end, take the easy way out */
|
||||
if (index == m_Size - 1)
|
||||
{
|
||||
m_Size--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, it's time to move stuff! */
|
||||
size_t remaining_indexes = (m_Size - 1) - index;
|
||||
cell *src = at(index + 1);
|
||||
cell *dest = at(index);
|
||||
memmove(dest, src, sizeof(cell)* m_BlockSize * remaining_indexes);
|
||||
|
||||
m_Size--;
|
||||
}
|
||||
|
||||
cell *insert_at(size_t index)
|
||||
{
|
||||
/* Make sure it'll fit */
|
||||
if (!GrowIfNeeded(1))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* move everything up */
|
||||
cell *src = at(index);
|
||||
cell *dst = at(index + 1);
|
||||
memmove(dst, src, sizeof(cell)* m_BlockSize * (m_Size - index));
|
||||
|
||||
m_Size++;
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
bool resize(size_t count)
|
||||
{
|
||||
if (count <= m_Size)
|
||||
{
|
||||
m_Size = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!GrowIfNeeded(count - m_Size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Size = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
CellArray *clone()
|
||||
{
|
||||
CellArray *array = new CellArray(m_BlockSize);
|
||||
array->m_AllocSize = m_AllocSize;
|
||||
array->m_Size = m_Size;
|
||||
array->m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
|
||||
|
||||
if (!array->m_Data)
|
||||
{
|
||||
delete array;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(array->m_Data, m_Data, sizeof(cell)* m_BlockSize * m_Size);
|
||||
return array;
|
||||
}
|
||||
|
||||
cell *base()
|
||||
{
|
||||
return m_Data;
|
||||
}
|
||||
|
||||
size_t mem_usage()
|
||||
{
|
||||
return m_AllocSize * m_BlockSize * sizeof(cell);
|
||||
}
|
||||
|
||||
private:
|
||||
bool GrowIfNeeded(size_t count)
|
||||
{
|
||||
/* Shortcut out if we can store this */
|
||||
if (m_Size + count <= m_AllocSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/* Set a base allocation size of 8 items */
|
||||
if (!m_AllocSize)
|
||||
{
|
||||
m_AllocSize = m_BaseSize;
|
||||
}
|
||||
/* If it's not enough, keep doubling */
|
||||
while (m_Size + count > m_AllocSize)
|
||||
{
|
||||
m_AllocSize *= 2;
|
||||
}
|
||||
/* finally, allocate the new block */
|
||||
if (m_Data)
|
||||
{
|
||||
m_Data = (cell *)realloc(m_Data, sizeof(cell)* m_BlockSize * m_AllocSize);
|
||||
}
|
||||
else {
|
||||
m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
|
||||
}
|
||||
return (m_Data != NULL);
|
||||
}
|
||||
private:
|
||||
cell *m_Data;
|
||||
size_t m_BlockSize;
|
||||
size_t m_AllocSize;
|
||||
size_t m_BaseSize;
|
||||
size_t m_Size;
|
||||
};
|
||||
|
||||
extern NativeHandle<CellArray> ArrayHandles;
|
||||
|
||||
#endif
|
@ -1,42 +1,16 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "debugger.h"
|
||||
#include "binlog.h"
|
||||
|
||||
#if !defined WIN32 && !defined _WIN32
|
||||
#define _snprintf snprintf
|
||||
#endif
|
||||
|
||||
/**
|
||||
* AMX Mod X Debugging Engine
|
||||
* Written by David "BAILOPAN" Anderson
|
||||
@ -285,11 +259,11 @@ void Debugger::BeginExec()
|
||||
m_Top++;
|
||||
assert(m_Top >= 0);
|
||||
|
||||
if (m_Top >= (int)m_pCalls.size())
|
||||
if (m_Top >= (int)m_pCalls.length())
|
||||
{
|
||||
Tracer *pTracer = new Tracer();
|
||||
m_pCalls.push_back(pTracer);
|
||||
assert(m_Top == (m_pCalls.size() - 1));
|
||||
m_pCalls.append(pTracer);
|
||||
assert(m_Top == static_cast<int>(m_pCalls.length() - 1));
|
||||
}
|
||||
|
||||
m_pCalls[m_Top]->Reset();
|
||||
@ -297,7 +271,7 @@ void Debugger::BeginExec()
|
||||
|
||||
void Debugger::EndExec()
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
m_pCalls[m_Top]->Reset();
|
||||
|
||||
@ -306,7 +280,7 @@ void Debugger::EndExec()
|
||||
|
||||
void Debugger::StepI()
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
#if defined BINLOG_ENABLED
|
||||
if (g_binlog_level & 32)
|
||||
@ -332,21 +306,21 @@ void Debugger::Reset()
|
||||
|
||||
int Debugger::GetTracedError()
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
return m_pCalls[m_Top]->m_Error;
|
||||
}
|
||||
|
||||
void Debugger::SetTracedError(int error)
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
m_pCalls[m_Top]->m_Error = error;
|
||||
}
|
||||
|
||||
trace_info_t *Debugger::GetTraceStart() const
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
return m_pCalls[m_Top]->GetEnd();
|
||||
}
|
||||
@ -372,7 +346,7 @@ trace_info_t *Debugger::GetNextTrace(trace_info_t *pTraceInfo)
|
||||
|
||||
bool Debugger::ErrorExists()
|
||||
{
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
return (m_pCalls[m_Top]->m_Error != AMX_ERR_NONE);
|
||||
}
|
||||
@ -382,7 +356,7 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||
if (!ErrorExists())
|
||||
return -1;
|
||||
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
|
||||
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length());
|
||||
|
||||
Tracer *pTracer = m_pCalls[m_Top];
|
||||
int error = pTracer->m_Error;
|
||||
@ -391,9 +365,9 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||
//trace_info_t *pTrace = pTracer->GetEnd();
|
||||
//cell cip = _CipAsVa(m_pAmx->cip);
|
||||
//cell *p_cip = NULL;
|
||||
int amx_err = AMX_ERR_NONE;
|
||||
//int amx_err = AMX_ERR_NONE;
|
||||
|
||||
size += _snprintf(buffer, maxLength, "Run time error %d: %s ", error, gen_err);
|
||||
size += ke::SafeSprintf(buffer, maxLength, "Run time error %d: %s ", error, gen_err);
|
||||
buffer += size;
|
||||
maxLength -= size;
|
||||
|
||||
@ -410,13 +384,13 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||
}*/
|
||||
//New code only requires this...
|
||||
num = (int)(_INT_PTR)m_pAmx->usertags[UT_NATIVE];
|
||||
amx_err = amx_GetNative(m_pAmx, num, native_name);
|
||||
/*amx_err = */amx_GetNative(m_pAmx, num, native_name);
|
||||
/*if (num)
|
||||
amx_err = amx_GetNative(m_pAmx, (int)*p_cip, native_name);
|
||||
else
|
||||
amx_err = AMX_ERR_NOTFOUND;*/
|
||||
//if (!amx_err)
|
||||
size += _snprintf(buffer, maxLength, "(native \"%s\")", native_name);
|
||||
size += ke::SafeSprintf(buffer, maxLength, "(native \"%s\")", native_name);
|
||||
}
|
||||
|
||||
return size;
|
||||
@ -547,8 +521,10 @@ int AMXAPI Debugger::DebugHook(AMX *amx)
|
||||
|
||||
void Debugger::Clear()
|
||||
{
|
||||
for (size_t i=0; i<m_pCalls.size(); i++)
|
||||
delete m_pCalls[i];
|
||||
for (size_t i = 0; i < m_pCalls.length(); i++)
|
||||
{
|
||||
delete m_pCalls[i];
|
||||
}
|
||||
|
||||
m_pCalls.clear();
|
||||
}
|
||||
@ -559,13 +535,18 @@ void Debugger::DisplayTrace(const char *message)
|
||||
AMXXLOG_Error("%s", message);
|
||||
|
||||
char buffer[512];
|
||||
FormatError(buffer, sizeof(buffer)-1);
|
||||
int length = FormatError(buffer, sizeof(buffer)-1);
|
||||
|
||||
const char *filename = _GetFilename();
|
||||
const char *version = _GetVersion();
|
||||
|
||||
AMXXLOG_Error("[AMXX] Displaying debug trace (plugin \"%s\")", filename);
|
||||
AMXXLOG_Error("[AMXX] %s", buffer);
|
||||
AMXXLOG_Error("[AMXX] Displaying debug trace (plugin \"%s\", version \"%s\")", filename, version);
|
||||
|
||||
if (length != -1) // Don't show blank line if AMX_ERR_NONE is set since there is no error message.
|
||||
{
|
||||
AMXXLOG_Error("[AMXX] %s", buffer);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
long lLine;
|
||||
const char *file, *function;
|
||||
@ -587,51 +568,76 @@ void Debugger::DisplayTrace(const char *message)
|
||||
|
||||
const char *Debugger::_GetFilename()
|
||||
{
|
||||
if (m_FileName.size() < 1)
|
||||
{
|
||||
const char *filename = "";
|
||||
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
|
||||
if (pl)
|
||||
{
|
||||
filename = pl->getName();
|
||||
} else {
|
||||
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(m_pAmx);
|
||||
if (a)
|
||||
filename = (*a).getName();
|
||||
}
|
||||
m_FileName.assign(filename);
|
||||
}
|
||||
if (m_FileName.length() < 1)
|
||||
{
|
||||
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
|
||||
if (pl)
|
||||
{
|
||||
m_FileName = pl->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto script : g_loadedscripts)
|
||||
{
|
||||
if (script->getAMX() == m_pAmx)
|
||||
{
|
||||
m_FileName = script->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_FileName.chars();
|
||||
}
|
||||
|
||||
return m_FileName.c_str();
|
||||
const char *Debugger::_GetVersion()
|
||||
{
|
||||
if (m_Version.length() < 1)
|
||||
{
|
||||
const char *version = "";
|
||||
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
|
||||
if (pl)
|
||||
{
|
||||
version = pl->getVersion();
|
||||
}
|
||||
|
||||
m_Version = version;
|
||||
}
|
||||
|
||||
return m_Version.chars();
|
||||
}
|
||||
|
||||
void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength)
|
||||
{
|
||||
const char *filename = "";
|
||||
char native[sNAMEMAX+1];
|
||||
const char *filename = "";
|
||||
char native[sNAMEMAX+1];
|
||||
for (auto script : g_loadedscripts)
|
||||
{
|
||||
if (script->getAMX() == amx)
|
||||
{
|
||||
filename = script->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t len = strlen(filename);
|
||||
for (size_t i=len-1; i<len; i--)
|
||||
{
|
||||
if ((filename[i] == '/' || filename[i] == '\\') && i != len - 1)
|
||||
{
|
||||
filename = &(filename[i+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
|
||||
if (a)
|
||||
filename = (*a).getName();
|
||||
size_t len = strlen(filename);
|
||||
for (size_t i=len-1; i>=0; i--)
|
||||
{
|
||||
if (filename[i] == '/' || filename[i] == '\\' && i != len - 1)
|
||||
{
|
||||
filename = &(filename[i+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == AMX_ERR_EXIT)
|
||||
{
|
||||
_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT));
|
||||
} else if (error == AMX_ERR_NATIVE) {
|
||||
amx_GetNative(amx, reinterpret_cast<long>(amx->usertags[UT_NATIVE]), native);
|
||||
_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native);
|
||||
} else {
|
||||
_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename);
|
||||
}
|
||||
if (error == AMX_ERR_EXIT)
|
||||
{
|
||||
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT));
|
||||
} else if (error == AMX_ERR_NATIVE) {
|
||||
amx_GetNative(amx, reinterpret_cast<long>(amx->usertags[UT_NATIVE]), native);
|
||||
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native);
|
||||
} else {
|
||||
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::GenericMessage(AMX *amx, int err)
|
||||
@ -691,17 +697,17 @@ int Handler::SetNativeFilter(const char *function)
|
||||
void Handler::SetErrorMsg(const char *msg)
|
||||
{
|
||||
if (!msg)
|
||||
m_MsgCache.clear();
|
||||
m_MsgCache = nullptr;
|
||||
else
|
||||
m_MsgCache.assign(msg);
|
||||
m_MsgCache = msg;
|
||||
}
|
||||
|
||||
const char *Handler::GetLastMsg()
|
||||
{
|
||||
if (m_MsgCache.size() < 1)
|
||||
if (m_MsgCache.length() < 1)
|
||||
return NULL;
|
||||
|
||||
return m_MsgCache.c_str();
|
||||
return m_MsgCache.chars();
|
||||
}
|
||||
|
||||
int Handler::HandleModule(const char *module, bool isClass)
|
||||
@ -722,7 +728,7 @@ int Handler::HandleModule(const char *module, bool isClass)
|
||||
m_pAmx->flags |= AMX_FLAG_PRENIT;
|
||||
amx_Push(m_pAmx, isClass ? 1 : 0);
|
||||
amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0);
|
||||
int err = amx_Exec(m_pAmx, &retval, m_iModFunc);
|
||||
int err = amx_ExecPerf(m_pAmx, &retval, m_iModFunc);
|
||||
amx_Release(m_pAmx, hea_addr);
|
||||
m_pAmx->flags &= ~AMX_FLAG_PRENIT;
|
||||
|
||||
@ -762,7 +768,7 @@ int Handler::HandleNative(const char *native, int index, int trap)
|
||||
amx_Push(m_pAmx, trap);
|
||||
amx_Push(m_pAmx, index);
|
||||
amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0);
|
||||
int err = amx_Exec(m_pAmx, &retval, m_iNatFunc);
|
||||
int err = amx_ExecPerf(m_pAmx, &retval, m_iNatFunc);
|
||||
if (err != AMX_ERR_NONE)
|
||||
{
|
||||
//LogError() took care of something for us.
|
||||
@ -808,8 +814,8 @@ int Handler::HandleError(const char *msg)
|
||||
return 0;
|
||||
|
||||
m_Handling = true;
|
||||
m_pTrace = NULL;
|
||||
m_FmtCache.clear();
|
||||
m_pTrace = nullptr;
|
||||
m_FmtCache = nullptr;
|
||||
|
||||
Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER];
|
||||
|
||||
@ -821,11 +827,11 @@ int Handler::HandleError(const char *msg)
|
||||
pDebugger->SetTracedError(error);
|
||||
m_pTrace = pDebugger->GetTraceStart();
|
||||
pDebugger->FormatError(_buffer, sizeof(_buffer)-1);
|
||||
m_FmtCache.assign(_buffer);
|
||||
m_FmtCache = _buffer;
|
||||
pDebugger->BeginExec();
|
||||
} else {
|
||||
Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1);
|
||||
m_FmtCache.assign(_buffer);
|
||||
m_FmtCache = _buffer;
|
||||
}
|
||||
|
||||
SetErrorMsg(msg);
|
||||
@ -835,7 +841,7 @@ int Handler::HandleError(const char *msg)
|
||||
amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0);
|
||||
amx_Push(m_pAmx, pDebugger ? 1 : 0);
|
||||
amx_Push(m_pAmx, error);
|
||||
int err = amx_Exec(m_pAmx, &result, m_iErrFunc);
|
||||
int err = amx_ExecPerf(m_pAmx, &result, m_iErrFunc);
|
||||
if (err != AMX_ERR_NONE)
|
||||
{
|
||||
//handle this manually.
|
||||
@ -857,8 +863,8 @@ int Handler::HandleError(const char *msg)
|
||||
amx_Release(m_pAmx, hea_addr);
|
||||
|
||||
m_Handling = false;
|
||||
m_pTrace = NULL;
|
||||
m_FmtCache.clear();
|
||||
m_pTrace = nullptr;
|
||||
m_FmtCache = nullptr;
|
||||
|
||||
if (err != AMX_ERR_NONE || !result)
|
||||
return 0;
|
||||
|
@ -1,38 +1,15 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_DEBUGGER_H_
|
||||
#define _INCLUDE_DEBUGGER_H_
|
||||
|
||||
#include "CVector.h"
|
||||
#include "amxdbg.h"
|
||||
|
||||
/**
|
||||
@ -138,15 +115,17 @@ private:
|
||||
cell _CipAsVa(cell cip);
|
||||
|
||||
const char *_GetFilename();
|
||||
const char *_GetVersion();
|
||||
public:
|
||||
AMX *m_pAmx;
|
||||
AMX_DBG *m_pAmxDbg;
|
||||
|
||||
int m_Top;
|
||||
cell *m_pOpcodeList;
|
||||
String m_FileName;
|
||||
|
||||
CVector<Tracer *> m_pCalls;
|
||||
ke::AString m_FileName;
|
||||
ke::AString m_Version;
|
||||
|
||||
ke::Vector<Tracer *> m_pCalls;
|
||||
};
|
||||
|
||||
typedef Debugger::Tracer::trace_info trace_info_t;
|
||||
@ -174,9 +153,9 @@ public:
|
||||
|
||||
const char *GetLastMsg();
|
||||
trace_info_t *GetTrace() const { return m_pTrace; }
|
||||
const char *GetFmtCache() { return m_FmtCache.c_str(); }
|
||||
const char *GetFmtCache() { return m_FmtCache.chars(); }
|
||||
|
||||
bool IsNativeFiltering() { return (m_iNatFunc > 0); }
|
||||
bool IsNativeFiltering() { return (m_iNatFunc > -1); }
|
||||
bool InNativeFilter() { return m_InNativeFilter; }
|
||||
private:
|
||||
AMX *m_pAmx;
|
||||
@ -190,8 +169,8 @@ private:
|
||||
//in the future, make this a stack!
|
||||
bool m_InNativeFilter;
|
||||
|
||||
String m_MsgCache;
|
||||
String m_FmtCache;
|
||||
ke::AString m_MsgCache;
|
||||
ke::AString m_FmtCache;
|
||||
|
||||
trace_info_t *m_pTrace;
|
||||
};
|
||||
|
120
amxmodx/emsg.cpp
120
amxmodx/emsg.cpp
@ -1,35 +1,14 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CMenu.h"
|
||||
|
||||
int gmsgAmmoPickup;
|
||||
int gmsgAmmoX;
|
||||
@ -51,6 +30,8 @@ int gmsgWeaponList;
|
||||
int gmsgintermission;
|
||||
int gmsgResetHUD;
|
||||
int gmsgRoundTime;
|
||||
int gmsgSayText;
|
||||
int gmsgInitHUD;
|
||||
|
||||
TeamIds g_teamsIds;
|
||||
WeaponsVault g_weaponsData[MAX_WEAPONS];
|
||||
@ -106,8 +87,47 @@ void Client_TeamInfo(void* mValue)
|
||||
case 1:
|
||||
if (index < 1 || index > gpGlobals->maxClients) break;
|
||||
char* msg = (char*)mValue;
|
||||
g_players[index].team.assign(msg);
|
||||
if (!msg) break;
|
||||
|
||||
auto pPlayer = GET_PLAYER_POINTER_I(index);
|
||||
|
||||
pPlayer->team = msg;
|
||||
g_teamsIds.registerTeam(msg, -1);
|
||||
pPlayer->teamId = g_teamsIds.findTeamId(msg);
|
||||
|
||||
if (pPlayer->teamId == -1)
|
||||
{
|
||||
/**
|
||||
* CS fix for SPECTATOR team.
|
||||
* -
|
||||
* When a player chooses spectator, ScoreInfo is sent before TeamInfo and with 0 as index.
|
||||
* This means for the first round of first spectator, SPECTATOR name is not associated with its index.
|
||||
* The following fix manually sets the team index when we hit SPECTATOR team.
|
||||
*/
|
||||
if (g_bmod_cstrike && !strcmp(msg, "SPECTATOR"))
|
||||
{
|
||||
pPlayer->teamId = 3;
|
||||
g_teamsIds.registerTeam(msg, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes in-between situation where the team name is not yet associated with a valid index
|
||||
* and ScoreInfo is executed later (used to retrieve the index). E.g. a player is dead,
|
||||
* then changes team. Index will return -1 until ScoreInfo is sent, usually at the next spawn.
|
||||
*/
|
||||
else if ((g_bmod_cstrike || g_bmod_dod || g_bmod_tfc || g_bmod_gearbox || g_bmod_valve)
|
||||
&& pPlayer->pEdict->pvPrivateData
|
||||
&& !pPlayer->IsAlive())
|
||||
{
|
||||
GET_OFFSET_NO_ERROR("CBasePlayer", m_iTeam);
|
||||
|
||||
const auto teamId = get_pdata<int>(pPlayer->pEdict, m_iTeam);
|
||||
|
||||
pPlayer->teamId = teamId;
|
||||
g_teamsIds.registerTeam(msg, teamId);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -190,7 +210,7 @@ void Client_WeaponList(void* mValue)
|
||||
wpnList |= (1<<iId);
|
||||
g_weaponsData[iId].iId = iId;
|
||||
g_weaponsData[iId].ammoSlot = iSlot;
|
||||
g_weaponsData[iId].fullName.assign(wpnName);
|
||||
g_weaponsData[iId].fullName = wpnName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,9 +231,15 @@ void Client_CurWeapon(void* mValue)
|
||||
case 2:
|
||||
if (!mPlayer) return;
|
||||
if (!iState || (iId < 1 || iId >= MAX_WEAPONS)) break;
|
||||
mPlayer->weapons[iId].clip = *(int*)mValue;
|
||||
mPlayer->current = iId;
|
||||
mPlayer->lastHit = mPlayer->lastTrace;
|
||||
|
||||
|
||||
if (*(int*)mValue < mPlayer->weapons[iId].clip && // Only update the lastHit vector if the clip size is decreasing
|
||||
*(int*)mValue != -1) // But not if it's a melee weapon
|
||||
{
|
||||
mPlayer->lastHit = mPlayer->lastTrace;
|
||||
}
|
||||
mPlayer->weapons[iId].clip = *(int*)mValue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +296,7 @@ void Client_ScoreInfo(void* mValue)
|
||||
pPlayer->deaths = deaths;
|
||||
pPlayer->teamId = *(int*)mValue;
|
||||
if (g_teamsIds.isNewTeam())
|
||||
g_teamsIds.registerTeam(pPlayer->team.c_str(), pPlayer->teamId);
|
||||
g_teamsIds.registerTeam(pPlayer->team.chars(), pPlayer->teamId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +310,7 @@ void Client_DamageEnd(void* mValue)
|
||||
g_events.parseValue(dead->death_killer);
|
||||
g_events.parseValue(dead->index);
|
||||
g_events.parseValue(dead->death_headshot);
|
||||
g_events.parseValue(dead->death_weapon.c_str());
|
||||
g_events.parseValue(dead->death_weapon.chars());
|
||||
g_events.parseValue(dead->death_tk ? 1 : 0);
|
||||
g_events.executeEvents();
|
||||
dead->death_killer = 0;
|
||||
@ -315,11 +341,31 @@ void Client_DeathMsg(void* mValue)
|
||||
case 3:
|
||||
if (!killer || !victim) break;
|
||||
victim->death_killer = killer_id;
|
||||
victim->death_weapon.assign((char*)mValue);
|
||||
victim->death_weapon = (char*)mValue;
|
||||
victim->death_headshot = hs;
|
||||
victim->death_tk = (killer->teamId == victim->teamId);
|
||||
}
|
||||
}
|
||||
|
||||
void Client_InitHUDEnd(void* mValue)
|
||||
{
|
||||
if (!g_bmod_cstrike)
|
||||
return;
|
||||
|
||||
CPlayer *pPlayer = mPlayer;
|
||||
|
||||
if (!pPlayer->teamIdsInitialized && !pPlayer->IsBot())
|
||||
{
|
||||
// This creates specific indexes (> maxplayers) for print_chat_color().
|
||||
// 33 : print_team_grey / spectator
|
||||
// 34 : print_team_red / terrorist
|
||||
// 35 : print_team_blue / ct
|
||||
UTIL_TeamInfo(pPlayer->pEdict, 33 + 1, "TERRORIST"); // print_team_red
|
||||
UTIL_TeamInfo(pPlayer->pEdict, 33 + 2, "CT"); // print_team_blue
|
||||
pPlayer->teamIdsInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Client_SendAudio(void* mValue)
|
||||
{
|
||||
|
@ -1,32 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "fakemeta.h"
|
||||
|
@ -1,32 +1,11 @@
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef __FAKEMETA_H__
|
||||
#define __FAKEMETA_H__
|
||||
|
1628
amxmodx/file.cpp
1628
amxmodx/file.cpp
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@
|
||||
#include <stdlib.h> /* for atof() */
|
||||
#include <stdio.h> /* for NULL */
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
// this file does not include amxmodx.h, so we have to include the memory manager here
|
||||
#ifdef MEMORY_TEST
|
||||
|
@ -1,6 +1,15 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "format.h"
|
||||
#include "amxmod_compat.h"
|
||||
#include "datastructs.h"
|
||||
|
||||
//Adapted from Quake3's vsprintf
|
||||
// thanks to cybermind for linking me to this :)
|
||||
@ -18,6 +27,7 @@
|
||||
#define SHORTINT 0x00000040 /* short integer */
|
||||
#define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
|
||||
#define FPT 0x00000100 /* floating point number */
|
||||
#define UPPERDIGITS 0x00000200 /* make alpha digits uppercase */
|
||||
#define to_digit(c) ((c) - '0')
|
||||
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
|
||||
#define to_char(n) ((n) + '0')
|
||||
@ -27,97 +37,134 @@
|
||||
return 0; \
|
||||
}
|
||||
|
||||
THash<String, lang_err> BadLang_Table;
|
||||
template size_t atcprintf<cell, cell>(cell *, size_t, const cell *, AMX *, cell *, int *);
|
||||
template size_t atcprintf<char, cell>(char *, size_t, const cell *, AMX *, cell *, int *);
|
||||
template size_t atcprintf<cell, char>(cell *, size_t, const char *, AMX *, cell *, int *);
|
||||
template size_t atcprintf<char, char>(char *, size_t, const char *, AMX *, cell *, int *);
|
||||
|
||||
static cvar_t *amx_mldebug = NULL;
|
||||
static cvar_t *amx_cl_langs = NULL;
|
||||
THash<ke::AString, lang_err> BadLang_Table;
|
||||
|
||||
const char *translate(AMX *amx, cell amxaddr, const char *key)
|
||||
static cvar_t *amx_mldebug = nullptr;
|
||||
static cvar_t *amx_cl_langs = nullptr;
|
||||
|
||||
const char *playerlang(const cell index)
|
||||
{
|
||||
const char *pLangName = NULL;
|
||||
const char *def = NULL;
|
||||
int status;
|
||||
cell *addr = get_amxaddr(amx, amxaddr);
|
||||
char name[4];
|
||||
if (addr[0] == LANG_PLAYER)
|
||||
const char *pLangName = nullptr;
|
||||
|
||||
if (index == LANG_PLAYER)
|
||||
{
|
||||
if (!amx_cl_langs)
|
||||
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
|
||||
if ( (int)amx_cl_langs->value == 0 )
|
||||
{
|
||||
pLangName = g_vault.get("server_language");
|
||||
} else {
|
||||
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
|
||||
}
|
||||
|
||||
if (static_cast<int>(amx_cl_langs->value) == 0)
|
||||
{
|
||||
pLangName = amxmodx_language->string;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(g_langMngr.GetDefLang())->pEdict, "lang");
|
||||
}
|
||||
} else if (addr[0] == LANG_SERVER) {
|
||||
pLangName = g_vault.get("server_language");
|
||||
} else if (addr[0] >= 1 && addr[0] <= gpGlobals->maxClients) {
|
||||
if (!amx_cl_langs)
|
||||
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
|
||||
if ( (int)amx_cl_langs->value == 0 )
|
||||
{
|
||||
pLangName = g_vault.get("server_language");
|
||||
} else {
|
||||
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(addr[0])->pEdict, "lang");
|
||||
}
|
||||
} else {
|
||||
get_amxstring_r(amx, amxaddr, name, 3);
|
||||
pLangName = name;
|
||||
}
|
||||
if (!pLangName || !isalpha(pLangName[0]))
|
||||
pLangName = "en";
|
||||
//next parameter!
|
||||
def = g_langMngr.GetDef(pLangName, key, status);
|
||||
|
||||
if (!amx_mldebug)
|
||||
amx_mldebug = CVAR_GET_POINTER("amx_mldebug");
|
||||
else if (index == LANG_SERVER)
|
||||
{
|
||||
pLangName = amxmodx_language->string;
|
||||
}
|
||||
else if (index >= 1 && index <= gpGlobals->maxClients)
|
||||
{
|
||||
if (!amx_cl_langs)
|
||||
{
|
||||
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
|
||||
}
|
||||
|
||||
if (static_cast<int>(amx_cl_langs->value) == 0)
|
||||
{
|
||||
pLangName = amxmodx_language->string;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(index)->pEdict, "lang");
|
||||
}
|
||||
}
|
||||
|
||||
return pLangName;
|
||||
}
|
||||
|
||||
const char *translate(AMX *amx, const char *lang, const char *key)
|
||||
{
|
||||
auto pLangName = lang;
|
||||
int status;
|
||||
|
||||
if (!pLangName || !isalpha(pLangName[0]))
|
||||
{
|
||||
pLangName = amxmodx_language->string;
|
||||
}
|
||||
|
||||
auto def = g_langMngr.GetDef(pLangName, key, status);
|
||||
|
||||
if (!amx_mldebug)
|
||||
{
|
||||
amx_mldebug = CVAR_GET_POINTER("amx_mldebug");
|
||||
}
|
||||
|
||||
auto debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0'));
|
||||
|
||||
bool debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0'));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
int debug_status;
|
||||
bool validlang = true;
|
||||
const char *testlang = amx_mldebug->string;
|
||||
auto validlang = true;
|
||||
auto testlang = amx_mldebug->string;
|
||||
|
||||
if (!g_langMngr.LangExists(testlang))
|
||||
{
|
||||
AMXXLOG_Error("[AMXX] \"%s\" is an invalid debug language", testlang);
|
||||
validlang = false;
|
||||
}
|
||||
|
||||
|
||||
g_langMngr.GetDef(testlang, key, debug_status);
|
||||
|
||||
|
||||
if (validlang && debug_status == ERR_BADKEY)
|
||||
AMXXLOG_Error("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx));
|
||||
}
|
||||
|
||||
if (def == NULL)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
if (status == ERR_BADLANG && (BadLang_Table.AltFindOrInsert(pLangName).last + 120.0f < gpGlobals->time))
|
||||
AMXXLOG_Error("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx));
|
||||
}
|
||||
}
|
||||
|
||||
if (!def)
|
||||
{
|
||||
if (debug && status == ERR_BADLANG)
|
||||
{
|
||||
ke::AString langName(pLangName);
|
||||
|
||||
auto &err = BadLang_Table.AltFindOrInsert(ke::Move(langName));
|
||||
|
||||
if (err.last + 120.0f < gpGlobals->time)
|
||||
{
|
||||
AMXXLOG_Error("[AMXX] Language \"%s\" not found", pLangName);
|
||||
BadLang_Table.AltFindOrInsert(pLangName).last = gpGlobals->time;
|
||||
err.last = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr[0] != LANG_SERVER)
|
||||
def = g_langMngr.GetDef(g_vault.get("server_language"), key, status);
|
||||
|
||||
if (!def && (strcmp(pLangName, "en") != 0 && strcmp(g_vault.get("server_language"), "en") != 0))
|
||||
if (strcmp(pLangName, amxmodx_language->string) != 0)
|
||||
{
|
||||
def = g_langMngr.GetDef(amxmodx_language->string, key, status);
|
||||
}
|
||||
|
||||
if (!def && (strcmp(pLangName, "en") != 0 && strcmp(amxmodx_language->string, "en") != 0))
|
||||
{
|
||||
def = g_langMngr.GetDef("en", key, status);
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void AddString(U **buf_p, size_t &maxlen, const cell *string, int width, int prec)
|
||||
template <typename U, typename S>
|
||||
void AddString(U **buf_p, size_t &maxlen, const S *string, int width, int prec)
|
||||
{
|
||||
int size = 0;
|
||||
U *buf;
|
||||
static cell nlstr[] = {'(','n','u','l','l',')','\0'};
|
||||
static S nlstr[] = {'(','n','u','l','l',')','\0'};
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
@ -142,6 +189,12 @@ void AddString(U **buf_p, size_t &maxlen, const cell *string, int width, int pre
|
||||
if (size > (int)maxlen)
|
||||
size = maxlen;
|
||||
|
||||
/* If precision is provided, make sure we don't truncate a multi-byte character */
|
||||
if (prec >= size && (string[size - 1] & 1 << 7))
|
||||
{
|
||||
size -= UTIL_CheckValidChar((cell *)string + size - 1);
|
||||
}
|
||||
|
||||
maxlen -= size;
|
||||
width -= size;
|
||||
|
||||
@ -158,71 +211,177 @@ void AddString(U **buf_p, size_t &maxlen, const cell *string, int width, int pre
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec)
|
||||
void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec, int flags)
|
||||
{
|
||||
U text[32];
|
||||
int digits;
|
||||
double signedVal;
|
||||
U *buf;
|
||||
int val;
|
||||
int digits; // non-fraction part digits
|
||||
double tmp; // temporary
|
||||
U *buf = *buf_p; // output buffer pointer
|
||||
int val; // temporary
|
||||
int sign = 0; // 0: positive, 1: negative
|
||||
int fieldlength; // for padding
|
||||
int significant_digits = 0; // number of significant digits written
|
||||
const int MAX_SIGNIFICANT_DIGITS = 16;
|
||||
|
||||
// default precision
|
||||
if (prec < 0)
|
||||
{
|
||||
prec = 6;
|
||||
}
|
||||
|
||||
// get the sign
|
||||
signedVal = fval;
|
||||
if (fval < 0)
|
||||
{
|
||||
fval = -fval;
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
// compute whole-part digits count
|
||||
digits = (int)log10(fval) + 1;
|
||||
|
||||
// Only print 0.something if 0 < fval < 1
|
||||
if (digits < 1)
|
||||
{
|
||||
digits = 1;
|
||||
}
|
||||
|
||||
// compute the field length
|
||||
fieldlength = digits + prec + ((prec > 0) ? 1 : 0) + sign;
|
||||
|
||||
// minus sign BEFORE left padding if padding with zeros
|
||||
if (sign && maxlen && (flags & ZEROPAD))
|
||||
{
|
||||
*buf++ = '-';
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
// right justify if required
|
||||
if ((flags & LADJUST) == 0)
|
||||
{
|
||||
while ((fieldlength < width) && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
// minus sign AFTER left padding if padding with spaces
|
||||
if (sign && maxlen && !(flags & ZEROPAD))
|
||||
{
|
||||
*buf++ = '-';
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
// write the whole part
|
||||
tmp = pow(10.0, digits-1);
|
||||
while ((digits--) && maxlen)
|
||||
{
|
||||
if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
|
||||
{
|
||||
*buf++ = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (int)(fval / tmp);
|
||||
*buf++ = '0' + val;
|
||||
fval -= val * tmp;
|
||||
tmp *= 0.1;
|
||||
}
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
// write the fraction part
|
||||
if (maxlen && prec)
|
||||
{
|
||||
*buf++ = '.';
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
tmp = pow(10.0, prec);
|
||||
|
||||
fval *= tmp;
|
||||
while (prec-- && maxlen)
|
||||
{
|
||||
if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
|
||||
{
|
||||
*buf++ = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp *= 0.1;
|
||||
val = (int)(fval / tmp);
|
||||
*buf++ = '0' + val;
|
||||
fval -= val * tmp;
|
||||
}
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
// left justify if required
|
||||
if (flags & LADJUST)
|
||||
{
|
||||
while ((fieldlength < width) && maxlen)
|
||||
{
|
||||
// right-padding only with spaces, ZEROPAD is ignored
|
||||
*buf++ = ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
// update parent's buffer pointer
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void AddBinary(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
|
||||
{
|
||||
char text[32];
|
||||
int digits;
|
||||
U *buf;
|
||||
|
||||
// write the float number
|
||||
digits = 0;
|
||||
val = (int)fval;
|
||||
do {
|
||||
text[digits++] = '0' + val % 10;
|
||||
val /= 10;
|
||||
do
|
||||
{
|
||||
if (val & 1)
|
||||
{
|
||||
text[digits++] = '1';
|
||||
}
|
||||
else
|
||||
{
|
||||
text[digits++] = '0';
|
||||
}
|
||||
val >>= 1;
|
||||
} while (val);
|
||||
|
||||
if (signedVal < 0)
|
||||
text[digits++] = '-';
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
while (digits < width && maxlen)
|
||||
if (!(flags & LADJUST))
|
||||
{
|
||||
*buf++ = ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
while (digits < width && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
while (digits-- && maxlen)
|
||||
{
|
||||
*buf++ = text[digits];
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
if (flags & LADJUST)
|
||||
{
|
||||
while (width-- && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
|
||||
if (prec < 0)
|
||||
prec = 6;
|
||||
// write the fraction
|
||||
digits = 0;
|
||||
while (digits < prec)
|
||||
{
|
||||
fval -= (int) fval;
|
||||
fval *= 10.0;
|
||||
val = (int) fval;
|
||||
text[digits++] = '0' + val % 10;
|
||||
}
|
||||
|
||||
if (digits > 0 && maxlen)
|
||||
{
|
||||
buf = *buf_p;
|
||||
*buf++ = '.';
|
||||
maxlen--;
|
||||
for (prec = 0; maxlen && prec < digits; prec++)
|
||||
{
|
||||
*buf++ = text[prec];
|
||||
maxlen--;
|
||||
}
|
||||
*buf_p = buf;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
@ -326,6 +485,66 @@ void AddInt(U **buf_p, size_t &maxlen, int val, int width, int flags)
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void AddHex(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
|
||||
{
|
||||
U text[32];
|
||||
int digits;
|
||||
U *buf;
|
||||
U digit;
|
||||
int hexadjust;
|
||||
|
||||
if (flags & UPPERDIGITS)
|
||||
{
|
||||
hexadjust = 'A' - '9' - 1;
|
||||
} else {
|
||||
hexadjust = 'a' - '9' - 1;
|
||||
}
|
||||
|
||||
digits = 0;
|
||||
do
|
||||
{
|
||||
digit = ('0' + val % 16);
|
||||
if (digit > '9')
|
||||
{
|
||||
digit += hexadjust;
|
||||
}
|
||||
|
||||
text[digits++] = digit;
|
||||
val /= 16;
|
||||
} while (val);
|
||||
|
||||
buf = *buf_p;
|
||||
|
||||
if( !(flags & LADJUST) )
|
||||
{
|
||||
while (digits < width && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
while (digits-- && maxlen)
|
||||
{
|
||||
*buf++ = text[digits];
|
||||
width--;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
if (flags & LADJUST)
|
||||
{
|
||||
while (width-- && maxlen)
|
||||
{
|
||||
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
|
||||
maxlen--;
|
||||
}
|
||||
}
|
||||
|
||||
*buf_p = buf;
|
||||
}
|
||||
|
||||
template <typename D, typename S>
|
||||
size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param)
|
||||
{
|
||||
@ -337,7 +556,7 @@ size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *para
|
||||
int width;
|
||||
int prec;
|
||||
int n;
|
||||
char sign;
|
||||
//char sign;
|
||||
const S *fmt;
|
||||
size_t llen = maxlen;
|
||||
|
||||
@ -365,7 +584,7 @@ size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *para
|
||||
flags = 0;
|
||||
width = 0;
|
||||
prec = -1;
|
||||
sign = '\0';
|
||||
//sign = '\0';
|
||||
|
||||
rflag:
|
||||
ch = static_cast<D>(*fmt++);
|
||||
@ -403,6 +622,12 @@ reswitch:
|
||||
case 'c':
|
||||
CHECK_ARGS(0);
|
||||
*buf_p++ = static_cast<D>(*get_amxaddr(amx, params[arg]));
|
||||
llen--;
|
||||
arg++;
|
||||
break;
|
||||
case 'b':
|
||||
CHECK_ARGS(0);
|
||||
AddBinary(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
case 'd':
|
||||
@ -418,43 +643,64 @@ reswitch:
|
||||
break;
|
||||
case 'f':
|
||||
CHECK_ARGS(0);
|
||||
AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec);
|
||||
AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec, flags);
|
||||
arg++;
|
||||
break;
|
||||
case 'X':
|
||||
CHECK_ARGS(0);
|
||||
flags |= UPPERDIGITS;
|
||||
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
case 'x':
|
||||
CHECK_ARGS(0);
|
||||
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
case 'a':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
// %a is passed a pointer directly to a cell string.
|
||||
cell* ptr=reinterpret_cast<cell*>(*get_amxaddr(amx, params[arg]));
|
||||
if (!ptr)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid vector string handle provided (%d)", *get_amxaddr(amx, params[arg]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
AddString(&buf_p, llen, ptr, width, prec);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
CHECK_ARGS(0);
|
||||
if (amx->flags & AMX_FLAG_OLDFILE)
|
||||
{
|
||||
cell *addr = get_amxaddr(amx, params[arg]);
|
||||
if (*addr & BCOMPAT_TRANSLATE_BITS)
|
||||
{
|
||||
const char *key, *def;
|
||||
if (!translate_bcompat(amx, addr, &key, &def))
|
||||
{
|
||||
goto break_to_normal_string;
|
||||
}
|
||||
arg++;
|
||||
size_t written = atcprintf(buf_p, llen, def, amx, params, &arg);
|
||||
buf_p += written;
|
||||
llen -= written;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break_to_normal_string:
|
||||
AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec);
|
||||
arg++;
|
||||
break;
|
||||
case 'L':
|
||||
case 'l':
|
||||
{
|
||||
CHECK_ARGS(1);
|
||||
cell addr = params[arg++];
|
||||
const char *lang;
|
||||
int len;
|
||||
if (ch == 'L')
|
||||
{
|
||||
CHECK_ARGS(1);
|
||||
auto currParam = params[arg++];
|
||||
lang = playerlang(*get_amxaddr(amx, currParam));
|
||||
if (!lang)
|
||||
lang = get_amxstring(amx, currParam, 2, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
lang = playerlang(g_langMngr.GetDefLang());
|
||||
}
|
||||
const char *key = get_amxstring(amx, params[arg++], 3, len);
|
||||
const char *def = translate(amx, addr, key);
|
||||
const char *def = translate(amx, lang, key);
|
||||
if (!def)
|
||||
{
|
||||
static char buf[255];
|
||||
snprintf(buf, sizeof(buf)-1, "ML_NOTFOUND: %s", key);
|
||||
ke::SafeSprintf(buf, sizeof(buf), "ML_NOTFOUND: %s", key);
|
||||
def = buf;
|
||||
}
|
||||
size_t written = atcprintf(buf_p, llen, def, amx, params, &arg);
|
||||
@ -462,6 +708,72 @@ break_to_normal_string:
|
||||
llen -= written;
|
||||
break;
|
||||
}
|
||||
case 'N':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
cell *addr = get_amxaddr(amx, params[arg]);
|
||||
char buffer[255];
|
||||
if (*addr)
|
||||
{
|
||||
CPlayer *player = NULL;
|
||||
|
||||
if (*addr >= 1 && *addr <= gpGlobals->maxClients)
|
||||
{
|
||||
player = GET_PLAYER_POINTER_I(*addr);
|
||||
}
|
||||
|
||||
if (!player || !player->initialized)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *auth = GETPLAYERAUTHID(player->pEdict);
|
||||
if (!auth || auth[0] == '\0')
|
||||
{
|
||||
auth = "STEAM_ID_PENDING";
|
||||
}
|
||||
|
||||
int userid = GETPLAYERUSERID(player->pEdict);
|
||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s<%d><%s><%s>", player->name.chars(), userid, auth, player->team.chars());
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeSprintf(buffer, sizeof(buffer), "Console<0><Console><Console>");
|
||||
}
|
||||
|
||||
AddString(&buf_p, llen, buffer, width, prec);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case 'n':
|
||||
{
|
||||
CHECK_ARGS(0);
|
||||
cell *addr = get_amxaddr(amx, params[arg]);
|
||||
const char *name = "Console";
|
||||
|
||||
if (*addr)
|
||||
{
|
||||
CPlayer *player = NULL;
|
||||
|
||||
if (*addr >= 1 && *addr <= gpGlobals->maxClients)
|
||||
{
|
||||
player = GET_PLAYER_POINTER_I(*addr);
|
||||
}
|
||||
|
||||
if (!player || !player->initialized)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = player->name.chars();
|
||||
}
|
||||
|
||||
AddString(&buf_p, llen, name, width, prec);
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
case '%':
|
||||
*buf_p++ = static_cast<D>(ch);
|
||||
if (!llen)
|
||||
@ -487,6 +799,14 @@ break_to_normal_string:
|
||||
done:
|
||||
*buf_p = static_cast<D>(0);
|
||||
*param = arg;
|
||||
|
||||
/* if max buffer length consumed, make sure we don't truncate a multi-byte character */
|
||||
if (llen <= 0 && *(buf_p - 1) & 1 << 7)
|
||||
{
|
||||
llen += UTIL_CheckValidChar(buf_p - 1);
|
||||
*(buf_p - llen) = static_cast<D>(0);
|
||||
}
|
||||
|
||||
return maxlen-llen;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#ifndef _INCLUDE_FORMATTING_H
|
||||
#define _INCLUDE_FORMATTING_H
|
||||
|
||||
@ -5,7 +14,7 @@
|
||||
template <typename D, typename S>
|
||||
size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param);
|
||||
|
||||
const char *translate(AMX *amx, cell amxaddr, const char *key);
|
||||
bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def);
|
||||
const char *playerlang(const cell index);
|
||||
const char *translate(AMX *amx, const char *lang, const char *key);
|
||||
|
||||
#endif //_INCLUDE_FORMATTING_H
|
||||
|
175
amxmodx/gameconfigs.cpp
Normal file
175
amxmodx/gameconfigs.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "gameconfigs.h"
|
||||
#include "amxmodx.h"
|
||||
#include "CGameConfigs.h"
|
||||
|
||||
NativeHandle<GameConfigNative> GameConfigHandle;
|
||||
|
||||
// native GameConfig:LoadGameConfigFile(const file[]);
|
||||
static cell AMX_NATIVE_CALL LoadGameConfigFile(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char *filename = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
IGameConfig *config = nullptr;
|
||||
char error[128];
|
||||
|
||||
if (!ConfigManager.LoadGameConfigFile(filename, &config, error, sizeof(error)))
|
||||
{
|
||||
ConfigManager.CloseGameConfigFile(config);
|
||||
LogError(amx, AMX_ERR_NATIVE, "Unable to open %s: %s", filename, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle = GameConfigHandle.create();
|
||||
|
||||
auto configHandle = GameConfigHandle.lookup(handle);
|
||||
|
||||
if (!configHandle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
configHandle->m_config = config;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// native GameConfGetOffset(GameConfig:handle, const key[]);
|
||||
static cell AMX_NATIVE_CALL GameConfGetOffset(AMX *amx, cell *params)
|
||||
{
|
||||
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length;
|
||||
TypeDescription value;
|
||||
|
||||
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||
|
||||
if (!handle->m_config->GetOffset(key, &value))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return value.fieldOffset;
|
||||
}
|
||||
|
||||
// native GameConfGetClassOffset(GameConfig:handle, const classname[], const key[]);
|
||||
static cell AMX_NATIVE_CALL GameConfGetClassOffset(AMX *amx, cell *params)
|
||||
{
|
||||
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length;
|
||||
TypeDescription value;
|
||||
|
||||
const char *classname = get_amxstring(amx, params[2], 0, length);
|
||||
const char *key = get_amxstring(amx, params[3], 1, length);
|
||||
|
||||
if (!handle->m_config->GetOffsetByClass(classname, key, &value))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return value.fieldOffset;
|
||||
}
|
||||
|
||||
// native bool:GameConfGetKeyValue(GameConfig:handle, const key[], buffer[], maxlen);
|
||||
static cell AMX_NATIVE_CALL GameConfGetKeyValue(AMX *amx, cell *params)
|
||||
{
|
||||
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length;
|
||||
const char *value;
|
||||
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||
|
||||
if (!(value = handle->m_config->GetKeyValue(key)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_amxstring_utf8(amx, params[3], value, strlen(value), params[4]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// native GameConfGetAddress(GameConfig:handle, const name[]);
|
||||
static cell AMX_NATIVE_CALL GameConfGetAddress(AMX *amx, cell *params)
|
||||
{
|
||||
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length;
|
||||
void *value;
|
||||
|
||||
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||
|
||||
if (!handle->m_config->GetAddress(key, &value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(value);
|
||||
}
|
||||
|
||||
// native CloseGameConfigFile(&GameConfig:handle);
|
||||
static cell AMX_NATIVE_CALL CloseGameConfigFile(AMX *amx, cell *params)
|
||||
{
|
||||
cell *address = get_amxaddr(amx, params[1]);
|
||||
|
||||
GameConfigNative *handle = GameConfigHandle.lookup(*address);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GameConfigHandle.destroy(*address))
|
||||
{
|
||||
*address = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AMX_NATIVE_INFO g_GameConfigNatives[] =
|
||||
{
|
||||
{ "LoadGameConfigFile" , LoadGameConfigFile },
|
||||
{ "GameConfGetOffset" , GameConfGetOffset },
|
||||
{ "GameConfGetClassOffset", GameConfGetClassOffset },
|
||||
{ "GameConfGetKeyValue" , GameConfGetKeyValue },
|
||||
{ "GameConfGetAddress" , GameConfGetAddress },
|
||||
{ "CloseGameConfigFile" , CloseGameConfigFile },
|
||||
{ nullptr , nullptr }
|
||||
};
|
18
amxmodx/gameconfigs.h
Normal file
18
amxmodx/gameconfigs.h
Normal file
@ -0,0 +1,18 @@
|
||||
// vim: set ts=4 sw=4 tw=99 noet:
|
||||
//
|
||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||
// Copyright (C) The AMX Mod X Development Team.
|
||||
//
|
||||
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://alliedmods.net/amxmodx-license
|
||||
|
||||
#include "IGameConfigs.h"
|
||||
#include "natives_handles.h"
|
||||
|
||||
struct GameConfigNative
|
||||
{
|
||||
IGameConfig *m_config;
|
||||
};
|
||||
|
||||
extern NativeHandle<GameConfigNative> GameConfigHandle;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user