Compare commits
1688 Commits
amxmodx-1.
...
1.9-dev
Author | SHA1 | Date | |
---|---|---|---|
363871a860 | |||
8e8dfa33ed | |||
f442b3d84f | |||
8817f3e541 | |||
81e4aa29a6 | |||
1754c0b959 | |||
bb4b818250 | |||
f5fea6ab7b | |||
f031b97e91 | |||
beaa8c436b | |||
f3d21a3fb1 | |||
3340884edb | |||
d1fc99fc28 | |||
5e7e1775bd | |||
9d4c9c5ce9 | |||
2064e224d1 | |||
73f52fd53a | |||
6c8c605fa3 | |||
d67510b841 | |||
00b769e3f2 | |||
f92e60a8ac | |||
8e902cb63b | |||
8fdc6540ca | |||
5eea3e5b42 | |||
1bfec70029 | |||
bdeb2a133f | |||
936c9477be | |||
4b335adfe8 | |||
e463e06480 | |||
d0c8084ac9 | |||
32a29f5a78 | |||
15a14a0a43 | |||
be3f2f540b | |||
4a2aecfe85 | |||
9ca3a685ed | |||
78ecb35e3c | |||
dafabc73c0 | |||
163afa041e | |||
c064459b67 | |||
4410d219f7 | |||
6fb27a03a7 | |||
5e48c9b6db | |||
9e962ce097 | |||
78d1c0f1cd | |||
691ae9f8d4 | |||
6cecb34e29 | |||
4ef0a78abd | |||
1f09bd53f6 | |||
c8bd4bb169 | |||
2dd36300bf | |||
c867d9a7cb | |||
b3980d2e5d | |||
2bc04236db | |||
211003750c | |||
6dba7c4f17 | |||
7515038e07 | |||
2bb5e92d93 | |||
77bbdbb59c | |||
70d822e17f | |||
6c53524d86 | |||
9eb1f427df | |||
5c5fbd83d1 | |||
be526418bf | |||
f63bc38f5c | |||
09b95aa6ab | |||
a0ea98da35 | |||
d867a95fd6 | |||
05bd01cd5e | |||
d93ee596bb | |||
523bb334d5 | |||
a635b383fc | |||
3238b25495 | |||
e993cdccae | |||
e059c1f5ab | |||
ddf0cc69dd | |||
9f00bf4f55 | |||
ac64ef041b | |||
7e23047c53 | |||
91f36f2308 | |||
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 | |||
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 | |||
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 |
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.
|
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.
|
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
|
24
.hgignore
24
.hgignore
@ -1,24 +0,0 @@
|
||||
# Binaries
|
||||
\.dll$
|
||||
\.exe$
|
||||
\.so$
|
||||
|
||||
# Files generated by Visual Studio
|
||||
\.aps$
|
||||
\.ncb$
|
||||
\.sdf$
|
||||
\.suo$
|
||||
\.user$
|
||||
|
||||
# Build directories
|
||||
/Debug.*
|
||||
/Release.*
|
||||
/JITDebug.*
|
||||
/JITRelease.*
|
||||
|
||||
# Files generated by Mac OS X Finder
|
||||
(^|/)\.DS_Store$
|
||||
|
||||
# Files generated by Windows Explorer
|
||||
(^|/)Desktop\.ini$
|
||||
(^|/)Thumbs\.db$
|
27
.travis.yml
Normal file
27
.travis.yml
Normal file
@ -0,0 +1,27 @@
|
||||
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
|
||||
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 python ../configure.py --enable-optimize
|
||||
- ambuild
|
508
AMBuildScript
Normal file
508
AMBuildScript
Normal file
@ -0,0 +1,508 @@
|
||||
# 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_clang:
|
||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||
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
|
97
amxmodx/AMBuilder
Normal file
97
amxmodx/AMBuilder
Normal file
@ -0,0 +1,97 @@
|
||||
# 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',
|
||||
]
|
||||
|
||||
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);
|
||||
|
||||
@ -222,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;
|
||||
}
|
||||
|
||||
@ -244,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) != 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_
|
@ -1,23 +1,23 @@
|
||||
// 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 "CString.h"
|
||||
|
||||
#include "amxmodx.h"
|
||||
|
||||
#include "CFlagManager.h"
|
||||
|
||||
void CFlagManager::SetFile(const char *Filename)
|
||||
{
|
||||
|
||||
m_strConfigFile.assign(g_mod_name.c_str());
|
||||
m_strConfigFile.append("/");
|
||||
m_strConfigFile.append(get_localinfo("amxx_configsdir","addons/amxmodx/configs"));
|
||||
m_strConfigFile.append("/");
|
||||
m_strConfigFile.append(Filename);
|
||||
|
||||
m_strConfigFile = build_pathname("%s/%s", get_localinfo("amxx_configsdir", "addons/amxmodx/configs"), Filename);
|
||||
|
||||
CreateIfNotExist();
|
||||
}
|
||||
@ -35,7 +35,7 @@ const int CFlagManager::LoadFile(const int force)
|
||||
if (!force && !NeedToLoad())
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
this->Clear();
|
||||
|
||||
@ -44,28 +44,25 @@ const int CFlagManager::LoadFile(const int force)
|
||||
|
||||
FILE *File;
|
||||
|
||||
File=fopen(m_strConfigFile.c_str(),"r");
|
||||
File=fopen(GetFile(),"r");
|
||||
|
||||
if (!File)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] FlagManager: Cannot open file \"%s\" (FILE pointer null!)",m_strConfigFile.c_str());
|
||||
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...
|
||||
String Line;
|
||||
char Line[512];
|
||||
char TempLine[512];
|
||||
|
||||
char Command[256];
|
||||
char Flags[256];
|
||||
|
||||
String TempLine;
|
||||
while (!feof(File))
|
||||
|
||||
while (!feof(File) && fgets(Line, sizeof(Line), File))
|
||||
{
|
||||
|
||||
Line._fread(File);
|
||||
|
||||
char *nonconst=const_cast<char *>(Line.c_str());
|
||||
|
||||
char *nonconst= Line;
|
||||
|
||||
// Strip out comments
|
||||
while (*nonconst)
|
||||
@ -78,15 +75,15 @@ const int CFlagManager::LoadFile(const int force)
|
||||
{
|
||||
nonconst++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Command[0]='\0';
|
||||
Flags[0]='\0';
|
||||
|
||||
// Extract the command
|
||||
TempLine.assign(Line.c_str());
|
||||
strncopy(TempLine, Line, sizeof(TempLine));
|
||||
|
||||
nonconst=const_cast<char *>(TempLine.c_str());
|
||||
nonconst = TempLine;
|
||||
|
||||
char *start=NULL;
|
||||
char *end=NULL;
|
||||
@ -122,7 +119,6 @@ done_with_command:
|
||||
|
||||
strncpy(Command,start,sizeof(Command)-1);
|
||||
|
||||
|
||||
// Now do the same thing for the flags
|
||||
nonconst=++end;
|
||||
|
||||
@ -159,28 +155,23 @@ done_with_flags:
|
||||
|
||||
strncpy(Flags,start,sizeof(Flags)-1);
|
||||
|
||||
|
||||
|
||||
//if (!isalnum(*Command))
|
||||
if (*Command == '"' ||
|
||||
*Command == '\0')
|
||||
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=const_cast<char *>(Line.c_str());
|
||||
*nonconst='\0';
|
||||
};
|
||||
|
||||
nonconst = Line;
|
||||
*nonconst = '\0';
|
||||
}
|
||||
|
||||
fclose(File);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -192,7 +183,6 @@ done_with_flags:
|
||||
*/
|
||||
void CFlagManager::AddFromFile(const char *Command, const char *Flags)
|
||||
{
|
||||
|
||||
CFlagEntry *Entry=new CFlagEntry;
|
||||
|
||||
Entry->SetName(Command);
|
||||
@ -201,8 +191,7 @@ void CFlagManager::AddFromFile(const char *Command, const char *Flags)
|
||||
// Link it
|
||||
m_FlagList.push_back(Entry);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
||||
{
|
||||
@ -211,7 +200,6 @@ void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int TempFlags=Flags;
|
||||
if (TempFlags==-1)
|
||||
{
|
||||
@ -226,7 +214,7 @@ void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
||||
|
||||
while (iter!=end)
|
||||
{
|
||||
if (strcmp((*iter)->GetName()->c_str(),Command)==0)
|
||||
if (strcmp((*iter)->GetName()->chars(),Command)==0)
|
||||
{
|
||||
CFlagEntry *Entry=(*iter);
|
||||
|
||||
@ -271,8 +259,14 @@ void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
|
||||
m_FlagList.push_back(Entry);
|
||||
|
||||
}
|
||||
|
||||
void CFlagManager::WriteCommands(void)
|
||||
{
|
||||
if (m_iDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<CFlagEntry *>::iterator iter;
|
||||
List<CFlagEntry *>::iterator end;
|
||||
FILE *File;
|
||||
@ -283,7 +277,7 @@ void CFlagManager::WriteCommands(void)
|
||||
// after we write so we do not re-read next map
|
||||
struct stat TempStat;
|
||||
|
||||
stat(m_strConfigFile.c_str(),&TempStat);
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
|
||||
|
||||
@ -293,7 +287,7 @@ void CFlagManager::WriteCommands(void)
|
||||
};
|
||||
|
||||
|
||||
File=fopen(m_strConfigFile.c_str(),"a");
|
||||
File = fopen(GetFile(), "a");
|
||||
|
||||
if (!File)
|
||||
{
|
||||
@ -309,18 +303,18 @@ void CFlagManager::WriteCommands(void)
|
||||
{
|
||||
if ((*iter)->NeedWritten())
|
||||
{
|
||||
if ((*iter)->GetComment()->size())
|
||||
if ((*iter)->GetComment()->length())
|
||||
{
|
||||
fprintf(File,"\"%s\" \t\"%s\" ; %s\n",(*iter)->GetName()->c_str(),(*iter)->GetFlags()->c_str(),(*iter)->GetComment()->c_str());
|
||||
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()->c_str(),(*iter)->GetFlags()->c_str());
|
||||
fprintf(File,"\"%s\" \t\"%s\"\n",(*iter)->GetName()->chars(),(*iter)->GetFlags()->chars());
|
||||
}
|
||||
(*iter)->SetNeedWritten(0);
|
||||
}
|
||||
++iter;
|
||||
};
|
||||
}
|
||||
|
||||
fclose(File);
|
||||
|
||||
@ -330,7 +324,7 @@ void CFlagManager::WriteCommands(void)
|
||||
// next map
|
||||
if (!NeedToRead)
|
||||
{
|
||||
stat(m_strConfigFile.c_str(),&TempStat);
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
m_Stat.st_mtime=TempStat.st_mtime;
|
||||
|
||||
@ -340,7 +334,6 @@ void CFlagManager::WriteCommands(void)
|
||||
|
||||
int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const
|
||||
{
|
||||
|
||||
// If flagmanager is disabled then ignore this
|
||||
if (m_iDisabled)
|
||||
{
|
||||
@ -384,8 +377,7 @@ int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, cons
|
||||
|
||||
// else use it
|
||||
return 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void CFlagManager::Clear(void)
|
||||
{
|
||||
@ -403,7 +395,7 @@ void CFlagManager::Clear(void)
|
||||
}
|
||||
|
||||
m_FlagList.clear();
|
||||
};
|
||||
}
|
||||
|
||||
void CFlagManager::CheckIfDisabled(void)
|
||||
{
|
||||
@ -415,4 +407,4 @@ void CFlagManager::CheckIfDisabled(void)
|
||||
{
|
||||
m_iDisabled=1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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 CFLAGMANAGER_H
|
||||
#define CFLAGMANAGER_H
|
||||
|
||||
@ -6,16 +15,15 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sh_list.h"
|
||||
#include "CString.h"
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include "CLibrarySys.h"
|
||||
|
||||
class CFlagEntry
|
||||
{
|
||||
private:
|
||||
String m_strName; // command name ("amx_slap")
|
||||
String m_strFlags; // string flags ("a","b")
|
||||
String m_strComment; // comment to write ("; admincmd.amxx")
|
||||
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
|
||||
@ -39,16 +47,17 @@ public:
|
||||
m_iNeedWritten=i;
|
||||
};
|
||||
|
||||
const String *GetName(void) const
|
||||
const ke::AString *GetName(void) const
|
||||
{
|
||||
return &m_strName;
|
||||
};
|
||||
|
||||
const String *GetFlags(void) const
|
||||
const ke::AString *GetFlags(void) const
|
||||
{
|
||||
return &m_strFlags;
|
||||
};
|
||||
const String *GetComment(void) const
|
||||
|
||||
const ke::AString *GetComment(void) const
|
||||
{
|
||||
return &m_strComment;
|
||||
};
|
||||
@ -60,7 +69,7 @@ public:
|
||||
|
||||
void SetName(const char *data)
|
||||
{
|
||||
m_strName.assign(data);
|
||||
m_strName = data;
|
||||
};
|
||||
void SetFlags(const char *flags)
|
||||
{
|
||||
@ -71,7 +80,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
m_strFlags.assign(flags);
|
||||
m_strFlags = flags;
|
||||
m_iFlags=UTIL_ReadFlags(flags);
|
||||
};
|
||||
void SetFlags(const int flags)
|
||||
@ -81,11 +90,11 @@ public:
|
||||
char FlagsString[32];
|
||||
UTIL_GetFlags(FlagsString, flags);
|
||||
|
||||
m_strFlags.assign(FlagsString);
|
||||
m_strFlags = FlagsString;
|
||||
};
|
||||
void SetComment(const char *comment)
|
||||
{
|
||||
m_strComment.assign(comment);
|
||||
m_strComment = comment;
|
||||
};
|
||||
void SetHidden(int i=1)
|
||||
{
|
||||
@ -100,7 +109,7 @@ class CFlagManager
|
||||
{
|
||||
private:
|
||||
List<CFlagEntry *> m_FlagList;
|
||||
String m_strConfigFile;
|
||||
ke::AString m_strConfigFile;
|
||||
struct stat m_Stat;
|
||||
int m_iForceRead;
|
||||
int m_iDisabled;
|
||||
@ -110,12 +119,12 @@ private:
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(m_strConfigFile.c_str(),"r");
|
||||
fp = fopen(GetFile(), "r");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
// File does not exist, create the header
|
||||
fp=fopen(m_strConfigFile.c_str(),"a");
|
||||
fp = fopen(GetFile(), "a");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
@ -134,6 +143,10 @@ private:
|
||||
fclose(fp);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Returns 1 if the timestamp for the file is different than the one we have loaded
|
||||
@ -143,7 +156,7 @@ private:
|
||||
{
|
||||
struct stat TempStat;
|
||||
|
||||
stat(m_strConfigFile.c_str(),&TempStat);
|
||||
stat(GetFile(), &TempStat);
|
||||
|
||||
// If the modified timestamp does not match the stored
|
||||
// timestamp than we need to re-read this file.
|
||||
@ -175,7 +188,7 @@ public:
|
||||
*/
|
||||
void SetFile(const char *Filename="cmdaccess.ini");
|
||||
|
||||
const char *GetFile(void) const { return m_strConfigFile.c_str(); };
|
||||
const char *GetFile(void) const { return m_strConfigFile.chars(); };
|
||||
|
||||
/**
|
||||
* Parse the file, and load all entries
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
@ -132,7 +120,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
// exec
|
||||
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);
|
||||
|
||||
@ -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,7 +323,7 @@ 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
|
||||
@ -329,7 +348,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 +379,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 +400,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 +431,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 +441,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 +453,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 +480,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 +488,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 +546,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;
|
||||
}
|
||||
|
||||
@ -590,7 +625,7 @@ int CForwardMngr::isSameSPForward(int id1, int id2)
|
||||
&& (fwd1->m_NumParams == fwd2->m_NumParams));
|
||||
}
|
||||
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num, int fwd_type)
|
||||
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num)
|
||||
{
|
||||
ForwardParam params[FORWARD_MAX_PARAMS];
|
||||
|
||||
@ -599,7 +634,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, ...)
|
||||
@ -710,13 +745,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
|
||||
@ -151,7 +127,7 @@ class CSPForward
|
||||
|
||||
int m_Func;
|
||||
bool m_HasFunc;
|
||||
String m_Name;
|
||||
ke::AString m_Name;
|
||||
bool m_InExec;
|
||||
bool m_ToDelete;
|
||||
|
||||
@ -176,7 +152,7 @@ public:
|
||||
|
||||
const char *getFuncName() const
|
||||
{
|
||||
return m_Name.c_str();
|
||||
return m_Name.chars();
|
||||
}
|
||||
|
||||
ForwardParam getParamType(int paramId) const
|
||||
@ -190,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;
|
||||
@ -209,7 +185,7 @@ 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);
|
||||
@ -235,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
186
amxmodx/CGameConfigs.h
Normal file
186
amxmodx/CGameConfigs.h
Normal file
@ -0,0 +1,186 @@
|
||||
// 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; \
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#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
|
||||
@ -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;
|
||||
}
|
||||
@ -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,7 +120,7 @@ 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(const char* frmt, va_list& vaptr);
|
||||
@ -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"
|
||||
@ -56,7 +34,7 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
// *****************************************************
|
||||
@ -41,6 +20,8 @@ void CPlayer::Init(edict_t* e, int i)
|
||||
initialized = false;
|
||||
ingame = false;
|
||||
authorized = false;
|
||||
disconnecting = false;
|
||||
teamIdsInitialized = false;
|
||||
|
||||
current = 0;
|
||||
teamId = -1;
|
||||
@ -51,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()
|
||||
@ -62,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++)
|
||||
@ -112,8 +83,8 @@ int CPlayer::NextHUDChannel()
|
||||
|
||||
bool CPlayer::Connect(const char* connectname, const char* ipaddress)
|
||||
{
|
||||
name.assign(connectname);
|
||||
ip.assign(ipaddress);
|
||||
name = connectname;
|
||||
ip = ipaddress;
|
||||
time = gpGlobals->time;
|
||||
death_killer = 0;
|
||||
menu = 0;
|
||||
@ -270,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)
|
||||
{
|
||||
@ -297,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;
|
||||
}
|
||||
@ -311,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;
|
||||
}
|
||||
|
@ -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,14 +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 authorized;
|
||||
bool vgui;
|
||||
bool disconnecting;
|
||||
bool vgui;
|
||||
bool teamIdsInitialized;
|
||||
|
||||
float time;
|
||||
float playtime;
|
||||
@ -110,7 +63,7 @@ public:
|
||||
int death_killer;
|
||||
int death_victim;
|
||||
bool death_tk;
|
||||
String death_weapon;
|
||||
ke::AString death_weapon;
|
||||
int newmenu;
|
||||
int page;
|
||||
|
||||
@ -185,7 +138,7 @@ public:
|
||||
|
||||
class ForceObject
|
||||
{
|
||||
String filename;
|
||||
ke::AString filename;
|
||||
FORCE_TYPE type;
|
||||
Vector mins;
|
||||
Vector maxs;
|
||||
@ -193,7 +146,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; }
|
||||
@ -248,17 +201,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; }
|
||||
};
|
||||
|
||||
@ -270,7 +222,7 @@ class TeamIds
|
||||
{
|
||||
struct TeamEle
|
||||
{
|
||||
String name;
|
||||
ke::AString name;
|
||||
int id;
|
||||
char tid;
|
||||
static char uid;
|
||||
|
@ -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"
|
||||
@ -52,7 +30,7 @@ typedef void (*PLUGINSUNLOADING_NEW)(void);
|
||||
|
||||
CModule::CModule(const char* fname)
|
||||
{
|
||||
m_Filename.assign(fname);
|
||||
m_Filename = fname;
|
||||
clear(false);
|
||||
}
|
||||
|
||||
@ -71,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]];
|
||||
}
|
||||
@ -118,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;
|
||||
@ -140,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,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)
|
||||
@ -217,11 +190,11 @@ 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.c_str(), dlerror());
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" failed to load (%s)", m_Filename.chars(), dlerror());
|
||||
#endif
|
||||
m_Status = MODULE_BADLOAD;
|
||||
return false;
|
||||
@ -233,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:
|
||||
@ -259,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";
|
||||
@ -285,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;
|
||||
}
|
||||
@ -304,18 +276,18 @@ bool CModule::queryModule()
|
||||
if (checkGame_New)
|
||||
{
|
||||
// This is an optional check; do not fail modules that do not have it
|
||||
int ret = checkGame_New(g_mod_name.c_str());
|
||||
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.c_str(), getVersion(), g_mod_name.c_str());
|
||||
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.c_str(), getVersion(), ret);
|
||||
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an unknown CheckGame code (value: %d)", m_Filename.chars(), getVersion(), ret);
|
||||
m_Status = MODULE_BADLOAD;
|
||||
break;
|
||||
}
|
||||
@ -328,7 +300,6 @@ bool CModule::queryModule()
|
||||
return true;
|
||||
} else {
|
||||
m_Status = MODULE_NOQUERY;
|
||||
m_Amxx = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -340,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;
|
||||
}
|
||||
|
||||
@ -408,10 +374,10 @@ void CModule::CallPluginsLoaded()
|
||||
return;
|
||||
|
||||
PLUGINSLOADED_NEW func = (PLUGINSLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsLoaded");
|
||||
|
||||
|
||||
if (!func)
|
||||
return;
|
||||
|
||||
|
||||
func();
|
||||
}
|
||||
|
||||
@ -434,6 +400,6 @@ const char* CModule::getStatus() const
|
||||
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
|
||||
@ -74,13 +52,12 @@ struct amxx_module_info_s
|
||||
|
||||
#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
|
||||
@ -92,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
|
||||
|
@ -1,54 +1,32 @@
|
||||
/* 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>
|
||||
|
||||
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 +42,10 @@ void CPluginMngr::Finalize()
|
||||
{
|
||||
if (m_Finalized)
|
||||
return;
|
||||
|
||||
|
||||
pNatives = BuildNativeTable();
|
||||
CPlugin *a = head;
|
||||
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (a->getStatusCode() == ps_running)
|
||||
@ -77,16 +55,16 @@ 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)
|
||||
{
|
||||
@ -94,27 +72,28 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
}
|
||||
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 +103,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;
|
||||
@ -158,8 +137,8 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
continue;
|
||||
}
|
||||
|
||||
CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, debugFlag);
|
||||
|
||||
CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, sizeof(error), debugFlag);
|
||||
|
||||
if (plugin->getStatusCode() == ps_bad_load)
|
||||
{
|
||||
char errorMsg[255];
|
||||
@ -167,6 +146,24 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
|
||||
plugin->setError(errorMsg);
|
||||
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(), "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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
@ -176,20 +173,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);
|
||||
@ -201,20 +198,20 @@ 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;
|
||||
}
|
||||
|
||||
@ -222,17 +219,17 @@ 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;
|
||||
}
|
||||
|
||||
@ -242,7 +239,7 @@ void CPluginMngr::CPlugin::AddToFailCounter(unsigned int i)
|
||||
if ((failcounter >= 3)
|
||||
&& (status ))
|
||||
{
|
||||
errorMsg.assign("This plugin is non-GPL which violates AMX Mod X's license.");
|
||||
errorMsg = "This plugin is non-GPL which violates AMX Mod X's license.";
|
||||
status = ps_bad_load;
|
||||
}
|
||||
}
|
||||
@ -251,7 +248,7 @@ const char* CPluginMngr::CPlugin::getStatus() const
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case ps_running:
|
||||
case ps_running:
|
||||
{
|
||||
if (m_Debug)
|
||||
{
|
||||
@ -266,42 +263,42 @@ 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";
|
||||
|
||||
|
||||
failcounter = 0;
|
||||
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);
|
||||
title = unk;
|
||||
author = unk;
|
||||
version = 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;
|
||||
@ -371,22 +368,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);
|
||||
@ -394,18 +391,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)
|
||||
@ -413,8 +410,8 @@ void CPluginMngr::CPlugin::unpauseFunction(int id)
|
||||
}
|
||||
|
||||
void CPluginMngr::CPlugin::setStatus(int a)
|
||||
{
|
||||
status = a;
|
||||
{
|
||||
status = a;
|
||||
g_commands.clearBufforedInfo(); // ugly way
|
||||
}
|
||||
|
||||
@ -426,7 +423,7 @@ void CPluginMngr::CPlugin::pausePlugin()
|
||||
// call plugin_pause if provided
|
||||
if (m_PauseFwd != -1)
|
||||
executeForwards(m_PauseFwd);
|
||||
|
||||
|
||||
setStatus(ps_paused);
|
||||
}
|
||||
}
|
||||
@ -438,7 +435,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)
|
||||
{
|
||||
@ -447,6 +444,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;
|
||||
@ -466,8 +506,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;
|
||||
@ -489,7 +528,7 @@ char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pl->path.assign(file);
|
||||
pl->path = file;
|
||||
|
||||
bufsize = pl->bufsize;
|
||||
|
||||
@ -558,7 +597,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;
|
||||
@ -571,7 +610,7 @@ void CPluginMngr::CacheAndLoadModules(const char *plugin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (hdr.stp <= 0)
|
||||
{
|
||||
return;
|
||||
@ -600,8 +639,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++)
|
||||
{
|
||||
@ -616,21 +655,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]);
|
||||
}
|
||||
@ -649,10 +688,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;
|
||||
}
|
||||
@ -660,9 +699,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')
|
||||
@ -682,24 +721,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;
|
||||
}
|
||||
@ -710,7 +751,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,11 +52,11 @@ 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 errorMsg;
|
||||
|
||||
unsigned int failcounter;
|
||||
int m_PauseFwd;
|
||||
@ -79,24 +66,27 @@ 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* 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 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); }
|
||||
@ -112,6 +102,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:
|
||||
@ -126,7 +122,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);
|
||||
|
||||
@ -159,7 +155,7 @@ public:
|
||||
CAmxxReader *file;
|
||||
size_t bufsize;
|
||||
char *buffer;
|
||||
String path;
|
||||
ke::AString path;
|
||||
};
|
||||
char *ReadIntoOrFromCache(const char *file, size_t &bufsize);
|
||||
void InvalidateCache();
|
||||
@ -168,7 +164,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() const
|
||||
{
|
||||
if (!v)
|
||||
return true;
|
||||
|
||||
if (v[0] == '\0')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
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<len; 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,502 +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(size_t amount)
|
||||
{
|
||||
// automatic grow
|
||||
size_t newSize = m_Size * 2;
|
||||
|
||||
if (newSize == 0)
|
||||
{
|
||||
newSize = 8;
|
||||
}
|
||||
|
||||
while (m_CurrentUsedSize + amount > newSize)
|
||||
{
|
||||
newSize *= 2;
|
||||
}
|
||||
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(size_t amount)
|
||||
{
|
||||
if (m_CurrentUsedSize + amount >= m_Size)
|
||||
{
|
||||
return Grow(amount);
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (!GrowIfNeeded(1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Data[m_CurrentUsedSize++] = 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();
|
||||
|
||||
if (!GrowIfNeeded(1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++m_CurrentUsedSize;
|
||||
|
||||
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__
|
||||
|
333
amxmodx/CoreConfig.cpp
Normal file
333
amxmodx/CoreConfig.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
// 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_PendingForwardPush)
|
||||
{
|
||||
m_PendingForwardPush = false;
|
||||
m_ConfigsExecuted = true;
|
||||
|
||||
executeForwards(m_ConfigsExecutedForward);
|
||||
}
|
||||
else if (!m_LegacyMapConfigsExecuted && m_legacyMapConfigNextTime <= gpGlobals->time)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
147
amxmodx/Makefile
147
amxmodx/Makefile
@ -1,147 +0,0 @@
|
||||
# (C)2004-2013 AMX Mod X Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
###########################################
|
||||
### EDIT THESE PATHS FOR YOUR OWN SETUP ###
|
||||
###########################################
|
||||
|
||||
HLSDK = ../../hlsdk/multiplayer
|
||||
MM_ROOT = ../../metamod/metamod
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
#####################################
|
||||
|
||||
PROJECT = amxmodx
|
||||
|
||||
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 nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \
|
||||
trie_natives.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
##############################################
|
||||
|
||||
C_OPT_FLAGS = -DNDEBUG -O2 -funroll-loops -fomit-frame-pointer -pipe
|
||||
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
|
||||
C_GCC4_FLAGS = -fvisibility=hidden
|
||||
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
||||
CPP = gcc
|
||||
CPP_OSX = clang
|
||||
|
||||
LINK = -Lzlib
|
||||
|
||||
INCLUDE = -I. -I$(HLSDK) -I$(HLSDK)/common -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared \
|
||||
-I$(MM_ROOT)
|
||||
|
||||
################################################
|
||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
||||
################################################
|
||||
|
||||
OS := $(shell uname -s)
|
||||
|
||||
ifeq "$(OS)" "Darwin"
|
||||
OBJECTS += JIT/amxexecn-darwin.o JIT/amxjitsn-darwin.o JIT/natives-darwin-x86.o \
|
||||
JIT/helpers-darwin-x86.o
|
||||
|
||||
CPP = $(CPP_OSX)
|
||||
LIB_EXT = dylib
|
||||
LIB_SUFFIX = _mm
|
||||
CFLAGS += -DOSX
|
||||
LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5 -Wl,-read_only_relocs,suppress -lz-darwin
|
||||
else
|
||||
OBJECTS += JIT/amxexecn.o JIT/amxjitsn.o JIT/natives-x86.o JIT/helpers-x86.o
|
||||
|
||||
LIB_EXT = so
|
||||
LIB_SUFFIX = _mm_i386
|
||||
CFLAGS += -DLINUX
|
||||
LINK += -shared -lz
|
||||
endif
|
||||
|
||||
LINK += -m32 -lm -ldl
|
||||
|
||||
CFLAGS += -DAMX_NOPROPLIST -DPAWN_CELL_SIZE=32 -DJIT -DASM32 -DHAVE_STDINT_H -fno-strict-aliasing \
|
||||
-m32 -Wall -Werror
|
||||
CPPFLAGS += -fno-exceptions -fno-rtti
|
||||
|
||||
BINARY = $(PROJECT)$(LIB_SUFFIX).$(LIB_EXT)
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS += $(C_DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS += $(C_OPT_FLAGS)
|
||||
LINK += -s
|
||||
endif
|
||||
|
||||
ifeq "$(BINLOG)" "true"
|
||||
LIB_SUFFIX := _bl$(LIB_SUFFIX)
|
||||
BIN_DIR := $(BIN_DIR)BinLog
|
||||
OBJECTS += binlog.cpp
|
||||
CFLAGS += -DBINLOG_ENABLED
|
||||
endif
|
||||
|
||||
IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0")
|
||||
|
||||
ifeq "$(IS_CLANG)" "1"
|
||||
CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/")
|
||||
CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/")
|
||||
else
|
||||
CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3)
|
||||
endif
|
||||
|
||||
# Clang || GCC >= 4
|
||||
ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1"
|
||||
CFLAGS += $(C_GCC4_FLAGS)
|
||||
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||
endif
|
||||
|
||||
# Clang >= 3 || GCC >= 4.7
|
||||
ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1"
|
||||
CFLAGS += -Wno-delete-non-virtual-dtor
|
||||
endif
|
||||
|
||||
# OS is Linux and not using clang
|
||||
ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1"
|
||||
LINK += -static-libgcc
|
||||
endif
|
||||
|
||||
OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
|
||||
# This will break if we include other Makefiles, but is fine for now. It allows
|
||||
# us to make a copy of this file that uses altered paths (ie. Makefile.mine)
|
||||
# or other changes without mucking up the original.
|
||||
MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
$(MAKE) -f $(MAKEFILE_NAME) $(PROJECT)
|
||||
|
||||
binlog:
|
||||
$(MAKE) -f $(MAKEFILE_NAME) all BINLOG=true
|
||||
|
||||
binlog_debug:
|
||||
$(MAKE) -f $(MAKEFILE_NAME) all BINLOG=true DEBUG=true
|
||||
|
||||
$(PROJECT): $(OBJ_BIN)
|
||||
$(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -o $(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) -f $(MAKEFILE_NAME) all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN_DIR)/*.o
|
||||
rm -f $(BIN_DIR)/$(BINARY)
|
||||
|
@ -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: amx.cpp 3707 2008-04-14 19:56:31Z sawce $
|
||||
*/
|
||||
|
||||
#define AMX_NODYNALOAD
|
||||
@ -936,7 +934,7 @@ int AMXAPI amx_Init(AMX *amx, void *program)
|
||||
|
||||
/* 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
|
||||
|
||||
@ -1175,12 +1173,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++)
|
||||
{
|
||||
@ -1640,7 +1638,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)
|
||||
{
|
||||
@ -1824,14 +1822,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:
|
||||
@ -1897,14 +1895,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:
|
||||
@ -1921,7 +1919,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);
|
||||
@ -1929,7 +1927,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);
|
||||
@ -2366,13 +2364,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);
|
||||
@ -2381,22 +2379,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;
|
||||
@ -4094,10 +4092,6 @@ int AMXAPI amx_GetLibraries(AMX *amx)
|
||||
return numLibraries;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#define _snprintf snprintf
|
||||
#endif
|
||||
|
||||
const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len)
|
||||
{
|
||||
AMX_HEADER *hdr = (AMX_HEADER *)amx->base;
|
||||
@ -4141,7 +4135,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 */
|
||||
|
@ -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: amx.h 3006 2006-08-28 11:08:18Z dvander $
|
||||
*/
|
||||
|
||||
#if defined FREEBSD && !defined __FreeBSD__
|
||||
@ -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 */
|
||||
|
@ -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: amxcore.cpp 1733 2005-07-25 06:03:43Z dvander $
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
# if !defined UNICODE /* for Windows */
|
||||
# define UNICODE
|
||||
|
@ -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: amxdbg.cpp 2345 2006-02-10 19:47:09Z faluco $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -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: amxdbg.h 2977 2006-08-27 02:17:18Z damagedsoul $
|
||||
*/
|
||||
|
||||
#ifndef AMXDBG_H_INCLUDED
|
||||
|
@ -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,6 +314,32 @@
|
||||
%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
|
||||
|
||||
%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
|
||||
global getMaxCodeSize, _getMaxCodeSize
|
||||
@ -1942,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
|
||||
@ -2238,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
|
||||
@ -2254,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:
|
||||
@ -2273,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
|
||||
@ -2287,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
|
||||
@ -2305,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
|
||||
@ -2320,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
|
||||
|
||||
|
@ -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
|
2704
amxmodx/amxmodx.cpp
2704
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
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#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"
|
||||
@ -69,6 +48,11 @@
|
||||
#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
|
||||
@ -85,8 +69,12 @@ 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[];
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||
#define DLPROC(m, func) GetProcAddress(m, func)
|
||||
#define DLFREE(m) FreeLibrary(m)
|
||||
@ -107,21 +95,13 @@ extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined PLATFORM_WINDOWS
|
||||
typedef HINSTANCE DLHANDLE;
|
||||
#else
|
||||
typedef void* DLHANDLE;
|
||||
#define INFINITE 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define PATH_SEP_CHAR '\\'
|
||||
#define ALT_SEP_CHAR '/'
|
||||
#else
|
||||
#define PATH_SEP_CHAR '/'
|
||||
#define ALT_SEP_CHAR '\\'
|
||||
#endif
|
||||
|
||||
#ifndef GETPLAYERAUTHID
|
||||
#define GETPLAYERAUTHID (*g_engfuncs.pfnGetPlayerAuthId)
|
||||
#endif
|
||||
@ -133,19 +113,34 @@ extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||
#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, 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))])
|
||||
@ -153,7 +148,7 @@ char *UTIL_VarArgs(const char *fmt, ...);
|
||||
|
||||
struct WeaponsVault
|
||||
{
|
||||
String fullName;
|
||||
ke::AString fullName;
|
||||
short int iId;
|
||||
short int ammoSlot;
|
||||
};
|
||||
@ -164,27 +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 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;
|
||||
@ -192,9 +188,15 @@ 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_language;
|
||||
extern cvar_t* hostname;
|
||||
extern cvar_t* mp_timelimit;
|
||||
extern fakecmd_t g_fakecmd;
|
||||
@ -235,6 +237,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*);
|
||||
@ -247,6 +251,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();
|
||||
@ -258,10 +263,6 @@ int loadModules(const char* filename, PLUG_LOADTIME now);
|
||||
void detachModules();
|
||||
void detachReloadModules();
|
||||
|
||||
#ifdef FAKEMETA
|
||||
void attachModules();
|
||||
#endif
|
||||
|
||||
// Count modules
|
||||
enum CountModulesMode
|
||||
{
|
||||
@ -282,23 +283,27 @@ 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(const char *fmt, ...);
|
||||
void report_error(int code, const char* fmt, ...);
|
||||
void* alloc_amxmemory(void**, int size);
|
||||
void free_amxmemory(void **ptr);
|
||||
// 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
|
||||
@ -333,6 +338,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);
|
||||
@ -353,6 +360,15 @@ enum AdminProperty
|
||||
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: amxtime.cpp 2511 2006-04-06 12:56:45Z damagedsoul $
|
||||
*/
|
||||
#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"
|
||||
|
@ -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
|
||||
@ -44,12 +23,12 @@
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#include "svn_version.h"
|
||||
#include <amxmodx_version.h>
|
||||
|
||||
CLog::CLog()
|
||||
{
|
||||
m_LogType = 0;
|
||||
m_LogFile.clear();
|
||||
m_LogFile = nullptr;
|
||||
m_FoundError = false;
|
||||
m_LoggedErrMap = false;
|
||||
}
|
||||
@ -62,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;
|
||||
@ -82,75 +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)
|
||||
{
|
||||
snprintf(name, sizeof(name), "%s/L%02d%02d%03d.log", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday, i);
|
||||
build_pathname_r(file, sizeof(file)-1, "%s", name);
|
||||
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\") (version \"%s\")\n", name, SVN_VERSION_STRING);
|
||||
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];
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
mkdir(build_pathname_r(file, sizeof(file)-1, "%s", g_log_dir.c_str()), 0700);
|
||||
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;
|
||||
|
||||
@ -167,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
|
||||
@ -190,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%04d%02d%02d.log", g_log_dir.c_str(), (curTime->tm_year + 1900), 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);
|
||||
@ -233,7 +218,7 @@ 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)
|
||||
@ -258,8 +243,8 @@ void CLog::LogError(const char *fmt, ...)
|
||||
va_end(arglst);
|
||||
|
||||
FILE *pF = NULL;
|
||||
snprintf(name, sizeof(name), "%s/error_%04d%02d%02d.log", g_log_dir.c_str(), curTime->tm_year + 1900, curTime->tm_mon + 1, curTime->tm_mday);
|
||||
build_pathname_r(file, sizeof(file)-1, "%s", name);
|
||||
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)
|
||||
@ -281,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,9 +49,9 @@ 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
|
||||
@ -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}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,321 +1,197 @@
|
||||
/* 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 DATASTRUCTS_H
|
||||
#define DATASTRUCTS_H
|
||||
|
||||
class CellVector
|
||||
{
|
||||
private:
|
||||
cell* data; // allocated with malloc
|
||||
size_t cellcount; // how many cells per element
|
||||
size_t cursize; // current size of the vector (maximum elements)
|
||||
size_t count; // how many units of the vector are in use
|
||||
|
||||
public:
|
||||
CellVector(): data(NULL), cellcount(0), cursize(0), count(0)
|
||||
{
|
||||
};
|
||||
CellVector(int cellsize): data(NULL), cellcount(cellsize), cursize(0), count(0)
|
||||
{
|
||||
};
|
||||
~CellVector()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
};
|
||||
size_t GetCellCount()
|
||||
{
|
||||
return cellcount;
|
||||
};
|
||||
void Grow(size_t howmany)
|
||||
{
|
||||
cursize+=howmany;
|
||||
if (data)
|
||||
{
|
||||
data=(cell*)realloc(data, (sizeof(cell) * cellcount) * cursize);
|
||||
}
|
||||
else
|
||||
{
|
||||
data=(cell*)malloc((sizeof(cell) * cellcount) * cursize);
|
||||
}
|
||||
};
|
||||
void FreeUnused(void)
|
||||
{
|
||||
if (cursize != count &&
|
||||
data != NULL)
|
||||
{
|
||||
cursize=count;
|
||||
data=(cell*)realloc(data, cursize * (sizeof(cell) * cellcount));
|
||||
}
|
||||
};
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds.
|
||||
int GetArray(size_t which, cell* output)
|
||||
{
|
||||
// make sure it is in bounds.
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// align output data
|
||||
cell* out=data + (cellcount * which);
|
||||
|
||||
memcpy(output, out, sizeof(cell) * cellcount);
|
||||
|
||||
return 1;
|
||||
};
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds
|
||||
int GetCell(size_t which, cell* output)
|
||||
{
|
||||
// check bounds
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*output=*(data + (cellcount * which));
|
||||
|
||||
return 1;
|
||||
}
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds
|
||||
int GetString(size_t which, cell* output, size_t size)
|
||||
{
|
||||
// check bounds
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cell* out=data + (cellcount * which);
|
||||
|
||||
size_t count=cellcount;
|
||||
|
||||
while (size-- &&
|
||||
count-- &&
|
||||
(*output++=*out++)!='\0')
|
||||
/* do nothing */ ;
|
||||
|
||||
// If size is zero here, then the string was never null terminated.
|
||||
if (size==0)
|
||||
{
|
||||
*out='\0';
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds
|
||||
int SetArray(size_t which, cell* output)
|
||||
{
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// align output
|
||||
cell* out=data + (cellcount * which);
|
||||
|
||||
memcpy(out, output, sizeof(cell) * cellcount);
|
||||
|
||||
return 1;
|
||||
};
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds
|
||||
int SetCell(size_t which, cell output)
|
||||
{
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// align output
|
||||
*(data + (cellcount * which))=output;
|
||||
|
||||
return 1;
|
||||
};
|
||||
// Returns 1 on success
|
||||
// 0 on out of bounds
|
||||
int SetString(size_t which, cell* output)
|
||||
{
|
||||
if (which >= count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// align output
|
||||
cell* out=data + (cellcount * which);
|
||||
|
||||
memcpy(out, output, sizeof(cell) * cellcount);
|
||||
|
||||
// now force a null terminator on the last entry.
|
||||
out+=(cellcount - 1);
|
||||
*out='\0';
|
||||
|
||||
return 1;
|
||||
};
|
||||
int Push()
|
||||
{
|
||||
if (count >= cursize)
|
||||
{
|
||||
// Grow in 8s to cause less reallocation
|
||||
this->Grow(8);
|
||||
};
|
||||
|
||||
this->count++;
|
||||
|
||||
return this->count-1;
|
||||
};
|
||||
int Size()
|
||||
{
|
||||
return this->count;
|
||||
};
|
||||
void Clear()
|
||||
{
|
||||
free(data);
|
||||
data=(cell*)malloc(sizeof(cell) * cellcount);
|
||||
cursize=1;
|
||||
count=0;
|
||||
};
|
||||
cell* GetCellPointer(size_t which)
|
||||
{
|
||||
if (which >= count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return data + (which * cellcount);
|
||||
};
|
||||
// Shifts all items from this item, and including this item up 1.
|
||||
int ShiftUpFrom(size_t which)
|
||||
{
|
||||
// No point shifting this.
|
||||
if (which > this->count)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
// First make a new item.
|
||||
this->Push();
|
||||
|
||||
// If we got an InsertAfter(lastitem), then which will equal this->count - 1
|
||||
// all we needed to do was Push()
|
||||
if (which == this->count ||
|
||||
which == this->count - 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Allocate a temporary buffer to store data in
|
||||
size_t tempbuffsize=(sizeof(cell) * cellcount) * (this->count - which);
|
||||
|
||||
cell* temp=(cell*)malloc(tempbuffsize);
|
||||
|
||||
// Copy old data to temp buffer
|
||||
memcpy(temp, GetCellPointer(which), tempbuffsize);
|
||||
|
||||
// Now copy temp buffer to adjusted location
|
||||
memcpy(GetCellPointer(which+1), temp, tempbuffsize);
|
||||
|
||||
// cleanup
|
||||
free(temp);
|
||||
|
||||
return 1;
|
||||
|
||||
};
|
||||
// Shifts all items from this item, and including this item down 1.
|
||||
// This deletes the item specified.
|
||||
int Delete(size_t which)
|
||||
{
|
||||
// No point shifting this.
|
||||
if (which >= this->count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i=which; i<this->count - 1; i++)
|
||||
{
|
||||
memcpy(GetCellPointer(i), GetCellPointer(i + 1), sizeof(cell) * cellcount);
|
||||
}
|
||||
this->count--;
|
||||
return 1;
|
||||
};
|
||||
int Swap(size_t item1, size_t item2)
|
||||
{
|
||||
if (item1 >= this->count ||
|
||||
item2 >= this->count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make a temp buffer to store item2
|
||||
cell* temp=(cell*)malloc(sizeof(cell) * cellcount);
|
||||
memcpy(temp, GetCellPointer(item2), sizeof(cell) * cellcount);
|
||||
|
||||
// copy item1 to item2
|
||||
memcpy(GetCellPointer(item2), GetCellPointer(item1), sizeof(cell) * cellcount);
|
||||
|
||||
// copy item2 to item1
|
||||
memcpy(GetCellPointer(item1), temp, sizeof(cell) * cellcount);
|
||||
|
||||
// Cleanup
|
||||
free(temp);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
extern CVector<CellVector*> VectorHolder;
|
||||
|
||||
|
||||
inline CellVector* HandleToVector(AMX* amx, int handle)
|
||||
{
|
||||
if (handle <= 0 ||
|
||||
handle > (int)VectorHolder.size())
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CellVector* ret=VectorHolder[handle-1];
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
// 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 == static_cast<int>(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<len; 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)
|
||||
@ -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);
|
||||
@ -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,7 +153,7 @@ 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 > -1); }
|
||||
bool InNativeFilter() { return m_InNativeFilter; }
|
||||
@ -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;
|
||||
};
|
||||
|
@ -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"
|
||||
@ -52,6 +30,8 @@ int gmsgWeaponList;
|
||||
int gmsgintermission;
|
||||
int gmsgResetHUD;
|
||||
int gmsgRoundTime;
|
||||
int gmsgSayText;
|
||||
int gmsgInitHUD;
|
||||
|
||||
TeamIds g_teamsIds;
|
||||
WeaponsVault g_weaponsData[MAX_WEAPONS];
|
||||
@ -107,9 +87,24 @@ 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;
|
||||
g_players[index].team = msg;
|
||||
g_teamsIds.registerTeam(msg, -1);
|
||||
g_players[index].teamId = g_teamsIds.findTeamId(msg);
|
||||
|
||||
/**
|
||||
* 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_players[index].teamId == -1 && g_bmod_cstrike && !strcmp(msg, "SPECTATOR"))
|
||||
{
|
||||
g_players[index].teamId = 3;
|
||||
g_teamsIds.registerTeam(msg, 3);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -192,7 +187,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +273,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +287,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;
|
||||
@ -323,11 +318,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__
|
||||
|
1611
amxmodx/file.cpp
1611
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,7 +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 "datastructs.h"
|
||||
#include "amxmod_compat.h"
|
||||
|
||||
//Adapted from Quake3's vsprintf
|
||||
// thanks to cybermind for linking me to this :)
|
||||
@ -34,97 +42,129 @@ template size_t atcprintf<char, cell>(char *, size_t, const cell *, AMX *, cell
|
||||
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 *);
|
||||
|
||||
THash<String, lang_err> BadLang_Table;
|
||||
THash<ke::AString, lang_err> BadLang_Table;
|
||||
|
||||
static cvar_t *amx_mldebug = NULL;
|
||||
static cvar_t *amx_cl_langs = NULL;
|
||||
static cvar_t *amx_mldebug = nullptr;
|
||||
static cvar_t *amx_cl_langs = nullptr;
|
||||
|
||||
const char *translate(AMX *amx, cell amxaddr, const char *key)
|
||||
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;
|
||||
|
||||
@ -149,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;
|
||||
|
||||
@ -286,6 +332,58 @@ void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec, int f
|
||||
*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;
|
||||
|
||||
digits = 0;
|
||||
do
|
||||
{
|
||||
if (val & 1)
|
||||
{
|
||||
text[digits++] = '1';
|
||||
}
|
||||
else
|
||||
{
|
||||
text[digits++] = '0';
|
||||
}
|
||||
val >>= 1;
|
||||
} 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 U>
|
||||
void AddUInt(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
|
||||
{
|
||||
@ -458,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;
|
||||
|
||||
@ -486,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++);
|
||||
@ -527,6 +625,11 @@ reswitch:
|
||||
llen--;
|
||||
arg++;
|
||||
break;
|
||||
case 'b':
|
||||
CHECK_ARGS(0);
|
||||
AddBinary(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
|
||||
arg++;
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
CHECK_ARGS(0);
|
||||
@ -571,38 +674,33 @@ reswitch:
|
||||
}
|
||||
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);
|
||||
@ -610,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)
|
||||
@ -635,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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user