mirror of
https://github.com/EssentialsX/Essentials.git
synced 2026-11-05 01:00:13 -05:00
Compare commits
3362
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f57557b43a | ||
|
|
0711fd6f9e | ||
|
|
b5ecbd1739 | ||
|
|
dda5e4e333 | ||
|
|
dde4a36df0 | ||
|
|
31b98fb9f3 | ||
|
|
289d34d96c | ||
|
|
eafd110ed0 | ||
|
|
e72644abf4 | ||
|
|
b267103274 | ||
|
|
3856a690eb | ||
|
|
f214696664 | ||
|
|
9e73c29b40 | ||
|
|
aca83bd462 | ||
|
|
189d6a23c6 | ||
|
|
441f88deea | ||
|
|
6d6666dace | ||
|
|
fb779533e6 | ||
|
|
7325113a8c | ||
|
|
827217823e | ||
|
|
060dfc69f4 | ||
|
|
b831713737 | ||
|
|
7da90b3a6b | ||
|
|
32540c23ab | ||
|
|
d24b0616f8 | ||
|
|
9aef2ef883 | ||
|
|
727d473319 | ||
|
|
8225e51867 | ||
|
|
1ba6c2a596 | ||
|
|
60a166aeb0 | ||
|
|
65c2155bca | ||
|
|
6031c01584 | ||
|
|
da8e8c8a25 | ||
|
|
70a750a32d | ||
|
|
7c63324504 | ||
|
|
dd41b10522 | ||
|
|
7948e764d4 | ||
|
|
82ede4530a | ||
|
|
e8ab2db8e8 | ||
|
|
8882e0214c | ||
|
|
4adb669cdd | ||
|
|
7e1d258dd3 | ||
|
|
417fe29e21 | ||
|
|
bd8ef2a25d | ||
|
|
fd01b75c33 | ||
|
|
1388755d2a | ||
|
|
97cc3d0066 | ||
|
|
694cf7a79e | ||
|
|
da89efb79f | ||
|
|
04ec013407 | ||
|
|
023cf6a1aa | ||
|
|
f7cbb141f8 | ||
|
|
5690952516 | ||
|
|
e94202c55a | ||
|
|
aa6ad271a0 | ||
|
|
3b41bb47b6 | ||
|
|
e7bdb7fabc | ||
|
|
110698223d | ||
|
|
437be593b9 | ||
|
|
502d37b574 | ||
|
|
df59f9f859 | ||
|
|
f436fbab6b | ||
|
|
8404720501 | ||
|
|
4431d452f1 | ||
|
|
6a529d6671 | ||
|
|
78fca9a67a | ||
|
|
0114b5e4f6 | ||
|
|
5a14a64b6c | ||
|
|
b555ea6350 | ||
|
|
361ae1dd16 | ||
|
|
58117eba88 | ||
|
|
6260b49b4f | ||
|
|
988239267b | ||
|
|
19cffe3872 | ||
|
|
3b1cef918e | ||
|
|
3553328f7a | ||
|
|
0202271f00 | ||
|
|
d91d6a419c | ||
|
|
5173090474 | ||
|
|
c26df8318f | ||
|
|
7b44f0088a | ||
|
|
aa4d3cc9fd | ||
|
|
246fd03265 | ||
|
|
55074872fe | ||
|
|
28559dda3a | ||
|
|
cbcfad5b2e | ||
|
|
a9ad440860 | ||
|
|
5104463593 | ||
|
|
4b1c51c21d | ||
|
|
236ef52980 | ||
|
|
f220c5b406 | ||
|
|
9415582fe1 | ||
|
|
a5a3630727 | ||
|
|
f4c36d9c43 | ||
|
|
492005d00a | ||
|
|
149d9b61cc | ||
|
|
77ffb6a3d5 | ||
|
|
d95b632884 | ||
|
|
579f554edb | ||
|
|
050287f306 | ||
|
|
dafe156212 | ||
|
|
48bf264178 | ||
|
|
769dbe8852 | ||
|
|
67bccb865a | ||
|
|
d1e60de04a | ||
|
|
89d592ce43 | ||
|
|
c06dda886d | ||
|
|
23d92fac63 | ||
|
|
5922b85290 | ||
|
|
814e5a643e | ||
|
|
3db3a272d5 | ||
|
|
2d703fbc80 | ||
|
|
b49d3cc21c | ||
|
|
02b5d2357a | ||
|
|
1206178eca | ||
|
|
3df3f8a812 | ||
|
|
7049952b07 | ||
|
|
a18ce40921 | ||
|
|
6a6383462d | ||
|
|
44301fae4f | ||
|
|
6ee84510ea | ||
|
|
6ecdc8d7fc | ||
|
|
35a2a4d803 | ||
|
|
7b67b3b858 | ||
|
|
4011810536 | ||
|
|
85ea07c97e | ||
|
|
41b2449cdd | ||
|
|
ec83a5fff2 | ||
|
|
ded6f06ed2 | ||
|
|
2605e050a0 | ||
|
|
19b1e19e42 | ||
|
|
f7a1149cac | ||
|
|
7dd52dab32 | ||
|
|
937aec600a | ||
|
|
4802053da6 | ||
|
|
0105dff7ac | ||
|
|
8cc448efcf | ||
|
|
982b358bf8 | ||
|
|
ffc80d61af | ||
|
|
f55956612c | ||
|
|
cd3b342d74 | ||
|
|
ba959586e2 | ||
|
|
4c07e584b7 | ||
|
|
280d1215de | ||
|
|
a2a95ed840 | ||
|
|
4bd9461282 | ||
|
|
96adef5269 | ||
|
|
9576ea25a6 | ||
|
|
a7fcafb245 | ||
|
|
73bb41d579 | ||
|
|
0a90d76493 | ||
|
|
010981d3c8 | ||
|
|
3353061e76 | ||
|
|
79bc34047b | ||
|
|
60c90408e7 | ||
|
|
1218c3e226 | ||
|
|
a05fc9d08e | ||
|
|
6906ef2154 | ||
|
|
7d25e84ebc | ||
|
|
121d935315 | ||
|
|
2f66a866d8 | ||
|
|
0e088c17a8 | ||
|
|
4cd8a6636b | ||
|
|
5c7fc763fc | ||
|
|
1e381a59be | ||
|
|
85111f25cb | ||
|
|
f78887a02e | ||
|
|
feba535637 | ||
|
|
3262143c73 | ||
|
|
18feb7967a | ||
|
|
e9b1511117 | ||
|
|
177e5f62f7 | ||
|
|
f3f4395da7 | ||
|
|
442e46b012 | ||
|
|
37d699d05b | ||
|
|
77ed1e1d4a | ||
|
|
50e4cd67b5 | ||
|
|
83a90eb553 | ||
|
|
c29599d39a | ||
|
|
692e0adde4 | ||
|
|
cdba518bae | ||
|
|
b70b67fa1f | ||
|
|
ff0ca9bc7b | ||
|
|
320bc25d94 | ||
|
|
425e955b5d | ||
|
|
33ae9a2597 | ||
|
|
19913d3612 | ||
|
|
a3eb58724f | ||
|
|
0afa00779c | ||
|
|
17d5545804 | ||
|
|
cd70662f01 | ||
|
|
a89c97409b | ||
|
|
102cb6d949 | ||
|
|
6c9c9ad42a | ||
|
|
acbc96fd55 | ||
|
|
ca721c1acb | ||
|
|
3bf669c42a | ||
|
|
cdc5f75fcb | ||
|
|
d74f19970b | ||
|
|
2ddde37771 | ||
|
|
c1c422e03d | ||
|
|
7608b7d658 | ||
|
|
d1d5ae814f | ||
|
|
452fa61717 | ||
|
|
825f697fd2 | ||
|
|
4ea71ae88e | ||
|
|
bdb32f5878 | ||
|
|
e3c726b8f6 | ||
|
|
96c6c7b1ca | ||
|
|
634d62f9ef | ||
|
|
2806156cf4 | ||
|
|
e642192461 | ||
|
|
959c788f22 | ||
|
|
cda520589a | ||
|
|
5c1db129d3 | ||
|
|
c718962426 | ||
|
|
575a11b645 | ||
|
|
f97c5fc1ff | ||
|
|
81397d98b8 | ||
|
|
82b2ff0b3f | ||
|
|
05fcb7b1aa | ||
|
|
c79db98978 | ||
|
|
303aa77901 | ||
|
|
65a4ef7ee5 | ||
|
|
1be7fbd8a6 | ||
|
|
935b5cfe0f | ||
|
|
bad02729db | ||
|
|
80f7ded687 | ||
|
|
f569b89d8f | ||
|
|
fec655a29c | ||
|
|
610774b0b9 | ||
|
|
9487665fae | ||
|
|
d5b43b7162 | ||
|
|
718d9d9d3a | ||
|
|
3705dbdd2b | ||
|
|
c37d516980 | ||
|
|
b27a6b5b8e | ||
|
|
98809fafd7 | ||
|
|
dd9a0de98d | ||
|
|
de2298cf0a | ||
|
|
56fb8b06cd | ||
|
|
3b1eb683e1 | ||
|
|
1029305382 | ||
|
|
9b39509e88 | ||
|
|
9da58dde5c | ||
|
|
e2507d2ff1 | ||
|
|
b867f121c9 | ||
|
|
3c6a869336 | ||
|
|
f357e76980 | ||
|
|
946a1fbb7c | ||
|
|
37acdc18f2 | ||
|
|
4dc1d2c50e | ||
|
|
ed72d117a5 | ||
|
|
a302913130 | ||
|
|
659f1a271a | ||
|
|
3fb4b7958d | ||
|
|
3ef0f20b0d | ||
|
|
340baa9703 | ||
|
|
0e9232ba81 | ||
|
|
299afdc6a1 | ||
|
|
04feed8524 | ||
|
|
773979cb37 | ||
|
|
c27d05fd4b | ||
|
|
52d814f2cc | ||
|
|
5009b3b545 | ||
|
|
4e165d375c | ||
|
|
306f7a7872 | ||
|
|
6c11569ac9 | ||
|
|
4be28ba193 | ||
|
|
a1e98f898b | ||
|
|
c5376d3088 | ||
|
|
3e1857b966 | ||
|
|
b8a8232bc3 | ||
|
|
504a7aef0f | ||
|
|
1ddb1822ef | ||
|
|
d3cd4e356d | ||
|
|
bef440760a | ||
|
|
768b92749f | ||
|
|
03b25a0f06 | ||
|
|
a44775cafb | ||
|
|
187c4eb371 | ||
|
|
49201b9945 | ||
|
|
6225dc8ed1 | ||
|
|
aa622f8d27 | ||
|
|
849efa9756 | ||
|
|
8aa764f69f | ||
|
|
de57a8c602 | ||
|
|
4873beb100 | ||
|
|
27d9f3725a | ||
|
|
16b2c3dee3 | ||
|
|
2ced9469d7 | ||
|
|
45c806128a | ||
|
|
3d60aa1747 | ||
|
|
967bb44d94 | ||
|
|
7298393ec9 | ||
|
|
817caf299f | ||
|
|
2ff29dab80 | ||
|
|
030eb3375b | ||
|
|
3237632eb4 | ||
|
|
b29f98c525 | ||
|
|
b2a5280971 | ||
|
|
613e852ffd | ||
|
|
823f1c2ee3 | ||
|
|
7d7c58fa7c | ||
|
|
a468ec5e08 | ||
|
|
ce1e584266 | ||
|
|
ecd6c5f81a | ||
|
|
61c1485083 | ||
|
|
9f6d0fa2d6 | ||
|
|
1c398f819e | ||
|
|
c7000846cd | ||
|
|
d3c4c2ba6a | ||
|
|
95ac4a4853 | ||
|
|
0d5da063fb | ||
|
|
06f04b8fba | ||
|
|
d24fbc9f55 | ||
|
|
7e40d13947 | ||
|
|
43e520a03e | ||
|
|
4e8e7bec3f | ||
|
|
fe7b6097c9 | ||
|
|
0d634853b6 | ||
|
|
29b05eb167 | ||
|
|
834454491e | ||
|
|
a9a80b5766 | ||
|
|
b21f42ee7c | ||
|
|
d92884800b | ||
|
|
e57d0e96e2 | ||
|
|
983f3a7935 | ||
|
|
37dfd81cc9 | ||
|
|
05400429db | ||
|
|
e4a8222d48 | ||
|
|
fb5ebdb0c2 | ||
|
|
1ef1cd98db | ||
|
|
d581f48cd1 | ||
|
|
752565b8f1 | ||
|
|
8e61753894 | ||
|
|
ba35efd021 | ||
|
|
09af6ad186 | ||
|
|
16a496c706 | ||
|
|
71d50f4e1e | ||
|
|
8a815b42d3 | ||
|
|
d69e3a2f48 | ||
|
|
e38b15531d | ||
|
|
fcc7c3af78 | ||
|
|
738efe8c50 | ||
|
|
938f94e130 | ||
|
|
ace361af60 | ||
|
|
d4138ce843 | ||
|
|
377c716d52 | ||
|
|
cd43355d4c | ||
|
|
1f0f77ff72 | ||
|
|
147c5e0ddf | ||
|
|
1518db17f8 | ||
|
|
ef1e57f445 | ||
|
|
87c6672212 | ||
|
|
ab087e941e | ||
|
|
4f70d623a1 | ||
|
|
ba143f8657 | ||
|
|
b6aea0a5f8 | ||
|
|
50e2d27d5b | ||
|
|
f0bf359df3 | ||
|
|
fd6717d06d | ||
|
|
126046a039 | ||
|
|
6705513cb3 | ||
|
|
28fb18b6c7 | ||
|
|
17bb5fe1da | ||
|
|
3e908b9c01 | ||
|
|
8977425475 | ||
|
|
8f92e3f217 | ||
|
|
f07f132cfd | ||
|
|
cd7e0963ce | ||
|
|
9dc58948b2 | ||
|
|
d16e67c51e | ||
|
|
5fa2ce7d9e | ||
|
|
0a0c45238c | ||
|
|
ea36ee37a2 | ||
|
|
a907dab432 | ||
|
|
9a3b4db387 | ||
|
|
cdabe4a46e | ||
|
|
29bc7ca19e | ||
|
|
36ee10a52b | ||
|
|
1a820ad9b7 | ||
|
|
dcbc106e62 | ||
|
|
cdf777384e | ||
|
|
3a6f04e461 | ||
|
|
d36f6e45de | ||
|
|
f8ddb50140 | ||
|
|
be076509f2 | ||
|
|
73457453bb | ||
|
|
3091849ff8 | ||
|
|
5136eb84f4 | ||
|
|
c14d565b56 | ||
|
|
57e87d9d4e | ||
|
|
c1eccf499e | ||
|
|
e5b76083b7 | ||
|
|
a8d9139b6c | ||
|
|
703186e931 | ||
|
|
e6fc459080 | ||
|
|
90feb9941f | ||
|
|
2c4ff35796 | ||
|
|
13ccabecf2 | ||
|
|
ed5aa1f469 | ||
|
|
b34697040a | ||
|
|
430f08b25f | ||
|
|
f85170eea3 | ||
|
|
5a0ec91159 | ||
|
|
a049a03faa | ||
|
|
365ae356bd | ||
|
|
04755cee33 | ||
|
|
e4fbe28f95 | ||
|
|
1bc0768683 | ||
|
|
1f42e1e2c1 | ||
|
|
91b2622ba2 | ||
|
|
eb341c0704 | ||
|
|
09eecb1c3b | ||
|
|
1562a8f3ca | ||
|
|
13fbd31124 | ||
|
|
433ebe4a21 | ||
|
|
e5c7ba72e5 | ||
|
|
203d6561ac | ||
|
|
117704b0bc | ||
|
|
7958cd0b88 | ||
|
|
51f2a04958 | ||
|
|
a27eb17684 | ||
|
|
05d2b6ccda | ||
|
|
ec61ffcaad | ||
|
|
ed0ad87632 | ||
|
|
4802744ce7 | ||
|
|
adf7e22324 | ||
|
|
09f63364dc | ||
|
|
8c256664b2 | ||
|
|
0354ffa4f8 | ||
|
|
d5f15b8283 | ||
|
|
c4009233a3 | ||
|
|
e02bceaf5d | ||
|
|
8796dbeb56 | ||
|
|
fd63a7df4e | ||
|
|
7fbc721db6 | ||
|
|
210494d0d1 | ||
|
|
9963476218 | ||
|
|
50f2e7a95f | ||
|
|
d7685dc1bc | ||
|
|
301a3a72df | ||
|
|
518a43db9c | ||
|
|
243e69649f | ||
|
|
781204aa20 | ||
|
|
9a714eb537 | ||
|
|
d5cbfefc21 | ||
|
|
12930cfce4 | ||
|
|
298c292ffb | ||
|
|
341263b934 | ||
|
|
11a03bbce9 | ||
|
|
3831464665 | ||
|
|
2fe05b4ff4 | ||
|
|
ec3dc50e20 | ||
|
|
171b2b6a37 | ||
|
|
14a02c0602 | ||
|
|
34e3582557 | ||
|
|
01592e9770 | ||
|
|
3fba6e9ad0 | ||
|
|
bbe0ca9302 | ||
|
|
e572788a8c | ||
|
|
4c0857fbb5 | ||
|
|
44ed1e2d44 | ||
|
|
8fd532c648 | ||
|
|
7c0fa46b4d | ||
|
|
85d0644868 | ||
|
|
4bd3cffc4e | ||
|
|
3ecebdc758 | ||
|
|
f13e355010 | ||
|
|
c28d749548 | ||
|
|
d0760ddd04 | ||
|
|
af5d2c2fca | ||
|
|
4bfabaa1d3 | ||
|
|
747420b4c8 | ||
|
|
78b710dc22 | ||
|
|
7973f544ff | ||
|
|
0b1e1676d0 | ||
|
|
705c1c60c8 | ||
|
|
abfec5a60f | ||
|
|
ca28d8aa84 | ||
|
|
198d852995 | ||
|
|
5f83766dc1 | ||
|
|
442d97a1b1 | ||
|
|
fcbd3deb6b | ||
|
|
dadc6b2d3a | ||
|
|
6231a25413 | ||
|
|
bc08b11011 | ||
|
|
36b08e9b1d | ||
|
|
d73ec779e0 | ||
|
|
6bc9f2140c | ||
|
|
a6f1e305ef | ||
|
|
5fda1d018b | ||
|
|
c919eba206 | ||
|
|
61b3ca531c | ||
|
|
96164f5851 | ||
|
|
4102b11f15 | ||
|
|
3c18efc4a6 | ||
|
|
cfc2b7ff2f | ||
|
|
ad94cca95b | ||
|
|
6ade8132af | ||
|
|
e5b5994593 | ||
|
|
944ddf8d70 | ||
|
|
8b0659a2b4 | ||
|
|
35388c3b19 | ||
|
|
27ab90ab2a | ||
|
|
d41af02ade | ||
|
|
e0a578d06c | ||
|
|
db47460a79 | ||
|
|
a1bcbdc181 | ||
|
|
d1dda6a166 | ||
|
|
7290dbc5a5 | ||
|
|
8bc47c45a4 | ||
|
|
1f5b659f2d | ||
|
|
a591dba8ef | ||
|
|
85d6c836a8 | ||
|
|
7498a5f983 | ||
|
|
63b5068591 | ||
|
|
c54da35a39 | ||
|
|
6789e5c0de | ||
|
|
1fed66d652 | ||
|
|
f42904e5ae | ||
|
|
58828d7924 | ||
|
|
ee64f7c4ff | ||
|
|
3c0424226e | ||
|
|
dd226dfdcf | ||
|
|
16e05cc17b | ||
|
|
13bceb9f5d | ||
|
|
03c652cd55 | ||
|
|
00301b26e6 | ||
|
|
611429b6f6 | ||
|
|
34979c8e84 | ||
|
|
3a6da5cd26 | ||
|
|
9c18b94ec8 | ||
|
|
5187be5d02 | ||
|
|
1c009e1ebc | ||
|
|
8927fe9ea9 | ||
|
|
63b5cb9ec7 | ||
|
|
30d5fbdf8d | ||
|
|
5960f55339 | ||
|
|
743ac51c4c | ||
|
|
2493c655f8 | ||
|
|
f1d9cda5eb | ||
|
|
a76b20f1b5 | ||
|
|
017082c07a | ||
|
|
352c92b880 | ||
|
|
948cce4ceb | ||
|
|
6fe87184ae | ||
|
|
c4c303dbfb | ||
|
|
87adbb477d | ||
|
|
3245ce10ac | ||
|
|
5540683013 | ||
|
|
75d1254dda | ||
|
|
83b944eb4b | ||
|
|
6cbb8c846b | ||
|
|
e0d69d05eb | ||
|
|
4f971ad8e5 | ||
|
|
fa59a3f65c | ||
|
|
8d921d78c5 | ||
|
|
953e44c4a4 | ||
|
|
b664159231 | ||
|
|
5867cd2e1b | ||
|
|
535fb43915 | ||
|
|
0952115776 | ||
|
|
79401c3cf7 | ||
|
|
0ab9f04ea4 | ||
|
|
04f14285e7 | ||
|
|
2a2aef53fb | ||
|
|
3651e672d4 | ||
|
|
9dfa650d7e | ||
|
|
a0a166b553 | ||
|
|
e7f4b46de8 | ||
|
|
b5148cd0ec | ||
|
|
e90b0c28c6 | ||
|
|
3a439bcdb5 | ||
|
|
23e8498b47 | ||
|
|
c9f1b0fdc5 | ||
|
|
19f6510840 | ||
|
|
0a1feaf044 | ||
|
|
890c32949d | ||
|
|
8b37bb5bd7 | ||
|
|
1aff0c2dcb | ||
|
|
a7f137d122 | ||
|
|
148fa7d6da | ||
|
|
20594d2523 | ||
|
|
142315140e | ||
|
|
8d3d2ebd50 | ||
|
|
e674056b3a | ||
|
|
785bd5bfcf | ||
|
|
fb72555e6b | ||
|
|
42f4d43682 | ||
|
|
caeb59ede4 | ||
|
|
992ef5dc91 | ||
|
|
d37433e81c | ||
|
|
d75e0ce26e | ||
|
|
09acbcdb05 | ||
|
|
864dadab80 | ||
|
|
d174cea42e | ||
|
|
e95fad0453 | ||
|
|
ebe6abd885 | ||
|
|
0a563b91a2 | ||
|
|
5cbcd7469b | ||
|
|
dabcb51034 | ||
|
|
0237d485bf | ||
|
|
b673630a7e | ||
|
|
282ec81af1 | ||
|
|
a267fb16b8 | ||
|
|
795ffec8b8 | ||
|
|
dba9dab985 | ||
|
|
abfa815cf1 | ||
|
|
872b25e0c5 | ||
|
|
3fa810e329 | ||
|
|
4951c4822e | ||
|
|
5842b5f51d | ||
|
|
ac4a1565a1 | ||
|
|
203e8b0a75 | ||
|
|
c75594f314 | ||
|
|
690dbea924 | ||
|
|
e7c81504a9 | ||
|
|
fdd5bc5a8e | ||
|
|
91bebabc7f | ||
|
|
5eec83f726 | ||
|
|
827891f10a | ||
|
|
f4fa24cd7f | ||
|
|
2bf1f24db2 | ||
|
|
34c6155fe9 | ||
|
|
3ead31ef14 | ||
|
|
d0ea32dfa1 | ||
|
|
7c1a0ed719 | ||
|
|
b050b13aa3 | ||
|
|
60548e4523 | ||
|
|
8fe002f820 | ||
|
|
65a2e942c4 | ||
|
|
4adb59ab98 | ||
|
|
fa0bbde236 | ||
|
|
e5b1e6c0ad | ||
|
|
731455649e | ||
|
|
ec1215b227 | ||
|
|
dcb14170b9 | ||
|
|
c266778c1e | ||
|
|
8116ce39d7 | ||
|
|
8167002092 | ||
|
|
5cddb84a58 | ||
|
|
a9e41841e9 | ||
|
|
37f6deab85 | ||
|
|
a4aa6a22b7 | ||
|
|
d57f7af453 | ||
|
|
7f8c801c07 | ||
|
|
c627b26f49 | ||
|
|
7c788dfa31 | ||
|
|
3896b27c54 | ||
|
|
97561667a0 | ||
|
|
bdb81123d6 | ||
|
|
f1c57371a3 | ||
|
|
873f9404bf | ||
|
|
7eac272386 | ||
|
|
e6d177c09a | ||
|
|
65f2051e87 | ||
|
|
767abe83f9 | ||
|
|
6eb63fd3fd | ||
|
|
03c59a9f17 | ||
|
|
3fd925c1fd | ||
|
|
6ea8f7b621 | ||
|
|
4e77fc0f0b | ||
|
|
6d347881b7 | ||
|
|
73ad945101 | ||
|
|
d39615d906 | ||
|
|
dcc6e2f23f | ||
|
|
24e068b94d | ||
|
|
6b6cf41782 | ||
|
|
d17bd144a2 | ||
|
|
a5686a17e2 | ||
|
|
2fab3b9957 | ||
|
|
9e2a9abee1 | ||
|
|
10eed23430 | ||
|
|
7967f62131 | ||
|
|
8102bab3ff | ||
|
|
dd026700be | ||
|
|
0001665ece | ||
|
|
d0a7c5a0ec | ||
|
|
ba97e5fff5 | ||
|
|
e90455463f | ||
|
|
72760096f5 | ||
|
|
148cbd06e0 | ||
|
|
62c2c57d4d | ||
|
|
b8f7918a4a | ||
|
|
526118e7d3 | ||
|
|
37c20d5b6d | ||
|
|
5b60998b0a | ||
|
|
833713bee2 | ||
|
|
cf1f2f8f03 | ||
|
|
f6cbda0e04 | ||
|
|
7d33814d5b | ||
|
|
7c59d61b32 | ||
|
|
844a4a0574 | ||
|
|
5968a6bc27 | ||
|
|
f94e242a75 | ||
|
|
ddee7d1b94 | ||
|
|
30fce436dd | ||
|
|
dfdc6a52be | ||
|
|
ba5ce33464 | ||
|
|
7809615896 | ||
|
|
27a297a18d | ||
|
|
bbf657e251 | ||
|
|
c6d2746959 | ||
|
|
d895d40fbf | ||
|
|
a1d40f24a7 | ||
|
|
fd697aeb83 | ||
|
|
6e05327934 | ||
|
|
a4871cac36 | ||
|
|
b17f5d32c9 | ||
|
|
3896bcbd64 | ||
|
|
9c986aa25f | ||
|
|
419d2d8282 | ||
|
|
d570570394 | ||
|
|
0347badeda | ||
|
|
eb924b9861 | ||
|
|
38c8a8e666 | ||
|
|
9f75f1aad3 | ||
|
|
a669163196 | ||
|
|
87842a36ba | ||
|
|
2d3691107d | ||
|
|
134fbdf1df | ||
|
|
ab490cd588 | ||
|
|
2e903acbaa | ||
|
|
06417910e2 | ||
|
|
c56dd6e302 | ||
|
|
19dcb33eb7 | ||
|
|
540fa98a44 | ||
|
|
7428b7f981 | ||
|
|
6fc19b92eb | ||
|
|
1a701e69ca | ||
|
|
569c848764 | ||
|
|
ad93d15197 | ||
|
|
4a0507a838 | ||
|
|
bc4737562d | ||
|
|
55f3a14343 | ||
|
|
72e99a8833 | ||
|
|
0eb5063332 | ||
|
|
ca387687a5 | ||
|
|
2d376bc72f | ||
|
|
58948b45b3 | ||
|
|
514f9b90f0 | ||
|
|
0c41363914 | ||
|
|
9bf0b65016 | ||
|
|
cdfe2b1487 | ||
|
|
fe936a683f | ||
|
|
e3cc5f2df8 | ||
|
|
3c0dc1e455 | ||
|
|
d5b781fd60 | ||
|
|
0a876c33a7 | ||
|
|
fc8ee7f25f | ||
|
|
cf448cd1cc | ||
|
|
928f05ca8f | ||
|
|
7b60552ec1 | ||
|
|
26045e2ec0 | ||
|
|
e5ebeaf724 | ||
|
|
dc24bb53c2 | ||
|
|
2175cb8a44 | ||
|
|
756ea346e6 | ||
|
|
23f3d69d38 | ||
|
|
a134e99c8c | ||
|
|
607f1980a1 | ||
|
|
fb4af9fefc | ||
|
|
447b9db397 | ||
|
|
77eb430b0b | ||
|
|
d4ab25b200 | ||
|
|
faaa4a4b1e | ||
|
|
a844e8b5ad | ||
|
|
84143d06fa | ||
|
|
9805f3f4d1 | ||
|
|
bae6f89fa5 | ||
|
|
a721e04119 | ||
|
|
6360c690cf | ||
|
|
aa75a3f20d | ||
|
|
3edfec2491 | ||
|
|
c364adcf00 | ||
|
|
7d6714f713 | ||
|
|
8485bd44f9 | ||
|
|
c0800afeeb | ||
|
|
046752f8c2 | ||
|
|
9307f9b9c1 | ||
|
|
ee2018416e | ||
|
|
6c38b6c6fb | ||
|
|
cafb297594 | ||
|
|
8bec43f7a2 | ||
|
|
fe1dd0d0f3 | ||
|
|
b066d4dd83 | ||
|
|
792c7d5e91 | ||
|
|
76498e86f5 | ||
|
|
540a15160c | ||
|
|
6eb5aded38 | ||
|
|
891605380f | ||
|
|
fe9348b3fb | ||
|
|
c592a9d361 | ||
|
|
fae159cdbd | ||
|
|
d7b0f74a75 | ||
|
|
d5301824fc | ||
|
|
28607ce58c | ||
|
|
9fb0ab57e6 | ||
|
|
6143b088c3 | ||
|
|
06e24b3bc2 | ||
|
|
3283b8c0a3 | ||
|
|
f43501e828 | ||
|
|
192ced4e4c | ||
|
|
dd65a1e76c | ||
|
|
0b042dad43 | ||
|
|
14384f6bfa | ||
|
|
b9f293f8a7 | ||
|
|
d03d85b52b | ||
|
|
cf9c9f7073 | ||
|
|
7fb263e75c | ||
|
|
1d20184f0b | ||
|
|
500384abf3 | ||
|
|
d1b18da36e | ||
|
|
3b3acbcfda | ||
|
|
6c35dfcb3d | ||
|
|
01ad006ca3 | ||
|
|
7e580920f6 | ||
|
|
5227824608 | ||
|
|
1c78f5cc3b | ||
|
|
306aab0d8d | ||
|
|
e33c42e123 | ||
|
|
9ccfd4aac0 | ||
|
|
549da08f87 | ||
|
|
b6c7799cc2 | ||
|
|
d063b5a894 | ||
|
|
cd78211cdf | ||
|
|
4e9d6d22dd | ||
|
|
3a3d1a5981 | ||
|
|
b15d868f77 | ||
|
|
a6232b6bb6 | ||
|
|
6ca3712b79 | ||
|
|
db6724acdf | ||
|
|
16c7bf2eb3 | ||
|
|
0331fafa77 | ||
|
|
1d63209691 | ||
|
|
140ece68d3 | ||
|
|
e95ca8444e | ||
|
|
dce381fb28 | ||
|
|
121b262d1b | ||
|
|
51b52ac343 | ||
|
|
8793add589 | ||
|
|
e4f6bb363d | ||
|
|
6bd34f44ef | ||
|
|
be60e10ebd | ||
|
|
56cfffb2ef | ||
|
|
20a59ddb6e | ||
|
|
bfa93cc189 | ||
|
|
480055b3d7 | ||
|
|
5e605f992a | ||
|
|
3634cab1a5 | ||
|
|
8e2ffe08f8 | ||
|
|
b6957db352 | ||
|
|
ff3b1e810f | ||
|
|
14c4ed8379 | ||
|
|
a224894380 | ||
|
|
f5a4c8f11e | ||
|
|
73ac6488ce | ||
|
|
c03765803c | ||
|
|
65fc8a9c41 | ||
|
|
e8e15d2cd4 | ||
|
|
d7849f4120 | ||
|
|
c48f68f0dc | ||
|
|
fe49e08340 | ||
|
|
5051f3c4d7 | ||
|
|
0c8695a888 | ||
|
|
d63e342f78 | ||
|
|
9f4ccf9eaf | ||
|
|
1f14ac5c18 | ||
|
|
8f71261646 | ||
|
|
1a9954428b | ||
|
|
e43ae47a78 | ||
|
|
57213dd625 | ||
|
|
ce5ffb9bd7 | ||
|
|
5375ff3790 | ||
|
|
37d4dc70e5 | ||
|
|
e7337d06b5 | ||
|
|
bcc76aff63 | ||
|
|
154d43819a | ||
|
|
318e0eabea | ||
|
|
0a2f1a3dfe | ||
|
|
b19dbb1b8f | ||
|
|
904a9700b2 | ||
|
|
f5daf7085e | ||
|
|
f500e2ce9a | ||
|
|
e2a67365f9 | ||
|
|
2273329e29 | ||
|
|
be1acfdccd | ||
|
|
2f39811a46 | ||
|
|
f995676fad | ||
|
|
ea4c966003 | ||
|
|
fe5de8a854 | ||
|
|
fa43f39015 | ||
|
|
4d0e6254dd | ||
|
|
e94e908bed | ||
|
|
179dbe19fd | ||
|
|
d6eb846488 | ||
|
|
6796d460dc | ||
|
|
4be2fc1a90 | ||
|
|
20f79f117f | ||
|
|
4169996e7a | ||
|
|
667fc18abf | ||
|
|
4f72ff47bc | ||
|
|
b7704a4ea8 | ||
|
|
ac0858dcdb | ||
|
|
7439dc01a5 | ||
|
|
090e0b6757 | ||
|
|
effad664d5 | ||
|
|
01bf7d1389 | ||
|
|
b7c7e4ad23 | ||
|
|
5ca02e6596 | ||
|
|
6b2f87c5a9 | ||
|
|
9a265aac48 | ||
|
|
5b052c170f | ||
|
|
555f151692 | ||
|
|
c22978c3f9 | ||
|
|
54b3a23ae2 | ||
|
|
f5b40dba34 | ||
|
|
f8160c6318 | ||
|
|
b113bb59d4 | ||
|
|
15bd41fefc | ||
|
|
4e6aef3d24 | ||
|
|
c798f995ca | ||
|
|
9bca2b44ab | ||
|
|
dde0b20775 | ||
|
|
ad13062117 | ||
|
|
d11a295ffd | ||
|
|
ffea359661 | ||
|
|
037456c99d | ||
|
|
5125a137f4 | ||
|
|
3f1c996959 | ||
|
|
53a7cd732f | ||
|
|
4fd026ff99 | ||
|
|
d9fbd68529 | ||
|
|
49d80462d1 | ||
|
|
1d859e49ad | ||
|
|
a2c43d822c | ||
|
|
7907565377 | ||
|
|
d1c014fe16 | ||
|
|
465041b98b | ||
|
|
ed56afda26 | ||
|
|
23f14bc2d5 | ||
|
|
c829a32555 | ||
|
|
ae984c2055 | ||
|
|
0c416c8366 | ||
|
|
51be2131f7 | ||
|
|
575a8142ff | ||
|
|
093a1f677b | ||
|
|
8311da2653 | ||
|
|
b5976a52e0 | ||
|
|
4e6c98ac57 | ||
|
|
a2c692af39 | ||
|
|
a131527a15 | ||
|
|
0b925e6fc0 | ||
|
|
97c8f5192e | ||
|
|
7c372cd978 | ||
|
|
02fe58161c | ||
|
|
2ba2ebaa43 | ||
|
|
549500eaf2 | ||
|
|
8e7589e450 | ||
|
|
9b69403ee1 | ||
|
|
6269ce9a3f | ||
|
|
0f6625aea9 | ||
|
|
dbceccaa3e | ||
|
|
6c7ba6a76f | ||
|
|
f76a517339 | ||
|
|
2c747ecf36 | ||
|
|
1f8b60081e | ||
|
|
a800359e0b | ||
|
|
4854961901 | ||
|
|
50a815bdb9 | ||
|
|
1690b9d83d | ||
|
|
7804516793 | ||
|
|
c54e9b5dba | ||
|
|
71936cfe22 | ||
|
|
27890e2b22 | ||
|
|
da6df89126 | ||
|
|
95ff197910 | ||
|
|
2215b0f53f | ||
|
|
3887fdd47d | ||
|
|
7e9328bd25 | ||
|
|
9d9af25c7f | ||
|
|
5a2fd19bcf | ||
|
|
3a50850734 | ||
|
|
812de5c35c | ||
|
|
bffea1d7c8 | ||
|
|
b00f458e67 | ||
|
|
80ef955eae | ||
|
|
44509ff6e4 | ||
|
|
e1d4129869 | ||
|
|
00655f724d | ||
|
|
4590e7ea26 | ||
|
|
2ac1ce4f56 | ||
|
|
f726035660 | ||
|
|
57bb1ee475 | ||
|
|
889dde7549 | ||
|
|
ada2fe01a2 | ||
|
|
cf29a0ba6a | ||
|
|
c929ebb89a | ||
|
|
8159530906 | ||
|
|
7e8ba9a256 | ||
|
|
b145ec59ea | ||
|
|
429a7275ee | ||
|
|
3bd0608b6e | ||
|
|
9307e0cb71 | ||
|
|
4672e51806 | ||
|
|
18811122b3 | ||
|
|
cbaf126a25 | ||
|
|
8e7abe325e | ||
|
|
ed9e4ecd28 | ||
|
|
bd866de950 | ||
|
|
4ecb6b5fdb | ||
|
|
0d6bca2080 | ||
|
|
05ef05dcac | ||
|
|
7ba097c640 | ||
|
|
6adacbb357 | ||
|
|
69f62574c4 | ||
|
|
b00c31730f | ||
|
|
f09180659d | ||
|
|
c12373bf41 | ||
|
|
04666b66b4 | ||
|
|
363aee70d5 | ||
|
|
01d03d5d41 | ||
|
|
4575fc5aff | ||
|
|
27e9e3aa88 | ||
|
|
b0187698b9 | ||
|
|
0364d4e0de | ||
|
|
86b57804c6 | ||
|
|
211dc220d8 | ||
|
|
aae586f79a | ||
|
|
32f49350cf | ||
|
|
9739784e75 | ||
|
|
a0e93af758 | ||
|
|
81c6291338 | ||
|
|
24509d60be | ||
|
|
f0947e9a7c | ||
|
|
92bb4e0e66 | ||
|
|
8f810ad447 | ||
|
|
3f35a6b59c | ||
|
|
427dd714c9 | ||
|
|
9d7a2043f7 | ||
|
|
ff3ec84b0d | ||
|
|
1f9e72c5e2 | ||
|
|
67be18566c | ||
|
|
862e71bc85 | ||
|
|
395655ba19 | ||
|
|
1bb569fff2 | ||
|
|
e66ad88451 | ||
|
|
3bf3093177 | ||
|
|
5eb82add06 | ||
|
|
8bd1a9f3bc | ||
|
|
145d24c34c | ||
|
|
229ff9f0e4 | ||
|
|
0557aa58b0 | ||
|
|
b40aa43872 | ||
|
|
a1cdfa19b0 | ||
|
|
d62b401db8 | ||
|
|
887957756e | ||
|
|
b6d6b24796 | ||
|
|
b6c0871daa | ||
|
|
b080187808 | ||
|
|
3c613fd59b | ||
|
|
547c6e4073 | ||
|
|
6098086a99 | ||
|
|
87f90e9bdd | ||
|
|
65b1821196 | ||
|
|
756321d280 | ||
|
|
3dbf69f163 | ||
|
|
e8ace54036 | ||
|
|
22e1c14e7e | ||
|
|
cd38aeb544 | ||
|
|
9e9409da1e | ||
|
|
36e580474f | ||
|
|
e007331581 | ||
|
|
8d435ec86e | ||
|
|
214d64e4ad | ||
|
|
737fadc390 | ||
|
|
10de6ac929 | ||
|
|
fe9fbf585f | ||
|
|
af3f3fb4c7 | ||
|
|
0e6a5240db | ||
|
|
f272a7ecd6 | ||
|
|
104caea3c9 | ||
|
|
44fbd05df7 | ||
|
|
6cfb5084e1 | ||
|
|
ae1804758a | ||
|
|
4b470b32c5 | ||
|
|
cfe89dde17 | ||
|
|
30dae51ddf | ||
|
|
0b11abf8f4 | ||
|
|
b673882b2f | ||
|
|
200dbda6d3 | ||
|
|
3538728733 | ||
|
|
5724c0c8df | ||
|
|
0b5718f7ff | ||
|
|
c6b0dfaa4c | ||
|
|
8fecd44786 | ||
|
|
2ee590d85c | ||
|
|
b469439f7b | ||
|
|
a7d6e5440b | ||
|
|
077074c855 | ||
|
|
c59a204827 | ||
|
|
1be30e4a0a | ||
|
|
28ec7c2d80 | ||
|
|
ee986768ce | ||
|
|
de485b8d48 | ||
|
|
e443776dc1 | ||
|
|
859ffeaa0b | ||
|
|
545d706a70 | ||
|
|
9ec0ca25a5 | ||
|
|
b0e165546e | ||
|
|
470f4c1b3e | ||
|
|
3b35763fef | ||
|
|
2d5c1fd51c | ||
|
|
088c54e386 | ||
|
|
e409363426 | ||
|
|
34599b7428 | ||
|
|
53c1c8a8b7 | ||
|
|
3f2c2aadbb | ||
|
|
a1a190bb02 | ||
|
|
6744b652e6 | ||
|
|
11b308cc8c | ||
|
|
c50f559512 | ||
|
|
98bee40bf7 | ||
|
|
970d342a60 | ||
|
|
2500c9af90 | ||
|
|
fa765d3077 | ||
|
|
9bc8f287a4 | ||
|
|
5e6ce8aecb | ||
|
|
6174e4a98b | ||
|
|
5c74af42a3 | ||
|
|
ce48f2f326 | ||
|
|
2affce875c | ||
|
|
52c8ebc61f | ||
|
|
a9249deea7 | ||
|
|
d99c35cc35 | ||
|
|
518650e842 | ||
|
|
20ff61909f | ||
|
|
f0e4e8c5ba | ||
|
|
63300866f9 | ||
|
|
c8212371ff | ||
|
|
0a6a79115a | ||
|
|
6798615507 | ||
|
|
016b39726c | ||
|
|
882ebae257 | ||
|
|
161862bc53 | ||
|
|
18b31a7e50 | ||
|
|
5b5be164b6 | ||
|
|
466b4ae7c5 | ||
|
|
e7c468b20d | ||
|
|
b9d09dd7b0 | ||
|
|
1c035457bb | ||
|
|
5070f15810 | ||
|
|
c8faf03f5b | ||
|
|
915cb51d1a | ||
|
|
52c3169a3c | ||
|
|
32b118d3c0 | ||
|
|
9ce1158aeb | ||
|
|
839bfe0c2e | ||
|
|
f39ef36115 | ||
|
|
eee18f40be | ||
|
|
4084445b5b | ||
|
|
8c882a5268 | ||
|
|
3b0e86ae67 | ||
|
|
3fecd3138d | ||
|
|
d48c02021d | ||
|
|
0b71b6e93d | ||
|
|
99d25bfaea | ||
|
|
46691871ad | ||
|
|
58440dd594 | ||
|
|
12c96e21b9 | ||
|
|
1d791fb110 | ||
|
|
0384ac5d42 | ||
|
|
def1569fcc | ||
|
|
7d7e87e63a | ||
|
|
8b26c7fc84 | ||
|
|
3017d2a7f4 | ||
|
|
23d2ffb134 | ||
|
|
ad2f446602 | ||
|
|
bcd5350a4d | ||
|
|
b6b2ee61a4 | ||
|
|
6362dbd5b3 | ||
|
|
ee55584117 | ||
|
|
e5b522ed14 | ||
|
|
df219db1a4 | ||
|
|
f8e273767e | ||
|
|
1bfab68932 | ||
|
|
901b835ae0 | ||
|
|
7d8d9d8959 | ||
|
|
b70b58660f | ||
|
|
18a6d1761a | ||
|
|
9a197d65a3 | ||
|
|
b68e451c13 | ||
|
|
11949a4315 | ||
|
|
f52858d058 | ||
|
|
90fc19cc7b | ||
|
|
ddb1f76a26 | ||
|
|
2584e0ab06 | ||
|
|
5dbf4f5a00 | ||
|
|
af02a28ce5 | ||
|
|
5e9f5904fd | ||
|
|
946051de71 | ||
|
|
427b97433e | ||
|
|
f3b005e331 | ||
|
|
5b64c31e86 | ||
|
|
723e458a81 | ||
|
|
309273dc6b | ||
|
|
d40e331c8a | ||
|
|
c57e902173 | ||
|
|
e864696b00 | ||
|
|
fed250fd74 | ||
|
|
5fe19dbd83 | ||
|
|
b836b3c041 | ||
|
|
9550ef2a0d | ||
|
|
bac26f966c | ||
|
|
278bb98649 | ||
|
|
3839b6f1f5 | ||
|
|
c0a58a5316 | ||
|
|
de7c2be960 | ||
|
|
c57c791e69 | ||
|
|
1ae2b094f3 | ||
|
|
dde8cd8f72 | ||
|
|
b3bad6a35a | ||
|
|
25e4096a12 | ||
|
|
e411f61296 | ||
|
|
caa3ac88aa | ||
|
|
f677d6a411 | ||
|
|
4232216f76 | ||
|
|
beef371ae6 | ||
|
|
872df26e9d | ||
|
|
8146858ee0 | ||
|
|
9b4e6e5dc6 | ||
|
|
53b1526906 | ||
|
|
82be7546d5 | ||
|
|
f400f81e4d | ||
|
|
5d1ea4aa88 | ||
|
|
7f8d62be02 | ||
|
|
3e725ef060 | ||
|
|
d5196e31b2 | ||
|
|
235f134514 | ||
|
|
6af1b923cc | ||
|
|
365888a8f9 | ||
|
|
b8f5c9a8e4 | ||
|
|
ae89c80d4e | ||
|
|
7436009ea4 | ||
|
|
84ce3d39d8 | ||
|
|
9aa88bdf8d | ||
|
|
f36f5ec0ce | ||
|
|
b1d422ba8f | ||
|
|
049577c97e | ||
|
|
92a9673652 | ||
|
|
1164bbd90d | ||
|
|
4ea629628d | ||
|
|
3e9a2377a8 | ||
|
|
48261daf89 | ||
|
|
97d176ea27 | ||
|
|
e25e02d154 | ||
|
|
50a9b5718c | ||
|
|
2615468a08 | ||
|
|
298e677373 | ||
|
|
64e089e15b | ||
|
|
be31b1695d | ||
|
|
6f85761f7f | ||
|
|
cf9d79d24c | ||
|
|
f53240191f | ||
|
|
27ee587887 | ||
|
|
601bdbff46 | ||
|
|
12bf4e9dcf | ||
|
|
59b501b2b1 | ||
|
|
9e20f556e1 | ||
|
|
375caa6f9e | ||
|
|
cc34c02623 | ||
|
|
cfa367dfc3 | ||
|
|
e1ff3542ae | ||
|
|
4951c204d2 | ||
|
|
122232a0e7 | ||
|
|
03368e45df | ||
|
|
e6b76cadbc | ||
|
|
06e3d33845 | ||
|
|
e853199d90 | ||
|
|
f7f7c2a68b | ||
|
|
99c73f3d67 | ||
|
|
6094485992 | ||
|
|
503d39ee55 | ||
|
|
bd5fd2980f | ||
|
|
a49895278b | ||
|
|
8d739d6a76 | ||
|
|
3963a528b3 | ||
|
|
7c686b4b58 | ||
|
|
0a17489c9c | ||
|
|
0926da3782 | ||
|
|
c056ba0059 | ||
|
|
df5d9a4db8 | ||
|
|
36c61eaa06 | ||
|
|
9908eb0619 | ||
|
|
64743ef428 | ||
|
|
2973b1335c | ||
|
|
52e9cc6ba1 | ||
|
|
62b4348842 | ||
|
|
eca3be5cf3 | ||
|
|
3fb4d1f3bf | ||
|
|
f96359e31c | ||
|
|
cf79daddde | ||
|
|
ed007589f3 | ||
|
|
b85aaea039 | ||
|
|
3a4e4c59e4 | ||
|
|
7f27de4bb7 | ||
|
|
a06a81c15d | ||
|
|
a29e1bfe51 | ||
|
|
3ccefb49c0 | ||
|
|
543672a2a8 | ||
|
|
8cba8da516 | ||
|
|
3b8df2d18e | ||
|
|
b8cdd7d1f7 | ||
|
|
92a2244650 | ||
|
|
75fe543579 | ||
|
|
7bc84d6cad | ||
|
|
2928e8a99f | ||
|
|
ffae86dd42 | ||
|
|
ff41588c3b | ||
|
|
66eb9202ce | ||
|
|
f17ad2c4e7 | ||
|
|
794dd788a3 | ||
|
|
b3cae17cab | ||
|
|
1ac5b4230e | ||
|
|
a3cae43f9f | ||
|
|
d329d27a4f | ||
|
|
e9c0bd3bab | ||
|
|
c43574eab9 | ||
|
|
09e8b87650 | ||
|
|
ee05bf371d | ||
|
|
fb9fc579d0 | ||
|
|
8b11b870b1 | ||
|
|
7401608cc5 | ||
|
|
4cfa3fc3a2 | ||
|
|
0d9db22d81 | ||
|
|
cc1ae2c243 | ||
|
|
53faf70d10 | ||
|
|
4d87033771 | ||
|
|
b08aaec6c0 | ||
|
|
152cf98a9d | ||
|
|
12cd467277 | ||
|
|
bb7c8c308d | ||
|
|
c15540862d | ||
|
|
ddc8c07cd7 | ||
|
|
0ef4dfd453 | ||
|
|
f50feedabb | ||
|
|
eb22254564 | ||
|
|
3cfde70ec6 | ||
|
|
f251c9e694 | ||
|
|
298da19334 | ||
|
|
e3c83be37e | ||
|
|
c1e39c7007 | ||
|
|
59515aed94 | ||
|
|
4eef8b5e84 | ||
|
|
8aac502ab6 | ||
|
|
3aca9f793b | ||
|
|
4483ff40b4 | ||
|
|
e8d9951ee8 | ||
|
|
bf675b230e | ||
|
|
ba6fd95247 | ||
|
|
419f51636a | ||
|
|
f6f71126a1 | ||
|
|
1f3e52a4b9 | ||
|
|
0bfe1ec1de | ||
|
|
00463a7899 | ||
|
|
11f87eccb0 | ||
|
|
0d2dea41e3 | ||
|
|
8009c1539a | ||
|
|
29ea24f715 | ||
|
|
a14104c529 | ||
|
|
d044ba2fb9 | ||
|
|
5eb3d9fa42 | ||
|
|
fc63f63de6 | ||
|
|
cd51d718ba | ||
|
|
200ad81862 | ||
|
|
c05ad0458f | ||
|
|
ecd2484cb9 | ||
|
|
43c2c02336 | ||
|
|
adb5189d42 | ||
|
|
ef3b052c64 | ||
|
|
f5624d4cb6 | ||
|
|
624f7ab9f6 | ||
|
|
dad348d3d0 | ||
|
|
3d0f0062a9 | ||
|
|
ab359f678a | ||
|
|
406c9e807e | ||
|
|
d858555263 | ||
|
|
72fd893733 | ||
|
|
9f015c1bda | ||
|
|
61ed77b60c | ||
|
|
e57aa0e088 | ||
|
|
2ad346e84c | ||
|
|
aa65a2b349 | ||
|
|
499a1aee7f | ||
|
|
3377e3483d | ||
|
|
427d8cc4e0 | ||
|
|
4e9a42671f | ||
|
|
a369f9aabb | ||
|
|
2f4a19a5b8 | ||
|
|
6d360421f8 | ||
|
|
03a10e80b9 | ||
|
|
1abacf00df | ||
|
|
3d29248ace | ||
|
|
3f5e2ad85a | ||
|
|
817174e18f | ||
|
|
df2ab974bc | ||
|
|
423a722152 | ||
|
|
34f6487ba2 | ||
|
|
522c3e85b2 | ||
|
|
188a214de9 | ||
|
|
d0795fc3e7 | ||
|
|
95a2fce9a6 | ||
|
|
d6ef0e1e50 | ||
|
|
f6fd0bdb32 | ||
|
|
cb052e690c | ||
|
|
6af622b6b1 | ||
|
|
dded3cae14 | ||
|
|
6a3c5694ac | ||
|
|
90c1df7cc7 | ||
|
|
ff8c7b3315 | ||
|
|
0e43233e46 | ||
|
|
db234b9837 | ||
|
|
42b77864cd | ||
|
|
f485cbc48b | ||
|
|
0292cb59cd | ||
|
|
3e519f95d5 | ||
|
|
18d0183364 | ||
|
|
96cf363567 | ||
|
|
cfc6ed9364 | ||
|
|
3de3f00b11 | ||
|
|
c69c78f15c | ||
|
|
0fdd367098 | ||
|
|
1a49cdd140 | ||
|
|
cd4bdb83d4 | ||
|
|
f6fc9777b5 | ||
|
|
9edc68bb2b | ||
|
|
8f1f68f2be | ||
|
|
c0ed8649d0 | ||
|
|
f26466831a | ||
|
|
c92ae00f9f | ||
|
|
66355f0ead | ||
|
|
eeb9c13276 | ||
|
|
9300529113 | ||
|
|
19e4acfc97 | ||
|
|
1cb9ddf9fe | ||
|
|
c801bc0173 | ||
|
|
88d025cd0f | ||
|
|
dc1469105b | ||
|
|
d3e0966b3f | ||
|
|
a15e0b3875 | ||
|
|
52ba151b81 | ||
|
|
aa6c6b4d48 | ||
|
|
7648e38ec2 | ||
|
|
a67520477b | ||
|
|
f8fb8935d7 | ||
|
|
8ae0ea98a3 | ||
|
|
5338f6b706 | ||
|
|
fdb5d85ba5 | ||
|
|
2b4b1520d3 | ||
|
|
07bcd17e0f | ||
|
|
8fb91c5a61 | ||
|
|
aa6d85eacc | ||
|
|
f5986194aa | ||
|
|
b646bda9d2 | ||
|
|
fe86f3a01d | ||
|
|
ae2a03d80c | ||
|
|
e4d7aacc5d | ||
|
|
129fd53d5a | ||
|
|
6bf57de64d | ||
|
|
f1eae9be6f | ||
|
|
a77c2d6d95 | ||
|
|
c476471978 | ||
|
|
8755935fcb | ||
|
|
9976cc847f | ||
|
|
56f86c9ae4 | ||
|
|
bdb5d095ca | ||
|
|
f38ed576c5 | ||
|
|
09f67c9723 | ||
|
|
98e427e831 | ||
|
|
ac6b74887f | ||
|
|
7276bcccab | ||
|
|
a7b62c65b8 | ||
|
|
f48ed6988d | ||
|
|
b8300cc35a | ||
|
|
a3e6996ef9 | ||
|
|
34daa5691c | ||
|
|
0457705850 | ||
|
|
5d5fee4612 | ||
|
|
43f4a69760 | ||
|
|
55cee73a48 | ||
|
|
51f554827c | ||
|
|
d6756a2605 | ||
|
|
b065f4a05a | ||
|
|
867bfbf1b8 | ||
|
|
7fe83dbd91 | ||
|
|
1a4c2e8484 | ||
|
|
84874c9855 | ||
|
|
6512a53a3f | ||
|
|
423c8c54dc | ||
|
|
160a1a04eb | ||
|
|
88c5b64694 | ||
|
|
19451c151e | ||
|
|
e4d041b9b0 | ||
|
|
3bcd3390fe | ||
|
|
35783ee429 | ||
|
|
66911bb0a9 | ||
|
|
d48c342e37 | ||
|
|
5c05870490 | ||
|
|
d76fe946b7 | ||
|
|
a738e49e3c | ||
|
|
9dc6e7ad1e | ||
|
|
293406a603 | ||
|
|
727c53eb2b | ||
|
|
274ad06665 | ||
|
|
5e6f6b2482 | ||
|
|
29c9a46c2f | ||
|
|
6d317fd26d | ||
|
|
8ebe55a294 | ||
|
|
af2c514f2a | ||
|
|
3042151fee | ||
|
|
59f67acfd0 | ||
|
|
7051801a85 | ||
|
|
0d02b91506 | ||
|
|
5f6cca83ce | ||
|
|
ed5743147b | ||
|
|
1bb7946e13 | ||
|
|
9ec1a6b78f | ||
|
|
76a96d1004 | ||
|
|
b49aaee66d | ||
|
|
0d34b9ae9f | ||
|
|
6044cca54f | ||
|
|
aaebb6143e | ||
|
|
c4ac744d35 | ||
|
|
162b67aaa6 | ||
|
|
2d70bb19f7 | ||
|
|
801acbb004 | ||
|
|
aeb1b4601c | ||
|
|
f5b32f51aa | ||
|
|
0b20055f60 | ||
|
|
2f30064ab4 | ||
|
|
a65d0db57d | ||
|
|
479dad9966 | ||
|
|
b7acccfc8b | ||
|
|
fbcfd4948b | ||
|
|
cdbdb5e8e9 | ||
|
|
6e20275cc7 | ||
|
|
aac9e4884d | ||
|
|
ddb3b13931 | ||
|
|
c62f762724 | ||
|
|
4bdeb1324d | ||
|
|
555a300378 | ||
|
|
ebc6b14284 | ||
|
|
041fa8537d | ||
|
|
7bbceed491 | ||
|
|
7a46de6b02 | ||
|
|
1ab2a51550 | ||
|
|
42dc6a2e07 | ||
|
|
9ba9223632 | ||
|
|
c4173c0486 | ||
|
|
049886797b | ||
|
|
a43cbe061a | ||
|
|
9d2358ed4d | ||
|
|
7913cfdb3c | ||
|
|
137d0df9dc | ||
|
|
d425ab5f93 | ||
|
|
012741fea6 | ||
|
|
006f996283 | ||
|
|
538a2425c5 | ||
|
|
79bdd8a212 | ||
|
|
28cbac6610 | ||
|
|
0a03696983 | ||
|
|
f0ab66c4c6 | ||
|
|
57184f01e9 | ||
|
|
02df03a4b1 | ||
|
|
3396cf6e02 | ||
|
|
e60f17bb53 | ||
|
|
eb0c71984c | ||
|
|
865b581d06 | ||
|
|
b093111920 | ||
|
|
c55e52539e | ||
|
|
1dfad57c6f | ||
|
|
6148583fb2 | ||
|
|
9160410a50 | ||
|
|
2588e20140 | ||
|
|
e291633ac8 | ||
|
|
dfc62bca76 | ||
|
|
f48871ff29 | ||
|
|
c2eb7b05b3 | ||
|
|
547e262061 | ||
|
|
62942bdb3d | ||
|
|
e8c2a9792f | ||
|
|
f1bc7a305a | ||
|
|
fd0134227c | ||
|
|
59c833aa9e | ||
|
|
f6e2db1eda | ||
|
|
eeb31e054f | ||
|
|
4629cad99b | ||
|
|
5e360995eb | ||
|
|
a72777d043 | ||
|
|
39d66b1c43 | ||
|
|
9a3295439b | ||
|
|
656a40abb2 | ||
|
|
7e80f440ca | ||
|
|
e353ec7f66 | ||
|
|
bacb84a943 | ||
|
|
bac2b3f878 | ||
|
|
8f41cc07e3 | ||
|
|
4f033d8073 | ||
|
|
284d7a23ca | ||
|
|
8777410d30 | ||
|
|
3356db080a | ||
|
|
55e8aa765b | ||
|
|
d2ee2e3646 | ||
|
|
d9a6974ae2 | ||
|
|
641fbca40c | ||
|
|
11fafb5339 | ||
|
|
e4b04db412 | ||
|
|
93b76446f5 | ||
|
|
e3183e66df | ||
|
|
9d1f25c455 | ||
|
|
9fe226b79a | ||
|
|
228ecd2a5c | ||
|
|
4eb6c9b54f | ||
|
|
c093b6e7c2 | ||
|
|
757a41f890 | ||
|
|
8427b41e30 | ||
|
|
159cbba809 | ||
|
|
8604debc4e | ||
|
|
22efa3e000 | ||
|
|
578576e317 | ||
|
|
98aa303ff5 | ||
|
|
c857832759 | ||
|
|
aab6af768d | ||
|
|
879560092f | ||
|
|
411b4e2b8f | ||
|
|
519785d09f | ||
|
|
231f9d49c1 | ||
|
|
e15a8c50d6 | ||
|
|
386b73dbdb | ||
|
|
c7f62700d5 | ||
|
|
85741288ce | ||
|
|
566a826cf1 | ||
|
|
28e069eb6b | ||
|
|
44584b11c5 | ||
|
|
b8e079ddcb | ||
|
|
35792f9728 | ||
|
|
353423efec | ||
|
|
889157371c | ||
|
|
896e14670f | ||
|
|
8f6c61fa99 | ||
|
|
1d6ac42311 | ||
|
|
61b115ceac | ||
|
|
a5ec8b9cbb | ||
|
|
5af1f50b65 | ||
|
|
093611fb2a | ||
|
|
709ddae508 | ||
|
|
cac53ab12e | ||
|
|
df55e162d4 | ||
|
|
ea9bf854cc | ||
|
|
f5c17fc7c7 | ||
|
|
2dda15d47f | ||
|
|
d9485cea8d | ||
|
|
e728236dd3 | ||
|
|
fe28faf79d | ||
|
|
66e87bdd1c | ||
|
|
4b5cc8cfd8 | ||
|
|
8b97a84652 | ||
|
|
16ca842929 | ||
|
|
984eca9723 | ||
|
|
5b55fd97e6 | ||
|
|
0c82c61574 | ||
|
|
32099a4109 | ||
|
|
ce51a07bf1 | ||
|
|
5e4659e6ae | ||
|
|
2f96ef1e97 | ||
|
|
5ea1bdec56 | ||
|
|
f338d3c135 | ||
|
|
20d019383f | ||
|
|
ee080e56c2 | ||
|
|
d9a238fb80 | ||
|
|
3ddf883d5d | ||
|
|
1111254e46 | ||
|
|
6185581962 | ||
|
|
24a9a74fd5 | ||
|
|
208d673c2b | ||
|
|
2b0506de77 | ||
|
|
d63e259461 | ||
|
|
c8a867be38 | ||
|
|
734286e8d3 | ||
|
|
96c5bebdf2 | ||
|
|
fc96d7e0e9 | ||
|
|
fa445790e7 | ||
|
|
20b61a6147 | ||
|
|
c61abadd91 | ||
|
|
89c1cc5503 | ||
|
|
db86648b84 | ||
|
|
e68035cc7a | ||
|
|
895c14430a | ||
|
|
664fe18bbe | ||
|
|
e60c65cfc5 | ||
|
|
6b70899484 | ||
|
|
973e918d3a | ||
|
|
5cfb9326f6 | ||
|
|
16857da2b4 | ||
|
|
ee7b50a014 | ||
|
|
56bd973e94 | ||
|
|
9ff0571cea | ||
|
|
fc019af9f6 | ||
|
|
937ef0bb85 | ||
|
|
45fe5f2c02 | ||
|
|
b1f427d52e | ||
|
|
46e9471a63 | ||
|
|
4d9685e10d | ||
|
|
fd3cdde354 | ||
|
|
d93719ebcf | ||
|
|
63b2766e2b | ||
|
|
6d552281d4 | ||
|
|
6436baf7a4 | ||
|
|
896298a9e8 | ||
|
|
7d0fafd084 | ||
|
|
32d44eb13d | ||
|
|
c275626bee | ||
|
|
861b04b680 | ||
|
|
d8e4862e82 | ||
|
|
4aaf0eda79 | ||
|
|
2f9dcfee16 | ||
|
|
292f8a8799 | ||
|
|
ec87104c57 | ||
|
|
d7588e61bc | ||
|
|
061794e86d | ||
|
|
b9285b2aeb | ||
|
|
2187b7536e | ||
|
|
86c0767833 | ||
|
|
090c1f6f83 | ||
|
|
69c40a2f1a | ||
|
|
42edd14939 | ||
|
|
dba47cb44c | ||
|
|
b020983471 | ||
|
|
13efbb666d | ||
|
|
8d77a3f941 | ||
|
|
8f785598b0 | ||
|
|
58b1b34e44 | ||
|
|
ffbc05144c | ||
|
|
207a8d1b4f | ||
|
|
919f3abe6d | ||
|
|
c1f66fc817 | ||
|
|
8d2b10d783 | ||
|
|
38b7fa64fa | ||
|
|
f5ed4dd6cd | ||
|
|
17dab04094 | ||
|
|
308f05b8bf | ||
|
|
48db088fb4 | ||
|
|
9965e41567 | ||
|
|
0ddcfafbc0 | ||
|
|
6f55e4b316 | ||
|
|
de91073dda | ||
|
|
a11e8d4236 | ||
|
|
bf8f0365d9 | ||
|
|
d5f702f2cb | ||
|
|
c1b4ed5920 | ||
|
|
cc83553d72 | ||
|
|
643a9be985 | ||
|
|
9f13653be6 | ||
|
|
5f5a9adf31 | ||
|
|
29746df914 | ||
|
|
c3b42993de | ||
|
|
964bdc6d30 | ||
|
|
3d5aa40965 | ||
|
|
26352ac6b6 | ||
|
|
00ec717e7d | ||
|
|
f70015e8c5 | ||
|
|
399be38680 | ||
|
|
3bceecdfb6 | ||
|
|
68b95c668d | ||
|
|
a7648c7c12 | ||
|
|
bda3c32370 | ||
|
|
9ce067a7fd | ||
|
|
ef7d323902 | ||
|
|
b83a8eccee | ||
|
|
51ddcdcf87 | ||
|
|
8ca738a436 | ||
|
|
f9b5d74f6d | ||
|
|
8960417d56 | ||
|
|
90730f63d5 | ||
|
|
13e07f64ec | ||
|
|
6308b1ecf3 | ||
|
|
dff7e81b7f | ||
|
|
bf0a11e4fe | ||
|
|
c9efe14ad3 | ||
|
|
64ee6b7914 | ||
|
|
6ae6c51dc0 | ||
|
|
8710a133ce | ||
|
|
32b1ce9e39 | ||
|
|
c982592674 | ||
|
|
ff02f0e270 | ||
|
|
8f52908eed | ||
|
|
8f8fc4a08d | ||
|
|
e63276242c | ||
|
|
3ddbeea45a | ||
|
|
7f972801bf | ||
|
|
36e354388c | ||
|
|
bbd0021a8b | ||
|
|
880fb29b44 | ||
|
|
31f3662101 | ||
|
|
5f2c759a8f | ||
|
|
a91cfbf43a | ||
|
|
33fa32cbff | ||
|
|
69e941670f | ||
|
|
af10a2050a | ||
|
|
ce9e630072 | ||
|
|
ef063c255e | ||
|
|
0e7d64f9e7 | ||
|
|
2a91f593de | ||
|
|
9186ca2c9a | ||
|
|
f1e4e49779 | ||
|
|
3740f200f8 | ||
|
|
5840c02efc | ||
|
|
f16907412d | ||
|
|
44a6f4d562 | ||
|
|
ec8c778f68 | ||
|
|
56df6b36a5 | ||
|
|
30b65a0bc7 | ||
|
|
0dc8980d32 | ||
|
|
fa8b8bec5a | ||
|
|
63c7d4519a | ||
|
|
2a816cef7b | ||
|
|
c2d904ac7d | ||
|
|
911224dc64 | ||
|
|
0ad765e1c8 | ||
|
|
9db040edd4 | ||
|
|
c0f3e9073d | ||
|
|
e4565de717 | ||
|
|
33382f9940 | ||
|
|
1d0c2f75dc | ||
|
|
c3f0d34293 | ||
|
|
c298fb9332 | ||
|
|
a1f1319990 | ||
|
|
2316bfbd28 | ||
|
|
96348a5e92 | ||
|
|
d9903efcf4 | ||
|
|
bc90deb87d | ||
|
|
c35e5bf53a | ||
|
|
8ea0a152d4 | ||
|
|
8e205768b3 | ||
|
|
fcfa3ce31d | ||
|
|
05aeba521f | ||
|
|
8dff1155bf | ||
|
|
b6648ad9bd | ||
|
|
40f03295a1 | ||
|
|
5fdb10a5bf | ||
|
|
e9bb2df87d | ||
|
|
be29e4da59 | ||
|
|
b2a0166c46 | ||
|
|
03b115d4c3 | ||
|
|
d522a4230f | ||
|
|
f17485b112 | ||
|
|
1f932434c2 | ||
|
|
92b0178ca7 | ||
|
|
d30c3ca2a6 | ||
|
|
fb60272439 | ||
|
|
80ad075f02 | ||
|
|
37029e6b5d | ||
|
|
631e0bbd0a | ||
|
|
3f31dc179b | ||
|
|
5b975672e8 | ||
|
|
335d8b7f20 | ||
|
|
379e75f3e6 | ||
|
|
2ca171a3f4 | ||
|
|
8036cc9924 | ||
|
|
6442e793a9 | ||
|
|
d745b866c0 | ||
|
|
4493d7d00c | ||
|
|
631692d763 | ||
|
|
ef341ae539 | ||
|
|
d0e3c1d946 | ||
|
|
82137e0703 | ||
|
|
a3b2ffdeef | ||
|
|
dd095e15cb | ||
|
|
46fc6c192c | ||
|
|
6506c290c8 | ||
|
|
b1bc73f938 | ||
|
|
09851acd1b | ||
|
|
df42c9051b | ||
|
|
24c93c11c0 | ||
|
|
5a13e9bbe5 | ||
|
|
05f337c63c | ||
|
|
eea0c9682c | ||
|
|
2f567812d2 | ||
|
|
88c1b785af | ||
|
|
5225fb22f8 | ||
|
|
fae5780e09 | ||
|
|
7ec65bf213 | ||
|
|
d40484d016 | ||
|
|
971902ae38 | ||
|
|
844be04d75 | ||
|
|
ef01332114 | ||
|
|
705b193450 | ||
|
|
20b9111495 | ||
|
|
1661eddc02 | ||
|
|
15be319d3e | ||
|
|
fddbd7a52a | ||
|
|
360e3e8801 | ||
|
|
4edc39360a | ||
|
|
cd126264e0 | ||
|
|
df0ccb5832 | ||
|
|
8afcd41ab2 | ||
|
|
b8a71761ec | ||
|
|
738ded7ae5 | ||
|
|
5535435215 | ||
|
|
4167dd2590 | ||
|
|
623ff0f629 | ||
|
|
6e4ba4302f | ||
|
|
3d4d616414 | ||
|
|
d6c91d2d04 | ||
|
|
cef8cf7b75 | ||
|
|
12786a260e | ||
|
|
6ea956b11c | ||
|
|
132aa0cc1d | ||
|
|
b5733d6597 | ||
|
|
7fc4a75d4d | ||
|
|
e9e9efd2d7 | ||
|
|
9e4493fbb4 | ||
|
|
a64cb31211 | ||
|
|
57de3f3ed2 | ||
|
|
74b63a6f2d | ||
|
|
faad91849d | ||
|
|
ce7d83adb6 | ||
|
|
76d1ea5cab | ||
|
|
9fb42375b8 | ||
|
|
2a7f3c6525 | ||
|
|
c65353350f | ||
|
|
1ae58d05b4 | ||
|
|
4f35a72174 | ||
|
|
addd55228b | ||
|
|
bb29d48268 | ||
|
|
d9ee9b036c | ||
|
|
95e630de92 | ||
|
|
2836c0862d | ||
|
|
286091cd32 | ||
|
|
20786654a4 | ||
|
|
8fde5102b9 | ||
|
|
133fdac343 | ||
|
|
2361b9e724 | ||
|
|
972d831d0d | ||
|
|
bfa34130a0 | ||
|
|
befe1fb39e | ||
|
|
378eaaaf1f | ||
|
|
51a55318d0 | ||
|
|
4663c89dd6 | ||
|
|
2a1c3fb8e0 | ||
|
|
0ac1a90b93 | ||
|
|
ab6b3bff90 | ||
|
|
2d00fd0c1e | ||
|
|
e5f4cb9a4d | ||
|
|
91701e8c2f | ||
|
|
9cef107bc3 | ||
|
|
76fd829e8c | ||
|
|
6ea422015c | ||
|
|
443a317184 | ||
|
|
50dca9abf5 | ||
|
|
f1e3d48248 | ||
|
|
63ce4a99b9 | ||
|
|
1ccda52e9f | ||
|
|
1679790157 | ||
|
|
6170540a24 | ||
|
|
987b2ff4d5 | ||
|
|
23a15cb11a | ||
|
|
41547e3243 | ||
|
|
a586edfd0b | ||
|
|
762bb65677 | ||
|
|
73c92bf742 | ||
|
|
2b8435342d | ||
|
|
9566499a2f | ||
|
|
343c3a1bdd | ||
|
|
9aeb49f6c3 | ||
|
|
7dae04759f | ||
|
|
e2f6e5a7fd | ||
|
|
d26fa6c5b8 | ||
|
|
82f9505a2e | ||
|
|
f8ce80c18a | ||
|
|
313fd30ce9 | ||
|
|
da216b05d9 | ||
|
|
d8132548f6 | ||
|
|
6fdeddd96b | ||
|
|
8082508db9 | ||
|
|
78e6da9504 | ||
|
|
0014d5cfcb | ||
|
|
6aeba173b9 | ||
|
|
a2813358af | ||
|
|
8e663b53ce | ||
|
|
214d9414da | ||
|
|
6d7881f876 | ||
|
|
19ccdf2193 | ||
|
|
35036ecc18 | ||
|
|
b3cc4dbe09 | ||
|
|
04bd9e8baf | ||
|
|
fdc262a205 | ||
|
|
32ea86bfd3 | ||
|
|
4807fb39e5 | ||
|
|
4ffe61a505 | ||
|
|
d74952927a | ||
|
|
f8cf3be87f | ||
|
|
ada266a0f9 | ||
|
|
115c4fa1d0 | ||
|
|
0c19b2feed | ||
|
|
04c833f648 | ||
|
|
4533d09fc9 | ||
|
|
7337b86a16 | ||
|
|
3db015b1c1 | ||
|
|
659d602b57 | ||
|
|
f82d7e806f | ||
|
|
a8088fb8c8 | ||
|
|
84c06fb746 | ||
|
|
ffe2a283d2 | ||
|
|
7e3fd48956 | ||
|
|
bd22aec38a | ||
|
|
675c4b7897 | ||
|
|
ad7009c77e | ||
|
|
3f783bb43b | ||
|
|
9fe7712bd6 | ||
|
|
24f56892ad | ||
|
|
b860e943f6 | ||
|
|
5dc2665377 | ||
|
|
dd9b7e0d3c | ||
|
|
18a15ca63c | ||
|
|
ef1492a2a2 | ||
|
|
298ab846c1 | ||
|
|
7fdb2ad7d3 | ||
|
|
3afe8d18f4 | ||
|
|
0b581580c7 | ||
|
|
01e78cd666 | ||
|
|
29d28456aa | ||
|
|
f3812786d0 | ||
|
|
999d922fb9 | ||
|
|
2d4a07b95b | ||
|
|
5c99eee0c0 | ||
|
|
1fc502a4ff | ||
|
|
e73983649f | ||
|
|
465cdae989 | ||
|
|
341cb89bb7 | ||
|
|
79004c7098 | ||
|
|
2988db08ca | ||
|
|
b04fa82be2 | ||
|
|
5d210d81dc | ||
|
|
c14b32123f | ||
|
|
f256930269 | ||
|
|
cde95d832e | ||
|
|
b9af4fb35c | ||
|
|
5056210a38 | ||
|
|
eacb847305 | ||
|
|
27ff43c0ac | ||
|
|
368c33a843 | ||
|
|
c210e8730b | ||
|
|
6c48e02c14 | ||
|
|
c54d68a660 | ||
|
|
33d3123104 | ||
|
|
df0b1cedd8 | ||
|
|
2b57381fb8 | ||
|
|
67b9a82e51 | ||
|
|
c4e10da646 | ||
|
|
fbb1c1278c | ||
|
|
9b49c5e0f4 | ||
|
|
186d4e2fd1 | ||
|
|
437b01e371 | ||
|
|
3bf36fecf9 | ||
|
|
c57332be63 | ||
|
|
292fb0cea1 | ||
|
|
3c4388f8be | ||
|
|
f930ff48a2 | ||
|
|
ef7b940e96 | ||
|
|
6497db837d | ||
|
|
87cb6190eb | ||
|
|
74c4c604da | ||
|
|
0937a35470 | ||
|
|
121f09caf0 | ||
|
|
ef8bd3422a | ||
|
|
2232d859fd | ||
|
|
0258abee29 | ||
|
|
9b8991788b | ||
|
|
9a91c99391 | ||
|
|
c6dd921f0c | ||
|
|
63e622374d | ||
|
|
ca25c71010 | ||
|
|
b5e559ff66 | ||
|
|
555bb76428 | ||
|
|
f210f8e20b | ||
|
|
e572e7c94c | ||
|
|
5c9d3c6b1a | ||
|
|
ccfc23d629 | ||
|
|
b5dd0fc671 | ||
|
|
8e3ee8576e | ||
|
|
4cec7fe5c1 | ||
|
|
6c3b2076ff | ||
|
|
cbc1aeacbe | ||
|
|
a1b2773bf5 | ||
|
|
9ecb501e00 | ||
|
|
3dcdad2233 | ||
|
|
3725a5e6d4 | ||
|
|
ed88f8aa06 | ||
|
|
d551e8c6d2 | ||
|
|
69ad186839 | ||
|
|
fc89867e4a | ||
|
|
bbb478c51f | ||
|
|
03445e5b9b | ||
|
|
0755fbf089 | ||
|
|
3a789bdcfe | ||
|
|
93db8bc7c1 | ||
|
|
62832ad43a | ||
|
|
52b104aca5 | ||
|
|
1f98fe710f | ||
|
|
a73986a358 | ||
|
|
257165584e | ||
|
|
8e92150cb7 | ||
|
|
4bb275e1b7 | ||
|
|
e5fc579071 | ||
|
|
26306f6fa3 | ||
|
|
0bfb079cbb | ||
|
|
6b18259af6 | ||
|
|
99c750d18b | ||
|
|
bb64fa468a | ||
|
|
66db3c6cfb | ||
|
|
c97763c3c8 | ||
|
|
ad3e8a3aba | ||
|
|
617959a11b | ||
|
|
a480091617 | ||
|
|
13a847e0ab | ||
|
|
a8a8b52977 | ||
|
|
226a75472c | ||
|
|
a1c88a140e | ||
|
|
2c3218b056 | ||
|
|
27db9e8c3b | ||
|
|
cf0e36c973 | ||
|
|
1218a0b217 | ||
|
|
adb75b69c2 | ||
|
|
010df964a1 | ||
|
|
0e2e8e16af | ||
|
|
6f28540d59 | ||
|
|
ce78125028 | ||
|
|
10b972bd07 | ||
|
|
371a6437ae | ||
|
|
78666ade2b | ||
|
|
8f00aa5542 | ||
|
|
b2d68fe213 | ||
|
|
a6c13974c4 | ||
|
|
fb0cd8fbf0 | ||
|
|
01d1ae442e | ||
|
|
dc13f46ff1 | ||
|
|
f125ac3b4a | ||
|
|
be29a373ab | ||
|
|
b28db7e435 | ||
|
|
3ac6cc11e3 | ||
|
|
9097bef728 | ||
|
|
68e401821f | ||
|
|
7f9a52c3f7 | ||
|
|
79671d08e4 | ||
|
|
d01d6bcd1b | ||
|
|
79a44b919c | ||
|
|
477e1a4f58 | ||
|
|
c028c385b6 | ||
|
|
f9bcc3100c | ||
|
|
3ea3d18922 | ||
|
|
3faedec602 | ||
|
|
2a88a314ce | ||
|
|
38293560d7 | ||
|
|
f57b3595ed | ||
|
|
e2e6bb3876 | ||
|
|
4e399778b4 | ||
|
|
9ba5f43315 | ||
|
|
0bde364125 | ||
|
|
87f5ec491e | ||
|
|
1f8a0a811f | ||
|
|
74d5590d3b | ||
|
|
258fbdb0e8 | ||
|
|
bd4a48c441 | ||
|
|
00bd6a3e02 | ||
|
|
28ad7b96d2 | ||
|
|
97204c0e8c | ||
|
|
46645cb39f | ||
|
|
dfd6fc78f0 | ||
|
|
ecf5d47e97 | ||
|
|
77df82eaff | ||
|
|
020f2c3ea5 | ||
|
|
5a855eede5 | ||
|
|
8b4273cbd1 | ||
|
|
30bc597851 | ||
|
|
13efadbb65 | ||
|
|
6bc3d7f0f4 | ||
|
|
e706614a3b | ||
|
|
cf68031110 | ||
|
|
5741cea3f5 | ||
|
|
7b879331db | ||
|
|
0a27a631e3 | ||
|
|
d8c6587532 | ||
|
|
d600f160fe | ||
|
|
d23c324035 | ||
|
|
52bfeff5b4 | ||
|
|
3dcb2a828e | ||
|
|
0b95a691a6 | ||
|
|
eba2bad113 | ||
|
|
4f21490ec8 | ||
|
|
f7daa20be8 | ||
|
|
a9ace1163f | ||
|
|
ba380e61ee | ||
|
|
bbc306970f | ||
|
|
7b997634ef | ||
|
|
1efbc3856c | ||
|
|
f769f96f74 | ||
|
|
3f69473072 | ||
|
|
d7bcf6508d | ||
|
|
61c4d8cb5e | ||
|
|
f7361eed98 | ||
|
|
deaa72b05d | ||
|
|
92bdd51cd4 | ||
|
|
0ed29c029d | ||
|
|
61903355cd | ||
|
|
889f60e58e | ||
|
|
c4f292f4ef | ||
|
|
36687e2659 | ||
|
|
948647926d | ||
|
|
4a4f443fee | ||
|
|
18d52821b7 | ||
|
|
ad7d751856 | ||
|
|
1151f1a29c | ||
|
|
0b1625f4c1 | ||
|
|
1363406b84 | ||
|
|
4b875ed4d9 | ||
|
|
42872650d2 | ||
|
|
fd87933aa9 | ||
|
|
269cf85457 | ||
|
|
5728f964a5 | ||
|
|
a7aa8be37a | ||
|
|
237c896fff | ||
|
|
fbb3d7344f | ||
|
|
8b660d32ac | ||
|
|
98bccf6cec | ||
|
|
936606ce7c | ||
|
|
a63748ca3a | ||
|
|
a1ce340ce0 | ||
|
|
a8df79661a | ||
|
|
f52e0ae7a8 | ||
|
|
648a5ef8dd | ||
|
|
0d610f761b | ||
|
|
e7afe4109e | ||
|
|
b11a1a7cf2 | ||
|
|
6a8a2dd28b | ||
|
|
a370a8e01c | ||
|
|
5e38a2180c | ||
|
|
f3bc94a547 | ||
|
|
ba0db53c44 | ||
|
|
ef98a6b54c | ||
|
|
8c9b755671 | ||
|
|
6c1da1d552 | ||
|
|
0df0be5762 | ||
|
|
83120f707f | ||
|
|
9d98edb4ee | ||
|
|
a50b0ac71d | ||
|
|
d674e65c11 | ||
|
|
4967279b8c | ||
|
|
4722e687fa | ||
|
|
332a59f3fc | ||
|
|
587f532991 | ||
|
|
10244d5f90 | ||
|
|
6f1a70dc8b | ||
|
|
7369155166 | ||
|
|
28d4609c8c | ||
|
|
d2966b64eb | ||
|
|
c8f8680ce9 | ||
|
|
9fcb412774 | ||
|
|
296af1069e | ||
|
|
b22e97b3cf | ||
|
|
dcf90cbf5a | ||
|
|
4dc2e2e3fd | ||
|
|
4d4779ecdc | ||
|
|
1c25d317dd | ||
|
|
651a62890a | ||
|
|
39b38f0619 | ||
|
|
4a194e8758 | ||
|
|
5a35da53a0 | ||
|
|
8d64c7c81b | ||
|
|
bea3583192 | ||
|
|
618d115233 | ||
|
|
5e476f4d61 | ||
|
|
5bc1b8df70 | ||
|
|
72e0ab2cb2 | ||
|
|
e0d189a5e0 | ||
|
|
91c193b773 | ||
|
|
4a18130354 | ||
|
|
7c6268fe20 | ||
|
|
6f213c23e2 | ||
|
|
cc606fe1aa | ||
|
|
ee8638841d | ||
|
|
9864a75c32 | ||
|
|
520427239f | ||
|
|
614a229ea7 | ||
|
|
2a4d40020e | ||
|
|
d6efae202a | ||
|
|
7b9c711486 | ||
|
|
e2bd22d984 | ||
|
|
2310b41b21 | ||
|
|
2ae9c577db | ||
|
|
7c9375ce2e | ||
|
|
9addc2ccd5 | ||
|
|
e180f6e6b3 | ||
|
|
f0e29552bc | ||
|
|
48d04216a7 | ||
|
|
ff6221f1a8 | ||
|
|
0bc33554f3 | ||
|
|
7c480e88d6 | ||
|
|
c357d19c56 | ||
|
|
86124b2705 | ||
|
|
99cefb2d74 | ||
|
|
600f99eb6b | ||
|
|
8ba7a24fd2 | ||
|
|
ef608c7595 | ||
|
|
2ea453110a | ||
|
|
a86efb5ebe | ||
|
|
e61fa58d2b | ||
|
|
ec5edf7bd2 | ||
|
|
8dbcebda53 | ||
|
|
28d2a9ed2e | ||
|
|
d47e9145f3 | ||
|
|
ae7c64619c | ||
|
|
bdef1780ac | ||
|
|
ced192e8fd | ||
|
|
0a9e9ca41d | ||
|
|
4982cc950e | ||
|
|
140a9100b7 | ||
|
|
0097f961b4 | ||
|
|
98d657ec4b | ||
|
|
63149d0b50 | ||
|
|
7a410919a0 | ||
|
|
aa7a39d0b0 | ||
|
|
9b88107897 | ||
|
|
147a2fc227 | ||
|
|
732dc3bf34 | ||
|
|
227cde75a7 | ||
|
|
e670d0af45 | ||
|
|
cd0fde05b7 | ||
|
|
8cf2ce7b73 | ||
|
|
1ecf592893 | ||
|
|
0dd0dba338 | ||
|
|
678ae78767 | ||
|
|
d8b6742543 | ||
|
|
2671f39951 | ||
|
|
d7ddf3c828 | ||
|
|
2b7cba936d | ||
|
|
2757c707bb | ||
|
|
f50c5276e4 | ||
|
|
a7e692fe37 | ||
|
|
02d273f15e | ||
|
|
778f5649c8 | ||
|
|
d7829bef28 | ||
|
|
d436d10b00 | ||
|
|
2d9254eb28 | ||
|
|
23393aea5f | ||
|
|
e1562e38bf | ||
|
|
4dcce2544e | ||
|
|
29fa2f0f19 | ||
|
|
b850ae93e9 | ||
|
|
21cb8efb90 | ||
|
|
cd7be1bb86 | ||
|
|
69cd17a1b1 | ||
|
|
872bc4df4c | ||
|
|
3083ba2627 | ||
|
|
35259892b8 | ||
|
|
fbc0f13b2b | ||
|
|
aa7f49cb85 | ||
|
|
720676542e | ||
|
|
1d7eb77f27 | ||
|
|
895f6269fc | ||
|
|
4bf0d3ab24 | ||
|
|
afccda6350 | ||
|
|
c0a176825c | ||
|
|
db6512b702 | ||
|
|
46d3f0827a | ||
|
|
838d7dd8f9 | ||
|
|
b9e5c8827f | ||
|
|
b8e000c7f9 | ||
|
|
5e7af93c77 | ||
|
|
077ad8cd0f | ||
|
|
0bf954e467 | ||
|
|
8a55afc4e1 | ||
|
|
2bc9f2e386 | ||
|
|
920e1a3b1f | ||
|
|
353253b9c5 | ||
|
|
1438230b70 | ||
|
|
240aebde98 | ||
|
|
d4e2ed782e | ||
|
|
f025cd9d2f | ||
|
|
1ff7082892 | ||
|
|
15fa10dd29 | ||
|
|
00b4bdadd4 | ||
|
|
3055dd93a5 | ||
|
|
94dc29cc4d | ||
|
|
22d1db5463 | ||
|
|
f2b4bb00b6 | ||
|
|
d2546ebd36 | ||
|
|
f1930e76d6 | ||
|
|
d722e6a9f0 | ||
|
|
8e6d4b1595 | ||
|
|
72065c81f3 | ||
|
|
2864d0186c | ||
|
|
9c9b2be011 | ||
|
|
2f40264c46 | ||
|
|
5cc24827fc | ||
|
|
da01bdc2b0 | ||
|
|
dfb81dd50f | ||
|
|
567d52459b | ||
|
|
80a96e2a73 | ||
|
|
c2f8467ca9 | ||
|
|
155ca46fef | ||
|
|
0952150235 | ||
|
|
30faa39070 | ||
|
|
3e367912ec | ||
|
|
f8cff25bda | ||
|
|
3e80bf479e | ||
|
|
84afc80873 | ||
|
|
27a943217e | ||
|
|
16834d85c5 | ||
|
|
44d8c85450 | ||
|
|
2a8e44dda8 | ||
|
|
00e3957190 | ||
|
|
a79b76e8d2 | ||
|
|
0a092ff5b3 | ||
|
|
e6aeefb12d | ||
|
|
924b6bd2ba | ||
|
|
f701090c89 | ||
|
|
b9195a561f | ||
|
|
d94e4095da | ||
|
|
fd61cd1750 | ||
|
|
e7ae8bcc47 | ||
|
|
edc4d62004 | ||
|
|
cdff690bb5 | ||
|
|
aa14cc39d9 | ||
|
|
cdf2c8beed | ||
|
|
3e06c06827 | ||
|
|
a2886d76d2 | ||
|
|
cc0a65bace | ||
|
|
d988546ef3 | ||
|
|
b7f2add7b4 | ||
|
|
b07f65c58b | ||
|
|
18e315a048 | ||
|
|
d3967297bb | ||
|
|
ea3631ddc2 | ||
|
|
992e473b72 | ||
|
|
0296f4fcf1 | ||
|
|
2fc16250a3 | ||
|
|
75f7b06a23 | ||
|
|
a7e834e5f9 | ||
|
|
59086932bd | ||
|
|
5611acf12c | ||
|
|
60142d872f | ||
|
|
1cf0ebbd7f | ||
|
|
736a6d273a | ||
|
|
71179e3dfd | ||
|
|
24cdc37987 | ||
|
|
b606f153f4 | ||
|
|
96ab1b4533 | ||
|
|
8718d59286 | ||
|
|
5d372b8149 | ||
|
|
1d62de7e5e | ||
|
|
3691417848 | ||
|
|
029162bba7 | ||
|
|
161a61e0c6 | ||
|
|
587addb73f | ||
|
|
d71bd7fb71 | ||
|
|
699ec273dd | ||
|
|
c1eed8ebcd | ||
|
|
b8d0cf4cc4 | ||
|
|
ff0dd00d79 | ||
|
|
e18d12f109 | ||
|
|
0a09b355b2 | ||
|
|
f9659dae68 | ||
|
|
78a580bc40 | ||
|
|
8c4d6ad4df | ||
|
|
9c9d4e1da5 | ||
|
|
ce50e1448b | ||
|
|
8e885a3a6e | ||
|
|
ecd96a81dd | ||
|
|
427108574e | ||
|
|
62381a7f52 | ||
|
|
b1b09ea542 | ||
|
|
e502a7e6fd | ||
|
|
acf4d0bcf5 | ||
|
|
6c3b13a7a4 | ||
|
|
cababcbfcf | ||
|
|
a032d0f19f | ||
|
|
f808e6fa8e | ||
|
|
842d9f73a4 | ||
|
|
c2893788e7 | ||
|
|
0b8a6c45c6 | ||
|
|
2049e630fb | ||
|
|
6fd82480a3 | ||
|
|
e919897f1b | ||
|
|
0fb5fc6bcc | ||
|
|
a7d61b1b8d | ||
|
|
be9a58457a | ||
|
|
b1cfc8a8ed | ||
|
|
6b9b6ba420 | ||
|
|
79c70b1f65 | ||
|
|
cfe634e8f7 | ||
|
|
8c8c6fe73a | ||
|
|
a4353bc8f2 | ||
|
|
4015351c85 | ||
|
|
e89f1d8a03 | ||
|
|
ff461be45d | ||
|
|
93f5a05f17 | ||
|
|
3eba7fb90f | ||
|
|
25d51cd79e | ||
|
|
a39824abb6 | ||
|
|
2ac4c8e665 | ||
|
|
a84afbaa6e | ||
|
|
41f7b4ec2d | ||
|
|
ce90e9710e | ||
|
|
930eb7ae86 | ||
|
|
cf79a8fdca | ||
|
|
1773a6060d | ||
|
|
5755d647a3 | ||
|
|
5032142a49 | ||
|
|
15e996f485 | ||
|
|
b37c08fd31 | ||
|
|
eaca7f9c09 | ||
|
|
00072501c9 | ||
|
|
b50bb03814 | ||
|
|
f55316281c | ||
|
|
413a7beaa4 | ||
|
|
88140f0610 | ||
|
|
4996171b6e | ||
|
|
d201286fc5 | ||
|
|
12b527be99 | ||
|
|
e666c27d96 | ||
|
|
56cfc47ef6 | ||
|
|
c4e4235f30 | ||
|
|
e045f9d983 | ||
|
|
ba8d060927 | ||
|
|
5f73bf12d7 | ||
|
|
616f92c214 | ||
|
|
298f3dc3b2 | ||
|
|
65741403e0 | ||
|
|
2b6d41ac5f | ||
|
|
a4936355b5 | ||
|
|
02d6eade28 | ||
|
|
089fa8c19b | ||
|
|
7c687831bc | ||
|
|
d43cb95d72 | ||
|
|
d588c3f271 | ||
|
|
eaa93d545d | ||
|
|
e324a21b60 | ||
|
|
b9cfd44588 | ||
|
|
44e9c6ebfc | ||
|
|
a836576211 | ||
|
|
1ad8c95e3e | ||
|
|
2dff343c10 | ||
|
|
fa2a041102 | ||
|
|
86f8f9c83f | ||
|
|
e359e8ab6e | ||
|
|
2f8f3aaa8d | ||
|
|
f5bf5ed251 | ||
|
|
979da6e713 | ||
|
|
6c86fe6117 | ||
|
|
9018fc8324 | ||
|
|
2f57961ce4 | ||
|
|
4478d438d6 | ||
|
|
9261b259a9 | ||
|
|
3f3d8c58bc | ||
|
|
e42f7e4ffa | ||
|
|
8a9353fd09 | ||
|
|
7d5e0352d2 | ||
|
|
05eef76134 | ||
|
|
e6ef67f7bf | ||
|
|
bbd93f333d | ||
|
|
84f7859ca9 | ||
|
|
1c0dffa67c | ||
|
|
5f3fb9b595 | ||
|
|
4ce1e2d9bf | ||
|
|
e40f364c1e | ||
|
|
6bd2d2c4b9 | ||
|
|
47f06e5c1b | ||
|
|
4c4df13c2f | ||
|
|
6ca037ae3e | ||
|
|
47c708fd33 | ||
|
|
c40b23d80e | ||
|
|
f17a790d78 | ||
|
|
bdf67db6ed | ||
|
|
3e203d193c | ||
|
|
a92eb4dee6 | ||
|
|
ed411ee217 | ||
|
|
368d3a4046 | ||
|
|
8aab57e86b | ||
|
|
e198b61eae | ||
|
|
9824cd75b6 | ||
|
|
562274706b | ||
|
|
03a93bfeff | ||
|
|
86749c433c | ||
|
|
17adafecf9 | ||
|
|
dd12e5db66 | ||
|
|
94947ecc21 | ||
|
|
8e50158af8 | ||
|
|
610fae63d2 | ||
|
|
ee072e844b | ||
|
|
0319415f1b | ||
|
|
8fdd32a210 | ||
|
|
32240cd00d | ||
|
|
94f9aedf4b | ||
|
|
fca3ad4df9 | ||
|
|
ba6cc5a9ee | ||
|
|
101ae201d6 | ||
|
|
5c1eea0953 | ||
|
|
733fcc9d87 | ||
|
|
738b895cba | ||
|
|
72aeec58ed | ||
|
|
4d8116cc39 | ||
|
|
54133cd75e | ||
|
|
322fe386f6 | ||
|
|
d2b30bad99 | ||
|
|
264eb318b8 | ||
|
|
cebe291a6f | ||
|
|
30d5468be0 | ||
|
|
fbfd62b73e | ||
|
|
0b9725bf77 | ||
|
|
3c268312a2 | ||
|
|
4c2d220176 | ||
|
|
a855eaf8d0 | ||
|
|
e5c70713b8 | ||
|
|
92267fa7f8 | ||
|
|
3c5f9e1616 | ||
|
|
c2db96edc8 | ||
|
|
4ca09cea2d | ||
|
|
9b39a227c9 | ||
|
|
a7a06963ac | ||
|
|
38655811b7 | ||
|
|
2f562f79aa | ||
|
|
ee608d944a | ||
|
|
9e975568be | ||
|
|
3dbabfa11d | ||
|
|
7a96fd1dce | ||
|
|
5174b6fe93 | ||
|
|
c6617324af | ||
|
|
c7b90f61f7 | ||
|
|
7beab59c1a | ||
|
|
55c9cacaa3 | ||
|
|
58fc3f4338 | ||
|
|
5379b3955f | ||
|
|
bf93bb2026 | ||
|
|
af73c11638 | ||
|
|
1a07815f4b | ||
|
|
52702894af | ||
|
|
73fb2d3735 | ||
|
|
7b482b612e | ||
|
|
bd6614328b | ||
|
|
45cd9597c9 | ||
|
|
b40d663c7e | ||
|
|
6513842d28 | ||
|
|
c8a07ecdb5 | ||
|
|
80f001fdb7 | ||
|
|
ab82f550cf | ||
|
|
6064b9760b | ||
|
|
7802192faa | ||
|
|
cd437f95f1 | ||
|
|
da735b496f | ||
|
|
fc288718b7 | ||
|
|
766f9b4dbd | ||
|
|
a1ac58d17c | ||
|
|
2fbdf7e4d6 | ||
|
|
d5ed474be7 | ||
|
|
1d92cb0e0a | ||
|
|
ab7a19b6e6 | ||
|
|
7b94adfac8 | ||
|
|
33d7776a8e | ||
|
|
d299309c67 | ||
|
|
fcf39ed85b | ||
|
|
0badd09ad3 | ||
|
|
cfc8faa43a | ||
|
|
b0586abc67 | ||
|
|
41235b6ee1 | ||
|
|
141a2bb190 | ||
|
|
fb71ebdfdf | ||
|
|
66ae1d5b94 | ||
|
|
ada077fead | ||
|
|
45367b17a5 | ||
|
|
76717350d6 | ||
|
|
b71a6ac5e1 | ||
|
|
58544c9eea | ||
|
|
f15cb410ce | ||
|
|
b0cec9782d | ||
|
|
1eac05799f | ||
|
|
8fac5f6beb | ||
|
|
a46497255e | ||
|
|
89670bdfd1 | ||
|
|
71e552c0d1 | ||
|
|
efec7c8f95 | ||
|
|
ed668fcac4 | ||
|
|
72015d42fc | ||
|
|
24ec84730e | ||
|
|
dab13931ca | ||
|
|
b1c7004d7e | ||
|
|
69ff8b28d8 | ||
|
|
0395b5d222 | ||
|
|
3b25235755 | ||
|
|
51d61e7a91 | ||
|
|
4d0ce90787 | ||
|
|
4d17b73291 | ||
|
|
f7a34c49fb | ||
|
|
d0a8dc4812 | ||
|
|
0466a60093 | ||
|
|
2c6a81a916 | ||
|
|
656f25dc97 | ||
|
|
329f93a4f6 | ||
|
|
b70f950479 | ||
|
|
38a2e2bcfd | ||
|
|
d9b91e0c34 | ||
|
|
4ae5579068 | ||
|
|
622d710aa9 | ||
|
|
f1a7be09c2 | ||
|
|
0742ca23c1 | ||
|
|
8823ce070e | ||
|
|
d77f6cbbf1 | ||
|
|
909c8b3cb5 | ||
|
|
5b7d29fa55 | ||
|
|
8dfb3c03c7 | ||
|
|
6e8031f477 | ||
|
|
81c545f45b | ||
|
|
65025d47c5 | ||
|
|
4f23e8aaeb | ||
|
|
aea2c00a95 | ||
|
|
eafe0380e1 | ||
|
|
3975ceb2a0 | ||
|
|
0a3ecbcd0e | ||
|
|
9679a90d88 | ||
|
|
c4a704b1a2 | ||
|
|
776900bd7b | ||
|
|
5683ea35fc | ||
|
|
78d4987d5d | ||
|
|
9f852b3a41 | ||
|
|
edca2cbdff | ||
|
|
c578302d7c | ||
|
|
dfce4b31f3 | ||
|
|
669edfc048 | ||
|
|
0a9c88a990 | ||
|
|
4e5e5a9684 | ||
|
|
97eada7dd6 | ||
|
|
a764f8c929 | ||
|
|
5da886593b | ||
|
|
4c5a88929c | ||
|
|
af7e427545 | ||
|
|
4638c5ab55 | ||
|
|
0c2e63baad | ||
|
|
ee61ce35c8 | ||
|
|
6ec5b4a5da | ||
|
|
d63ad6fc0c | ||
|
|
641a4b9dff | ||
|
|
31001d6b1a | ||
|
|
d1a1559dca | ||
|
|
0d56b700bf | ||
|
|
cafdb919e4 | ||
|
|
808f448399 | ||
|
|
10d902e730 | ||
|
|
0436962ee7 | ||
|
|
2bebb0bd61 | ||
|
|
1e04e3f80d | ||
|
|
c32e10caac | ||
|
|
120440d45b | ||
|
|
61b85901a3 | ||
|
|
f0b3acf491 | ||
|
|
f2d624a795 | ||
|
|
9e1d7aca92 | ||
|
|
3b43f7bf03 | ||
|
|
2f18c6edf1 | ||
|
|
79f8699174 | ||
|
|
602681dcc2 | ||
|
|
3e63047c38 | ||
|
|
4f2f166824 | ||
|
|
fc782f286d | ||
|
|
425c548611 | ||
|
|
593f1dd67f | ||
|
|
8cff4348a6 | ||
|
|
40271f2ddf | ||
|
|
aa1205f42d | ||
|
|
2e15de483d | ||
|
|
77b0415c1b | ||
|
|
43b3a9df23 | ||
|
|
8b47b80b0b | ||
|
|
13da8c3adc | ||
|
|
a10190df51 | ||
|
|
ecfa745484 | ||
|
|
20d439578b | ||
|
|
dd7f1bcf25 | ||
|
|
3b855255cf | ||
|
|
23283426e0 | ||
|
|
c958bc78dd | ||
|
|
24ec242ecf | ||
|
|
9068c13e39 | ||
|
|
024aff0af5 | ||
|
|
57c1d75779 | ||
|
|
8c434783a2 | ||
|
|
85ae839211 | ||
|
|
b218d33a24 | ||
|
|
6e0f4674d5 | ||
|
|
62812e1e3a | ||
|
|
63680b4911 | ||
|
|
071254ed8d | ||
|
|
93980629d3 | ||
|
|
f299771044 | ||
|
|
8c013b7680 | ||
|
|
78fe659677 | ||
|
|
98de950ae2 | ||
|
|
96eb9c5db7 | ||
|
|
45c1e347b0 | ||
|
|
0559b935e9 | ||
|
|
409f337973 | ||
|
|
7f5f6b6ac9 | ||
|
|
dc36a50d85 | ||
|
|
74f0babc7d | ||
|
|
5eeaeaee5d | ||
|
|
fa58503c9f | ||
|
|
9fca3728c3 | ||
|
|
56fccb9645 | ||
|
|
cab40d7893 | ||
|
|
faa3a5e027 | ||
|
|
1c0838aa5d | ||
|
|
32fa834f3f | ||
|
|
051af644a7 | ||
|
|
9b9a6a3148 | ||
|
|
711426fe69 | ||
|
|
18c9c812d7 | ||
|
|
bc798977b5 | ||
|
|
853d7cb668 | ||
|
|
3eac027ddb | ||
|
|
1247401a5f | ||
|
|
9846362836 | ||
|
|
16fc88b50c | ||
|
|
fee3d7c0d3 | ||
|
|
5020f6b990 | ||
|
|
a48f6c8c30 | ||
|
|
8d6b864b5b | ||
|
|
deca5e5e73 | ||
|
|
9b731cc39c | ||
|
|
78cd64c388 | ||
|
|
d9e15729fd | ||
|
|
0fbe2da9cb | ||
|
|
d3397279f6 | ||
|
|
705efc6002 | ||
|
|
3a60191a9d | ||
|
|
95e6db6797 | ||
|
|
e37b1946f5 | ||
|
|
6d1e2dd10e | ||
|
|
0668c4214e | ||
|
|
1b4c803ce3 | ||
|
|
8d00da9e98 | ||
|
|
1524a06ac6 | ||
|
|
9ca820d45e | ||
|
|
27102d1c38 | ||
|
|
18b5405c76 | ||
|
|
de541f6654 | ||
|
|
9d398b1d2e | ||
|
|
caeb3279cb | ||
|
|
06247732da | ||
|
|
fc7689354f | ||
|
|
a50b74bb36 | ||
|
|
a21b5fac76 | ||
|
|
3d9022d8fa | ||
|
|
4e10470acd | ||
|
|
3cc1a462f5 | ||
|
|
cd7bf5eff2 | ||
|
|
8da3b490d9 | ||
|
|
00c87c0e60 | ||
|
|
507ecc47b6 | ||
|
|
6ac8abdac8 | ||
|
|
4a29dd4c9c | ||
|
|
6d06636bc2 | ||
|
|
da857895fc | ||
|
|
425a2184c6 | ||
|
|
6919b52f61 | ||
|
|
8eb7428ad1 | ||
|
|
327a57de3c | ||
|
|
01ba8dbc3f | ||
|
|
a97b3abca3 | ||
|
|
d927d04765 | ||
|
|
6dc2e96509 | ||
|
|
26a0cd0761 | ||
|
|
75b7f7ac22 | ||
|
|
d08ea5a650 | ||
|
|
1bd1665faa | ||
|
|
b3847270fa | ||
|
|
055603b09e | ||
|
|
34f5c19f99 | ||
|
|
602bd5b0d4 | ||
|
|
45de85dae2 | ||
|
|
8b9ff2c58a | ||
|
|
1599a36642 | ||
|
|
1e30f23ca6 | ||
|
|
2f74510cce | ||
|
|
08bff3ea5f | ||
|
|
90d2451ce2 | ||
|
|
5b5df254d5 | ||
|
|
a028abe036 | ||
|
|
677534c0b7 | ||
|
|
2d319fe5aa | ||
|
|
bbd2c53dd8 | ||
|
|
d1eb7e5614 | ||
|
|
d9ee666770 | ||
|
|
9f744beb13 | ||
|
|
62a297ec6d | ||
|
|
3f9e19d279 | ||
|
|
c9e64d9e46 | ||
|
|
25759064ff | ||
|
|
cd24ffbada | ||
|
|
cdae0898c7 | ||
|
|
f02691863b | ||
|
|
4c8d0ea2d9 | ||
|
|
ec4f5cc34d | ||
|
|
e8a42e3947 | ||
|
|
e8dd963545 | ||
|
|
1c0a5c49a5 | ||
|
|
bb83dcc828 | ||
|
|
0eefb7f5a1 | ||
|
|
fe95cfe03b | ||
|
|
7a6368a980 | ||
|
|
9e86681722 | ||
|
|
25bd91eb80 | ||
|
|
6504c88bf7 | ||
|
|
6a75d6fe86 | ||
|
|
bc876611d0 | ||
|
|
798ea77736 | ||
|
|
21ef83c0ff | ||
|
|
bd7af593e7 | ||
|
|
f73a5d0e8d | ||
|
|
f7bc04bc34 | ||
|
|
aa43703094 | ||
|
|
381886245b | ||
|
|
08642ada20 | ||
|
|
10cb4c03b7 | ||
|
|
e7d1cb8bb6 | ||
|
|
5a7d733cbf | ||
|
|
e23f491500 | ||
|
|
98b716dfbf | ||
|
|
2ddd31a37d | ||
|
|
2b99ed9a2a | ||
|
|
eeea16a99a | ||
|
|
e52996609a | ||
|
|
932de33349 | ||
|
|
195604997b | ||
|
|
a3a3f81e11 | ||
|
|
d0f3fb4417 | ||
|
|
183602ac28 | ||
|
|
37370f722c | ||
|
|
e2e51c9c95 | ||
|
|
bf1e073ef4 | ||
|
|
767703bfc9 | ||
|
|
0e0a96b6d8 | ||
|
|
3f73272524 | ||
|
|
d72f831519 | ||
|
|
c6f25c0df6 | ||
|
|
17058c220c | ||
|
|
0e99b35ab2 | ||
|
|
e795c6ed0b | ||
|
|
f3345247ed | ||
|
|
1101a3243d | ||
|
|
c7638efc7e | ||
|
|
d90053c8c4 | ||
|
|
6235983ddd | ||
|
|
7a249abc67 | ||
|
|
c2c613b652 | ||
|
|
590357004d | ||
|
|
9dbeb1407c | ||
|
|
1ef8ab70d1 | ||
|
|
c09ada201c | ||
|
|
d7139cb16c | ||
|
|
10f82a6723 | ||
|
|
2aed3af3c4 | ||
|
|
c45d38ca69 | ||
|
|
576642a573 | ||
|
|
9d545dcbf1 | ||
|
|
71d8744840 | ||
|
|
32c689e0f5 | ||
|
|
5b62661404 | ||
|
|
a7df8a1a0a | ||
|
|
b14e7c197f | ||
|
|
97eed50ccc | ||
|
|
b8453ac792 | ||
|
|
fe7f479e63 | ||
|
|
50ea442bf0 | ||
|
|
5d45495371 | ||
|
|
e30d900289 | ||
|
|
2cc96e995b | ||
|
|
47cf1289d7 | ||
|
|
d2506cd928 | ||
|
|
1dbb11ea55 | ||
|
|
b60363b6bd | ||
|
|
00033c11bc | ||
|
|
c588b78adb | ||
|
|
7bd7992b24 | ||
|
|
6f86b7400a | ||
|
|
e13a2c371d | ||
|
|
0cbded9fca | ||
|
|
3e6e71ca41 | ||
|
|
1b2e3b1951 | ||
|
|
e53a480c22 | ||
|
|
7280c1c468 | ||
|
|
b7221516dc | ||
|
|
71aaf81bba | ||
|
|
160c3f428c | ||
|
|
3c3e8d167f | ||
|
|
7ca2b65c4f | ||
|
|
a8cbb5c8f5 | ||
|
|
72028086c0 | ||
|
|
dddf529ff5 | ||
|
|
b3de0aabae | ||
|
|
77c6a3b730 | ||
|
|
bb54dbb688 | ||
|
|
0a74da88d6 | ||
|
|
d0b94938e0 | ||
|
|
a0cba8e63d | ||
|
|
a4d7b5dcf8 | ||
|
|
c503adabc5 | ||
|
|
8a22258945 | ||
|
|
29a190f93a | ||
|
|
5c0b522026 | ||
|
|
c46f14665c | ||
|
|
20c973dab2 | ||
|
|
49cb482ca5 | ||
|
|
033c2e22cd | ||
|
|
2f434291cb | ||
|
|
42d01471d3 | ||
|
|
c5eb1bb105 | ||
|
|
3c9057f68e | ||
|
|
96f0dd5824 | ||
|
|
71358629f4 | ||
|
|
284fef00e7 | ||
|
|
d20519ef8b | ||
|
|
0dc1270aed | ||
|
|
cd0d37f73c | ||
|
|
56fce34539 | ||
|
|
165a76d492 | ||
|
|
9570e5cfd9 | ||
|
|
c6bb10489e | ||
|
|
3d7d4a47d9 | ||
|
|
968c849b13 | ||
|
|
1746569e1a | ||
|
|
209c91d3de | ||
|
|
7d7c1d34cf | ||
|
|
c3ad486f65 | ||
|
|
7bcec32134 | ||
|
|
b19b08dc6e | ||
|
|
264e175d6c | ||
|
|
bcd4fd9bff | ||
|
|
3e88fb44f4 | ||
|
|
518b013a63 | ||
|
|
e752538568 | ||
|
|
970364886c | ||
|
|
07f859e38b | ||
|
|
c806059958 | ||
|
|
14bce8fd82 | ||
|
|
17be04cd99 | ||
|
|
b93847f077 | ||
|
|
6476158462 | ||
|
|
6dd73ff9d0 | ||
|
|
b72083fb18 | ||
|
|
ca11d4d98b | ||
|
|
12cb4fd5f8 | ||
|
|
4df4eba2a5 | ||
|
|
762105d692 | ||
|
|
e4ce814c2f | ||
|
|
87cd693020 | ||
|
|
baadd4b1cb | ||
|
|
adf3755abb | ||
|
|
5c280e7cb7 | ||
|
|
4a149855ab | ||
|
|
cf000b04e4 | ||
|
|
79cd8d6065 | ||
|
|
5b930cdc3b | ||
|
|
c09329e5be | ||
|
|
c513014732 | ||
|
|
bada36be68 | ||
|
|
e5e81eda72 | ||
|
|
45cf2ae960 | ||
|
|
d0d0117411 | ||
|
|
5d79863cfc | ||
|
|
b85756f8b1 | ||
|
|
8776f4c1c0 | ||
|
|
5e8fd3993d | ||
|
|
d3033716ca | ||
|
|
6cf2bb5cd9 | ||
|
|
267495a406 | ||
|
|
a8937f7bf0 | ||
|
|
dfd63a81ac | ||
|
|
dfbc1956c9 | ||
|
|
c0490c0890 | ||
|
|
2da802d4b7 | ||
|
|
adffbab678 | ||
|
|
e11525ab64 | ||
|
|
8dcd591beb | ||
|
|
a40c936bcf | ||
|
|
5c2622b390 | ||
|
|
c7046b696a | ||
|
|
9ac5ce8a75 | ||
|
|
5c55e18d33 | ||
|
|
19d233454e | ||
|
|
1f761ee1cb | ||
|
|
1db5d61945 | ||
|
|
1e34a396cd | ||
|
|
ba96117f55 | ||
|
|
96b217cbe8 | ||
|
|
0dd5c0370e | ||
|
|
bdf32cde9e | ||
|
|
e91ed60441 | ||
|
|
8577202f48 | ||
|
|
7819b9d2f0 | ||
|
|
15c0565923 | ||
|
|
2b25ca2932 | ||
|
|
c7a6677d52 | ||
|
|
c3d5b32986 | ||
|
|
cbfb524195 | ||
|
|
b16a1f7237 | ||
|
|
e28f1b1be3 | ||
|
|
b512a243e7 | ||
|
|
873c9880dd | ||
|
|
e6736e48a5 | ||
|
|
caf598f55b | ||
|
|
619e099a04 | ||
|
|
faba1e3604 | ||
|
|
7cb728b15f | ||
|
|
3e3c7f0d54 | ||
|
|
a45c19a08b | ||
|
|
eb74a1de9c | ||
|
|
8450734cf1 | ||
|
|
016299a1dd | ||
|
|
d27ff9abb6 | ||
|
|
cdf5d45483 | ||
|
|
0b60d4efe2 | ||
|
|
d31e434e4d | ||
|
|
fabc1c3dd9 | ||
|
|
68fbc40605 | ||
|
|
8b7c5cf2ed | ||
|
|
1811631b93 | ||
|
|
7cec1564b9 | ||
|
|
a75eefcdd4 | ||
|
|
6a9027da6d | ||
|
|
e55aa3cea7 | ||
|
|
1ce2c60bf4 | ||
|
|
7ba49afa0b | ||
|
|
6da705c86f | ||
|
|
c3fa56322b | ||
|
|
53cfab229b | ||
|
|
b62217f301 | ||
|
|
d9a8453995 | ||
|
|
e6181928e8 | ||
|
|
c33499797e | ||
|
|
860f6a41ac | ||
|
|
8aa7b1f301 | ||
|
|
6efd3eaa27 | ||
|
|
d2d8d191da | ||
|
|
cea5c81d44 | ||
|
|
504f28df1a | ||
|
|
74a57553f6 | ||
|
|
35576ab64a | ||
|
|
33605517ff | ||
|
|
6da6e4d2e8 | ||
|
|
c0fa03ede2 | ||
|
|
301b609e93 | ||
|
|
b6bbe237ea | ||
|
|
de7ab13c03 | ||
|
|
7a0f4da860 | ||
|
|
1bbbfe1c96 | ||
|
|
25ebe68389 | ||
|
|
7737d19c5a | ||
|
|
622ca4bf8a | ||
|
|
b090afbeb3 | ||
|
|
dce149511e | ||
|
|
21a248e94d | ||
|
|
f1aed4b521 | ||
|
|
7564ebf79e | ||
|
|
b9aecbe1d4 | ||
|
|
49eb451a76 | ||
|
|
64d866a77d | ||
|
|
f75779aa7a | ||
|
|
5622882602 | ||
|
|
b3d3928db8 | ||
|
|
6df3b9008a | ||
|
|
c36ca65e09 | ||
|
|
2e788802fe | ||
|
|
b0552019f5 | ||
|
|
dae69622a5 | ||
|
|
696b930fb2 | ||
|
|
e43a62f992 | ||
|
|
02c1cb05c7 | ||
|
|
b44d738867 | ||
|
|
e1818f7e62 | ||
|
|
e5081db7e4 | ||
|
|
ba346bd797 | ||
|
|
0670ece7f3 | ||
|
|
a8da3eebd7 | ||
|
|
056303b53c | ||
|
|
454f7d30de | ||
|
|
6d1c270976 | ||
|
|
d1001274bb | ||
|
|
3099855562 | ||
|
|
3f26d4ad98 | ||
|
|
bae337cc49 | ||
|
|
3823e7a108 | ||
|
|
1c2221f52f | ||
|
|
1b780a4364 | ||
|
|
ac3e65a829 | ||
|
|
332f19177e | ||
|
|
6ab57b9abe | ||
|
|
862f3aad59 | ||
|
|
e277acf80e | ||
|
|
9f893e68e9 | ||
|
|
833a5b2b55 | ||
|
|
340f0c68eb | ||
|
|
a5e3182dad | ||
|
|
10ae9c3aa2 | ||
|
|
bcf903de92 | ||
|
|
ad08d27504 | ||
|
|
d24f77dbd5 | ||
|
|
a5b38ce1a4 | ||
|
|
5d048d2c1d | ||
|
|
13d3cc3306 | ||
|
|
9f02fb4dd4 | ||
|
|
07baa6e611 | ||
|
|
50bd5869bf | ||
|
|
fa49fc91d2 | ||
|
|
28f478dd04 | ||
|
|
6fb8dad0ec | ||
|
|
9f605e9a88 | ||
|
|
e5b91dae73 | ||
|
|
e1749fecd1 | ||
|
|
358edff798 | ||
|
|
34f13ba89c | ||
|
|
945ba6f8ab | ||
|
|
46f05ee92f | ||
|
|
6d46fc66ce | ||
|
|
ed7fe9213f | ||
|
|
9c68cbae72 | ||
|
|
c0df771539 | ||
|
|
9bd0c33fef | ||
|
|
8042cefd3d | ||
|
|
16a0f44b4d | ||
|
|
1a2acb43ae | ||
|
|
36d07cb539 | ||
|
|
6ca1cdec4f | ||
|
|
e2abf05a27 | ||
|
|
d9e6f2975a | ||
|
|
d8ac3587ac | ||
|
|
85c4fbdf4f | ||
|
|
5a7f38fa29 | ||
|
|
417148f5da | ||
|
|
a85cbdd505 | ||
|
|
b4d91978c7 | ||
|
|
16bde87982 | ||
|
|
270533652b | ||
|
|
03d640260d | ||
|
|
f27b2290dc | ||
|
|
efda9beece | ||
|
|
c7c7e5e4ce | ||
|
|
f61f80164d | ||
|
|
d16fef9f7f | ||
|
|
4425d53664 | ||
|
|
ee5e015a63 | ||
|
|
839ce3d526 | ||
|
|
cc06117210 | ||
|
|
cbd5b6c0f4 | ||
|
|
867e66e774 | ||
|
|
45ffeaffec | ||
|
|
f91b622646 | ||
|
|
40a9c28699 | ||
|
|
081491d0a1 | ||
|
|
8d0230d6a8 | ||
|
|
37e5260cda | ||
|
|
19b8031933 | ||
|
|
99211fd407 | ||
|
|
3d839c2b21 | ||
|
|
e1e7a1cfdb | ||
|
|
0ed7f87ee0 | ||
|
|
579bbc9f2c | ||
|
|
e672de949c | ||
|
|
f72762bcb2 | ||
|
|
7ecc3c25b0 | ||
|
|
adcffba7cf | ||
|
|
e271e60144 | ||
|
|
16be86953f | ||
|
|
1f527cdb9e | ||
|
|
11e8240c5c | ||
|
|
4aecc034c2 | ||
|
|
a111a07bca | ||
|
|
eb71097546 | ||
|
|
c7fcb72d6c | ||
|
|
04af8ef329 | ||
|
|
4cdf803ab7 | ||
|
|
4595c15bee | ||
|
|
1e3d2fbfd2 | ||
|
|
57c25bf151 | ||
|
|
ae030b227a | ||
|
|
4f85751694 | ||
|
|
6b0d0daa2e | ||
|
|
401498a4f7 | ||
|
|
8bb50189bc | ||
|
|
eb665a059a | ||
|
|
3dc29be083 | ||
|
|
82e5447526 | ||
|
|
066f3fd726 | ||
|
|
f0acf733a5 | ||
|
|
96c4dd2ab9 | ||
|
|
df3b9a7ef9 | ||
|
|
70a3a5919e | ||
|
|
688d37ee60 | ||
|
|
3dcf8bc8fc | ||
|
|
7039d613ee | ||
|
|
256c963370 | ||
|
|
7b8c2a4575 | ||
|
|
7f1ba0d6ae | ||
|
|
7e5b79aa14 | ||
|
|
086343ee48 | ||
|
|
a1ad512a80 | ||
|
|
9bb2ef9cbe | ||
|
|
832910d480 | ||
|
|
13da2b2924 | ||
|
|
84ac520353 | ||
|
|
5613975314 | ||
|
|
662d30ae45 | ||
|
|
57bee443b1 | ||
|
|
621618e41f | ||
|
|
6ccb60813a | ||
|
|
b34119901e | ||
|
|
b317aef8c9 | ||
|
|
fdbc6fa94f | ||
|
|
0ffe24903a | ||
|
|
e550a7cc44 | ||
|
|
82165a2af6 | ||
|
|
63a4fe32c1 | ||
|
|
1c44a25a4a | ||
|
|
cf21ecee2e | ||
|
|
5467e502a5 | ||
|
|
6af9ec266b | ||
|
|
faa7e0e7a9 | ||
|
|
aa3606007a | ||
|
|
db5974970d | ||
|
|
ba2539db67 | ||
|
|
21d0661d79 | ||
|
|
9f3eb461a9 | ||
|
|
34b0deba29 | ||
|
|
d9a93d8dff | ||
|
|
747776344b | ||
|
|
f979a79081 | ||
|
|
367e9840cc | ||
|
|
ea590c2ed1 | ||
|
|
d93120257b | ||
|
|
e763b362d9 | ||
|
|
e5eb1ca0cb | ||
|
|
ea2649db5e | ||
|
|
b53fc9cadc | ||
|
|
4b35e1b729 | ||
|
|
40e106db13 | ||
|
|
3dc0659f66 | ||
|
|
e652ed2981 | ||
|
|
28db891aa5 | ||
|
|
b63ae9b771 | ||
|
|
27c84ceaac | ||
|
|
d67ccd03ca | ||
|
|
96b0f27c51 |
No files matched your search
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="lib/bukkit-0.0.1-SNAPSHOT.jar"/>
|
||||
<classpathentry kind="lib" path="lib/craftbukkit-0.0.1-SNAPSHOT.jar"/>
|
||||
<classpathentry kind="lib" path="lib/Permissions3.jar"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Help!
|
||||
about: Encountered a problem with EssentialsX? Not sure how to fix it?
|
||||
|
||||
---
|
||||
|
||||
<!-- EssentialsX help guide
|
||||
|
||||
Don't write inside the arrows as they will be hidden when you post your issue.
|
||||
|
||||
Want faster support? Come join our Discord server to get help sooner:
|
||||
https://discord.gg/F7gexAQ
|
||||
|
||||
If you're happy to wait (or you were sent here from Discord), read on:
|
||||
|
||||
1. Fill out the template.
|
||||
This will help us understand what problem you've encountered and help us
|
||||
find a solution.
|
||||
|
||||
2. Check the Common Issues page.
|
||||
Read through the wiki page to see if you've encountered a regular issue:
|
||||
https://essentialsx.github.io/#/Common-Issues
|
||||
|
||||
3. Delete this line and all above lines before posting your issue! -->
|
||||
|
||||
### Information
|
||||
|
||||
Full output of `/ess version`:
|
||||
|
||||
<!-- Replace this with the command output -->
|
||||
|
||||
**Server log:** <!-- Upload `logs/latest.log` to https://gist.github.com/ -->
|
||||
|
||||
**EssentialsX config** <!-- Upload `plugins/Essentials/config.yml` to https://gist.github.com/ -->
|
||||
|
||||
### Help request
|
||||
|
||||
**Problem**
|
||||
<!-- What problem did you encounter? -->
|
||||
|
||||
**What I have tried**
|
||||
<!-- What have you tried so far? -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- If relevant, include any screenshots here. -->
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
name: Report a bug
|
||||
about: Report an EssentialsX bug. Only use this if you're 100% sure there's something wrong with EssentialsX - otherwise, try "Help!".
|
||||
|
||||
---
|
||||
|
||||
<!-- EssentialsX bug reporting guide
|
||||
|
||||
Don't put anything inside this block, as it won't be included in the issue.
|
||||
|
||||
If you are reporting a bug, please follow the following steps:
|
||||
|
||||
1. Fill out the template in full.
|
||||
Run the commands in the console. Don't just put "latest" as a version,
|
||||
or we will ignore it.
|
||||
|
||||
2. When linking files, do not attach them to the post!
|
||||
Copy and paste any logs into https://gist.github.com/, then paste a
|
||||
link to them in the relevant parts of the template. Avoid using
|
||||
Hastebin or Pastebin, as this makes providing support more difficult.
|
||||
**DO NOT drag files into this box!**
|
||||
|
||||
3. If you are reporting a performance issue, please include a link to a
|
||||
Timings and/or profiler report.
|
||||
|
||||
4. If you are reporting a bug with commands or something else in-game,
|
||||
please include screenshots to help us diagnose the problem.
|
||||
|
||||
5. Make sure not to write between the arrows, as anything there will be
|
||||
hidden.
|
||||
|
||||
6. Delete this line and all above lines before posting your issue! -->
|
||||
|
||||
### Information
|
||||
|
||||
**Full output of `/ess version`**:
|
||||
|
||||
```
|
||||
<!-- Run the command in your console, and copy and paste the whole output here -->
|
||||
```
|
||||
|
||||
**Server log**: <!-- Upload `logs/latest.log` to https://gist.github.com/, replace this with link -->
|
||||
|
||||
**EssentialsX config**: <!-- Upload `plugins/Essentials/config.yml` to https://gist.github.com/, replace this with link -->
|
||||
|
||||
### Details
|
||||
|
||||
**Description**
|
||||
<!-- Replace this with a brief summary of the bug. -->
|
||||
|
||||
**Steps to reproduce**
|
||||
<!-- Replace this with exactly what you did to cause the bug. -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- Replace this with what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- Replace this with screenshots, if necessary. -->
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Request a feature
|
||||
about: Suggest a feature you want to see in EssentialsX!
|
||||
|
||||
---
|
||||
|
||||
<!-- EssentialsX feature request guide
|
||||
|
||||
Fill out the template. Don't write inside the arrows as they will be hidden
|
||||
when you post your issue.
|
||||
|
||||
Not sure if your feature fits in EssentialsX? Feel free to ask on our Discord
|
||||
server: https://discord.gg/F7gexAQ
|
||||
|
||||
If you have a feature suggestion for EssentialsX, read the following tips:
|
||||
|
||||
1. Fill out the template.
|
||||
This will help us understand what you're requesting and why you want us
|
||||
to add it.
|
||||
|
||||
2. Keep it simple.
|
||||
Make sure it's easy to understand what you're requesting. A good way is
|
||||
to keep it to one request per GitHub issue, as we can then easily track
|
||||
feature requests.
|
||||
|
||||
3. Check whether it has already been asked or added.
|
||||
You can search the issue tracker to see if your feature has already been
|
||||
requested at https://github.com/EssentialsX/Essentials/issues. You can
|
||||
also check the wiki at https://essentialsx.github.io/ to see if the
|
||||
feature was recently added.
|
||||
|
||||
4. Ask yourself: "Does this belong in EssentialsX?"
|
||||
There are lots of features that we reject because most servers won't
|
||||
need or use them. If your feature is very specific or already exists in
|
||||
another plugin, it might not be a good fit for EssentialsX.
|
||||
|
||||
5. Delete this line and all above lines before posting your issue! -->
|
||||
|
||||
### Feature request
|
||||
|
||||
**Feature description**
|
||||
<!-- What feature are you suggesting? -->
|
||||
|
||||
**How the feature is useful**
|
||||
<!-- How is the feature useful to players, server owners and/or developers? -->
|
||||
+17
-46
@@ -1,47 +1,18 @@
|
||||
.DS_Store
|
||||
/BuildAll/nbproject/private/
|
||||
/EssentialsProtect/nbproject/private/
|
||||
/EssentialsChat/nbproject/private/
|
||||
/EssentialsGroupBridge/nbproject/private/
|
||||
/EssentialsGeoIP/nbproject/private/
|
||||
/EssentialsSpawn/nbproject/private/
|
||||
/EssentialsXMPP/nbproject/private/
|
||||
/EssentialsGroupManager/nbproject/private/
|
||||
/BuildAll/build/
|
||||
/EssentialsGroupBridge/dist/
|
||||
/EssentialsGroupBridge/build/
|
||||
/EssentialsGeoIP/dist/
|
||||
/EssentialsGeoIP/build/
|
||||
/EssentialsGroupManager/build/
|
||||
/EssentialsGroupManager/dist/
|
||||
/BuildAll/dist/
|
||||
/EssentialsChat/build/
|
||||
/EssentialsChat/dist/
|
||||
/EssentialsSpawn/build/
|
||||
/EssentialsSpawn/dist/
|
||||
/EssentialsXMPP/dist/
|
||||
/EssentialsXMPP/build/
|
||||
/EssentialsProtect/dist/
|
||||
/EssentialsProtect/build/
|
||||
/EssentialsPermissionsCommands/nbproject/private/
|
||||
/EssentialsPermissionsCommands/build/
|
||||
/EssentialsPermissionsCommands/dist/
|
||||
/Essentials/nbproject/private/
|
||||
/Essentials/dist/
|
||||
/Essentials/build/
|
||||
/YamlAnnotations/
|
||||
/EssentialsUpdate/nbproject/private/
|
||||
/EssentialsRelease/
|
||||
/EssentialsUpdate/dist/
|
||||
/EssentialsUpdate/build/
|
||||
/WebPush/apikey.php
|
||||
/WebPush/nbproject/private
|
||||
/.idea
|
||||
# IDE files
|
||||
*.classpath
|
||||
*.project
|
||||
*.settings/
|
||||
.idea/
|
||||
*.iml
|
||||
/EssentialsSigns/nbproject/private/
|
||||
/Essentials2Compat/nbproject/private/
|
||||
/Essentials2Compat/dist/
|
||||
/Essentials2Compat/build/
|
||||
/EssentialsGroupManager/bin
|
||||
/EssentialsGroupManager/.externalToolBuilders
|
||||
/EssentialsGeoIP/build
|
||||
.DS_Store
|
||||
|
||||
# Essentials files
|
||||
/Essentials/userdata
|
||||
/Essentials/config.yml
|
||||
/Essentials/kits.yml
|
||||
/Essentials/userdata/testplayer1.yml
|
||||
/Essentials/usermap.csv
|
||||
|
||||
# Build files
|
||||
target/
|
||||
jars/
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Essentials</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
language: java
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- .buildtools
|
||||
- $HOME/.m2
|
||||
|
||||
before_install:
|
||||
- chmod +x scripts/buildtools.sh
|
||||
- scripts/buildtools.sh
|
||||
@@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="BuildAll" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project BuildAll.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="BuildAll-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,8 +0,0 @@
|
||||
build.xml.data.CRC32=51b33957
|
||||
build.xml.script.CRC32=7a797370
|
||||
build.xml.stylesheet.CRC32=28e38971@1.44.1.45
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=51b33957
|
||||
nbproject/build-impl.xml.script.CRC32=c5170bed
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=fcddb364@1.50.1.46
|
||||
@@ -1,129 +0,0 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.run.all.processors=true
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=BuildAll
|
||||
application.vendor=
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=120
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap=none
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineAnnotationArgs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineArrayInit=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineAssignment=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineBinaryOp=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineCallArgs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineDisjunctiveCatchTypes=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineFor=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineImplements=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineMethodParams=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineParenthesized=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineTernaryOp=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineThrows=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineTryResources=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.blankLinesAfterClassHeader=0
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.blankLinesBeforeClass=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.expand-tabs=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.indent-shift-width=4
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.indentCasesFromSwitch=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeCatchOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeElseOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeFinallyOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeWhileOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceAfterTypeCast=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaces-per-tab=4
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.tab-size=4
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/BuildAll.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
includes=**
|
||||
jar.compress=true
|
||||
javac.classpath=\
|
||||
${reference.Essentials.jar}:\
|
||||
${reference.EssentialsChat.jar}:\
|
||||
${reference.EssentialsProtect.jar}:\
|
||||
${reference.EssentialsSpawn.jar}:\
|
||||
${reference.EssentialsGeoIP.jar}:\
|
||||
${reference.EssentialsGroupBridge.jar}:\
|
||||
${reference.EssentialsXMPP.jar}:\
|
||||
${reference.EssentialsGroupManager.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.6
|
||||
javac.target=1.6
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=default_platform
|
||||
project.Essentials=../Essentials
|
||||
project.EssentialsChat=../EssentialsChat
|
||||
project.EssentialsGeoIP=../EssentialsGeoIP
|
||||
project.EssentialsGroupBridge=../EssentialsGroupBridge
|
||||
project.EssentialsGroupManager=../EssentialsGroupManager
|
||||
project.EssentialsProtect=../EssentialsProtect
|
||||
project.EssentialsSpawn=../EssentialsSpawn
|
||||
project.EssentialsXMPP=../EssentialsXMPP
|
||||
reference.Essentials.jar=${project.Essentials}/dist/Essentials.jar
|
||||
reference.EssentialsChat.jar=${project.EssentialsChat}/dist/EssentialsChat.jar
|
||||
reference.EssentialsGeoIP.jar=${project.EssentialsGeoIP}/dist/EssentialsGeoIP.jar
|
||||
reference.EssentialsGroupBridge.jar=${project.EssentialsGroupBridge}/dist/EssentialsGroupBridge.jar
|
||||
reference.EssentialsGroupManager.jar=${project.EssentialsGroupManager}/dist/EssentialsGroupManager.jar
|
||||
reference.EssentialsProtect.jar=${project.EssentialsProtect}/dist/EssentialsProtect.jar
|
||||
reference.EssentialsSpawn.jar=${project.EssentialsSpawn}/dist/EssentialsSpawn.jar
|
||||
reference.EssentialsXMPP.jar=${project.EssentialsXMPP}/dist/EssentialsXMPP.jar
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>BuildAll</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
<libraries xmlns="http://www.netbeans.org/ns/ant-project-libraries/1">
|
||||
<definitions>..\lib\nblibraries.properties</definitions>
|
||||
</libraries>
|
||||
<references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
|
||||
<reference>
|
||||
<foreign-project>Essentials</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsChat</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsGeoIP</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsGroupBridge</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsGroupManager</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsProtect</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsSpawn</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
<reference>
|
||||
<foreign-project>EssentialsXMPP</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
</references>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="Essentials" default="default" basedir=".">
|
||||
|
||||
<description>Builds, tests, and runs the project Essentials.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
||||
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="Essentials-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
<!--target name="-post-jar">
|
||||
<jar jarfile="${dist.dir}/Essentials.jar">
|
||||
<zipfileset src="${dist.jar}" excludes="META-INF/*" />
|
||||
<zipfileset src="${dist.dir}/lib/Register.jar" excludes="META-INF/*" />
|
||||
<manifest>
|
||||
<attribute name="Classpath" value="Essentials.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target-->
|
||||
</project>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,11 +0,0 @@
|
||||
build.xml.data.CRC32=7d758acf
|
||||
build.xml.script.CRC32=3233ee78
|
||||
build.xml.stylesheet.CRC32=28e38971@1.38.2.45
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=a830bc14
|
||||
nbproject/build-impl.xml.script.CRC32=a9f8842a
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=fcddb364@1.50.1.46
|
||||
nbproject/profiler-build-impl.xml.data.CRC32=ab78ce15
|
||||
nbproject/profiler-build-impl.xml.script.CRC32=abda56ed
|
||||
nbproject/profiler-build-impl.xml.stylesheet.CRC32=f10cf54c@1.11.1
|
||||
@@ -1,3 +0,0 @@
|
||||
DoNotUseThreads
|
||||
LongVariable
|
||||
SignatureDeclareThrowsException
|
||||
@@ -1,154 +0,0 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=lombok.core.AnnotationProcessor
|
||||
annotation.processing.run.all.processors=false
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=Essentials
|
||||
application.vendor=
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=120
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap=none
|
||||
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineAnnotationArgs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineArrayInit=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineAssignment=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineBinaryOp=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineCallArgs=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineDisjunctiveCatchTypes=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineFor=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineImplements=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineMethodParams=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineParenthesized=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineTernaryOp=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineThrows=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineTryResources=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.blankLinesAfterClassHeader=0
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.blankLinesBeforeClass=2
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.expand-tabs=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.importGroupsOrder=*
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.indent-shift-width=4
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.indentCasesFromSwitch=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement=NEW_LINE
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeCatchOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeElseOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeFinallyOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.placeWhileOnNewLine=true
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.separateImportGroups=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceAfterTypeCast=false
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaces-per-tab=4
|
||||
auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.tab-size=4
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/Essentials.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.BOSEconomy7.jar=../lib/BOSEconomy7.jar
|
||||
file.reference.bPermissions.jar=../lib/bPermissions.jar
|
||||
file.reference.bpermissions2.jar=../lib/bpermissions2.jar
|
||||
file.reference.bukkit.jar=../lib/bukkit.jar
|
||||
file.reference.craftbukkit.jar=../lib/craftbukkit.jar
|
||||
file.reference.iCo4.jar=../lib/iCo4.jar
|
||||
file.reference.iCo5.jar=../lib/iCo5.jar
|
||||
file.reference.iCo6.jar=../lib/iCo6.jar
|
||||
file.reference.lombok.jar=../lib/lombok-0.10.8.jar
|
||||
file.reference.MultiCurrency.jar=../lib/MultiCurrency.jar
|
||||
file.reference.Permissions3.jar=../lib/Permissions3.jar
|
||||
file.reference.PermissionsBukkit-1.2.jar=../lib/PermissionsBukkit-1.2.jar
|
||||
file.reference.PermissionsEx.jar=../lib/PermissionsEx.jar
|
||||
file.reference.Privileges.jar=..\\lib\\Privileges.jar
|
||||
file.reference.Vault.jar=../lib/Vault.jar
|
||||
includes=**
|
||||
jar.archive.disabled=${jnlp.enabled}
|
||||
jar.compress=true
|
||||
jar.index=${jnlp.enabled}
|
||||
javac.classpath=\
|
||||
${file.reference.Permissions3.jar}:\
|
||||
${file.reference.iCo4.jar}:\
|
||||
${file.reference.iCo5.jar}:\
|
||||
${file.reference.iCo6.jar}:\
|
||||
${file.reference.MultiCurrency.jar}:\
|
||||
${file.reference.BOSEconomy7.jar}:\
|
||||
${file.reference.PermissionsEx.jar}:\
|
||||
${file.reference.bPermissions.jar}:\
|
||||
${file.reference.PermissionsBukkit-1.2.jar}:\
|
||||
${file.reference.lombok.jar}:\
|
||||
${reference.EssentialsGroupManager.jar}:\
|
||||
${file.reference.bukkit.jar}:\
|
||||
${file.reference.craftbukkit.jar}:\
|
||||
${file.reference.Vault.jar}:\
|
||||
${file.reference.Privileges.jar}:\
|
||||
${file.reference.bpermissions2.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.6
|
||||
javac.target=1.6
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit_4.10.classpath}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.reference.PermissionsEx.jar=../lib/PermissionsEx-javadoc.jar
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=Essentials Docs.
|
||||
jnlp.codebase.type=no.codebase
|
||||
jnlp.descriptor=application
|
||||
jnlp.enabled=false
|
||||
jnlp.mixed.code=default
|
||||
jnlp.offline-allowed=false
|
||||
jnlp.signed=false
|
||||
jnlp.signing=
|
||||
jnlp.signing.alias=
|
||||
jnlp.signing.keystore=
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=true
|
||||
platform.active=default_platform
|
||||
project.EssentialsGroupManager=../EssentialsGroupManager
|
||||
reference.EssentialsGroupManager.jar=../EssentialsGroupManager/dist/EssentialsGroupManager.jar
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=-Djline.terminal=jline.UnsupportedTerminal
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>Essentials</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
<libraries xmlns="http://www.netbeans.org/ns/ant-project-libraries/1">
|
||||
<definitions>../lib/nblibraries.properties</definitions>
|
||||
</libraries>
|
||||
<references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
|
||||
<reference>
|
||||
<foreign-project>EssentialsGroupManager</foreign-project>
|
||||
<artifact-type>jar</artifact-type>
|
||||
<script>build.xml</script>
|
||||
<target>jar</target>
|
||||
<clean-target>clean</clean-target>
|
||||
<id>jar</id>
|
||||
</reference>
|
||||
</references>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -0,0 +1,118 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>EssentialsXParent</artifactId>
|
||||
<version>2.16.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>EssentialsX</artifactId>
|
||||
|
||||
<build>
|
||||
<finalName>EssentialsX-${full.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<showDeprecation>false</showDeprecation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>io.papermc.lib</pattern>
|
||||
<shadedPattern>com.earth2me.essentials.paperlib</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>1.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>NMSProvider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>UpdatedMetaProvider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>1_8_R1Provider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>1_8_R2Provider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>LegacyProvider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>ReflectionProvider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>FlattenedProvider</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
This is the book file.
|
||||
|
||||
This file format works similar to the info.txt, motd.txt and rules.txt
|
||||
|
||||
Place content in here that you would like to be used by books ingame.
|
||||
|
||||
You can use this content by using the book:<section> meta option in kits or item spawning.
|
||||
|
||||
#Colors
|
||||
Minecraft colors:
|
||||
&0 &&0 &1 &&1 &2 &&2 &3 &&3
|
||||
&4 &&4 &5 &&5 &6 &&6 &7 &&7
|
||||
&8 &&8 &9 &&9 &a &&a &b &&b
|
||||
&c &&c &d &&d &e &&e &f &&f
|
||||
&0
|
||||
&&k &kMagic&r &&l &lBold
|
||||
&&m &mStrike&r &&n &nUline
|
||||
&&o &oItalic&r &&r &rReset
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.PluginCommandYamlParser;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class AlternativeCommandsHandler {
|
||||
private static final Logger LOGGER = Logger.getLogger("Essentials");
|
||||
private final transient Map<String, List<PluginCommand>> altcommands = new HashMap<>();
|
||||
private final transient Map<String, String> disabledList = new HashMap<>();
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public AlternativeCommandsHandler(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
for (Plugin plugin : ess.getServer().getPluginManager().getPlugins()) {
|
||||
if (plugin.isEnabled()) {
|
||||
addPlugin(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void addPlugin(final Plugin plugin) {
|
||||
if (plugin.getDescription().getMain().contains("com.earth2me.essentials")) {
|
||||
return;
|
||||
}
|
||||
final List<Command> commands = PluginCommandYamlParser.parse(plugin);
|
||||
final String pluginName = plugin.getDescription().getName().toLowerCase(Locale.ENGLISH);
|
||||
|
||||
for (Command command : commands) {
|
||||
final PluginCommand pc = (PluginCommand) command;
|
||||
final List<String> labels = new ArrayList<>(pc.getAliases());
|
||||
labels.add(pc.getName());
|
||||
|
||||
PluginCommand reg = ess.getServer().getPluginCommand(pluginName + ":" + pc.getName().toLowerCase(Locale.ENGLISH));
|
||||
if (reg == null) {
|
||||
reg = ess.getServer().getPluginCommand(pc.getName().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
if (reg == null || !reg.getPlugin().equals(plugin)) {
|
||||
continue;
|
||||
}
|
||||
for (String label : labels) {
|
||||
List<PluginCommand> plugincommands = altcommands.get(label.toLowerCase(Locale.ENGLISH));
|
||||
if (plugincommands == null) {
|
||||
plugincommands = new ArrayList<>();
|
||||
altcommands.put(label.toLowerCase(Locale.ENGLISH), plugincommands);
|
||||
}
|
||||
boolean found = false;
|
||||
for (PluginCommand pc2 : plugincommands) {
|
||||
if (pc2.getPlugin().equals(plugin)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
plugincommands.add(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlugin(final Plugin plugin) {
|
||||
final Iterator<Map.Entry<String, List<PluginCommand>>> iterator = altcommands.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final Map.Entry<String, List<PluginCommand>> entry = iterator.next();
|
||||
final Iterator<PluginCommand> pcIterator = entry.getValue().iterator();
|
||||
while (pcIterator.hasNext()) {
|
||||
final PluginCommand pc = pcIterator.next();
|
||||
if (pc.getPlugin() == null || pc.getPlugin().equals(plugin)) {
|
||||
pcIterator.remove();
|
||||
}
|
||||
}
|
||||
if (entry.getValue().isEmpty()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PluginCommand getAlternative(final String label) {
|
||||
final List<PluginCommand> commands = altcommands.get(label);
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (commands.size() == 1) {
|
||||
return commands.get(0);
|
||||
}
|
||||
// return the first command that is not an alias
|
||||
for (PluginCommand command : commands) {
|
||||
if (command.getName().equalsIgnoreCase(label)) {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
// return the first alias
|
||||
return commands.get(0);
|
||||
}
|
||||
|
||||
public void executed(final String label, final PluginCommand pc) {
|
||||
final String altString = pc.getPlugin().getName() + ":" + pc.getLabel();
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, "Essentials: Alternative command " + label + " found, using " + altString);
|
||||
}
|
||||
disabledList.put(label, altString);
|
||||
}
|
||||
|
||||
public Map<String, String> disabledCommands() {
|
||||
return disabledList;
|
||||
}
|
||||
}
|
||||
@@ -1,153 +1,132 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IBackup;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.ISettings;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import lombok.Cleanup;
|
||||
import org.bukkit.Bukkit;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Backup implements Runnable, IBackup
|
||||
{
|
||||
private static final Logger LOGGER = Bukkit.getLogger();
|
||||
private transient final Server server;
|
||||
private transient final IEssentials ess;
|
||||
private transient final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private transient int taskId = -1;
|
||||
private transient final AtomicBoolean active = new AtomicBoolean(false);
|
||||
|
||||
public Backup(final IEssentials ess)
|
||||
{
|
||||
this.ess = ess;
|
||||
server = ess.getServer();
|
||||
if (server.getOnlinePlayers().length > 0)
|
||||
{
|
||||
startTask();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startTask()
|
||||
{
|
||||
if (running.compareAndSet(false, true))
|
||||
{
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
final long interval = settings.getData().getGeneral().getBackup().getInterval() * 1200; // minutes -> ticks
|
||||
if (interval < 1200)
|
||||
{
|
||||
running.set(false);
|
||||
return;
|
||||
}
|
||||
taskId = ess.scheduleSyncRepeatingTask(this, interval, interval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (!active.compareAndSet(false, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
final String command = settings.getData().getGeneral().getBackup().getCommand();
|
||||
if (command == null || command.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
LOGGER.log(Level.INFO, _("backupStarted"));
|
||||
final CommandSender consoleSender = server.getConsoleSender();
|
||||
server.dispatchCommand(consoleSender, "save-all");
|
||||
server.dispatchCommand(consoleSender, "save-off");
|
||||
|
||||
ess.scheduleAsyncDelayedTask(new BackupRunner(command));
|
||||
}
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
private class BackupRunner implements Runnable
|
||||
{
|
||||
private final transient String command;
|
||||
public class Backup implements Runnable {
|
||||
private static final Logger LOGGER = Logger.getLogger("Essentials");
|
||||
private transient final Server server;
|
||||
private transient final IEssentials ess;
|
||||
private transient boolean running = false;
|
||||
private transient int taskId = -1;
|
||||
private transient boolean active = false;
|
||||
|
||||
public BackupRunner(final String command)
|
||||
{
|
||||
this.command = command;
|
||||
}
|
||||
public Backup(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
server = ess.getServer();
|
||||
if (!ess.getOnlinePlayers().isEmpty()) {
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startTask();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
final ProcessBuilder childBuilder = new ProcessBuilder(command);
|
||||
childBuilder.redirectErrorStream(true);
|
||||
childBuilder.directory(ess.getDataFolder().getParentFile().getParentFile());
|
||||
final Process child = childBuilder.start();
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(child.getInputStream()));
|
||||
try
|
||||
{
|
||||
child.waitFor();
|
||||
String line;
|
||||
do
|
||||
{
|
||||
line = reader.readLine();
|
||||
if (line != null)
|
||||
{
|
||||
LOGGER.log(Level.INFO, line);
|
||||
}
|
||||
}
|
||||
while (line != null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ess.scheduleSyncDelayedTask(new EnableSavingRunner());
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onPlayerJoin() {
|
||||
startTask();
|
||||
}
|
||||
|
||||
public synchronized void stopTask() {
|
||||
running = false;
|
||||
if (taskId != -1) {
|
||||
server.getScheduler().cancelTask(taskId);
|
||||
}
|
||||
taskId = -1;
|
||||
}
|
||||
|
||||
private class EnableSavingRunner implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
server.dispatchCommand(server.getConsoleSender(), "save-on");
|
||||
if (server.getOnlinePlayers().length == 0)
|
||||
{
|
||||
running.set(false);
|
||||
if (taskId != -1)
|
||||
{
|
||||
server.getScheduler().cancelTask(taskId);
|
||||
}
|
||||
}
|
||||
private synchronized void startTask() {
|
||||
if (!running) {
|
||||
final long interval = ess.getSettings().getBackupInterval() * 1200; // minutes -> ticks
|
||||
if (interval < 1200) {
|
||||
return;
|
||||
}
|
||||
taskId = ess.scheduleSyncRepeatingTask(this, interval, interval);
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
||||
active.set(false);
|
||||
LOGGER.log(Level.INFO, _("backupFinished"));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
if (active) {
|
||||
return;
|
||||
}
|
||||
active = true;
|
||||
final String command = ess.getSettings().getBackupCommand();
|
||||
if (command == null || "".equals(command)) {
|
||||
return;
|
||||
}
|
||||
if ("save-all".equalsIgnoreCase(command)) {
|
||||
final CommandSender cs = server.getConsoleSender();
|
||||
server.dispatchCommand(cs, "save-all");
|
||||
active = false;
|
||||
return;
|
||||
}
|
||||
LOGGER.log(Level.INFO, tl("backupStarted"));
|
||||
final CommandSender cs = server.getConsoleSender();
|
||||
server.dispatchCommand(cs, "save-all");
|
||||
server.dispatchCommand(cs, "save-off");
|
||||
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final ProcessBuilder childBuilder = new ProcessBuilder(command);
|
||||
childBuilder.redirectErrorStream(true);
|
||||
childBuilder.directory(ess.getDataFolder().getParentFile().getParentFile());
|
||||
final Process child = childBuilder.start();
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(child.getInputStream()));
|
||||
try {
|
||||
String line;
|
||||
do {
|
||||
line = reader.readLine();
|
||||
if (line != null) {
|
||||
LOGGER.log(Level.INFO, line);
|
||||
}
|
||||
} while (line != null);
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
child.waitFor();
|
||||
} catch (InterruptedException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
class BackupEnableSaveTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
server.dispatchCommand(cs, "save-on");
|
||||
if (ess.getOnlinePlayers().isEmpty()) {
|
||||
stopTask();
|
||||
}
|
||||
active = false;
|
||||
LOGGER.log(Level.INFO, tl("backupFinished"));
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new BackupEnableSaveTask());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
|
||||
public class ChargeException extends Exception {
|
||||
public ChargeException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ChargeException(final String message, final Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public class CommandSource {
|
||||
protected CommandSender sender;
|
||||
|
||||
public CommandSource(final CommandSender base) {
|
||||
this.sender = base;
|
||||
}
|
||||
|
||||
public final CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public final Player getPlayer() {
|
||||
if (sender instanceof Player) {
|
||||
return (Player) sender;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isPlayer() {
|
||||
return (sender instanceof Player);
|
||||
}
|
||||
|
||||
public final CommandSender setSender(final CommandSender base) {
|
||||
return this.sender = base;
|
||||
}
|
||||
|
||||
|
||||
public void sendMessage(String message) {
|
||||
if (!message.isEmpty()) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,77 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IReplyTo;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.messaging.SimpleMessageRecipient;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
||||
public final class Console implements IReplyTo
|
||||
{
|
||||
private static Console instance = new Console();
|
||||
private CommandSender replyTo;
|
||||
public final static String NAME = "Console";
|
||||
public final class Console implements IMessageRecipient {
|
||||
public static final String NAME = "Console";
|
||||
private static Console instance; // Set in essentials
|
||||
|
||||
private final IEssentials ess;
|
||||
private final IMessageRecipient messageRecipient;
|
||||
|
||||
private Console()
|
||||
{
|
||||
}
|
||||
public static Console getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplyTo(final CommandSender user)
|
||||
{
|
||||
replyTo = user;
|
||||
}
|
||||
static void setInstance(IEssentials ess) { // Called in Essentials#onEnable()
|
||||
instance = new Console(ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Console#getCommandSender()}
|
||||
*/
|
||||
@Deprecated
|
||||
public static CommandSender getCommandSender(Server server) throws Exception {
|
||||
return server.getConsoleSender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSender getReplyTo()
|
||||
{
|
||||
return replyTo;
|
||||
}
|
||||
private Console(IEssentials ess) {
|
||||
this.ess = ess;
|
||||
this.messageRecipient = new SimpleMessageRecipient(ess, this);
|
||||
}
|
||||
|
||||
public static Console getConsoleReplyTo()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
public CommandSender getCommandSender() {
|
||||
return ess.getServer().getConsoleSender();
|
||||
}
|
||||
|
||||
@Override public String getName() {
|
||||
return Console.NAME;
|
||||
}
|
||||
|
||||
@Override public String getDisplayName() {
|
||||
return Console.NAME;
|
||||
}
|
||||
|
||||
@Override public void sendMessage(String message) {
|
||||
getCommandSender().sendMessage(message);
|
||||
}
|
||||
|
||||
@Override public boolean isReachable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ================================
|
||||
* >> DELEGATE METHODS
|
||||
* ================================ */
|
||||
|
||||
@Override public MessageResponse sendMessage(IMessageRecipient recipient, String message) {
|
||||
return this.messageRecipient.sendMessage(recipient, message);
|
||||
}
|
||||
|
||||
@Override public MessageResponse onReceiveMessage(IMessageRecipient sender, String message) {
|
||||
return this.messageRecipient.onReceiveMessage(sender, message);
|
||||
}
|
||||
|
||||
@Override public IMessageRecipient getReplyRecipient() {
|
||||
return this.messageRecipient.getReplyRecipient();
|
||||
}
|
||||
|
||||
@Override public void setReplyRecipient(IMessageRecipient recipient) {
|
||||
this.messageRecipient.setReplyRecipient(recipient);
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* This utility class is used for converting between the ingame
|
||||
* time in ticks to ingame time as a friendly string.
|
||||
* Note that the time is INGAME.
|
||||
*
|
||||
* http://www.minecraftwiki.net/wiki/Day/night_cycle
|
||||
*
|
||||
* @author Olof Larsson
|
||||
*/
|
||||
public final class DescParseTickFormat
|
||||
{
|
||||
public static final Map<String, Integer> nameToTicks = new LinkedHashMap<String, Integer>();
|
||||
public static final Set<String> resetAliases = new HashSet<String>();
|
||||
public static final int ticksAtMidnight = 18000;
|
||||
public static final int ticksPerDay = 24000;
|
||||
public static final int ticksPerHour = 1000;
|
||||
public static final double ticksPerMinute = 1000d / 60d;
|
||||
public static final double ticksPerSecond = 1000d / 60d / 60d;
|
||||
private static final SimpleDateFormat SDFTwentyFour = new SimpleDateFormat("HH:mm", Locale.ENGLISH);
|
||||
private static final SimpleDateFormat SDFTwelve = new SimpleDateFormat("h:mmaa", Locale.ENGLISH);
|
||||
|
||||
static
|
||||
{
|
||||
SDFTwentyFour.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
SDFTwelve.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
|
||||
nameToTicks.put("sunrise", 23000);
|
||||
nameToTicks.put("dawn", 23000);
|
||||
|
||||
nameToTicks.put("daystart", 0);
|
||||
nameToTicks.put("day", 0);
|
||||
|
||||
nameToTicks.put("morning", 1000);
|
||||
|
||||
nameToTicks.put("midday", 6000);
|
||||
nameToTicks.put("noon", 6000);
|
||||
|
||||
nameToTicks.put("afternoon", 9000);
|
||||
|
||||
nameToTicks.put("sunset", 12000);
|
||||
nameToTicks.put("dusk", 12000);
|
||||
nameToTicks.put("sundown", 12000);
|
||||
nameToTicks.put("nightfall", 12000);
|
||||
|
||||
nameToTicks.put("nightstart", 14000);
|
||||
nameToTicks.put("night", 14000);
|
||||
|
||||
nameToTicks.put("midnight", 18000);
|
||||
|
||||
resetAliases.add("reset");
|
||||
resetAliases.add("normal");
|
||||
resetAliases.add("default");
|
||||
}
|
||||
|
||||
private DescParseTickFormat()
|
||||
{
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PARSE. From describing String to int
|
||||
// --------------------------------------------
|
||||
public static long parse(String desc) throws NumberFormatException
|
||||
{
|
||||
// Only look at alphanumeric and lowercase and : for 24:00
|
||||
desc = desc.toLowerCase(Locale.ENGLISH).replaceAll("[^A-Za-z0-9:]", "");
|
||||
|
||||
// Detect ticks format
|
||||
try
|
||||
{
|
||||
return parseTicks(desc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Detect 24-hour format
|
||||
try
|
||||
{
|
||||
return parse24(desc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Detect 12-hour format
|
||||
try
|
||||
{
|
||||
return parse12(desc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Detect aliases
|
||||
try
|
||||
{
|
||||
return parseAlias(desc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Well we failed to understand...
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
public static long parseTicks(String desc) throws NumberFormatException
|
||||
{
|
||||
if (!desc.matches("^[0-9]+ti?c?k?s?$"))
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
desc = desc.replaceAll("[^0-9]", "");
|
||||
|
||||
return Long.parseLong(desc) % 24000;
|
||||
}
|
||||
|
||||
public static long parse24(String desc) throws NumberFormatException
|
||||
{
|
||||
if (!desc.matches("^[0-9]{2}[^0-9]?[0-9]{2}$"))
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
desc = desc.toLowerCase(Locale.ENGLISH).replaceAll("[^0-9]", "");
|
||||
|
||||
if (desc.length() != 4)
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
final int hours = Integer.parseInt(desc.substring(0, 2));
|
||||
final int minutes = Integer.parseInt(desc.substring(2, 4));
|
||||
|
||||
return hoursMinutesToTicks(hours, minutes);
|
||||
}
|
||||
|
||||
public static long parse12(String desc) throws NumberFormatException
|
||||
{
|
||||
if (!desc.matches("^[0-9]{1,2}([^0-9]?[0-9]{2})?(pm|am)$"))
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
|
||||
desc = desc.toLowerCase(Locale.ENGLISH).replaceAll("[^0-9]", "");
|
||||
|
||||
if (desc.length() > 4)
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
if (desc.length() == 4)
|
||||
{
|
||||
hours += Integer.parseInt(desc.substring(0, 2));
|
||||
minutes += Integer.parseInt(desc.substring(2, 4));
|
||||
}
|
||||
else if (desc.length() == 3)
|
||||
{
|
||||
hours += Integer.parseInt(desc.substring(0, 1));
|
||||
minutes += Integer.parseInt(desc.substring(1, 3));
|
||||
}
|
||||
else if (desc.length() == 2)
|
||||
{
|
||||
hours += Integer.parseInt(desc.substring(0, 2));
|
||||
}
|
||||
else if (desc.length() == 1)
|
||||
{
|
||||
hours += Integer.parseInt(desc.substring(0, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
if (desc.endsWith("pm") && hours != 12)
|
||||
{
|
||||
hours += 12;
|
||||
}
|
||||
|
||||
if (desc.endsWith("am") && hours == 12)
|
||||
{
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
return hoursMinutesToTicks(hours, minutes);
|
||||
}
|
||||
|
||||
public static long hoursMinutesToTicks(final int hours, final int minutes)
|
||||
{
|
||||
long ret = ticksAtMidnight;
|
||||
ret += (hours) * ticksPerHour;
|
||||
|
||||
ret += (minutes / 60.0) * ticksPerHour;
|
||||
|
||||
ret %= ticksPerDay;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static long parseAlias(final String desc) throws NumberFormatException
|
||||
{
|
||||
final Integer ret = nameToTicks.get(desc);
|
||||
if (ret == null)
|
||||
{
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static boolean meansReset(final String desc)
|
||||
{
|
||||
return resetAliases.contains(desc);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// FORMAT. From int to describing String
|
||||
// --------------------------------------------
|
||||
public static String format(final long ticks)
|
||||
{
|
||||
return _("timeFormat", format24(ticks), format12(ticks), formatTicks(ticks));
|
||||
}
|
||||
|
||||
public static String formatTicks(final long ticks)
|
||||
{
|
||||
return (ticks % ticksPerDay) + "ticks";
|
||||
}
|
||||
|
||||
public static String format24(final long ticks)
|
||||
{
|
||||
synchronized (SDFTwentyFour)
|
||||
{
|
||||
return formatDateFormat(ticks, SDFTwentyFour);
|
||||
}
|
||||
}
|
||||
|
||||
public static String format12(final long ticks)
|
||||
{
|
||||
synchronized (SDFTwelve)
|
||||
{
|
||||
return formatDateFormat(ticks, SDFTwelve);
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatDateFormat(final long ticks, final SimpleDateFormat format)
|
||||
{
|
||||
final Date date = ticksToDate(ticks);
|
||||
return format.format(date);
|
||||
}
|
||||
|
||||
public static Date ticksToDate(long ticks)
|
||||
{
|
||||
// Assume the server time starts at 0. It would start on a day.
|
||||
// But we will simulate that the server started with 0 at midnight.
|
||||
ticks = ticks - ticksAtMidnight + ticksPerDay;
|
||||
|
||||
// How many ingame days have passed since the server start?
|
||||
final long days = ticks / ticksPerDay;
|
||||
ticks = ticks - days * ticksPerDay;
|
||||
|
||||
// How many hours on the last day?
|
||||
final long hours = ticks / ticksPerHour;
|
||||
ticks = ticks - hours * ticksPerHour;
|
||||
|
||||
// How many minutes on the last day?
|
||||
final long minutes = (long)Math.floor(ticks / ticksPerMinute);
|
||||
final double dticks = ticks - minutes * ticksPerMinute;
|
||||
|
||||
// How many seconds on the last day?
|
||||
final long seconds = (long)Math.floor(dticks / ticksPerSecond);
|
||||
|
||||
// Now we create an english GMT calendar (We wan't no daylight savings)
|
||||
final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.ENGLISH);
|
||||
cal.setLenient(true);
|
||||
|
||||
// And we set the time to 0! And append the time that passed!
|
||||
cal.set(0, Calendar.JANUARY, 1, 0, 0, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, (int)days);
|
||||
cal.add(Calendar.HOUR_OF_DAY, (int)hours);
|
||||
cal.add(Calendar.MINUTE, (int)minutes);
|
||||
cal.add(Calendar.SECOND, (int)seconds + 1); // To solve rounding errors.
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.*;
|
||||
import com.earth2me.essentials.perm.Permissions;
|
||||
import com.earth2me.essentials.settings.MoneyHolder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Economy implements IEconomy
|
||||
{
|
||||
private final IEssentials ess;
|
||||
private final MoneyHolder npcs;
|
||||
|
||||
public Economy(IEssentials ess)
|
||||
{
|
||||
this.ess = ess;
|
||||
this.npcs = new MoneyHolder(ess);
|
||||
}
|
||||
|
||||
private double getNPCBalance(String name) throws UserDoesNotExistException
|
||||
{
|
||||
npcs.acquireReadLock();
|
||||
try
|
||||
{
|
||||
Map<String, Double> balances = npcs.getData().getBalances();
|
||||
if (balances == null)
|
||||
{
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
Double balance = npcs.getData().getBalances().get(name.toLowerCase(Locale.ENGLISH));
|
||||
if (balance == null)
|
||||
{
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
finally
|
||||
{
|
||||
npcs.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void setNPCBalance(String name, double balance, boolean checkExistance) throws UserDoesNotExistException
|
||||
{
|
||||
npcs.acquireWriteLock();
|
||||
try
|
||||
{
|
||||
Map<String, Double> balances = npcs.getData().getBalances();
|
||||
if (balances == null)
|
||||
{
|
||||
balances = new HashMap<String, Double>();
|
||||
npcs.getData().setBalances(balances);
|
||||
}
|
||||
if (checkExistance && !balances.containsKey(name.toLowerCase(Locale.ENGLISH)))
|
||||
{
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
balances.put(name.toLowerCase(Locale.ENGLISH), balance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
npcs.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private double getStartingBalance()
|
||||
{
|
||||
double startingBalance = 0;
|
||||
ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
try
|
||||
{
|
||||
startingBalance = settings.getData().getEconomy().getStartingBalance();
|
||||
}
|
||||
finally
|
||||
{
|
||||
settings.unlock();
|
||||
}
|
||||
return startingBalance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload()
|
||||
{
|
||||
this.npcs.onReload(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMoney(String name) throws UserDoesNotExistException
|
||||
{
|
||||
IUser user = ess.getUser(name);
|
||||
if (user == null)
|
||||
{
|
||||
return getNPCBalance(name);
|
||||
}
|
||||
return user.getMoney();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMoney(String name, double balance) throws NoLoanPermittedException, UserDoesNotExistException
|
||||
{
|
||||
IUser user = ess.getUser(name);
|
||||
if (user == null)
|
||||
{
|
||||
setNPCBalance(name, balance, true);
|
||||
return;
|
||||
}
|
||||
if (balance < 0.0 && !Permissions.ECO_LOAN.isAuthorized(user))
|
||||
{
|
||||
throw new NoLoanPermittedException();
|
||||
}
|
||||
user.setMoney(balance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBalance(String name) throws NoLoanPermittedException, UserDoesNotExistException
|
||||
{
|
||||
setMoney(name, getStartingBalance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(double amount)
|
||||
{
|
||||
return Util.formatCurrency(amount, ess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerExists(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
getMoney(name);
|
||||
return true;
|
||||
}
|
||||
catch (UserDoesNotExistException ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNPC(String name) throws UserDoesNotExistException
|
||||
{
|
||||
boolean result = ess.getUser(name) == null;
|
||||
if (result)
|
||||
{
|
||||
getNPCBalance(name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createNPC(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isNPC(name))
|
||||
{
|
||||
|
||||
setNPCBalance(name, getStartingBalance(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (UserDoesNotExistException ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
setNPCBalance(name, getStartingBalance(), false);
|
||||
return true;
|
||||
}
|
||||
catch (UserDoesNotExistException ex1)
|
||||
{
|
||||
//This should never happen!
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNPC(String name) throws UserDoesNotExistException
|
||||
{
|
||||
npcs.acquireWriteLock();
|
||||
try
|
||||
{
|
||||
Map<String, Double> balances = npcs.getData().getBalances();
|
||||
if (balances == null)
|
||||
{
|
||||
balances = new HashMap<String, Double>();
|
||||
npcs.getData().setBalances(balances);
|
||||
}
|
||||
if (balances.containsKey(name.toLowerCase(Locale.ENGLISH)))
|
||||
{
|
||||
balances.remove(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
npcs.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,269 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
|
||||
public final class Enchantments
|
||||
{
|
||||
public class Enchantments {
|
||||
private static final Map<String, Enchantment> ENCHANTMENTS = new HashMap<String, Enchantment>();
|
||||
private static final Map<String, Enchantment> ALIASENCHANTMENTS = new HashMap<String, Enchantment>();
|
||||
private static boolean isFlat;
|
||||
|
||||
private Enchantments()
|
||||
{
|
||||
}
|
||||
|
||||
private static final transient Pattern NUMPATTERN = Pattern.compile("\\d+");
|
||||
private static final Map<String, Enchantment> ENCHANTMENTS = new HashMap<String, Enchantment>();
|
||||
static {
|
||||
ENCHANTMENTS.put("alldamage", Enchantment.DAMAGE_ALL);
|
||||
ALIASENCHANTMENTS.put("alldmg", Enchantment.DAMAGE_ALL);
|
||||
ENCHANTMENTS.put("sharpness", Enchantment.DAMAGE_ALL);
|
||||
ALIASENCHANTMENTS.put("sharp", Enchantment.DAMAGE_ALL);
|
||||
ALIASENCHANTMENTS.put("dal", Enchantment.DAMAGE_ALL);
|
||||
|
||||
static
|
||||
{
|
||||
ENCHANTMENTS.put("alldamage", Enchantment.DAMAGE_ALL);
|
||||
ENCHANTMENTS.put("alldmg", Enchantment.DAMAGE_ALL);
|
||||
ENCHANTMENTS.put("sharpness", Enchantment.DAMAGE_ALL);
|
||||
ENCHANTMENTS.put("arthropodsdamage", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ENCHANTMENTS.put("ardmg", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ENCHANTMENTS.put("baneofarthropods", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ENCHANTMENTS.put("undeaddamage", Enchantment.DAMAGE_UNDEAD);
|
||||
ENCHANTMENTS.put("smite", Enchantment.DAMAGE_UNDEAD);
|
||||
ENCHANTMENTS.put("digspeed", Enchantment.DIG_SPEED);
|
||||
ENCHANTMENTS.put("efficiency", Enchantment.DIG_SPEED);
|
||||
ENCHANTMENTS.put("durability", Enchantment.DURABILITY);
|
||||
ENCHANTMENTS.put("dura", Enchantment.DURABILITY);
|
||||
ENCHANTMENTS.put("unbreaking", Enchantment.DURABILITY);
|
||||
ENCHANTMENTS.put("fireaspect", Enchantment.FIRE_ASPECT);
|
||||
ENCHANTMENTS.put("fire", Enchantment.FIRE_ASPECT);
|
||||
ENCHANTMENTS.put("knockback", Enchantment.KNOCKBACK);
|
||||
ENCHANTMENTS.put("blockslootbonus", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
ENCHANTMENTS.put("fortune", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
ENCHANTMENTS.put("mobslootbonus", Enchantment.LOOT_BONUS_MOBS);
|
||||
ENCHANTMENTS.put("mobloot", Enchantment.LOOT_BONUS_MOBS);
|
||||
ENCHANTMENTS.put("looting", Enchantment.LOOT_BONUS_MOBS);
|
||||
ENCHANTMENTS.put("oxygen", Enchantment.OXYGEN);
|
||||
ENCHANTMENTS.put("respiration", Enchantment.OXYGEN);
|
||||
ENCHANTMENTS.put("protection", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
ENCHANTMENTS.put("prot", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
ENCHANTMENTS.put("explosionsprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ENCHANTMENTS.put("expprot", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ENCHANTMENTS.put("blastprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ENCHANTMENTS.put("fallprotection", Enchantment.PROTECTION_FALL);
|
||||
ENCHANTMENTS.put("fallprot", Enchantment.PROTECTION_FALL);
|
||||
ENCHANTMENTS.put("featherfalling", Enchantment.PROTECTION_FALL);
|
||||
ENCHANTMENTS.put("fireprotection", Enchantment.PROTECTION_FIRE);
|
||||
ENCHANTMENTS.put("fireprot", Enchantment.PROTECTION_FIRE);
|
||||
ENCHANTMENTS.put("projectileprotection", Enchantment.PROTECTION_PROJECTILE);
|
||||
ENCHANTMENTS.put("projprot", Enchantment.PROTECTION_PROJECTILE);
|
||||
ENCHANTMENTS.put("silktouch", Enchantment.SILK_TOUCH);
|
||||
ENCHANTMENTS.put("waterworker", Enchantment.WATER_WORKER);
|
||||
ENCHANTMENTS.put("aquaaffinity", Enchantment.WATER_WORKER);
|
||||
ENCHANTMENTS.put("firearrow", Enchantment.ARROW_FIRE);
|
||||
ENCHANTMENTS.put("arrowdamage", Enchantment.ARROW_DAMAGE);
|
||||
ENCHANTMENTS.put("arrowknockback", Enchantment.ARROW_KNOCKBACK);
|
||||
ENCHANTMENTS.put("arrowkb", Enchantment.ARROW_KNOCKBACK);
|
||||
ENCHANTMENTS.put("infinitearrows", Enchantment.ARROW_INFINITE);
|
||||
ENCHANTMENTS.put("infarrows", Enchantment.ARROW_INFINITE);
|
||||
}
|
||||
|
||||
public static Enchantment getByName(final String name) {
|
||||
Enchantment enchantment;
|
||||
if (NUMPATTERN.matcher(name).matches()) {
|
||||
enchantment = Enchantment.getById(Integer.parseInt(name));
|
||||
} else {
|
||||
enchantment = Enchantment.getByName(name.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
if (enchantment == null)
|
||||
{
|
||||
enchantment = ENCHANTMENTS.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
return enchantment;
|
||||
}
|
||||
ENCHANTMENTS.put("ardmg", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ENCHANTMENTS.put("baneofarthropods", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ALIASENCHANTMENTS.put("baneofarthropod", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ALIASENCHANTMENTS.put("arthropod", Enchantment.DAMAGE_ARTHROPODS);
|
||||
ALIASENCHANTMENTS.put("dar", Enchantment.DAMAGE_ARTHROPODS);
|
||||
|
||||
public static Set<Entry<String, Enchantment>> entrySet()
|
||||
{
|
||||
return ENCHANTMENTS.entrySet();
|
||||
}
|
||||
ENCHANTMENTS.put("undeaddamage", Enchantment.DAMAGE_UNDEAD);
|
||||
ENCHANTMENTS.put("smite", Enchantment.DAMAGE_UNDEAD);
|
||||
ALIASENCHANTMENTS.put("du", Enchantment.DAMAGE_UNDEAD);
|
||||
|
||||
ENCHANTMENTS.put("digspeed", Enchantment.DIG_SPEED);
|
||||
ENCHANTMENTS.put("efficiency", Enchantment.DIG_SPEED);
|
||||
ALIASENCHANTMENTS.put("minespeed", Enchantment.DIG_SPEED);
|
||||
ALIASENCHANTMENTS.put("cutspeed", Enchantment.DIG_SPEED);
|
||||
ALIASENCHANTMENTS.put("ds", Enchantment.DIG_SPEED);
|
||||
ALIASENCHANTMENTS.put("eff", Enchantment.DIG_SPEED);
|
||||
|
||||
ENCHANTMENTS.put("durability", Enchantment.DURABILITY);
|
||||
ALIASENCHANTMENTS.put("dura", Enchantment.DURABILITY);
|
||||
ENCHANTMENTS.put("unbreaking", Enchantment.DURABILITY);
|
||||
ALIASENCHANTMENTS.put("d", Enchantment.DURABILITY);
|
||||
|
||||
ENCHANTMENTS.put("thorns", Enchantment.THORNS);
|
||||
ENCHANTMENTS.put("highcrit", Enchantment.THORNS);
|
||||
ALIASENCHANTMENTS.put("thorn", Enchantment.THORNS);
|
||||
ALIASENCHANTMENTS.put("highercrit", Enchantment.THORNS);
|
||||
ALIASENCHANTMENTS.put("t", Enchantment.THORNS);
|
||||
|
||||
ENCHANTMENTS.put("fireaspect", Enchantment.FIRE_ASPECT);
|
||||
ENCHANTMENTS.put("fire", Enchantment.FIRE_ASPECT);
|
||||
ALIASENCHANTMENTS.put("meleefire", Enchantment.FIRE_ASPECT);
|
||||
ALIASENCHANTMENTS.put("meleeflame", Enchantment.FIRE_ASPECT);
|
||||
ALIASENCHANTMENTS.put("fa", Enchantment.FIRE_ASPECT);
|
||||
|
||||
ENCHANTMENTS.put("knockback", Enchantment.KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("kback", Enchantment.KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("kb", Enchantment.KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("k", Enchantment.KNOCKBACK);
|
||||
|
||||
ALIASENCHANTMENTS.put("blockslootbonus", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
ENCHANTMENTS.put("fortune", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
ALIASENCHANTMENTS.put("fort", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
ALIASENCHANTMENTS.put("lbb", Enchantment.LOOT_BONUS_BLOCKS);
|
||||
|
||||
ALIASENCHANTMENTS.put("mobslootbonus", Enchantment.LOOT_BONUS_MOBS);
|
||||
ENCHANTMENTS.put("mobloot", Enchantment.LOOT_BONUS_MOBS);
|
||||
ENCHANTMENTS.put("looting", Enchantment.LOOT_BONUS_MOBS);
|
||||
ALIASENCHANTMENTS.put("lbm", Enchantment.LOOT_BONUS_MOBS);
|
||||
|
||||
ALIASENCHANTMENTS.put("oxygen", Enchantment.OXYGEN);
|
||||
ENCHANTMENTS.put("respiration", Enchantment.OXYGEN);
|
||||
ALIASENCHANTMENTS.put("breathing", Enchantment.OXYGEN);
|
||||
ENCHANTMENTS.put("breath", Enchantment.OXYGEN);
|
||||
ALIASENCHANTMENTS.put("o", Enchantment.OXYGEN);
|
||||
|
||||
ENCHANTMENTS.put("protection", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
ALIASENCHANTMENTS.put("prot", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
ENCHANTMENTS.put("protect", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
ALIASENCHANTMENTS.put("p", Enchantment.PROTECTION_ENVIRONMENTAL);
|
||||
|
||||
ALIASENCHANTMENTS.put("explosionsprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("explosionprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("expprot", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("blastprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("bprotection", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("bprotect", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ENCHANTMENTS.put("blastprotect", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
ALIASENCHANTMENTS.put("pe", Enchantment.PROTECTION_EXPLOSIONS);
|
||||
|
||||
ALIASENCHANTMENTS.put("fallprotection", Enchantment.PROTECTION_FALL);
|
||||
ENCHANTMENTS.put("fallprot", Enchantment.PROTECTION_FALL);
|
||||
ENCHANTMENTS.put("featherfall", Enchantment.PROTECTION_FALL);
|
||||
ALIASENCHANTMENTS.put("featherfalling", Enchantment.PROTECTION_FALL);
|
||||
ALIASENCHANTMENTS.put("pfa", Enchantment.PROTECTION_FALL);
|
||||
|
||||
ALIASENCHANTMENTS.put("fireprotection", Enchantment.PROTECTION_FIRE);
|
||||
ALIASENCHANTMENTS.put("flameprotection", Enchantment.PROTECTION_FIRE);
|
||||
ENCHANTMENTS.put("fireprotect", Enchantment.PROTECTION_FIRE);
|
||||
ALIASENCHANTMENTS.put("flameprotect", Enchantment.PROTECTION_FIRE);
|
||||
ENCHANTMENTS.put("fireprot", Enchantment.PROTECTION_FIRE);
|
||||
ALIASENCHANTMENTS.put("flameprot", Enchantment.PROTECTION_FIRE);
|
||||
ALIASENCHANTMENTS.put("pf", Enchantment.PROTECTION_FIRE);
|
||||
|
||||
ENCHANTMENTS.put("projectileprotection", Enchantment.PROTECTION_PROJECTILE);
|
||||
ENCHANTMENTS.put("projprot", Enchantment.PROTECTION_PROJECTILE);
|
||||
ALIASENCHANTMENTS.put("pp", Enchantment.PROTECTION_PROJECTILE);
|
||||
|
||||
ENCHANTMENTS.put("silktouch", Enchantment.SILK_TOUCH);
|
||||
ALIASENCHANTMENTS.put("softtouch", Enchantment.SILK_TOUCH);
|
||||
ALIASENCHANTMENTS.put("st", Enchantment.SILK_TOUCH);
|
||||
|
||||
ENCHANTMENTS.put("waterworker", Enchantment.WATER_WORKER);
|
||||
ENCHANTMENTS.put("aquaaffinity", Enchantment.WATER_WORKER);
|
||||
ALIASENCHANTMENTS.put("watermine", Enchantment.WATER_WORKER);
|
||||
ALIASENCHANTMENTS.put("ww", Enchantment.WATER_WORKER);
|
||||
|
||||
ALIASENCHANTMENTS.put("firearrow", Enchantment.ARROW_FIRE);
|
||||
ENCHANTMENTS.put("flame", Enchantment.ARROW_FIRE);
|
||||
ENCHANTMENTS.put("flamearrow", Enchantment.ARROW_FIRE);
|
||||
ALIASENCHANTMENTS.put("af", Enchantment.ARROW_FIRE);
|
||||
|
||||
ENCHANTMENTS.put("arrowdamage", Enchantment.ARROW_DAMAGE);
|
||||
ENCHANTMENTS.put("power", Enchantment.ARROW_DAMAGE);
|
||||
ALIASENCHANTMENTS.put("arrowpower", Enchantment.ARROW_DAMAGE);
|
||||
ALIASENCHANTMENTS.put("ad", Enchantment.ARROW_DAMAGE);
|
||||
|
||||
ENCHANTMENTS.put("arrowknockback", Enchantment.ARROW_KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("arrowkb", Enchantment.ARROW_KNOCKBACK);
|
||||
ENCHANTMENTS.put("punch", Enchantment.ARROW_KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("arrowpunch", Enchantment.ARROW_KNOCKBACK);
|
||||
ALIASENCHANTMENTS.put("ak", Enchantment.ARROW_KNOCKBACK);
|
||||
|
||||
ALIASENCHANTMENTS.put("infinitearrows", Enchantment.ARROW_INFINITE);
|
||||
ENCHANTMENTS.put("infarrows", Enchantment.ARROW_INFINITE);
|
||||
ENCHANTMENTS.put("infinity", Enchantment.ARROW_INFINITE);
|
||||
ALIASENCHANTMENTS.put("infinite", Enchantment.ARROW_INFINITE);
|
||||
ALIASENCHANTMENTS.put("unlimited", Enchantment.ARROW_INFINITE);
|
||||
ALIASENCHANTMENTS.put("unlimitedarrows", Enchantment.ARROW_INFINITE);
|
||||
ALIASENCHANTMENTS.put("ai", Enchantment.ARROW_INFINITE);
|
||||
|
||||
ENCHANTMENTS.put("luck", Enchantment.LUCK);
|
||||
ALIASENCHANTMENTS.put("luckofsea", Enchantment.LUCK);
|
||||
ALIASENCHANTMENTS.put("luckofseas", Enchantment.LUCK);
|
||||
ALIASENCHANTMENTS.put("rodluck", Enchantment.LUCK);
|
||||
|
||||
ENCHANTMENTS.put("lure", Enchantment.LURE);
|
||||
ALIASENCHANTMENTS.put("rodlure", Enchantment.LURE);
|
||||
|
||||
// 1.8
|
||||
try {
|
||||
Enchantment depthStrider = Enchantment.getByName("DEPTH_STRIDER");
|
||||
if (depthStrider != null) {
|
||||
ENCHANTMENTS.put("depthstrider", depthStrider);
|
||||
ALIASENCHANTMENTS.put("depth", depthStrider);
|
||||
ALIASENCHANTMENTS.put("strider", depthStrider);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
// 1.9
|
||||
try {
|
||||
Enchantment frostWalker = Enchantment.getByName("FROST_WALKER");
|
||||
if (frostWalker != null) {
|
||||
ENCHANTMENTS.put("frostwalker", frostWalker);
|
||||
ALIASENCHANTMENTS.put("frost", frostWalker);
|
||||
ALIASENCHANTMENTS.put("walker", frostWalker);
|
||||
}
|
||||
|
||||
Enchantment mending = Enchantment.getByName("MENDING");
|
||||
if (mending != null) {
|
||||
ENCHANTMENTS.put("mending", mending);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
// 1.11
|
||||
try {
|
||||
Enchantment bindingCurse = Enchantment.getByName("BINDING_CURSE");
|
||||
if (bindingCurse != null) {
|
||||
ENCHANTMENTS.put("bindingcurse", bindingCurse);
|
||||
ALIASENCHANTMENTS.put("bindcurse", bindingCurse);
|
||||
ALIASENCHANTMENTS.put("binding", bindingCurse);
|
||||
ALIASENCHANTMENTS.put("bind", bindingCurse);
|
||||
}
|
||||
Enchantment vanishingCurse = Enchantment.getByName("VANISHING_CURSE");
|
||||
if (vanishingCurse != null) {
|
||||
ENCHANTMENTS.put("vanishingcurse", vanishingCurse);
|
||||
ALIASENCHANTMENTS.put("vanishcurse", vanishingCurse);
|
||||
ALIASENCHANTMENTS.put("vanishing", vanishingCurse);
|
||||
ALIASENCHANTMENTS.put("vanish", vanishingCurse);
|
||||
}
|
||||
Enchantment sweeping = Enchantment.getByName("SWEEPING_EDGE");
|
||||
if (sweeping != null) {
|
||||
ENCHANTMENTS.put("sweepingedge", sweeping);
|
||||
ALIASENCHANTMENTS.put("sweepedge", sweeping);
|
||||
ALIASENCHANTMENTS.put("sweeping", sweeping);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
|
||||
try { // 1.13
|
||||
Enchantment loyalty = Enchantment.getByName("LOYALTY");
|
||||
if (loyalty != null) {
|
||||
ENCHANTMENTS.put("loyalty", loyalty);
|
||||
ALIASENCHANTMENTS.put("loyal", loyalty);
|
||||
ALIASENCHANTMENTS.put("return", loyalty);
|
||||
}
|
||||
Enchantment impaling = Enchantment.getByName("IMPALING");
|
||||
if (impaling != null) {
|
||||
ENCHANTMENTS.put("impaling", impaling);
|
||||
ALIASENCHANTMENTS.put("impale", impaling);
|
||||
ALIASENCHANTMENTS.put("oceandamage", impaling);
|
||||
ALIASENCHANTMENTS.put("oceandmg", impaling);
|
||||
}
|
||||
Enchantment riptide = Enchantment.getByName("RIPTIDE");
|
||||
if (riptide != null) {
|
||||
ENCHANTMENTS.put("riptide", riptide);
|
||||
ALIASENCHANTMENTS.put("rip", riptide);
|
||||
ALIASENCHANTMENTS.put("tide", riptide);
|
||||
ALIASENCHANTMENTS.put("launch", riptide);
|
||||
}
|
||||
Enchantment channelling = Enchantment.getByName("CHANNELING");
|
||||
if (channelling != null) {
|
||||
ENCHANTMENTS.put("channelling", channelling);
|
||||
ALIASENCHANTMENTS.put("chanelling", channelling);
|
||||
ALIASENCHANTMENTS.put("channeling", channelling);
|
||||
ALIASENCHANTMENTS.put("chaneling", channelling);
|
||||
ALIASENCHANTMENTS.put("channel", channelling);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
try {
|
||||
Class<?> namespacedKeyClass = Class.forName("org.bukkit.NamespacedKey");
|
||||
Class<?> enchantmentClass = Class.forName("org.bukkit.enchantments.Enchantment");
|
||||
enchantmentClass.getDeclaredMethod("getByKey", namespacedKeyClass);
|
||||
isFlat = true;
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
isFlat = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Enchantment getByName(String name) {
|
||||
Enchantment enchantment = null;
|
||||
if (isFlat) { // 1.13+ only
|
||||
enchantment = Enchantment.getByKey(NamespacedKey.minecraft(name.toLowerCase()));
|
||||
}
|
||||
|
||||
if (enchantment == null) {
|
||||
enchantment = Enchantment.getByName(name.toUpperCase());
|
||||
}
|
||||
if (enchantment == null) {
|
||||
enchantment = ENCHANTMENTS.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
if (enchantment == null) {
|
||||
enchantment = ALIASENCHANTMENTS.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
return enchantment;
|
||||
}
|
||||
|
||||
public static Set<Entry<String, Enchantment>> entrySet() {
|
||||
return ENCHANTMENTS.entrySet();
|
||||
}
|
||||
|
||||
public static Set<String> keySet() {
|
||||
return ENCHANTMENTS.keySet();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,64 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public class EssentialsBlockListener implements Listener {
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public EssentialsBlockListener(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onBlockPlace(final BlockPlaceEvent event) {
|
||||
// Do not rely on getItemInHand();
|
||||
// http://leaky.bukkit.org/issues/663
|
||||
final ItemStack is = LocationUtil.convertBlockToItem(event.getBlockPlaced());
|
||||
|
||||
if (is == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is.getType() == MaterialUtil.SPAWNER && event.getItemInHand() != null && event.getPlayer() != null && event.getItemInHand().getType() == MaterialUtil.SPAWNER) {
|
||||
final BlockState blockState = event.getBlockPlaced().getState();
|
||||
if (blockState instanceof CreatureSpawner) {
|
||||
final CreatureSpawner spawner = (CreatureSpawner) blockState;
|
||||
final EntityType type = ess.getSpawnerProvider().getEntityType(event.getItemInHand());
|
||||
if (type != null && Mob.fromBukkitType(type) != null) {
|
||||
if (ess.getUser(event.getPlayer()).isAuthorized("essentials.spawnerconvert." + Mob.fromBukkitType(type).name().toLowerCase(Locale.ENGLISH))) {
|
||||
spawner.setSpawnedType(type);
|
||||
spawner.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.hasUnlimited(is) && user.getBase().getGameMode() == GameMode.SURVIVAL) {
|
||||
class UnlimitedItemSpawnTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
user.getBase().getInventory().addItem(is);
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new UnlimitedItemSpawnTask());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.*;
|
||||
import com.earth2me.essentials.commands.EssentialsCommand;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.commands.NoChargeException;
|
||||
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.PluginCommandYamlParser;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public class EssentialsCommandHandler implements ICommandHandler
|
||||
{
|
||||
private final transient ClassLoader classLoader;
|
||||
private final transient String commandPath;
|
||||
private final transient String permissionPrefix;
|
||||
private final transient IEssentialsModule module;
|
||||
private static final transient Logger LOGGER = Bukkit.getLogger();
|
||||
private final transient Map<String, List<PluginCommand>> altcommands = new HashMap<String, List<PluginCommand>>();
|
||||
private final transient Map<String, String> disabledList = new HashMap<String, String>();
|
||||
private final transient Map<String, IEssentialsCommand> commands = new HashMap<String, IEssentialsCommand>();
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public EssentialsCommandHandler(ClassLoader classLoader, String commandPath, String permissionPrefix, IEssentials ess)
|
||||
{
|
||||
this(classLoader, commandPath, permissionPrefix, null, ess);
|
||||
}
|
||||
|
||||
public EssentialsCommandHandler(ClassLoader classLoader, String commandPath, String permissionPrefix, IEssentialsModule module, IEssentials ess)
|
||||
{
|
||||
this.classLoader = classLoader;
|
||||
this.commandPath = commandPath;
|
||||
this.permissionPrefix = permissionPrefix;
|
||||
this.module = module;
|
||||
this.ess = ess;
|
||||
for (Plugin plugin : ess.getServer().getPluginManager().getPlugins())
|
||||
{
|
||||
if (plugin.isEnabled())
|
||||
{
|
||||
addPlugin(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleCommand(final CommandSender sender, final Command command, final String commandLabel, final String[] args)
|
||||
{
|
||||
boolean disabled = false;
|
||||
boolean overridden = false;
|
||||
ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
try
|
||||
{
|
||||
disabled = settings.getData().getCommands().isDisabled(command.getName());
|
||||
overridden = !disabled || settings.getData().getCommands().isOverridden(command.getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
settings.unlock();
|
||||
}
|
||||
// Allow plugins to override the command via onCommand
|
||||
if (!overridden && (!commandLabel.startsWith("e") || commandLabel.equalsIgnoreCase(command.getName())))
|
||||
{
|
||||
final PluginCommand pc = getAlternative(commandLabel);
|
||||
if (pc != null)
|
||||
{
|
||||
|
||||
executed(commandLabel, pc.getLabel());
|
||||
try
|
||||
{
|
||||
return pc.execute(sender, commandLabel, args);
|
||||
}
|
||||
catch (final Exception ex)
|
||||
{
|
||||
final ArrayList<StackTraceElement> elements = new ArrayList<StackTraceElement>(Arrays.asList(ex.getStackTrace()));
|
||||
elements.remove(0);
|
||||
final ArrayList<StackTraceElement> toRemove = new ArrayList<StackTraceElement>();
|
||||
for (final StackTraceElement e : elements)
|
||||
{
|
||||
if (e.getClassName().equals("com.earth2me.essentials.Essentials"))
|
||||
{
|
||||
toRemove.add(e);
|
||||
}
|
||||
}
|
||||
elements.removeAll(toRemove);
|
||||
final StackTraceElement[] trace = elements.toArray(new StackTraceElement[elements.size()]);
|
||||
ex.setStackTrace(trace);
|
||||
ex.printStackTrace();
|
||||
sender.sendMessage(ChatColor.RED + "An internal error occurred while attempting to perform this command");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IUser user = null;
|
||||
if (sender instanceof Player)
|
||||
{
|
||||
user = ess.getUser((Player)sender);
|
||||
LOGGER.log(Level.INFO, String.format("[PLAYER_COMMAND] %s: /%s %s ", ((Player)sender).getName(), commandLabel, EssentialsCommand.getFinalArg(args, 0)));
|
||||
}
|
||||
|
||||
// Check for disabled commands
|
||||
if (disabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
final String commandName = command.getName().toLowerCase(Locale.ENGLISH);
|
||||
IEssentialsCommand cmd = commands.get(commandName);
|
||||
if (cmd == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
cmd = (IEssentialsCommand)classLoader.loadClass(commandPath + commandName).newInstance();
|
||||
cmd.init(ess, commandName);
|
||||
cmd.setEssentialsModule(module);
|
||||
commands.put(commandName, cmd);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sender.sendMessage(_("commandNotLoaded", commandName));
|
||||
LOGGER.log(Level.SEVERE, _("commandNotLoaded", commandName), ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check authorization
|
||||
if (sender != null && cmd.isAuthorized(sender))
|
||||
{
|
||||
LOGGER.log(Level.WARNING, _("deniedAccessCommand", user.getName()));
|
||||
user.sendMessage(_("noAccessCommand"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Run the command
|
||||
try
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
cmd.run(sender, command, commandLabel, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.acquireReadLock();
|
||||
try
|
||||
{
|
||||
cmd.run(user, command, commandLabel, args);
|
||||
}
|
||||
finally
|
||||
{
|
||||
user.unlock();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (NoChargeException ex)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (NotEnoughArgumentsException ex)
|
||||
{
|
||||
sender.sendMessage(command.getDescription());
|
||||
sender.sendMessage(command.getUsage().replaceAll("<command>", commandLabel));
|
||||
if (!ex.getMessage().isEmpty())
|
||||
{
|
||||
sender.sendMessage(ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Throwable ex)
|
||||
{
|
||||
showCommandError(sender, commandLabel, ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Throwable ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, _("commandFailed", commandLabel), ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCommandError(final CommandSender sender, final String commandLabel, final Throwable exception)
|
||||
{
|
||||
sender.sendMessage(_("errorWithMessage", exception.getMessage()));
|
||||
if (ess.getSettings().isDebug())
|
||||
{
|
||||
LOGGER.log(Level.WARNING, _("errorCallingCommand", commandLabel), exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload()
|
||||
{
|
||||
}
|
||||
|
||||
public final void addPlugin(final Plugin plugin)
|
||||
{
|
||||
if (plugin.getDescription().getMain().contains("com.earth2me.essentials"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
final List<Command> commands = PluginCommandYamlParser.parse(plugin);
|
||||
final String pluginName = plugin.getDescription().getName().toLowerCase(Locale.ENGLISH);
|
||||
|
||||
for (Command command : commands)
|
||||
{
|
||||
final PluginCommand pc = (PluginCommand)command;
|
||||
final List<String> labels = new ArrayList<String>(pc.getAliases());
|
||||
labels.add(pc.getName());
|
||||
|
||||
PluginCommand reg = ess.getServer().getPluginCommand(pluginName + ":" + pc.getName().toLowerCase(Locale.ENGLISH));
|
||||
if (reg == null)
|
||||
{
|
||||
reg = ess.getServer().getPluginCommand(pc.getName().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
if (reg == null || !reg.getPlugin().equals(plugin))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (String label : labels)
|
||||
{
|
||||
List<PluginCommand> plugincommands = altcommands.get(label.toLowerCase(Locale.ENGLISH));
|
||||
if (plugincommands == null)
|
||||
{
|
||||
plugincommands = new ArrayList<PluginCommand>();
|
||||
altcommands.put(label.toLowerCase(Locale.ENGLISH), plugincommands);
|
||||
}
|
||||
boolean found = false;
|
||||
for (PluginCommand pc2 : plugincommands)
|
||||
{
|
||||
if (pc2.getPlugin().equals(plugin))
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
plugincommands.add(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlugin(final Plugin plugin)
|
||||
{
|
||||
final Iterator<Map.Entry<String, List<PluginCommand>>> iterator = altcommands.entrySet().iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
final Map.Entry<String, List<PluginCommand>> entry = iterator.next();
|
||||
final Iterator<PluginCommand> pcIterator = entry.getValue().iterator();
|
||||
while (pcIterator.hasNext())
|
||||
{
|
||||
final PluginCommand pc = pcIterator.next();
|
||||
if (pc.getPlugin() == null || pc.getPlugin().equals(plugin))
|
||||
{
|
||||
pcIterator.remove();
|
||||
}
|
||||
}
|
||||
if (entry.getValue().isEmpty())
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PluginCommand getAlternative(final String label)
|
||||
{
|
||||
final List<PluginCommand> commands = altcommands.get(label);
|
||||
if (commands == null || commands.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (commands.size() == 1)
|
||||
{
|
||||
return commands.get(0);
|
||||
}
|
||||
// return the first command that is not an alias
|
||||
for (PluginCommand command : commands)
|
||||
{
|
||||
if (command.getName().equalsIgnoreCase(label))
|
||||
{
|
||||
return command;
|
||||
}
|
||||
}
|
||||
// return the first alias
|
||||
return commands.get(0);
|
||||
}
|
||||
|
||||
public void executed(final String label, final String otherLabel)
|
||||
{
|
||||
if (ess.getSettings().isDebug())
|
||||
{
|
||||
LOGGER.log(Level.INFO, "Essentials: Alternative command " + label + " found, using " + otherLabel);
|
||||
}
|
||||
disabledList.put(label, otherLabel);
|
||||
}
|
||||
|
||||
public Map<String, String> disabledCommands()
|
||||
{
|
||||
return disabledList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,661 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import net.ess3.api.InvalidWorldException;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class EssentialsConf extends YamlConfiguration {
|
||||
protected static final Logger LOGGER = Logger.getLogger("Essentials");
|
||||
protected final File configFile;
|
||||
protected String templateName = null;
|
||||
protected static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
private Class<?> resourceClass = EssentialsConf.class;
|
||||
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
|
||||
private final AtomicInteger pendingDiskWrites = new AtomicInteger(0);
|
||||
private final AtomicBoolean transaction = new AtomicBoolean(false);
|
||||
|
||||
public EssentialsConf(final File configFile) {
|
||||
super();
|
||||
this.configFile = configFile.getAbsoluteFile();
|
||||
}
|
||||
|
||||
private final byte[] bytebuffer = new byte[1024];
|
||||
|
||||
public synchronized void load() {
|
||||
if (pendingDiskWrites.get() != 0) {
|
||||
LOGGER.log(Level.INFO, "File {0} not read, because it''s not yet written to disk.", configFile);
|
||||
return;
|
||||
}
|
||||
if (!configFile.getParentFile().exists()) {
|
||||
if (!configFile.getParentFile().mkdirs()) {
|
||||
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
|
||||
}
|
||||
}
|
||||
// This will delete files where the first character is 0. In most cases they are broken.
|
||||
if (configFile.exists() && configFile.length() != 0) {
|
||||
try {
|
||||
final InputStream input = new FileInputStream(configFile);
|
||||
try {
|
||||
if (input.read() == 0) {
|
||||
input.close();
|
||||
configFile.delete();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
LOGGER.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!configFile.exists()) {
|
||||
if (legacyFileExists()) {
|
||||
convertLegacyFile();
|
||||
} else if (altFileExists()) {
|
||||
convertAltFile();
|
||||
} else if (templateName != null) {
|
||||
LOGGER.log(Level.INFO, tl("creatingConfigFromTemplate", configFile.toString()));
|
||||
createFromTemplate();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
try (FileInputStream inputStream = new FileInputStream(configFile)) {
|
||||
long startSize = configFile.length();
|
||||
if (startSize > Integer.MAX_VALUE) {
|
||||
throw new InvalidConfigurationException("File too big");
|
||||
}
|
||||
ByteBuffer buffer = ByteBuffer.allocate((int) startSize);
|
||||
int length;
|
||||
while ((length = inputStream.read(bytebuffer)) != -1) {
|
||||
if (length > buffer.remaining()) {
|
||||
ByteBuffer resize = ByteBuffer.allocate(buffer.capacity() + length - buffer.remaining());
|
||||
int resizePosition = buffer.position();
|
||||
buffer.rewind();
|
||||
resize.put(buffer);
|
||||
resize.position(resizePosition);
|
||||
buffer = resize;
|
||||
}
|
||||
buffer.put(bytebuffer, 0, length);
|
||||
}
|
||||
buffer.rewind();
|
||||
final CharBuffer data = CharBuffer.allocate(buffer.capacity());
|
||||
CharsetDecoder decoder = UTF8.newDecoder();
|
||||
CoderResult result = decoder.decode(buffer, data, true);
|
||||
if (result.isError()) {
|
||||
buffer.rewind();
|
||||
data.clear();
|
||||
LOGGER.log(Level.INFO, "File " + configFile.getAbsolutePath() + " is not utf-8 encoded, trying " + Charset.defaultCharset().displayName());
|
||||
decoder = Charset.defaultCharset().newDecoder();
|
||||
result = decoder.decode(buffer, data, true);
|
||||
if (result.isError()) {
|
||||
throw new InvalidConfigurationException("Invalid Characters in file " + configFile.getAbsolutePath());
|
||||
} else {
|
||||
decoder.flush(data);
|
||||
}
|
||||
} else {
|
||||
decoder.flush(data);
|
||||
}
|
||||
final int end = data.position();
|
||||
data.rewind();
|
||||
super.loadFromString(data.subSequence(0, end).toString());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
File broken = new File(configFile.getAbsolutePath() + ".broken." + System.currentTimeMillis());
|
||||
configFile.renameTo(broken);
|
||||
LOGGER.log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean legacyFileExists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void convertLegacyFile() {
|
||||
LOGGER.log(Level.SEVERE, "Unable to import legacy config file.");
|
||||
}
|
||||
|
||||
public boolean altFileExists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void convertAltFile() {
|
||||
LOGGER.log(Level.SEVERE, "Unable to import alt config file.");
|
||||
}
|
||||
|
||||
private void createFromTemplate() {
|
||||
InputStream istr = null;
|
||||
OutputStream ostr = null;
|
||||
try {
|
||||
istr = resourceClass.getResourceAsStream(templateName);
|
||||
if (istr == null) {
|
||||
LOGGER.log(Level.SEVERE, tl("couldNotFindTemplate", templateName));
|
||||
return;
|
||||
}
|
||||
ostr = new FileOutputStream(configFile);
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = 0;
|
||||
length = istr.read(buffer);
|
||||
while (length > 0) {
|
||||
ostr.write(buffer, 0, length);
|
||||
length = istr.read(buffer);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, tl("failedToWriteConfig", configFile.toString()), ex);
|
||||
} finally {
|
||||
try {
|
||||
if (istr != null) {
|
||||
istr.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(EssentialsConf.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
try {
|
||||
if (ostr != null) {
|
||||
ostr.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, tl("failedToCloseConfig", configFile.toString()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTemplateName(final String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public void setTemplateName(final String templateName, final Class<?> resClass) {
|
||||
this.templateName = templateName;
|
||||
this.resourceClass = resClass;
|
||||
}
|
||||
|
||||
public void startTransaction() {
|
||||
transaction.set(true);
|
||||
}
|
||||
|
||||
public void stopTransaction() {
|
||||
transaction.set(false);
|
||||
save();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
save(configFile);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveWithError() throws IOException {
|
||||
save(configFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void save(final File file) throws IOException {
|
||||
if (!transaction.get()) {
|
||||
delayedSave(file);
|
||||
}
|
||||
}
|
||||
|
||||
//This may be aborted if there are stagnant requests sitting in queue.
|
||||
//This needs fixed to discard outstanding save requests.
|
||||
public synchronized void forceSave() {
|
||||
try {
|
||||
Future<?> future = delayedSave(configFile);
|
||||
if (future != null) {
|
||||
future.get();
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void cleanup() {
|
||||
forceSave();
|
||||
}
|
||||
|
||||
private Future<?> delayedSave(final File file) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException("File cannot be null");
|
||||
}
|
||||
|
||||
final String data = saveToString();
|
||||
|
||||
if (data.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
pendingDiskWrites.incrementAndGet();
|
||||
|
||||
return EXECUTOR_SERVICE.submit(new WriteRunner(configFile, data, pendingDiskWrites));
|
||||
}
|
||||
|
||||
|
||||
private static class WriteRunner implements Runnable {
|
||||
private final File configFile;
|
||||
private final String data;
|
||||
private final AtomicInteger pendingDiskWrites;
|
||||
|
||||
private WriteRunner(final File configFile, final String data, final AtomicInteger pendingDiskWrites) {
|
||||
this.configFile = configFile;
|
||||
this.data = data;
|
||||
this.pendingDiskWrites = pendingDiskWrites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//long startTime = System.nanoTime();
|
||||
synchronized (configFile) {
|
||||
if (pendingDiskWrites.get() > 1) {
|
||||
// Writes can be skipped, because they are stored in a queue (in the executor).
|
||||
// Only the last is actually written.
|
||||
pendingDiskWrites.decrementAndGet();
|
||||
//LOGGER.log(Level.INFO, configFile + " skipped writing in " + (System.nanoTime() - startTime) + " nsec.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Files.createParentDirs(configFile);
|
||||
|
||||
if (!configFile.exists()) {
|
||||
try {
|
||||
LOGGER.log(Level.INFO, tl("creatingEmptyConfig", configFile.toString()));
|
||||
if (!configFile.createNewFile()) {
|
||||
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()));
|
||||
return;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, tl("failedToCreateConfig", configFile.toString()), ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(configFile)) {
|
||||
try (OutputStreamWriter writer = new OutputStreamWriter(fos, UTF8)) {
|
||||
writer.write(data);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.SEVERE, e.getMessage(), e);
|
||||
} finally {
|
||||
//LOGGER.log(Level.INFO, configFile + " written to disk in " + (System.nanoTime() - startTime) + " nsec.");
|
||||
pendingDiskWrites.decrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasProperty(final String path) {
|
||||
return isSet(path);
|
||||
}
|
||||
|
||||
public Location getLocation(final String path, final Server server) throws InvalidWorldException {
|
||||
final String worldString = (path == null ? "" : path + ".") + "world";
|
||||
final String worldName = getString(worldString);
|
||||
if (worldName == null || worldName.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final World world = server.getWorld(worldName);
|
||||
if (world == null) {
|
||||
throw new InvalidWorldException(worldName);
|
||||
}
|
||||
return new Location(world, getDouble((path == null ? "" : path + ".") + "x", 0), getDouble((path == null ? "" : path + ".") + "y", 0), getDouble((path == null ? "" : path + ".") + "z", 0), (float) getDouble((path == null ? "" : path + ".") + "yaw", 0), (float) getDouble((path == null ? "" : path + ".") + "pitch", 0));
|
||||
}
|
||||
|
||||
public void setProperty(final String path, final Location loc) {
|
||||
set((path == null ? "" : path + ".") + "world", loc.getWorld().getName());
|
||||
set((path == null ? "" : path + ".") + "x", loc.getX());
|
||||
set((path == null ? "" : path + ".") + "y", loc.getY());
|
||||
set((path == null ? "" : path + ".") + "z", loc.getZ());
|
||||
set((path == null ? "" : path + ".") + "yaw", loc.getYaw());
|
||||
set((path == null ? "" : path + ".") + "pitch", loc.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(final String path) {
|
||||
final ItemStack stack = new ItemStack(Material.valueOf(getString(path + ".type", "AIR")), getInt(path + ".amount", 1), (short) getInt(path + ".damage", 0));
|
||||
final ConfigurationSection enchants = getConfigurationSection(path + ".enchant");
|
||||
if (enchants != null) {
|
||||
for (String enchant : enchants.getKeys(false)) {
|
||||
final Enchantment enchantment = Enchantment.getByName(enchant.toUpperCase(Locale.ENGLISH));
|
||||
if (enchantment == null) {
|
||||
continue;
|
||||
}
|
||||
final int level = getInt(path + ".enchant." + enchant, enchantment.getStartLevel());
|
||||
stack.addUnsafeEnchantment(enchantment, level);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
/*
|
||||
* ,
|
||||
* (byte)getInt(path + ".data", 0)
|
||||
*/
|
||||
}
|
||||
|
||||
public void setProperty(final String path, final ItemStack stack) {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("type", stack.getType().toString());
|
||||
map.put("amount", stack.getAmount());
|
||||
map.put("damage", stack.getDurability());
|
||||
Map<Enchantment, Integer> enchantments = stack.getEnchantments();
|
||||
if (!enchantments.isEmpty()) {
|
||||
Map<String, Integer> enchant = new HashMap<>();
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
enchant.put(entry.getKey().getName().toLowerCase(Locale.ENGLISH), entry.getValue());
|
||||
}
|
||||
map.put("enchant", enchant);
|
||||
}
|
||||
// getData().getData() is broken
|
||||
//map.put("data", stack.getDurability());
|
||||
set(path, map);
|
||||
}
|
||||
|
||||
public void setProperty(String path, List object) {
|
||||
set(path, new ArrayList(object));
|
||||
}
|
||||
|
||||
public void setProperty(String path, Map object) {
|
||||
set(path, new LinkedHashMap(object));
|
||||
}
|
||||
|
||||
public Object getProperty(String path) {
|
||||
return get(path);
|
||||
}
|
||||
|
||||
public void setProperty(final String path, final BigDecimal bigDecimal) {
|
||||
set(path, bigDecimal.toString());
|
||||
}
|
||||
|
||||
public void setProperty(String path, Object object) {
|
||||
set(path, object);
|
||||
}
|
||||
|
||||
public void removeProperty(String path) {
|
||||
set(path, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object get(String path) {
|
||||
return super.get(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object get(String path, Object def) {
|
||||
return super.get(path, def);
|
||||
}
|
||||
|
||||
public synchronized BigDecimal getBigDecimal(final String path, final BigDecimal def) {
|
||||
final String input = super.getString(path);
|
||||
return toBigDecimal(input, def);
|
||||
}
|
||||
|
||||
public static BigDecimal toBigDecimal(final String input, final BigDecimal def) {
|
||||
if (input == null || input.isEmpty()) {
|
||||
return def;
|
||||
} else {
|
||||
try {
|
||||
return new BigDecimal(input, MathContext.DECIMAL128);
|
||||
} catch (NumberFormatException e) {
|
||||
return def;
|
||||
} catch (ArithmeticException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean getBoolean(String path) {
|
||||
return super.getBoolean(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean getBoolean(String path, boolean def) {
|
||||
return super.getBoolean(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Boolean> getBooleanList(String path) {
|
||||
return super.getBooleanList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Byte> getByteList(String path) {
|
||||
return super.getByteList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Character> getCharacterList(String path) {
|
||||
return super.getCharacterList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ConfigurationSection getConfigurationSection(String path) {
|
||||
return super.getConfigurationSection(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getDouble(String path) {
|
||||
return super.getDouble(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getDouble(final String path, final double def) {
|
||||
return super.getDouble(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Double> getDoubleList(String path) {
|
||||
return super.getDoubleList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Float> getFloatList(String path) {
|
||||
return super.getFloatList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getInt(String path) {
|
||||
return super.getInt(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getInt(String path, int def) {
|
||||
return super.getInt(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Integer> getIntegerList(String path) {
|
||||
return super.getIntegerList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized ItemStack getItemStack(String path, ItemStack def) {
|
||||
return super.getItemStack(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Set<String> getKeys(boolean deep) {
|
||||
return super.getKeys(deep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<?> getList(String path) {
|
||||
return super.getList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<?> getList(String path, List<?> def) {
|
||||
return super.getList(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized long getLong(String path) {
|
||||
return super.getLong(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized long getLong(final String path, final long def) {
|
||||
return super.getLong(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Long> getLongList(String path) {
|
||||
return super.getLongList(path);
|
||||
}
|
||||
|
||||
public synchronized Map<String, Object> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Map<?, ?>> getMapList(String path) {
|
||||
return super.getMapList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized OfflinePlayer getOfflinePlayer(String path) {
|
||||
return super.getOfflinePlayer(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized OfflinePlayer getOfflinePlayer(String path, OfflinePlayer def) {
|
||||
return super.getOfflinePlayer(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<Short> getShortList(String path) {
|
||||
return super.getShortList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String getString(String path) {
|
||||
return super.getString(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String getString(String path, String def) {
|
||||
return super.getString(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<String> getStringList(String path) {
|
||||
return super.getStringList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Map<String, Object> getValues(boolean deep) {
|
||||
return super.getValues(deep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Vector getVector(String path) {
|
||||
return super.getVector(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Vector getVector(String path, Vector def) {
|
||||
return super.getVector(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isBoolean(String path) {
|
||||
return super.isBoolean(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isConfigurationSection(String path) {
|
||||
return super.isConfigurationSection(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isDouble(String path) {
|
||||
return super.isDouble(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isInt(String path) {
|
||||
return super.isInt(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isItemStack(String path) {
|
||||
return super.isItemStack(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isList(String path) {
|
||||
return super.isList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isLong(String path) {
|
||||
return super.isLong(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isOfflinePlayer(String path) {
|
||||
return super.isOfflinePlayer(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isSet(String path) {
|
||||
return super.isSet(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isString(String path) {
|
||||
return super.isString(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isVector(String path) {
|
||||
return super.isVector(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void set(String path, Object value) {
|
||||
super.set(path, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class EssentialsEntityListener implements Listener {
|
||||
private static final Logger LOGGER = Logger.getLogger("Essentials");
|
||||
private static final transient Pattern powertoolPlayer = Pattern.compile("\\{player\\}");
|
||||
private final IEssentials ess;
|
||||
|
||||
public EssentialsEntityListener(IEssentials ess) {
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
// This method does something undocumented reguarding certain bucket types #EasterEgg
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onEntityDamage(final EntityDamageByEntityEvent event) {
|
||||
final Entity eAttack = event.getDamager();
|
||||
final Entity eDefend = event.getEntity();
|
||||
if (eAttack instanceof Player) {
|
||||
final User attacker = ess.getUser((Player) eAttack);
|
||||
if (eDefend instanceof Player) {
|
||||
onPlayerVsPlayerDamage(event, (Player) eDefend, attacker);
|
||||
} else if (eDefend instanceof Ageable) {
|
||||
final ItemStack hand = attacker.getBase().getItemInHand();
|
||||
if (ess.getSettings().isMilkBucketEasterEggEnabled()
|
||||
&& hand != null && hand.getType() == Material.MILK_BUCKET) {
|
||||
((Ageable) eDefend).setBaby();
|
||||
hand.setType(Material.BUCKET);
|
||||
attacker.getBase().setItemInHand(hand);
|
||||
attacker.getBase().updateInventory();
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
attacker.updateActivityOnInteract(true);
|
||||
} else if (eAttack instanceof Projectile && eDefend instanceof Player) {
|
||||
final Projectile projectile = (Projectile) event.getDamager();
|
||||
//This should return a ProjectileSource on 1.7.3 beta +
|
||||
final Object shooter = projectile.getShooter();
|
||||
if (shooter instanceof Player) {
|
||||
final User attacker = ess.getUser((Player) shooter);
|
||||
onPlayerVsPlayerDamage(event, (Player) eDefend, attacker);
|
||||
attacker.updateActivityOnInteract(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onPlayerVsPlayerDamage(final EntityDamageByEntityEvent event, final Player defender, final User attacker) {
|
||||
if (ess.getSettings().getLoginAttackDelay() > 0 && (System.currentTimeMillis() < (attacker.getLastLogin() + ess.getSettings().getLoginAttackDelay())) && !attacker.isAuthorized("essentials.pvpdelay.exempt")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (!defender.equals(attacker.getBase()) && (attacker.hasInvulnerabilityAfterTeleport() || ess.getUser(defender).hasInvulnerabilityAfterTeleport())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (attacker.isGodModeEnabled() && !attacker.isAuthorized("essentials.god.pvp")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (attacker.isHidden() && !attacker.isAuthorized("essentials.vanish.pvp")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (attacker.arePowerToolsEnabled()) {
|
||||
onPlayerVsPlayerPowertool(event, defender, attacker);
|
||||
}
|
||||
}
|
||||
|
||||
private void onPlayerVsPlayerPowertool(final EntityDamageByEntityEvent event, final Player defender, final User attacker) {
|
||||
final List<String> commandList = attacker.getPowertool(attacker.getBase().getItemInHand());
|
||||
if (commandList != null && !commandList.isEmpty()) {
|
||||
for (final String tempCommand : commandList) {
|
||||
final String command = powertoolPlayer.matcher(tempCommand).replaceAll(defender.getName());
|
||||
if (command != null && !command.isEmpty() && !command.equals(tempCommand)) {
|
||||
|
||||
class PowerToolInteractTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
attacker.getServer().dispatchCommand(attacker.getBase(), command);
|
||||
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", attacker.getName(), command));
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new PowerToolInteractTask());
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityDamage(final EntityDamageEvent event) {
|
||||
if (event.getEntity() instanceof Player && ess.getUser((Player) event.getEntity()).isGodModeEnabled()) {
|
||||
final Player player = (Player) event.getEntity();
|
||||
player.setFireTicks(0);
|
||||
player.setRemainingAir(player.getMaximumAir());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityCombust(final EntityCombustEvent event) {
|
||||
if (event.getEntity() instanceof Player && ess.getUser((Player) event.getEntity()).isGodModeEnabled()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onEntityCombustByEntity(final EntityCombustByEntityEvent event) {
|
||||
if (event.getCombuster() instanceof Arrow && event.getEntity() instanceof Player) {
|
||||
Arrow combuster = (Arrow) event.getCombuster();
|
||||
if (combuster.getShooter() instanceof Player) {
|
||||
final User srcCombuster = ess.getUser(((Player) combuster.getShooter()).getUniqueId());
|
||||
if (srcCombuster.isGodModeEnabled() && !srcCombuster.isAuthorized("essentials.god.pvp")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (srcCombuster.isHidden() && !srcCombuster.isAuthorized("essentials.vanish.pvp")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerDeathEvent(final PlayerDeathEvent event) {
|
||||
final User user = ess.getUser(event.getEntity());
|
||||
if (user.isAuthorized("essentials.back.ondeath") && !ess.getSettings().isCommandDisabled("back")) {
|
||||
user.setLastLocation();
|
||||
user.sendMessage(tl("backAfterDeath"));
|
||||
}
|
||||
if (!ess.getSettings().areDeathMessagesEnabled()) {
|
||||
event.setDeathMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerDeathExpEvent(final PlayerDeathEvent event) {
|
||||
final User user = ess.getUser(event.getEntity());
|
||||
if (user.isAuthorized("essentials.keepxp")) {
|
||||
event.setKeepLevel(true);
|
||||
event.setDroppedExp(0);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onFoodLevelChange(final FoodLevelChangeEvent event) {
|
||||
if (event.getEntity() instanceof Player) {
|
||||
final User user = ess.getUser((Player) event.getEntity());
|
||||
if (user.isGodModeEnabled()) {
|
||||
if (user.isGodModeEnabledRaw()) {
|
||||
user.getBase().setFoodLevel(20);
|
||||
user.getBase().setSaturation(10);
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityRegainHealth(final EntityRegainHealthEvent event) {
|
||||
if (event.getRegainReason() == RegainReason.SATIATED && event.getEntity() instanceof Player && ess.getUser((Player) event.getEntity()).isAfk() && ess.getSettings().getFreezeAfkPlayers()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPotionSplashEvent(final PotionSplashEvent event) {
|
||||
for (LivingEntity entity : event.getAffectedEntities()) {
|
||||
if (entity instanceof Player && ess.getUser((Player) entity).isGodModeEnabled()) {
|
||||
event.setIntensity(entity, 0d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityShootBow(EntityShootBowEvent event) {
|
||||
if (event.getEntity() instanceof Player) {
|
||||
final User user = ess.getUser((Player) event.getEntity());
|
||||
if (user.isAfk()) {
|
||||
user.updateActivityOnInteract(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityTarget(EntityTargetEvent event) {
|
||||
if (event.getTarget() instanceof Player) {
|
||||
final User user = ess.getUser((Player) event.getTarget());
|
||||
if (user.isVanished()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,831 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.TextInput;
|
||||
import com.earth2me.essentials.textreader.TextPager;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.IEssentials;
|
||||
|
||||
import org.bukkit.BanEntry;
|
||||
import org.bukkit.BanList;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class EssentialsPlayerListener implements Listener {
|
||||
private static final Logger LOGGER = Logger.getLogger("Essentials");
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public EssentialsPlayerListener(final IEssentials parent) {
|
||||
this.ess = parent;
|
||||
}
|
||||
|
||||
public void registerEvents() {
|
||||
ess.getServer().getPluginManager().registerEvents(this, ess);
|
||||
if (isEntityPickupEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new PlayerListener1_12(), ess);
|
||||
} else {
|
||||
ess.getServer().getPluginManager().registerEvents(new PlayerListenerPre1_12(), ess);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerRespawn(final PlayerRespawnEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
updateCompass(user);
|
||||
user.setDisplayNick();
|
||||
|
||||
if (ess.getSettings().isTeleportInvulnerability()) {
|
||||
user.enableInvulnerabilityAfterTeleport();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerChat(final AsyncPlayerChatEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isMuted()) {
|
||||
event.setCancelled(true);
|
||||
user.sendMessage(tl("voiceSilenced"));
|
||||
LOGGER.info(tl("mutedUserSpeaks", user.getName(), event.getMessage()));
|
||||
}
|
||||
try {
|
||||
final Iterator<Player> it = event.getRecipients().iterator();
|
||||
while (it.hasNext()) {
|
||||
final User u = ess.getUser(it.next());
|
||||
if (u.isIgnoredPlayer(user)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Ignore could not block chat due to custom chat plugin event.", ex);
|
||||
} else {
|
||||
ess.getLogger().info("Ignore could not block chat due to custom chat plugin event.");
|
||||
}
|
||||
}
|
||||
|
||||
user.updateActivityOnInteract(true);
|
||||
user.setDisplayNick();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerMove(final PlayerMoveEvent event) {
|
||||
if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockZ() == event.getTo().getBlockZ() && event.getFrom().getBlockY() == event.getTo().getBlockY()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ess.getSettings().cancelAfkOnMove() && !ess.getSettings().getFreezeAfkPlayers()) {
|
||||
event.getHandlers().unregister(this);
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, "Unregistering move listener");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isAfk() && ess.getSettings().getFreezeAfkPlayers()) {
|
||||
final Location from = event.getFrom();
|
||||
final Location origTo = event.getTo();
|
||||
final Location to = origTo.clone();
|
||||
if (origTo.getY() >= from.getBlockY() + 1) {
|
||||
user.updateActivityOnMove(true);
|
||||
return;
|
||||
}
|
||||
to.setX(from.getX());
|
||||
to.setY(from.getY());
|
||||
to.setZ(from.getZ());
|
||||
try {
|
||||
event.setTo(LocationUtil.getSafeDestination(to));
|
||||
} catch (Exception ex) {
|
||||
event.setTo(to);
|
||||
}
|
||||
return;
|
||||
}
|
||||
final Location afk = user.getAfkPosition();
|
||||
if (afk == null || !event.getTo().getWorld().equals(afk.getWorld()) || afk.distanceSquared(event.getTo()) > 9) {
|
||||
user.updateActivityOnMove(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerQuit(final PlayerQuitEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
|
||||
if (ess.getSettings().allowSilentJoinQuit() && user.isAuthorized("essentials.silentquit")) {
|
||||
event.setQuitMessage(null);
|
||||
} else if (ess.getSettings().isCustomQuitMessage() && event.getQuitMessage() != null) {
|
||||
final Player player = event.getPlayer();
|
||||
final String msg = ess.getSettings().getCustomQuitMessage()
|
||||
.replace("{PLAYER}", player.getDisplayName())
|
||||
.replace("{USERNAME}", player.getName())
|
||||
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
|
||||
|
||||
event.setQuitMessage(msg.isEmpty() ? null : msg);
|
||||
}
|
||||
|
||||
user.startTransaction();
|
||||
if (ess.getSettings().removeGodOnDisconnect() && user.isGodModeEnabled()) {
|
||||
user.setGodModeEnabled(false);
|
||||
}
|
||||
if (user.isVanished()) {
|
||||
user.setVanished(false);
|
||||
}
|
||||
user.setLogoutLocation();
|
||||
if (user.isRecipeSee()) {
|
||||
user.getBase().getOpenInventory().getTopInventory().clear();
|
||||
}
|
||||
|
||||
for (HumanEntity viewer : user.getBase().getInventory().getViewers()) {
|
||||
if (viewer instanceof Player) {
|
||||
User uviewer = ess.getUser((Player) viewer);
|
||||
if (uviewer.isInvSee()) {
|
||||
uviewer.getBase().closeInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user.updateActivityOnInteract(false);
|
||||
if (!user.isHidden()) {
|
||||
user.setLastLogout(System.currentTimeMillis());
|
||||
}
|
||||
user.stopTransaction();
|
||||
|
||||
user.dispose();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||
final String joinMessage = event.getJoinMessage();
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delayedJoin(event.getPlayer(), joinMessage);
|
||||
}
|
||||
});
|
||||
if (ess.getSettings().allowSilentJoinQuit() || ess.getSettings().isCustomJoinMessage()) {
|
||||
event.setJoinMessage(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void delayedJoin(final Player player, final String message) {
|
||||
if (!player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ess.getBackup().onPlayerJoin();
|
||||
final User dUser = ess.getUser(player);
|
||||
|
||||
dUser.startTransaction();
|
||||
if (dUser.isNPC()) {
|
||||
dUser.setNPC(false);
|
||||
}
|
||||
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
dUser.checkMuteTimeout(currentTime);
|
||||
dUser.updateActivityOnInteract(false);
|
||||
dUser.stopTransaction();
|
||||
|
||||
class DelayJoinTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
final User user = ess.getUser(player);
|
||||
|
||||
if (!user.getBase().isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.startTransaction();
|
||||
|
||||
user.setLastAccountName(user.getBase().getName());
|
||||
user.setLastLogin(currentTime);
|
||||
user.setDisplayNick();
|
||||
updateCompass(user);
|
||||
|
||||
if (!ess.getVanishedPlayersNew().isEmpty() && !user.isAuthorized("essentials.vanish.see")) {
|
||||
for (String p : ess.getVanishedPlayersNew()) {
|
||||
Player toVanish = ess.getServer().getPlayerExact(p);
|
||||
if (toVanish != null && toVanish.isOnline()) {
|
||||
user.getBase().hidePlayer(toVanish);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Hiding vanished player: " + p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.sleepingignored")) {
|
||||
user.getBase().setSleepingIgnored(true);
|
||||
}
|
||||
|
||||
if (ess.getSettings().allowSilentJoinQuit() && (user.isAuthorized("essentials.silentjoin") || user.isAuthorized("essentials.silentjoin.vanish"))) {
|
||||
if (user.isAuthorized("essentials.silentjoin.vanish")) {
|
||||
user.setVanished(true);
|
||||
}
|
||||
} else if (message == null) {
|
||||
//NOOP
|
||||
} else if (ess.getSettings().isCustomJoinMessage()) {
|
||||
String msg = ess.getSettings().getCustomJoinMessage()
|
||||
.replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName())
|
||||
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUserMap().getUniqueUsers()))
|
||||
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()));
|
||||
if (!msg.isEmpty()) {
|
||||
ess.getServer().broadcastMessage(msg);
|
||||
}
|
||||
} else if (ess.getSettings().allowSilentJoinQuit()) {
|
||||
ess.getServer().broadcastMessage(message);
|
||||
}
|
||||
|
||||
int motdDelay = ess.getSettings().getMotdDelay() / 50;
|
||||
DelayMotdTask motdTask = new DelayMotdTask(user);
|
||||
if (motdDelay > 0) {
|
||||
ess.scheduleSyncDelayedTask(motdTask, motdDelay);
|
||||
} else {
|
||||
motdTask.run();
|
||||
}
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("mail") && user.isAuthorized("essentials.mail")) {
|
||||
final List<String> mail = user.getMails();
|
||||
if (mail.isEmpty()) {
|
||||
if (ess.getSettings().isNotifyNoNewMail()) {
|
||||
user.sendMessage(tl("noNewMail")); // Only notify if they want us to.
|
||||
}
|
||||
} else {
|
||||
user.notifyOfMail();
|
||||
}
|
||||
}
|
||||
|
||||
if (user.isAuthorized("essentials.fly.safelogin")) {
|
||||
user.getBase().setFallDistance(0);
|
||||
if (LocationUtil.shouldFly(user.getLocation())) {
|
||||
user.getBase().setAllowFlight(true);
|
||||
user.getBase().setFlying(true);
|
||||
if (ess.getSettings().isSendFlyEnableOnJoin()) {
|
||||
user.getBase().sendMessage(tl("flyMode", tl("enabled"), user.getDisplayName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.isAuthorized("essentials.speed")) {
|
||||
user.getBase().setFlySpeed(0.1f);
|
||||
user.getBase().setWalkSpeed(0.2f);
|
||||
}
|
||||
|
||||
if (user.isSocialSpyEnabled() && !user.isAuthorized("essentials.socialspy")) {
|
||||
user.setSocialSpyEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set socialspy to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
if (user.isGodModeEnabled() && !user.isAuthorized("essentials.god")) {
|
||||
user.setGodModeEnabled(false);
|
||||
ess.getLogger().log(Level.INFO, "Set god mode to false for {0} because they had it enabled without permission.", user.getName());
|
||||
}
|
||||
|
||||
user.setConfirmingClearCommand(null);
|
||||
user.getConfirmingPayments().clear();
|
||||
|
||||
user.stopTransaction();
|
||||
}
|
||||
|
||||
class DelayMotdTask implements Runnable {
|
||||
private User user;
|
||||
|
||||
public DelayMotdTask(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
IText tempInput = null;
|
||||
|
||||
if (!ess.getSettings().isCommandDisabled("motd")) {
|
||||
try {
|
||||
tempInput = new TextInput(user.getSource(), "motd", true, ess);
|
||||
} catch (IOException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final IText input = tempInput;
|
||||
|
||||
if (input != null && !input.getLines().isEmpty() && user.isAuthorized("essentials.motd")) {
|
||||
final IText output = new KeywordReplacer(input, user.getSource(), ess);
|
||||
final TextPager pager = new TextPager(output, true);
|
||||
pager.showPage("1", null, "motd", user.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ess.scheduleSyncDelayedTask(new DelayJoinTask());
|
||||
}
|
||||
|
||||
// Makes the compass item ingame always point to the first essentials home. #EasterEgg
|
||||
// EssentialsX: This can now optionally require a permission to enable, if set in the config.
|
||||
private void updateCompass(final User user) {
|
||||
if (ess.getSettings().isCompassTowardsHomePerm() && !user.isAuthorized("essentials.home.compass")) return;
|
||||
|
||||
Location loc = user.getHome(user.getLocation());
|
||||
if (loc == null) {
|
||||
loc = user.getBase().getBedSpawnLocation();
|
||||
}
|
||||
if (loc != null) {
|
||||
user.getBase().setCompassTarget(loc);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLoginBanned(final PlayerLoginEvent event) {
|
||||
switch (event.getResult()) {
|
||||
case KICK_BANNED:
|
||||
BanEntry banEntry = ess.getServer().getBanList(BanList.Type.NAME).getBanEntry(event.getPlayer().getName());
|
||||
if (banEntry != null) {
|
||||
Date banExpiry = banEntry.getExpiration();
|
||||
if (banExpiry != null) {
|
||||
String expiry = DateUtil.formatDateDiff(banExpiry.getTime());
|
||||
event.setKickMessage(tl("tempbanJoin", expiry, banEntry.getReason()));
|
||||
} else {
|
||||
event.setKickMessage(tl("banJoin", banEntry.getReason()));
|
||||
}
|
||||
} else {
|
||||
banEntry = ess.getServer().getBanList(BanList.Type.IP).getBanEntry(event.getAddress().getHostAddress());
|
||||
if (banEntry != null) {
|
||||
event.setKickMessage(tl("banIpJoin", banEntry.getReason()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerLogin(final PlayerLoginEvent event) {
|
||||
switch (event.getResult()) {
|
||||
case KICK_FULL:
|
||||
final User kfuser = ess.getUser(event.getPlayer());
|
||||
if (kfuser.isAuthorized("essentials.joinfullserver")) {
|
||||
event.allow();
|
||||
return;
|
||||
}
|
||||
event.disallow(Result.KICK_FULL, tl("serverFull"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerTeleport(final PlayerTeleportEvent event) {
|
||||
final boolean backListener = ess.getSettings().registerBackInListener();
|
||||
final boolean teleportInvulnerability = ess.getSettings().isTeleportInvulnerability();
|
||||
if (backListener || teleportInvulnerability) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
//There is TeleportCause.COMMMAND but plugins have to actively pass the cause in on their teleports.
|
||||
if (backListener && (event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) {
|
||||
user.setLastLocation();
|
||||
}
|
||||
if (teleportInvulnerability && (event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) {
|
||||
user.enableInvulnerabilityAfterTeleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerEggThrow(final PlayerEggThrowEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
final ItemStack stack = new ItemStack(Material.EGG, 1);
|
||||
if (user.hasUnlimited(stack)) {
|
||||
user.getBase().getInventory().addItem(stack);
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onPlayerBucketEmpty(final PlayerBucketEmptyEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.hasUnlimited(new ItemStack(event.getBucket()))) {
|
||||
event.getItemStack().setType(event.getBucket());
|
||||
ess.scheduleSyncDelayedTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final String cmd = event.getMessage().toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH);
|
||||
|
||||
PluginCommand pluginCommand = ess.getServer().getPluginCommand(cmd);
|
||||
|
||||
if (ess.getSettings().getSocialSpyCommands().contains(cmd) || ess.getSettings().getSocialSpyCommands().contains("*")) {
|
||||
if (pluginCommand == null
|
||||
|| (!pluginCommand.getName().equals("msg") && !pluginCommand.getName().equals("r"))) { // /msg and /r are handled in SimpleMessageRecipient
|
||||
User user = ess.getUser(player);
|
||||
if (!user.isAuthorized("essentials.chat.spy.exempt")) {
|
||||
for (User spyer : ess.getOnlineUsers()) {
|
||||
if (spyer.isSocialSpyEnabled() && !player.equals(spyer.getBase())) {
|
||||
if (user.isMuted() && ess.getSettings().getSocialSpyListenMutedPlayers()) {
|
||||
spyer.sendMessage(tl("socialSpyMutedPrefix") + player.getDisplayName() + ": " + event.getMessage());
|
||||
} else {
|
||||
spyer.sendMessage(tl("socialSpyPrefix") + player.getDisplayName() + ": " + event.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ess.getUser(player).isMuted() && (ess.getSettings().getMuteCommands().contains(cmd) || ess.getSettings().getMuteCommands().contains("*"))) {
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(tl("voiceSilenced"));
|
||||
LOGGER.info(tl("mutedUserSpeaks", player.getName(), event.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean broadcast = true; // whether to broadcast the updated activity
|
||||
boolean update = true; // Only modified when the command is afk
|
||||
|
||||
if (pluginCommand != null) {
|
||||
// Switch case for commands that shouldn't broadcast afk activity.
|
||||
switch (pluginCommand.getName()) {
|
||||
case "afk":
|
||||
update = false;
|
||||
case "vanish":
|
||||
broadcast = false;
|
||||
}
|
||||
}
|
||||
final User user = ess.getUser(player);
|
||||
if (update) {
|
||||
user.updateActivityOnInteract(broadcast);
|
||||
}
|
||||
|
||||
if (ess.getSettings().isCommandCooldownsEnabled() && pluginCommand != null
|
||||
&& !user.isAuthorized("essentials.commandcooldowns.bypass")) {
|
||||
int argStartIndex = event.getMessage().indexOf(" ");
|
||||
String args = argStartIndex == -1 ? "" // No arguments present
|
||||
: " " + event.getMessage().substring(argStartIndex); // arguments start at argStartIndex; substring from there.
|
||||
String fullCommand = pluginCommand.getName() + args;
|
||||
|
||||
// Used to determine whether a user already has an existing cooldown
|
||||
// If so, no need to check for (and write) new ones.
|
||||
boolean cooldownFound = false;
|
||||
|
||||
// Iterate over a copy of getCommandCooldowns in case of concurrent modifications
|
||||
for (Entry<Pattern, Long> entry : new HashMap<>(user.getCommandCooldowns()).entrySet()) {
|
||||
// Remove any expired cooldowns
|
||||
if (entry.getValue() <= System.currentTimeMillis()) {
|
||||
user.clearCommandCooldown(entry.getKey());
|
||||
// Don't break in case there are other command cooldowns left to clear.
|
||||
} else if (entry.getKey().matcher(fullCommand).matches()) {
|
||||
// User's current cooldown hasn't expired, inform and terminate cooldown code.
|
||||
if (entry.getValue() > System.currentTimeMillis()) {
|
||||
String commandCooldownTime = DateUtil.formatDateDiff(entry.getValue());
|
||||
user.sendMessage(tl("commandCooldown", commandCooldownTime));
|
||||
cooldownFound = true;
|
||||
event.setCancelled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cooldownFound) {
|
||||
Entry<Pattern, Long> cooldownEntry = ess.getSettings().getCommandCooldownEntry(fullCommand);
|
||||
|
||||
if (cooldownEntry != null) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Applying " + cooldownEntry.getValue() + "ms cooldown on /" + fullCommand + " for" + user.getName() + ".");
|
||||
}
|
||||
Date expiry = new Date(System.currentTimeMillis() + cooldownEntry.getValue());
|
||||
user.addCommandCooldown(cooldownEntry.getKey(), expiry, ess.getSettings().isCommandCooldownPersistent(fullCommand));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerChangedWorldFlyReset(final PlayerChangedWorldEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.getBase().getGameMode() != GameMode.CREATIVE
|
||||
// COMPAT: String compare for 1.7.10
|
||||
&& !user.getBase().getGameMode().name().equals("SPECTATOR")
|
||||
&& !user.isAuthorized("essentials.fly")) {
|
||||
user.getBase().setFallDistance(0f);
|
||||
user.getBase().setAllowFlight(false);
|
||||
}
|
||||
if (!user.isAuthorized("essentials.speed")) {
|
||||
user.getBase().setFlySpeed(0.1f);
|
||||
user.getBase().setWalkSpeed(0.2f);
|
||||
} else {
|
||||
if (user.getBase().getFlySpeed() > ess.getSettings().getMaxFlySpeed() && !user.isAuthorized("essentials.speed.bypass")) {
|
||||
user.getBase().setFlySpeed((float) ess.getSettings().getMaxFlySpeed());
|
||||
} else {
|
||||
user.getBase().setFlySpeed(user.getBase().getFlySpeed() * 0.99999f);
|
||||
}
|
||||
|
||||
if (user.getBase().getWalkSpeed() > ess.getSettings().getMaxWalkSpeed() && !user.isAuthorized("essentials.speed.bypass")) {
|
||||
user.getBase().setWalkSpeed((float) ess.getSettings().getMaxWalkSpeed());
|
||||
} else {
|
||||
user.getBase().setWalkSpeed(user.getBase().getWalkSpeed() * 0.99999f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
final String newWorld = event.getPlayer().getLocation().getWorld().getName();
|
||||
user.setDisplayNick();
|
||||
updateCompass(user);
|
||||
if (ess.getSettings().getNoGodWorlds().contains(newWorld) && user.isGodModeEnabledRaw()) {
|
||||
// Player god mode is never disabled in order to retain it when changing worlds once more.
|
||||
// With that said, players will still take damage as per the result of User#isGodModeEnabled()
|
||||
user.sendMessage(tl("noGodWorldWarning"));
|
||||
}
|
||||
|
||||
if (!user.getWorld().getName().equals(newWorld)) {
|
||||
user.sendMessage(tl("currentWorld", newWorld));
|
||||
}
|
||||
if (user.isVanished()) {
|
||||
user.setVanished(user.isAuthorized("essentials.vanish"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerInteract(final PlayerInteractEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
if (!event.isCancelled() && MaterialUtil.isBed(event.getClickedBlock().getType()) && ess.getSettings().getUpdateBedAtDaytime()) {
|
||||
User player = ess.getUser(event.getPlayer());
|
||||
if (player.isAuthorized("essentials.sethome.bed") && player.getWorld().getEnvironment().equals(World.Environment.NORMAL)) {
|
||||
player.getBase().setBedSpawnLocation(event.getClickedBlock().getLocation());
|
||||
player.sendMessage(tl("bedSet", player.getLocation().getWorld().getName(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LEFT_CLICK_AIR:
|
||||
if (event.getPlayer().isFlying()) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isFlyClickJump()) {
|
||||
useFlyClickJump(user);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case LEFT_CLICK_BLOCK:
|
||||
if (event.getItem() != null && event.getItem().getType() != Material.AIR) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.hasPowerTools() && user.arePowerToolsEnabled() && usePowertools(user, event.getItem().getType())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ess.getUser(event.getPlayer()).updateActivityOnInteract(true);
|
||||
}
|
||||
|
||||
// This method allows the /jump lock feature to work, allows teleporting while flying #EasterEgg
|
||||
private void useFlyClickJump(final User user) {
|
||||
try {
|
||||
final Location otarget = LocationUtil.getTarget(user.getBase());
|
||||
|
||||
class DelayedClickJumpTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
Location loc = user.getLocation();
|
||||
loc.setX(otarget.getX());
|
||||
loc.setZ(otarget.getZ());
|
||||
while (LocationUtil.isBlockDamaging(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ())) {
|
||||
loc.setY(loc.getY() + 1d);
|
||||
}
|
||||
PaperLib.teleportAsync(user.getBase(), loc, TeleportCause.PLUGIN);
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
|
||||
} catch (Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean usePowertools(final User user, final Material material) {
|
||||
final List<String> commandList = user.getPowertool(material);
|
||||
if (commandList == null || commandList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
boolean used = false;
|
||||
// We need to loop through each command and execute
|
||||
for (final String command : commandList) {
|
||||
if (command.contains("{player}")) {
|
||||
continue;
|
||||
} else if (command.startsWith("c:")) {
|
||||
used = true;
|
||||
user.getBase().chat(command.substring(2));
|
||||
} else {
|
||||
used = true;
|
||||
|
||||
class PowerToolUseTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
user.getServer().dispatchCommand(user.getBase(), command);
|
||||
LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", user.getName(), command));
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new PowerToolUseTask());
|
||||
|
||||
}
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onInventoryClickEvent(final InventoryClickEvent event) {
|
||||
Player refreshPlayer = null;
|
||||
final Inventory top = event.getView().getTopInventory();
|
||||
final InventoryType type = top.getType();
|
||||
|
||||
final Inventory clickedInventory;
|
||||
if (event.getRawSlot() < 0) {
|
||||
clickedInventory = null;
|
||||
} else {
|
||||
clickedInventory = event.getRawSlot() < top.getSize() ? top : event.getView().getBottomInventory();
|
||||
}
|
||||
|
||||
if (type == InventoryType.PLAYER) {
|
||||
final User user = ess.getUser((Player) event.getWhoClicked());
|
||||
final InventoryHolder invHolder = top.getHolder();
|
||||
if (invHolder != null && invHolder instanceof HumanEntity) {
|
||||
final User invOwner = ess.getUser((Player) invHolder);
|
||||
if (user.isInvSee() && (!user.isAuthorized("essentials.invsee.modify") || invOwner.isAuthorized("essentials.invsee.preventmodify") || !invOwner.getBase().isOnline())) {
|
||||
event.setCancelled(true);
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
}
|
||||
} else if (type == InventoryType.ENDER_CHEST) {
|
||||
final User user = ess.getUser((Player) event.getWhoClicked());
|
||||
if (user.isEnderSee() && (!user.isAuthorized("essentials.enderchest.modify"))) {
|
||||
event.setCancelled(true);
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
} else if (type == InventoryType.WORKBENCH) {
|
||||
User user = ess.getUser((Player) event.getWhoClicked());
|
||||
if (user.isRecipeSee()) {
|
||||
event.setCancelled(true);
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
} else if (type == InventoryType.CHEST && top.getSize() == 9) {
|
||||
final User user = ess.getUser((Player) event.getWhoClicked());
|
||||
final InventoryHolder invHolder = top.getHolder();
|
||||
if (invHolder != null && invHolder instanceof HumanEntity && user.isInvSee()) {
|
||||
event.setCancelled(true);
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
} else if (clickedInventory != null && clickedInventory.getType() == InventoryType.PLAYER) {
|
||||
if (ess.getSettings().isDirectHatAllowed() && event.getClick() == ClickType.LEFT && event.getSlot() == 39
|
||||
&& event.getCursor().getType() != Material.AIR && event.getCursor().getType().getMaxDurability() == 0
|
||||
&& !MaterialUtil.isSkull(event.getCursor().getType())
|
||||
&& ess.getUser(event.getWhoClicked()).isAuthorized("essentials.hat")) {
|
||||
event.setCancelled(true);
|
||||
final PlayerInventory inv = (PlayerInventory) clickedInventory;
|
||||
final ItemStack head = inv.getHelmet();
|
||||
inv.setHelmet(event.getCursor());
|
||||
event.setCursor(head);
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshPlayer != null) {
|
||||
final Player player = refreshPlayer;
|
||||
ess.scheduleSyncDelayedTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.updateInventory();
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onInventoryCloseEvent(final InventoryCloseEvent event) {
|
||||
Player refreshPlayer = null;
|
||||
final Inventory top = event.getView().getTopInventory();
|
||||
final InventoryType type = top.getType();
|
||||
if (type == InventoryType.PLAYER) {
|
||||
final User user = ess.getUser((Player) event.getPlayer());
|
||||
user.setInvSee(false);
|
||||
refreshPlayer = user.getBase();
|
||||
} else if (type == InventoryType.ENDER_CHEST) {
|
||||
final User user = ess.getUser((Player) event.getPlayer());
|
||||
user.setEnderSee(false);
|
||||
refreshPlayer = user.getBase();
|
||||
} else if (type == InventoryType.WORKBENCH) {
|
||||
final User user = ess.getUser((Player) event.getPlayer());
|
||||
if (user.isRecipeSee()) {
|
||||
user.setRecipeSee(false);
|
||||
event.getView().getTopInventory().clear();
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
} else if (type == InventoryType.CHEST && top.getSize() == 9) {
|
||||
final InventoryHolder invHolder = top.getHolder();
|
||||
if (invHolder != null && invHolder instanceof HumanEntity) {
|
||||
final User user = ess.getUser((Player) event.getPlayer());
|
||||
user.setInvSee(false);
|
||||
refreshPlayer = user.getBase();
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshPlayer != null) {
|
||||
final Player player = refreshPlayer;
|
||||
ess.scheduleSyncDelayedTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.updateInventory();
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerFishEvent(final PlayerFishEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
user.updateActivityOnInteract(true);
|
||||
}
|
||||
|
||||
private static boolean isEntityPickupEvent() {
|
||||
try {
|
||||
Class.forName("org.bukkit.event.entity.EntityPickupItemEvent");
|
||||
return true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private final class PlayerListenerPre1_12 implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerPickupItem(final org.bukkit.event.player.PlayerPickupItemEvent event) {
|
||||
if (ess.getSettings().getDisableItemPickupWhileAfk()) {
|
||||
if (ess.getUser(event.getPlayer()).isAfk()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class PlayerListener1_12 implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerPickupItem(final org.bukkit.event.entity.EntityPickupItemEvent event) {
|
||||
if (ess.getSettings().getDisableItemPickupWhileAfk() && event.getEntity() instanceof Player) {
|
||||
if (ess.getUser((Player) event.getEntity()).isAfk()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.register.payment.Methods;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class EssentialsPluginListener implements Listener, IConf {
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public EssentialsPluginListener(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPluginEnable(final PluginEnableEvent event) {
|
||||
if (event.getPlugin().getName().equals("EssentialsChat")) {
|
||||
ess.getSettings().setEssentialsChatActive(true);
|
||||
}
|
||||
ess.getPermissionsHandler().setUseSuperperms(ess.getSettings().useBukkitPermissions());
|
||||
ess.getPermissionsHandler().checkPermissions();
|
||||
ess.getAlternativeCommandsHandler().addPlugin(event.getPlugin());
|
||||
if (!Methods.hasMethod() && Methods.setMethod(ess.getServer().getPluginManager())) {
|
||||
ess.getLogger().log(Level.INFO, "Payment method found (" + Methods.getMethod().getLongName() + " version: " + ess.getPaymentMethod().getMethod().getVersion() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPluginDisable(final PluginDisableEvent event) {
|
||||
if (event.getPlugin().getName().equals("EssentialsChat")) {
|
||||
ess.getSettings().setEssentialsChatActive(false);
|
||||
}
|
||||
ess.getAlternativeCommandsHandler().removePlugin(event.getPlugin());
|
||||
// Check to see if the plugin thats being disabled is the one we are using
|
||||
if (ess.getPaymentMethod() != null && Methods.hasMethod() && Methods.checkDisabled(event.getPlugin())) {
|
||||
Methods.reset();
|
||||
ess.getLogger().log(Level.INFO, "Payment method was disabled. No longer accepting payments.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerListPingEvent;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class EssentialsServerListener implements Listener {
|
||||
private static List<String> ignoredSLPECallers = Arrays.asList(
|
||||
".LegacyPingHandler.channelRead(" // CB responding to pings from pre-Netty clients
|
||||
);
|
||||
|
||||
private final transient IEssentials ess;
|
||||
private boolean unsupportedLogged = false;
|
||||
private boolean npeWarned = false;
|
||||
private boolean isPaperSample;
|
||||
private Method setSampleText;
|
||||
private Method getSampleText;
|
||||
|
||||
public EssentialsServerListener(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
|
||||
if (ReflUtil.getClassCached("com.destroystokyo.paper.event.server.PaperServerListPingEvent") == null) {
|
||||
// This workaround is only necessary for older Paper builds
|
||||
setSampleText = ReflUtil.getMethodCached(ServerListPingEvent.class, "setSampleText", List.class);
|
||||
getSampleText = ReflUtil.getMethodCached(ServerListPingEvent.class, "getSampleText");
|
||||
if (setSampleText != null && getSampleText != null) {
|
||||
ess.getLogger().info("ServerListPingEvent: Paper 1.12.2 setSampleText API");
|
||||
isPaperSample = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ess.getLogger().info("ServerListPingEvent: Spigot iterator API");
|
||||
isPaperSample = false;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onServerListPing(final ServerListPingEvent event) throws Exception {
|
||||
if (isPaperSample) {
|
||||
try {
|
||||
List<String> playerNames = (List<String>) getSampleText.invoke(event, null);
|
||||
playerNames.removeIf(player -> ess.getUser(player).isVanished());
|
||||
setSampleText.invoke(event, playerNames);
|
||||
} catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
|
||||
if (!unsupportedLogged && shouldWarnSLPECaller(e)) {
|
||||
ess.getLogger().log(Level.WARNING, "Unable to hide players from server list ping "
|
||||
+ "using Paper 1.12 method!", e);
|
||||
unsupportedLogged = true;
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
if (!npeWarned && shouldWarnSLPECaller(e)) {
|
||||
npeWarned = true;
|
||||
Exception ex = new Exception("A plugin has fired a ServerListPingEvent "
|
||||
+ "without implementing Paper's methods. Point the author to https://git.io/v7Xzl.");
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Iterator<Player> iterator = event.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Player player = iterator.next();
|
||||
if (ess.getUser(player).isVanished()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
if (!unsupportedLogged && shouldWarnSLPECaller(e)) {
|
||||
ess.getLogger().log(Level.WARNING, "Could not hide vanished players while handling " + event.getClass().getName(), e);
|
||||
unsupportedLogged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we warn about this SLPE caller, or should we silently ignore it?
|
||||
* This checks against the ignoredSLPECallers strings, and if it matches one of those, we
|
||||
* return false.
|
||||
*
|
||||
* @param throwable A throwable caught by a catch block
|
||||
* @return Whether or not to send a warning about this particular caller
|
||||
*/
|
||||
private boolean shouldWarnSLPECaller(Throwable throwable) {
|
||||
final int maxStackDepth = 20; // Limit the depth when searching through the stack trace
|
||||
int depth = 0;
|
||||
for (StackTraceElement element : throwable.getStackTrace()) {
|
||||
depth++;
|
||||
if (depth > maxStackDepth) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (String ignoredString : ignoredSLPECallers) {
|
||||
if (element.toString().contains(ignoredString)) {
|
||||
return false; // We know about this error and should ignore it, so don't warn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true; // We don't know for certain that we can ignore this, so warn just to be safe
|
||||
}
|
||||
}
|
||||
@@ -1,82 +1,106 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.ISettings;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.perm.Permissions;
|
||||
import com.earth2me.essentials.user.UserData.TimestampType;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class EssentialsTimer implements Runnable
|
||||
{
|
||||
private final transient IEssentials ess;
|
||||
private final transient Set<IUser> onlineUsers = new HashSet<IUser>();
|
||||
|
||||
EssentialsTimer(final IEssentials ess)
|
||||
{
|
||||
this.ess = ess;
|
||||
}
|
||||
public class EssentialsTimer implements Runnable {
|
||||
private final transient IEssentials ess;
|
||||
private final transient Set<UUID> onlineUsers = new HashSet<>(); // Field is necessary for hidden users
|
||||
private transient long lastPoll = System.nanoTime();
|
||||
private final LinkedList<Double> history = new LinkedList<>();
|
||||
private int skip1 = 0;
|
||||
private int skip2 = 0;
|
||||
private final long maxTime = 10 * 1000000;
|
||||
private final long tickInterval = 50;
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
for (Player player : ess.getServer().getOnlinePlayers())
|
||||
{
|
||||
EssentialsTimer(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
history.add(20d);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
final IUser user = ess.getUser(player);
|
||||
onlineUsers.add(user);
|
||||
user.setLastOnlineActivity(currentTime);
|
||||
user.checkActivity();
|
||||
@Override
|
||||
public void run() {
|
||||
final long startTime = System.nanoTime();
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
long timeSpent = (startTime - lastPoll) / 1000;
|
||||
if (timeSpent == 0) {
|
||||
timeSpent = 1;
|
||||
}
|
||||
if (history.size() > 10) {
|
||||
history.remove();
|
||||
}
|
||||
double tps = tickInterval * 1000000.0 / timeSpent;
|
||||
if (tps <= 21) {
|
||||
history.add(tps);
|
||||
}
|
||||
lastPoll = startTime;
|
||||
int count = 0;
|
||||
for (Player player : ess.getOnlinePlayers()) {
|
||||
count++;
|
||||
if (skip1 > 0) {
|
||||
skip1--;
|
||||
continue;
|
||||
}
|
||||
if (count % 10 == 0) {
|
||||
if (System.nanoTime() - startTime > maxTime / 2) {
|
||||
skip1 = count - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final User user = ess.getUser(player);
|
||||
onlineUsers.add(user.getBase().getUniqueId());
|
||||
user.setLastOnlineActivity(currentTime);
|
||||
user.checkActivity();
|
||||
} catch (Exception e) {
|
||||
ess.getLogger().log(Level.WARNING, "EssentialsTimer Error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean mailDisabled = false;
|
||||
ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
try
|
||||
{
|
||||
mailDisabled = settings.getData().getCommands().isDisabled("mail");
|
||||
}
|
||||
finally
|
||||
{
|
||||
settings.unlock();
|
||||
}
|
||||
// New mail notification
|
||||
if (user != null && !mailDisabled && Permissions.MAIL.isAuthorized(user) && !user.gotMailInfo())
|
||||
{
|
||||
final List<String> mail = user.getMails();
|
||||
if (mail != null && !mail.isEmpty())
|
||||
{
|
||||
user.sendMessage(_("youHaveNewMail", mail.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ess.getLogger().log(Level.WARNING, "EssentialsTimer Error:", e);
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
final Iterator<UUID> iterator = onlineUsers.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
count++;
|
||||
if (skip2 > 0) {
|
||||
skip2--;
|
||||
continue;
|
||||
}
|
||||
if (count % 10 == 0) {
|
||||
if (System.nanoTime() - startTime > maxTime) {
|
||||
skip2 = count - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
final User user = ess.getUser(iterator.next());
|
||||
// Not sure why this would happen, but it does
|
||||
if (user == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (user.getLastOnlineActivity() < currentTime && user.getLastOnlineActivity() > user.getLastLogout()) {
|
||||
if (!user.isHidden()) {
|
||||
user.setLastLogout(user.getLastOnlineActivity());
|
||||
}
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
user.checkMuteTimeout(currentTime);
|
||||
user.checkJailTimeout(currentTime);
|
||||
user.resetInvulnerabilityAfterTeleport();
|
||||
}
|
||||
}
|
||||
|
||||
final Iterator<IUser> iterator = onlineUsers.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
final IUser user = iterator.next();
|
||||
if (user.getLastOnlineActivity() < currentTime && user.getLastOnlineActivity() > user.getTimestamp(TimestampType.LOGOUT))
|
||||
{
|
||||
user.setTimestamp(TimestampType.LOGOUT, user.getLastOnlineActivity());
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
user.checkMuteTimeout(currentTime);
|
||||
user.checkJailTimeout(currentTime);
|
||||
}
|
||||
}
|
||||
public double getAverageTPS() {
|
||||
double avg = 0;
|
||||
for (Double f : history) {
|
||||
if (f != null) {
|
||||
avg += f;
|
||||
}
|
||||
}
|
||||
return avg / history.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,722 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.BanLookup;
|
||||
import com.earth2me.essentials.craftbukkit.FakeWorld;
|
||||
import com.earth2me.essentials.settings.Spawns;
|
||||
import com.earth2me.essentials.storage.YamlStorageWriter;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Maps;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.BanList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class EssentialsUpgrade {
|
||||
private final static Logger LOGGER = Logger.getLogger("Essentials");
|
||||
private final transient IEssentials ess;
|
||||
private final transient EssentialsConf doneFile;
|
||||
|
||||
EssentialsUpgrade(final IEssentials essentials) {
|
||||
ess = essentials;
|
||||
if (!ess.getDataFolder().exists()) {
|
||||
ess.getDataFolder().mkdirs();
|
||||
}
|
||||
doneFile = new EssentialsConf(new File(ess.getDataFolder(), "upgrades-done.yml"));
|
||||
doneFile.load();
|
||||
}
|
||||
|
||||
public void convertKits() {
|
||||
Kits kits = ess.getKits();
|
||||
EssentialsConf config = kits.getConfig();
|
||||
if (doneFile.getBoolean("kitsyml", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Attempting to convert old kits in config.yml to new kits.yml");
|
||||
|
||||
ConfigurationSection section = ess.getSettings().getKitSection();
|
||||
if (section == null) {
|
||||
LOGGER.info("No kits found to migrate.");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> legacyKits = ess.getSettings().getKitSection().getValues(true);
|
||||
|
||||
for (Map.Entry<String, Object> entry : legacyKits.entrySet()) {
|
||||
LOGGER.info("Converting " + entry.getKey());
|
||||
config.set("kits." + entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
config.save();
|
||||
doneFile.setProperty("kitsyml", true);
|
||||
doneFile.save();
|
||||
LOGGER.info("Done converting kits.");
|
||||
}
|
||||
|
||||
private void moveMotdRulesToFile(String name) {
|
||||
if (doneFile.getBoolean("move" + name + "ToFile", false)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final File file = new File(ess.getDataFolder(), name + ".txt");
|
||||
if (file.exists()) {
|
||||
return;
|
||||
}
|
||||
final File configFile = new File(ess.getDataFolder(), "config.yml");
|
||||
if (!configFile.exists()) {
|
||||
return;
|
||||
}
|
||||
final EssentialsConf conf = new EssentialsConf(configFile);
|
||||
conf.load();
|
||||
List<String> lines = conf.getStringList(name);
|
||||
if (lines != null && !lines.isEmpty()) {
|
||||
if (!file.createNewFile()) {
|
||||
throw new IOException("Failed to create file " + file);
|
||||
}
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
|
||||
for (String line : lines) {
|
||||
writer.println(line);
|
||||
}
|
||||
writer.close();
|
||||
}
|
||||
doneFile.setProperty("move" + name + "ToFile", true);
|
||||
doneFile.save();
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.SEVERE, tl("upgradingFilesError"), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLinesFromConfig(File file, String regex, String info) throws Exception {
|
||||
boolean needUpdate = false;
|
||||
final BufferedReader bReader = new BufferedReader(new FileReader(file));
|
||||
final File tempFile = File.createTempFile("essentialsupgrade", ".tmp.yml", ess.getDataFolder());
|
||||
final BufferedWriter bWriter = new BufferedWriter(new FileWriter(tempFile));
|
||||
do {
|
||||
final String line = bReader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
if (line.matches(regex)) {
|
||||
if (!needUpdate && info != null) {
|
||||
bWriter.write(info, 0, info.length());
|
||||
bWriter.newLine();
|
||||
}
|
||||
needUpdate = true;
|
||||
} else {
|
||||
if (line.endsWith("\r\n")) {
|
||||
bWriter.write(line, 0, line.length() - 2);
|
||||
} else if (line.endsWith("\r") || line.endsWith("\n")) {
|
||||
bWriter.write(line, 0, line.length() - 1);
|
||||
} else {
|
||||
bWriter.write(line, 0, line.length());
|
||||
}
|
||||
bWriter.newLine();
|
||||
}
|
||||
} while (true);
|
||||
bReader.close();
|
||||
bWriter.close();
|
||||
if (needUpdate) {
|
||||
if (!file.renameTo(new File(file.getParentFile(), file.getName().concat("." + System.currentTimeMillis() + ".upgradebackup")))) {
|
||||
throw new Exception(tl("configFileMoveError"));
|
||||
}
|
||||
if (!tempFile.renameTo(file)) {
|
||||
throw new Exception(tl("configFileRenameError"));
|
||||
}
|
||||
} else {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUsersPowerToolsFormat() {
|
||||
if (doneFile.getBoolean("updateUsersPowerToolsFormat", false)) {
|
||||
return;
|
||||
}
|
||||
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdataFolder.exists() || !userdataFolder.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
final File[] userFiles = userdataFolder.listFiles();
|
||||
|
||||
for (File file : userFiles) {
|
||||
if (!file.isFile() || !file.getName().endsWith(".yml")) {
|
||||
continue;
|
||||
}
|
||||
final EssentialsConf config = new EssentialsConf(file);
|
||||
try {
|
||||
config.load();
|
||||
if (config.hasProperty("powertools")) {
|
||||
@SuppressWarnings("unchecked") final Map<String, Object> powertools = config.getConfigurationSection("powertools").getValues(false);
|
||||
if (powertools == null) {
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : powertools.entrySet()) {
|
||||
if (entry.getValue() instanceof String) {
|
||||
List<String> temp = new ArrayList<>();
|
||||
temp.add((String) entry.getValue());
|
||||
powertools.put(entry.getKey(), temp);
|
||||
}
|
||||
}
|
||||
config.forceSave();
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
LOGGER.log(Level.INFO, "File: " + file.toString());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("updateUsersPowerToolsFormat", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private void updateUsersHomesFormat() {
|
||||
if (doneFile.getBoolean("updateUsersHomesFormat", false)) {
|
||||
return;
|
||||
}
|
||||
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdataFolder.exists() || !userdataFolder.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
final File[] userFiles = userdataFolder.listFiles();
|
||||
|
||||
for (File file : userFiles) {
|
||||
if (!file.isFile() || !file.getName().endsWith(".yml")) {
|
||||
continue;
|
||||
}
|
||||
final EssentialsConf config = new EssentialsConf(file);
|
||||
try {
|
||||
|
||||
config.load();
|
||||
if (config.hasProperty("home") && config.hasProperty("home.default")) {
|
||||
@SuppressWarnings("unchecked") final String defworld = (String) config.getProperty("home.default");
|
||||
final Location defloc = getFakeLocation(config, "home.worlds." + defworld);
|
||||
if (defloc != null) {
|
||||
config.setProperty("homes.home", defloc);
|
||||
}
|
||||
|
||||
Set<String> worlds = config.getConfigurationSection("home.worlds").getKeys(false);
|
||||
Location loc;
|
||||
String worldName;
|
||||
|
||||
if (worlds == null) {
|
||||
continue;
|
||||
}
|
||||
for (String world : worlds) {
|
||||
if (defworld.equalsIgnoreCase(world)) {
|
||||
continue;
|
||||
}
|
||||
loc = getFakeLocation(config, "home.worlds." + world);
|
||||
if (loc == null) {
|
||||
continue;
|
||||
}
|
||||
worldName = loc.getWorld().getName().toLowerCase(Locale.ENGLISH);
|
||||
if (worldName != null && !worldName.isEmpty()) {
|
||||
config.setProperty("homes." + worldName, loc);
|
||||
}
|
||||
}
|
||||
config.removeProperty("home");
|
||||
config.forceSave();
|
||||
}
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
LOGGER.log(Level.INFO, "File: " + file.toString());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("updateUsersHomesFormat", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private void sanitizeAllUserFilenames() {
|
||||
if (doneFile.getBoolean("sanitizeAllUserFilenames", false)) {
|
||||
return;
|
||||
}
|
||||
final File usersFolder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!usersFolder.exists()) {
|
||||
return;
|
||||
}
|
||||
final File[] listOfFiles = usersFolder.listFiles();
|
||||
for (File listOfFile : listOfFiles) {
|
||||
final String filename = listOfFile.getName();
|
||||
if (!listOfFile.isFile() || !filename.endsWith(".yml")) {
|
||||
continue;
|
||||
}
|
||||
final String sanitizedFilename = StringUtil.sanitizeFileName(filename.substring(0, filename.length() - 4)) + ".yml";
|
||||
if (sanitizedFilename.equals(filename)) {
|
||||
continue;
|
||||
}
|
||||
final File tmpFile = new File(listOfFile.getParentFile(), sanitizedFilename + ".tmp");
|
||||
final File newFile = new File(listOfFile.getParentFile(), sanitizedFilename);
|
||||
if (!listOfFile.renameTo(tmpFile)) {
|
||||
LOGGER.log(Level.WARNING, tl("userdataMoveError", filename, sanitizedFilename));
|
||||
continue;
|
||||
}
|
||||
if (newFile.exists()) {
|
||||
LOGGER.log(Level.WARNING, tl("duplicatedUserdata", filename, sanitizedFilename));
|
||||
continue;
|
||||
}
|
||||
if (!tmpFile.renameTo(newFile)) {
|
||||
LOGGER.log(Level.WARNING, tl("userdataMoveBackError", sanitizedFilename, sanitizedFilename));
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("sanitizeAllUserFilenames", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private World getFakeWorld(final String name) {
|
||||
final File bukkitDirectory = ess.getDataFolder().getParentFile().getParentFile();
|
||||
final File worldDirectory = new File(bukkitDirectory, name);
|
||||
if (worldDirectory.exists() && worldDirectory.isDirectory()) {
|
||||
return new FakeWorld(worldDirectory.getName(), World.Environment.NORMAL);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Location getFakeLocation(EssentialsConf config, String path) {
|
||||
String worldName = config.getString((path != null ? path + "." : "") + "world");
|
||||
if (worldName == null || worldName.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
World world = getFakeWorld(worldName);
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
return new Location(world, config.getDouble((path != null ? path + "." : "") + "x", 0), config.getDouble((path != null ? path + "." : "") + "y", 0), config.getDouble((path != null ? path + "." : "") + "z", 0), (float) config.getDouble((path != null ? path + "." : "") + "yaw", 0), (float) config.getDouble((path != null ? path + "." : "") + "pitch", 0));
|
||||
}
|
||||
|
||||
private void deleteOldItemsCsv() {
|
||||
if (doneFile.getBoolean("deleteOldItemsCsv", false)) {
|
||||
return;
|
||||
}
|
||||
final File file = new File(ess.getDataFolder(), "items.csv");
|
||||
if (file.exists()) {
|
||||
try {
|
||||
final Set<BigInteger> oldconfigs = new HashSet<>();
|
||||
oldconfigs.add(new BigInteger("66ec40b09ac167079f558d1099e39f10", 16)); // sep 1
|
||||
oldconfigs.add(new BigInteger("34284de1ead43b0bee2aae85e75c041d", 16)); // crlf
|
||||
oldconfigs.add(new BigInteger("c33bc9b8ee003861611bbc2f48eb6f4f", 16)); // jul 24
|
||||
oldconfigs.add(new BigInteger("6ff17925430735129fc2a02f830c1daa", 16)); // crlf
|
||||
|
||||
MessageDigest digest = ManagedFile.getDigest();
|
||||
final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
||||
final byte[] buffer = new byte[1024];
|
||||
try (DigestInputStream dis = new DigestInputStream(bis, digest)) {
|
||||
while (dis.read(buffer) != -1) {
|
||||
}
|
||||
}
|
||||
|
||||
BigInteger hash = new BigInteger(1, digest.digest());
|
||||
if (oldconfigs.contains(hash) && !file.delete()) {
|
||||
throw new IOException("Could not delete file " + file.toString());
|
||||
}
|
||||
doneFile.setProperty("deleteOldItemsCsv", true);
|
||||
doneFile.save();
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSpawnsToNewSpawnsConfig() {
|
||||
if (doneFile.getBoolean("updateSpawnsToNewSpawnsConfig", false)) {
|
||||
return;
|
||||
}
|
||||
final File configFile = new File(ess.getDataFolder(), "spawn.yml");
|
||||
if (configFile.exists()) {
|
||||
|
||||
final EssentialsConf config = new EssentialsConf(configFile);
|
||||
try {
|
||||
config.load();
|
||||
if (!config.hasProperty("spawns")) {
|
||||
final Spawns spawns = new Spawns();
|
||||
Set<String> keys = config.getKeys(false);
|
||||
for (String group : keys) {
|
||||
Location loc = getFakeLocation(config, group);
|
||||
spawns.getSpawns().put(group.toLowerCase(Locale.ENGLISH), loc);
|
||||
}
|
||||
if (!configFile.renameTo(new File(ess.getDataFolder(), "spawn.yml.old"))) {
|
||||
throw new Exception(tl("fileRenameError", "spawn.yml"));
|
||||
}
|
||||
try (PrintWriter writer = new PrintWriter(configFile)) {
|
||||
new YamlStorageWriter(writer).save(spawns);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("updateSpawnsToNewSpawnsConfig", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private void updateJailsToNewJailsConfig() {
|
||||
if (doneFile.getBoolean("updateJailsToNewJailsConfig", false)) {
|
||||
return;
|
||||
}
|
||||
final File configFile = new File(ess.getDataFolder(), "jail.yml");
|
||||
if (configFile.exists()) {
|
||||
|
||||
final EssentialsConf config = new EssentialsConf(configFile);
|
||||
try {
|
||||
config.load();
|
||||
if (!config.hasProperty("jails")) {
|
||||
final com.earth2me.essentials.settings.Jails jails = new com.earth2me.essentials.settings.Jails();
|
||||
Set<String> keys = config.getKeys(false);
|
||||
for (String jailName : keys) {
|
||||
Location loc = getFakeLocation(config, jailName);
|
||||
jails.getJails().put(jailName.toLowerCase(Locale.ENGLISH), loc);
|
||||
}
|
||||
if (!configFile.renameTo(new File(ess.getDataFolder(), "jail.yml.old"))) {
|
||||
throw new Exception(tl("fileRenameError", "jail.yml"));
|
||||
}
|
||||
try (PrintWriter writer = new PrintWriter(configFile)) {
|
||||
new YamlStorageWriter(writer).save(jails);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
doneFile.setProperty("updateJailsToNewJailsConfig", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private void warnMetrics() {
|
||||
if (doneFile.getBoolean("warnMetrics", false)) {
|
||||
return;
|
||||
}
|
||||
doneFile.setProperty("warnMetrics", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
private void uuidFileChange() {
|
||||
if (doneFile.getBoolean("uuidFileChange", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Boolean ignoreUFCache = doneFile.getBoolean("ignore-userfiles-cache", false);
|
||||
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdir.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int countFiles = 0;
|
||||
int countReqFiles = 0;
|
||||
for (String string : userdir.list()) {
|
||||
if (!string.endsWith(".yml") || string.length() < 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
countFiles++;
|
||||
|
||||
final String name = string.substring(0, string.length() - 4);
|
||||
UUID uuid = null;
|
||||
|
||||
try {
|
||||
uuid = UUID.fromString(name);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
countReqFiles++;
|
||||
}
|
||||
|
||||
if (countFiles > 100) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (countReqFiles < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ess.getLogger().info("#### Starting Essentials UUID userdata conversion in a few seconds. ####");
|
||||
ess.getLogger().info("We recommend you take a backup of your server before upgrading from the old username system.");
|
||||
|
||||
try {
|
||||
Thread.sleep(15000);
|
||||
} catch (InterruptedException ex) {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
uuidFileConvert(ess, ignoreUFCache);
|
||||
|
||||
doneFile.setProperty("uuidFileChange", true);
|
||||
doneFile.save();
|
||||
}
|
||||
|
||||
public static void uuidFileConvert(IEssentials ess, Boolean ignoreUFCache) {
|
||||
ess.getLogger().info("Starting Essentials UUID userdata conversion");
|
||||
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdir.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int countFiles = 0;
|
||||
int countFails = 0;
|
||||
int countEssCache = 0;
|
||||
int countBukkit = 0;
|
||||
|
||||
ess.getLogger().info("Found " + userdir.list().length + " files to convert...");
|
||||
|
||||
for (String string : userdir.list()) {
|
||||
if (!string.endsWith(".yml") || string.length() < 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int showProgress = countFiles % 250;
|
||||
|
||||
if (showProgress == 0) {
|
||||
ess.getUserMap().getUUIDMap().forceWriteUUIDMap();
|
||||
ess.getLogger().info("Converted " + countFiles + "/" + userdir.list().length);
|
||||
}
|
||||
|
||||
countFiles++;
|
||||
|
||||
String name = string.substring(0, string.length() - 4);
|
||||
EssentialsUserConf config;
|
||||
UUID uuid = null;
|
||||
try {
|
||||
uuid = UUID.fromString(name);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
File file = new File(userdir, string);
|
||||
EssentialsConf conf = new EssentialsConf(file);
|
||||
conf.load();
|
||||
conf.setProperty("lastAccountName", name);
|
||||
conf.save();
|
||||
|
||||
String uuidConf = ignoreUFCache ? "force-uuid" : "uuid";
|
||||
|
||||
String uuidString = conf.getString(uuidConf, null);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
try {
|
||||
uuid = UUID.fromString(uuidString);
|
||||
countEssCache++;
|
||||
break;
|
||||
} catch (Exception ex2) {
|
||||
if (conf.getBoolean("npc", false)) {
|
||||
uuid = UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8));
|
||||
break;
|
||||
}
|
||||
|
||||
org.bukkit.OfflinePlayer player = ess.getServer().getOfflinePlayer(name);
|
||||
uuid = player.getUniqueId();
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
countBukkit++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
conf.forceSave();
|
||||
config = new EssentialsUserConf(name, uuid, new File(userdir, uuid + ".yml"));
|
||||
config.convertLegacyFile();
|
||||
ess.getUserMap().trackUUID(uuid, name, false);
|
||||
continue;
|
||||
}
|
||||
countFails++;
|
||||
}
|
||||
}
|
||||
ess.getUserMap().getUUIDMap().forceWriteUUIDMap();
|
||||
|
||||
ess.getLogger().info("Converted " + countFiles + "/" + countFiles + ". Conversion complete.");
|
||||
ess.getLogger().info("Converted via cache: " + countEssCache + " :: Converted via lookup: " + countBukkit + " :: Failed to convert: " + countFails);
|
||||
ess.getLogger().info("To rerun the conversion type /essentials uuidconvert");
|
||||
}
|
||||
|
||||
public void banFormatChange() {
|
||||
if (doneFile.getBoolean("banFormatChange", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ess.getLogger().info("Starting Essentials ban format conversion");
|
||||
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdir.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int countFiles = 0;
|
||||
|
||||
ess.getLogger().info("Found " + userdir.list().length + " files to convert...");
|
||||
|
||||
for (String string : userdir.list()) {
|
||||
if (!string.endsWith(".yml") || string.length() < 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int showProgress = countFiles % 250;
|
||||
|
||||
if (showProgress == 0) {
|
||||
ess.getLogger().info("Converted " + countFiles + "/" + userdir.list().length);
|
||||
}
|
||||
|
||||
countFiles++;
|
||||
final File pFile = new File(userdir, string);
|
||||
final EssentialsConf conf = new EssentialsConf(pFile);
|
||||
conf.load();
|
||||
|
||||
String banReason;
|
||||
Long banTimeout;
|
||||
|
||||
try {
|
||||
banReason = conf.getConfigurationSection("ban").getString("reason");
|
||||
} catch (NullPointerException n) {
|
||||
banReason = null;
|
||||
}
|
||||
|
||||
final String playerName = conf.getString("lastAccountName");
|
||||
if (playerName != null && playerName.length() > 1 && banReason != null && banReason.length() > 1) {
|
||||
try {
|
||||
if (conf.getConfigurationSection("ban").contains("timeout")) {
|
||||
banTimeout = Long.parseLong(conf.getConfigurationSection("ban").getString("timeout"));
|
||||
} else {
|
||||
banTimeout = 0L;
|
||||
}
|
||||
} catch (NumberFormatException n) {
|
||||
banTimeout = 0L;
|
||||
}
|
||||
|
||||
if (BanLookup.isBanned(ess, playerName)) {
|
||||
updateBan(playerName, banReason, banTimeout);
|
||||
}
|
||||
}
|
||||
conf.removeProperty("ban");
|
||||
conf.save();
|
||||
}
|
||||
|
||||
doneFile.setProperty("banFormatChange", true);
|
||||
doneFile.save();
|
||||
ess.getLogger().info("Ban format update complete.");
|
||||
}
|
||||
|
||||
private void updateBan(String playerName, String banReason, Long banTimeout) {
|
||||
if (banTimeout == 0) {
|
||||
Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, banReason, null, Console.NAME);
|
||||
} else {
|
||||
Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, banReason, new Date(banTimeout), Console.NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private static final FileFilter YML_FILTER = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.isFile() && pathname.getName().endsWith(".yml");
|
||||
}
|
||||
};
|
||||
|
||||
private static final String PATTERN_CONFIG_UUID_REGEX = "(?mi)^uuid:\\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\s*$";
|
||||
private static final Pattern PATTERN_CONFIG_UUID = Pattern.compile(PATTERN_CONFIG_UUID_REGEX);
|
||||
|
||||
private static final String PATTERN_CONFIG_NAME_REGEX = "(?mi)^lastAccountName:\\s*[\"\']?(\\w+)[\"\']?\\s*$";
|
||||
private static final Pattern PATTERN_CONFIG_NAME = Pattern.compile(PATTERN_CONFIG_NAME_REGEX);
|
||||
|
||||
private void repairUserMap() {
|
||||
if (doneFile.getBoolean("userMapRepaired", false)) {
|
||||
return;
|
||||
}
|
||||
ess.getLogger().info("Starting usermap repair");
|
||||
|
||||
File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdataFolder.isDirectory()) {
|
||||
ess.getLogger().warning("Missing userdata folder, aborting");
|
||||
return;
|
||||
}
|
||||
File[] files = userdataFolder.listFiles(YML_FILTER);
|
||||
|
||||
final DecimalFormat format = new DecimalFormat("#0.00");
|
||||
final Map<String, UUID> names = Maps.newHashMap();
|
||||
|
||||
for (int index = 0; index < files.length; index++) {
|
||||
final File file = files[index];
|
||||
try {
|
||||
UUID uuid = null;
|
||||
final String filename = file.getName();
|
||||
final String configData = new String(java.nio.file.Files.readAllBytes(file.toPath()), Charsets.UTF_8);
|
||||
|
||||
if (filename.length() > 36) {
|
||||
try {
|
||||
// ".yml" ending has 4 chars...
|
||||
uuid = UUID.fromString(filename.substring(0, filename.length() - 4));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
final Matcher uuidMatcher = PATTERN_CONFIG_UUID.matcher(configData);
|
||||
if (uuidMatcher.find()) {
|
||||
try {
|
||||
uuid = UUID.fromString(uuidMatcher.group(1));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
// Don't import
|
||||
continue;
|
||||
}
|
||||
|
||||
final Matcher nameMatcher = PATTERN_CONFIG_NAME.matcher(configData);
|
||||
if (nameMatcher.find()) {
|
||||
final String username = nameMatcher.group(1);
|
||||
if (username != null && username.length() > 0) {
|
||||
names.put(StringUtil.safeString(username), uuid);
|
||||
}
|
||||
}
|
||||
|
||||
if (index % 1000 == 0) {
|
||||
ess.getLogger().info("Reading: " + format.format((100d * (double) index) / files.length)
|
||||
+ "%");
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while reading file: ", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ess.getUserMap().getNames().putAll(names);
|
||||
ess.getUserMap().reloadConfig();
|
||||
|
||||
doneFile.setProperty("userMapRepaired", true);
|
||||
doneFile.save();
|
||||
ess.getLogger().info("Completed usermap repair.");
|
||||
}
|
||||
|
||||
public void beforeSettings() {
|
||||
if (!ess.getDataFolder().exists()) {
|
||||
ess.getDataFolder().mkdirs();
|
||||
}
|
||||
moveMotdRulesToFile("motd");
|
||||
moveMotdRulesToFile("rules");
|
||||
}
|
||||
|
||||
public void afterSettings() {
|
||||
sanitizeAllUserFilenames();
|
||||
updateUsersPowerToolsFormat();
|
||||
updateUsersHomesFormat();
|
||||
deleteOldItemsCsv();
|
||||
updateSpawnsToNewSpawnsConfig();
|
||||
updateJailsToNewJailsConfig();
|
||||
uuidFileChange();
|
||||
banFormatChange();
|
||||
warnMetrics();
|
||||
repairUserMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class EssentialsUserConf extends EssentialsConf {
|
||||
public final String username;
|
||||
public final UUID uuid;
|
||||
|
||||
public EssentialsUserConf(final String username, final UUID uuid, final File configFile) {
|
||||
super(configFile);
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean legacyFileExists() {
|
||||
final File file = new File(configFile.getParentFile(), username + ".yml");
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertLegacyFile() {
|
||||
final File file = new File(configFile.getParentFile(), username + ".yml");
|
||||
try {
|
||||
Files.move(file, new File(configFile.getParentFile(), uuid + ".yml"));
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
|
||||
}
|
||||
|
||||
setProperty("lastAccountName", username);
|
||||
}
|
||||
|
||||
private File getAltFile() {
|
||||
final UUID fn = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username.toLowerCase(Locale.ENGLISH)).getBytes(Charsets.UTF_8));
|
||||
return new File(configFile.getParentFile(), fn.toString() + ".yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean altFileExists() {
|
||||
if (username.equals(username.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
return getAltFile().exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertAltFile() {
|
||||
try {
|
||||
Files.move(getAltFile(), new File(configFile.getParentFile(), uuid + ".yml"));
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to migrate user: " + username, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,83 +7,69 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public class ExecuteTimer
|
||||
{
|
||||
private final transient List<ExecuteRecord> times;
|
||||
private final transient DecimalFormat decimalFormat = new DecimalFormat("#0.000", DecimalFormatSymbols.getInstance(Locale.US));
|
||||
public class ExecuteTimer {
|
||||
private final transient List<ExecuteRecord> times;
|
||||
private final transient DecimalFormat decimalFormat = new DecimalFormat("#0.000", DecimalFormatSymbols.getInstance(Locale.US));
|
||||
|
||||
|
||||
public ExecuteTimer()
|
||||
{
|
||||
times = new ArrayList<ExecuteRecord>();
|
||||
}
|
||||
public ExecuteTimer() {
|
||||
times = new ArrayList<ExecuteRecord>();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
times.clear();
|
||||
mark("start");
|
||||
public void start() {
|
||||
times.clear();
|
||||
mark("start");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void mark(final String label)
|
||||
{
|
||||
if (!times.isEmpty() || "start".equals(label))
|
||||
{
|
||||
times.add(new ExecuteRecord(label, System.nanoTime()));
|
||||
}
|
||||
}
|
||||
public void mark(final String label) {
|
||||
if (!times.isEmpty() || "start".equals(label)) {
|
||||
times.add(new ExecuteRecord(label, System.nanoTime()));
|
||||
}
|
||||
}
|
||||
|
||||
public String end()
|
||||
{
|
||||
final StringBuilder output = new StringBuilder();
|
||||
output.append("execution time: ");
|
||||
String mark;
|
||||
long time0 = 0;
|
||||
long time1 = 0;
|
||||
long time2 = 0;
|
||||
double duration;
|
||||
public String end() {
|
||||
final StringBuilder output = new StringBuilder();
|
||||
output.append("execution time: ");
|
||||
String mark;
|
||||
long time0 = 0;
|
||||
long time1 = 0;
|
||||
long time2 = 0;
|
||||
double duration;
|
||||
|
||||
for (ExecuteRecord pair : times)
|
||||
{
|
||||
mark = (String)pair.getMark();
|
||||
time2 = (Long)pair.getTime();
|
||||
if (time1 > 0)
|
||||
{
|
||||
duration = (time2 - time1)/1000000.0;
|
||||
output.append(mark).append(": ").append(decimalFormat.format(duration)).append("ms - ");
|
||||
}
|
||||
else
|
||||
{
|
||||
time0 = time2;
|
||||
}
|
||||
time1 = time2;
|
||||
}
|
||||
duration = (time1 - time0)/1000000.0;
|
||||
output.append("Total: ").append(decimalFormat.format(duration)).append("ms");
|
||||
times.clear();
|
||||
return output.toString();
|
||||
}
|
||||
for (ExecuteRecord pair : times) {
|
||||
mark = pair.getMark();
|
||||
time2 = pair.getTime();
|
||||
if (time1 > 0) {
|
||||
duration = (time2 - time1) / 1000000.0;
|
||||
output.append(mark).append(": ").append(decimalFormat.format(duration)).append("ms - ");
|
||||
} else {
|
||||
time0 = time2;
|
||||
}
|
||||
time1 = time2;
|
||||
}
|
||||
duration = (time1 - time0) / 1000000.0;
|
||||
output.append("Total: ").append(decimalFormat.format(duration)).append("ms");
|
||||
times.clear();
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
|
||||
static private class ExecuteRecord
|
||||
{
|
||||
private final String mark;
|
||||
private final long time;
|
||||
private static class ExecuteRecord {
|
||||
private final String mark;
|
||||
private final long time;
|
||||
|
||||
public ExecuteRecord(final String mark, final long time)
|
||||
{
|
||||
this.mark = mark;
|
||||
this.time = time;
|
||||
}
|
||||
public ExecuteRecord(final String mark, final long time) {
|
||||
this.mark = mark;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getMark()
|
||||
{
|
||||
return mark;
|
||||
}
|
||||
public String getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
public long getTime()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
}
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.II18n;
|
||||
import net.ess3.api.IEssentials;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -12,166 +12,155 @@ import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class I18n implements II18n
|
||||
{
|
||||
private static I18n instance;
|
||||
private static final String MESSAGES = "messages";
|
||||
private final transient Locale defaultLocale = Locale.getDefault();
|
||||
private transient Locale currentLocale = defaultLocale;
|
||||
private transient ResourceBundle customBundle;
|
||||
private transient ResourceBundle localeBundle;
|
||||
private final transient ResourceBundle defaultBundle;
|
||||
private final transient Map<String, MessageFormat> messageFormatCache = new HashMap<String, MessageFormat>();
|
||||
private final transient IEssentials ess;
|
||||
public class I18n implements net.ess3.api.II18n {
|
||||
private static I18n instance;
|
||||
private static final String MESSAGES = "messages";
|
||||
private final transient Locale defaultLocale = Locale.getDefault();
|
||||
private transient Locale currentLocale = defaultLocale;
|
||||
private transient ResourceBundle customBundle;
|
||||
private transient ResourceBundle localeBundle;
|
||||
private final transient ResourceBundle defaultBundle;
|
||||
private transient Map<String, MessageFormat> messageFormatCache = new HashMap<String, MessageFormat>();
|
||||
private final transient IEssentials ess;
|
||||
private static final Pattern NODOUBLEMARK = Pattern.compile("''");
|
||||
private static final ResourceBundle NULL_BUNDLE = new ResourceBundle() {
|
||||
public Enumeration<String> getKeys() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public I18n(final IEssentials ess)
|
||||
{
|
||||
this.ess = ess;
|
||||
customBundle = ResourceBundle.getBundle(MESSAGES, defaultLocale, new FileResClassLoader(I18n.class.getClassLoader(), ess));
|
||||
localeBundle = ResourceBundle.getBundle(MESSAGES, defaultLocale);
|
||||
defaultBundle = ResourceBundle.getBundle(MESSAGES, Locale.ENGLISH);
|
||||
}
|
||||
protected Object handleGetObject(String key) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public void onEnable()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
public I18n(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
defaultBundle = ResourceBundle.getBundle(MESSAGES, Locale.ENGLISH);
|
||||
localeBundle = defaultBundle;
|
||||
customBundle = NULL_BUNDLE;
|
||||
}
|
||||
|
||||
public void onDisable()
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getCurrentLocale()
|
||||
{
|
||||
return currentLocale;
|
||||
}
|
||||
public void onDisable() {
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public String translate(final String string)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
return customBundle.getString(string);
|
||||
}
|
||||
catch (MissingResourceException ex)
|
||||
{
|
||||
return localeBundle.getString(string);
|
||||
}
|
||||
}
|
||||
catch (MissingResourceException ex)
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex);
|
||||
return defaultBundle.getString(string);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Locale getCurrentLocale() {
|
||||
return currentLocale;
|
||||
}
|
||||
|
||||
public static String _(final String string, final Object... objects)
|
||||
{
|
||||
if (instance == null) {
|
||||
return "";
|
||||
}
|
||||
if (objects.length == 0)
|
||||
{
|
||||
return instance.translate(string);
|
||||
}
|
||||
else
|
||||
{
|
||||
return instance.format(string, objects);
|
||||
}
|
||||
}
|
||||
private String translate(final String string) {
|
||||
try {
|
||||
try {
|
||||
return customBundle.getString(string);
|
||||
} catch (MissingResourceException ex) {
|
||||
return localeBundle.getString(string);
|
||||
}
|
||||
} catch (MissingResourceException ex) {
|
||||
Logger.getLogger("Essentials").log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex);
|
||||
return defaultBundle.getString(string);
|
||||
}
|
||||
}
|
||||
|
||||
public String format(final String string, final Object... objects)
|
||||
{
|
||||
final String format = translate(string);
|
||||
MessageFormat messageFormat = messageFormatCache.get(format);
|
||||
if (messageFormat == null)
|
||||
{
|
||||
messageFormat = new MessageFormat(format);
|
||||
messageFormatCache.put(format, messageFormat);
|
||||
}
|
||||
return messageFormat.format(objects);
|
||||
}
|
||||
public static String tl(final String string, final Object... objects) {
|
||||
if (instance == null) {
|
||||
return "";
|
||||
}
|
||||
if (objects.length == 0) {
|
||||
return NODOUBLEMARK.matcher(instance.translate(string)).replaceAll("'");
|
||||
} else {
|
||||
return instance.format(string, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLocale(final String loc)
|
||||
{
|
||||
if (loc == null || loc.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final String[] parts = loc.split("[_\\.]");
|
||||
if (parts.length == 1)
|
||||
{
|
||||
currentLocale = new Locale(parts[0]);
|
||||
}
|
||||
if (parts.length == 2)
|
||||
{
|
||||
currentLocale = new Locale(parts[0], parts[1]);
|
||||
}
|
||||
if (parts.length == 3)
|
||||
{
|
||||
currentLocale = new Locale(parts[0], parts[1], parts[2]);
|
||||
}
|
||||
Logger.getLogger("Minecraft").log(Level.INFO, String.format("Using locale %s", currentLocale.toString()));
|
||||
customBundle = ResourceBundle.getBundle(MESSAGES, currentLocale, new FileResClassLoader(I18n.class.getClassLoader(), ess));
|
||||
localeBundle = ResourceBundle.getBundle(MESSAGES, currentLocale);
|
||||
}
|
||||
public String format(final String string, final Object... objects) {
|
||||
String format = translate(string);
|
||||
MessageFormat messageFormat = messageFormatCache.get(format);
|
||||
if (messageFormat == null) {
|
||||
try {
|
||||
messageFormat = new MessageFormat(format);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Invalid Translation key for '" + string + "': " + e.getMessage());
|
||||
format = format.replaceAll("\\{(\\D*?)\\}", "\\[$1\\]");
|
||||
messageFormat = new MessageFormat(format);
|
||||
}
|
||||
messageFormatCache.put(format, messageFormat);
|
||||
}
|
||||
return messageFormat.format(objects).replace(' ', ' '); // replace nbsp with a space
|
||||
}
|
||||
|
||||
public static String capitalCase(final String input)
|
||||
{
|
||||
return input == null || input.length() == 0
|
||||
? input
|
||||
: input.toUpperCase(Locale.ENGLISH).charAt(0)
|
||||
+ input.toLowerCase(Locale.ENGLISH).substring(1);
|
||||
}
|
||||
public void updateLocale(final String loc) {
|
||||
if (loc != null && !loc.isEmpty()) {
|
||||
final String[] parts = loc.split("[_\\.]");
|
||||
if (parts.length == 1) {
|
||||
currentLocale = new Locale(parts[0]);
|
||||
}
|
||||
if (parts.length == 2) {
|
||||
currentLocale = new Locale(parts[0], parts[1]);
|
||||
}
|
||||
if (parts.length == 3) {
|
||||
currentLocale = new Locale(parts[0], parts[1], parts[2]);
|
||||
}
|
||||
}
|
||||
ResourceBundle.clearCache();
|
||||
messageFormatCache = new HashMap<String, MessageFormat>();
|
||||
Logger.getLogger("Essentials").log(Level.INFO, String.format("Using locale %s", currentLocale.toString()));
|
||||
|
||||
try {
|
||||
localeBundle = ResourceBundle.getBundle(MESSAGES, currentLocale);
|
||||
} catch (MissingResourceException ex) {
|
||||
localeBundle = NULL_BUNDLE;
|
||||
}
|
||||
|
||||
try {
|
||||
customBundle = ResourceBundle.getBundle(MESSAGES, currentLocale, new FileResClassLoader(I18n.class.getClassLoader(), ess));
|
||||
} catch (MissingResourceException ex) {
|
||||
customBundle = NULL_BUNDLE;
|
||||
}
|
||||
}
|
||||
|
||||
public static String capitalCase(final String input) {
|
||||
return input == null || input.length() == 0 ? input : input.toUpperCase(Locale.ENGLISH).charAt(0) + input.toLowerCase(Locale.ENGLISH).substring(1);
|
||||
}
|
||||
|
||||
|
||||
private static class FileResClassLoader extends ClassLoader
|
||||
{
|
||||
private final transient File dataFolder;
|
||||
private static class FileResClassLoader extends ClassLoader {
|
||||
private final transient File dataFolder;
|
||||
|
||||
public FileResClassLoader(final ClassLoader classLoader, final IEssentials ess)
|
||||
{
|
||||
super(classLoader);
|
||||
this.dataFolder = ess.getDataFolder();
|
||||
}
|
||||
FileResClassLoader(final ClassLoader classLoader, final IEssentials ess) {
|
||||
super(classLoader);
|
||||
this.dataFolder = ess.getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(final String string)
|
||||
{
|
||||
final File file = new File(dataFolder, string);
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
return super.getResource(string);
|
||||
}
|
||||
@Override
|
||||
public URL getResource(final String string) {
|
||||
final File file = new File(dataFolder, string);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
return file.toURI().toURL();
|
||||
} catch (MalformedURLException ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(final String string)
|
||||
{
|
||||
final File file = new File(dataFolder, string);
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
return super.getResourceAsStream(string);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public InputStream getResourceAsStream(final String string) {
|
||||
final File file = new File(dataFolder, string);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
return new FileInputStream(file);
|
||||
} catch (FileNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
public interface IConf {
|
||||
void reloadConfig();
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IItemDb;
|
||||
import com.earth2me.essentials.api.IJails;
|
||||
import com.earth2me.essentials.api.IWarps;
|
||||
import com.earth2me.essentials.metrics.Metrics;
|
||||
import com.earth2me.essentials.perm.PermissionsHandler;
|
||||
import com.earth2me.essentials.register.payment.Methods;
|
||||
import net.ess3.nms.SpawnerProvider;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IEssentials extends Plugin {
|
||||
void addReloadListener(IConf listener);
|
||||
|
||||
void reload();
|
||||
|
||||
List<String> onTabCompleteEssentials(CommandSender sender, Command command, String commandLabel, String[] args, ClassLoader classLoader, String commandPath, String permissionPrefix, IEssentialsModule module);
|
||||
|
||||
boolean onCommandEssentials(CommandSender sender, Command command, String commandLabel, String[] args, ClassLoader classLoader, String commandPath, String permissionPrefix, IEssentialsModule module);
|
||||
|
||||
@Deprecated
|
||||
User getUser(Object base);
|
||||
|
||||
User getUser(UUID base);
|
||||
|
||||
User getUser(String base);
|
||||
|
||||
User getUser(Player base);
|
||||
|
||||
I18n getI18n();
|
||||
|
||||
User getOfflineUser(String name);
|
||||
|
||||
World getWorld(String name);
|
||||
|
||||
int broadcastMessage(String message);
|
||||
|
||||
int broadcastMessage(IUser sender, String message);
|
||||
|
||||
int broadcastMessage(String permission, String message);
|
||||
|
||||
ISettings getSettings();
|
||||
|
||||
BukkitScheduler getScheduler();
|
||||
|
||||
IJails getJails();
|
||||
|
||||
IWarps getWarps();
|
||||
|
||||
Worth getWorth();
|
||||
|
||||
Backup getBackup();
|
||||
|
||||
Kits getKits();
|
||||
|
||||
Methods getPaymentMethod();
|
||||
|
||||
BukkitTask runTaskAsynchronously(Runnable run);
|
||||
|
||||
BukkitTask runTaskLaterAsynchronously(Runnable run, long delay);
|
||||
|
||||
BukkitTask runTaskTimerAsynchronously(Runnable run, long delay, long period);
|
||||
|
||||
int scheduleSyncDelayedTask(Runnable run);
|
||||
|
||||
int scheduleSyncDelayedTask(Runnable run, long delay);
|
||||
|
||||
int scheduleSyncRepeatingTask(Runnable run, long delay, long period);
|
||||
|
||||
TNTExplodeListener getTNTListener();
|
||||
|
||||
PermissionsHandler getPermissionsHandler();
|
||||
|
||||
AlternativeCommandsHandler getAlternativeCommandsHandler();
|
||||
|
||||
void showError(CommandSource sender, Throwable exception, String commandLabel);
|
||||
|
||||
IItemDb getItemDb();
|
||||
|
||||
UserMap getUserMap();
|
||||
|
||||
Metrics getMetrics();
|
||||
|
||||
void setMetrics(Metrics metrics);
|
||||
|
||||
EssentialsTimer getTimer();
|
||||
|
||||
@Deprecated
|
||||
List<String> getVanishedPlayers();
|
||||
|
||||
Collection<Player> getOnlinePlayers();
|
||||
|
||||
Iterable<User> getOnlineUsers();
|
||||
|
||||
SpawnerProvider getSpawnerProvider();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
|
||||
public interface IEssentialsModule {
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.signs.EssentialsSign;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public interface ISettings extends IConf {
|
||||
boolean areSignsDisabled();
|
||||
|
||||
IText getAnnounceNewPlayerFormat();
|
||||
|
||||
boolean getAnnounceNewPlayers();
|
||||
|
||||
String getNewPlayerKit();
|
||||
|
||||
String getBackupCommand();
|
||||
|
||||
long getBackupInterval();
|
||||
|
||||
String getChatFormat(String group);
|
||||
|
||||
int getChatRadius();
|
||||
|
||||
int getNearRadius();
|
||||
|
||||
char getChatShout();
|
||||
|
||||
char getChatQuestion();
|
||||
|
||||
BigDecimal getCommandCost(IEssentialsCommand cmd);
|
||||
|
||||
BigDecimal getCommandCost(String label);
|
||||
|
||||
String getCurrencySymbol();
|
||||
|
||||
int getOversizedStackSize();
|
||||
|
||||
int getDefaultStackSize();
|
||||
|
||||
double getHealCooldown();
|
||||
|
||||
Set<String> getSocialSpyCommands();
|
||||
|
||||
boolean getSocialSpyListenMutedPlayers();
|
||||
|
||||
Set<String> getMuteCommands();
|
||||
|
||||
/**
|
||||
* @Deprecated in favor of {@link Kits#getKits()}
|
||||
*/
|
||||
@Deprecated
|
||||
ConfigurationSection getKits();
|
||||
|
||||
/**
|
||||
* @Deprecated in favor of {@link Kits#getKit(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Object> getKit(String kit);
|
||||
|
||||
/**
|
||||
* @Deprecated in favor of {@link Kits#addKit(String, List, long)}}
|
||||
*/
|
||||
@Deprecated
|
||||
void addKit(String name, List<String> lines, long delay);
|
||||
|
||||
@Deprecated
|
||||
ConfigurationSection getKitSection();
|
||||
|
||||
boolean isSkippingUsedOneTimeKitsFromKitList();
|
||||
|
||||
String getLocale();
|
||||
|
||||
String getNewbieSpawn();
|
||||
|
||||
String getNicknamePrefix();
|
||||
|
||||
ChatColor getOperatorColor() throws Exception;
|
||||
|
||||
boolean getPerWarpPermission();
|
||||
|
||||
boolean getProtectBoolean(final String configName, boolean def);
|
||||
|
||||
int getProtectCreeperMaxHeight();
|
||||
|
||||
List<Material> getProtectList(final String configName);
|
||||
|
||||
boolean getProtectPreventSpawn(final String creatureName);
|
||||
|
||||
String getProtectString(final String configName);
|
||||
|
||||
boolean getRespawnAtHome();
|
||||
|
||||
Set getMultipleHomes();
|
||||
|
||||
int getHomeLimit(String set);
|
||||
|
||||
int getHomeLimit(User user);
|
||||
|
||||
int getSpawnMobLimit();
|
||||
|
||||
BigDecimal getStartingBalance();
|
||||
|
||||
boolean isTeleportSafetyEnabled();
|
||||
|
||||
boolean isForceDisableTeleportSafety();
|
||||
|
||||
double getTeleportCooldown();
|
||||
|
||||
double getTeleportDelay();
|
||||
|
||||
boolean hidePermissionlessHelp();
|
||||
|
||||
boolean isCommandDisabled(final IEssentialsCommand cmd);
|
||||
|
||||
boolean isCommandDisabled(String label);
|
||||
|
||||
boolean isCommandOverridden(String name);
|
||||
|
||||
boolean isDebug();
|
||||
|
||||
boolean isEcoDisabled();
|
||||
|
||||
@Deprecated
|
||||
boolean isTradeInStacks(int id);
|
||||
|
||||
boolean isTradeInStacks(Material type);
|
||||
|
||||
List<Material> itemSpawnBlacklist();
|
||||
|
||||
List<EssentialsSign> enabledSigns();
|
||||
|
||||
boolean permissionBasedItemSpawn();
|
||||
|
||||
boolean showNonEssCommandsInHelp();
|
||||
|
||||
boolean warnOnBuildDisallow();
|
||||
|
||||
boolean warnOnSmite();
|
||||
|
||||
BigDecimal getMaxMoney();
|
||||
|
||||
BigDecimal getMinMoney();
|
||||
|
||||
boolean isEcoLogEnabled();
|
||||
|
||||
boolean isEcoLogUpdateEnabled();
|
||||
|
||||
boolean removeGodOnDisconnect();
|
||||
|
||||
boolean changeDisplayName();
|
||||
|
||||
boolean changePlayerListName();
|
||||
|
||||
boolean isPlayerCommand(String string);
|
||||
|
||||
boolean useBukkitPermissions();
|
||||
|
||||
boolean addPrefixSuffix();
|
||||
|
||||
boolean disablePrefix();
|
||||
|
||||
boolean disableSuffix();
|
||||
|
||||
long getAutoAfk();
|
||||
|
||||
long getAutoAfkKick();
|
||||
|
||||
boolean getFreezeAfkPlayers();
|
||||
|
||||
boolean cancelAfkOnMove();
|
||||
|
||||
boolean cancelAfkOnInteract();
|
||||
|
||||
boolean isAfkListName();
|
||||
|
||||
String getAfkListName();
|
||||
|
||||
boolean areDeathMessagesEnabled();
|
||||
|
||||
void setDebug(boolean debug);
|
||||
|
||||
Set<String> getNoGodWorlds();
|
||||
|
||||
boolean getUpdateBedAtDaytime();
|
||||
|
||||
boolean allowUnsafeEnchantments();
|
||||
|
||||
boolean getRepairEnchanted();
|
||||
|
||||
boolean isWorldTeleportPermissions();
|
||||
|
||||
boolean isWorldHomePermissions();
|
||||
|
||||
boolean registerBackInListener();
|
||||
|
||||
boolean getDisableItemPickupWhileAfk();
|
||||
|
||||
EventPriority getRespawnPriority();
|
||||
|
||||
EventPriority getSpawnJoinPriority();
|
||||
|
||||
long getTpaAcceptCancellation();
|
||||
|
||||
long getTeleportInvulnerability();
|
||||
|
||||
boolean isTeleportInvulnerability();
|
||||
|
||||
long getLoginAttackDelay();
|
||||
|
||||
int getSignUsePerSecond();
|
||||
|
||||
double getMaxFlySpeed();
|
||||
|
||||
double getMaxWalkSpeed();
|
||||
|
||||
int getMailsPerMinute();
|
||||
|
||||
long getEconomyLagWarning();
|
||||
|
||||
long getPermissionsLagWarning();
|
||||
|
||||
void setEssentialsChatActive(boolean b);
|
||||
|
||||
long getMaxTempban();
|
||||
|
||||
Map<String, Object> getListGroupConfig();
|
||||
|
||||
int getMaxNickLength();
|
||||
|
||||
boolean ignoreColorsInMaxLength();
|
||||
|
||||
boolean hideDisplayNameInVanish();
|
||||
|
||||
int getMaxUserCacheCount();
|
||||
|
||||
boolean allowSilentJoinQuit();
|
||||
|
||||
boolean isCustomJoinMessage();
|
||||
|
||||
String getCustomJoinMessage();
|
||||
|
||||
boolean isCustomQuitMessage();
|
||||
|
||||
String getCustomQuitMessage();
|
||||
|
||||
boolean isNotifyNoNewMail();
|
||||
|
||||
boolean isDropItemsIfFull();
|
||||
|
||||
boolean isLastMessageReplyRecipient();
|
||||
|
||||
BigDecimal getMinimumPayAmount();
|
||||
|
||||
long getLastMessageReplyRecipientTimeout();
|
||||
|
||||
boolean isMilkBucketEasterEggEnabled();
|
||||
|
||||
boolean isSendFlyEnableOnJoin();
|
||||
|
||||
boolean isWorldTimePermissions();
|
||||
|
||||
boolean isSpawnOnJoin();
|
||||
|
||||
List<String> getSpawnOnJoinGroups();
|
||||
|
||||
boolean isUserInSpawnOnJoinGroup(IUser user);
|
||||
|
||||
boolean isTeleportToCenterLocation();
|
||||
|
||||
boolean isCommandCooldownsEnabled();
|
||||
|
||||
long getCommandCooldownMs(String label);
|
||||
|
||||
Entry<Pattern, Long> getCommandCooldownEntry(String label);
|
||||
|
||||
boolean isCommandCooldownPersistent(String label);
|
||||
|
||||
boolean isNpcsInBalanceRanking();
|
||||
|
||||
NumberFormat getCurrencyFormat();
|
||||
|
||||
List<EssentialsSign> getUnprotectedSignNames();
|
||||
|
||||
boolean isPastebinCreateKit();
|
||||
|
||||
boolean isAllowBulkBuySell();
|
||||
|
||||
boolean isAddingPrefixInPlayerlist();
|
||||
|
||||
boolean isAddingSuffixInPlayerlist();
|
||||
|
||||
int getNotifyPlayerOfMailCooldown();
|
||||
|
||||
int getMotdDelay();
|
||||
|
||||
boolean isDirectHatAllowed();
|
||||
|
||||
List<String> getDefaultEnabledConfirmCommands();
|
||||
|
||||
boolean isConfirmCommandEnabledByDefault(String commandName);
|
||||
|
||||
boolean isCompassTowardsHomePerm();
|
||||
|
||||
boolean isAllowWorldInBroadcastworld();
|
||||
|
||||
String getItemDbType();
|
||||
|
||||
boolean isForceEnableRecipe();
|
||||
|
||||
boolean allowOldIdSigns();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
|
||||
public interface ITarget {
|
||||
Location getLocation();
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import net.ess3.api.ITeleport;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public interface IUser {
|
||||
boolean isAuthorized(String node);
|
||||
|
||||
boolean isAuthorized(IEssentialsCommand cmd);
|
||||
|
||||
boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix);
|
||||
|
||||
void healCooldown() throws Exception;
|
||||
|
||||
void giveMoney(BigDecimal value) throws MaxMoneyException;
|
||||
|
||||
void giveMoney(final BigDecimal value, final CommandSource initiator) throws MaxMoneyException;
|
||||
|
||||
void payUser(final User reciever, final BigDecimal value) throws Exception;
|
||||
|
||||
void takeMoney(BigDecimal value);
|
||||
|
||||
void takeMoney(final BigDecimal value, final CommandSource initiator);
|
||||
|
||||
boolean canAfford(BigDecimal value);
|
||||
|
||||
Boolean canSpawnItem(final Material material);
|
||||
|
||||
void setLastLocation();
|
||||
|
||||
void setLogoutLocation();
|
||||
|
||||
void requestTeleport(final User player, final boolean here);
|
||||
|
||||
/**
|
||||
* Returns whether this user has an outstanding teleport request to deal with.
|
||||
*
|
||||
* @return whether there is a teleport request
|
||||
*/
|
||||
boolean hasOutstandingTeleportRequest();
|
||||
|
||||
ITeleport getTeleport();
|
||||
|
||||
BigDecimal getMoney();
|
||||
|
||||
void setMoney(final BigDecimal value) throws MaxMoneyException;
|
||||
|
||||
void setAfk(final boolean set);
|
||||
|
||||
/**
|
||||
* 'Hidden' Represents when a player is hidden from others. This status includes when the player is hidden via other
|
||||
* supported plugins. Use isVanished() if you want to check if a user is vanished by Essentials.
|
||||
*
|
||||
* @return If the user is hidden or not
|
||||
*
|
||||
* @see isVanished
|
||||
*/
|
||||
boolean isHidden();
|
||||
|
||||
void setHidden(boolean vanish);
|
||||
|
||||
boolean isGodModeEnabled();
|
||||
|
||||
String getGroup();
|
||||
|
||||
boolean inGroup(final String group);
|
||||
|
||||
boolean canBuild();
|
||||
|
||||
long getTeleportRequestTime();
|
||||
|
||||
void enableInvulnerabilityAfterTeleport();
|
||||
|
||||
void resetInvulnerabilityAfterTeleport();
|
||||
|
||||
boolean hasInvulnerabilityAfterTeleport();
|
||||
|
||||
/**
|
||||
* 'Vanished' Represents when a player is hidden from others by Essentials. This status does NOT include when the
|
||||
* player is hidden via other plugins. Use isHidden() if you want to check if a user is vanished by any supported
|
||||
* plugin.
|
||||
*
|
||||
* @return If the user is vanished or not
|
||||
*
|
||||
* @see isHidden
|
||||
*/
|
||||
boolean isVanished();
|
||||
|
||||
void setVanished(boolean vanish);
|
||||
|
||||
boolean isIgnoreExempt();
|
||||
|
||||
void sendMessage(String message);
|
||||
|
||||
/*
|
||||
* UserData
|
||||
*/
|
||||
Location getHome(String name) throws Exception;
|
||||
|
||||
Location getHome(Location loc) throws Exception;
|
||||
|
||||
List<String> getHomes();
|
||||
|
||||
void setHome(String name, Location loc);
|
||||
|
||||
void delHome(String name) throws Exception;
|
||||
|
||||
boolean hasHome();
|
||||
|
||||
Location getLastLocation();
|
||||
|
||||
Location getLogoutLocation();
|
||||
|
||||
long getLastTeleportTimestamp();
|
||||
|
||||
void setLastTeleportTimestamp(long time);
|
||||
|
||||
String getJail();
|
||||
|
||||
void setJail(String jail);
|
||||
|
||||
List<String> getMails();
|
||||
|
||||
void addMail(String mail);
|
||||
|
||||
boolean isAfk();
|
||||
|
||||
void setIgnoreMsg(boolean ignoreMsg);
|
||||
|
||||
boolean isIgnoreMsg();
|
||||
|
||||
void setConfigProperty(String node, Object object);
|
||||
|
||||
Set<String> getConfigKeys();
|
||||
|
||||
Map<String, Object> getConfigMap();
|
||||
|
||||
Map<String, Object> getConfigMap(String node);
|
||||
|
||||
Map<Pattern, Long> getCommandCooldowns();
|
||||
|
||||
Date getCommandCooldownExpiry(String label);
|
||||
|
||||
void addCommandCooldown(Pattern pattern, Date expiresAt, boolean save);
|
||||
|
||||
boolean clearCommandCooldown(Pattern pattern);
|
||||
|
||||
/*
|
||||
* PlayerExtension
|
||||
*/
|
||||
Player getBase();
|
||||
|
||||
CommandSource getSource();
|
||||
|
||||
String getName();
|
||||
|
||||
String getAfkMessage();
|
||||
|
||||
void setAfkMessage(final String message);
|
||||
|
||||
long getAfkSince();
|
||||
|
||||
boolean isAcceptingPay();
|
||||
|
||||
void setAcceptingPay(boolean acceptingPay);
|
||||
|
||||
boolean isPromptingPayConfirm();
|
||||
|
||||
void setPromptingPayConfirm(boolean prompt);
|
||||
|
||||
boolean isPromptingClearConfirm();
|
||||
|
||||
void setPromptingClearConfirm(boolean prompt);
|
||||
|
||||
Map<User, BigDecimal> getConfirmingPayments();
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.storage.ManagedFile;
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.IItemDb;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.perm.Permissions;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.Cleanup;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
||||
public class ItemDb implements IItemDb
|
||||
{
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public ItemDb(final IEssentials ess)
|
||||
{
|
||||
this.ess = ess;
|
||||
file = new ManagedFile("items.csv", ess);
|
||||
}
|
||||
private final transient Map<String, Long> items = new HashMap<String, Long>();
|
||||
private final transient ManagedFile file;
|
||||
private static final Pattern SPLIT = Pattern.compile("[^a-zA-Z0-9]");
|
||||
|
||||
@Override
|
||||
public void onReload()
|
||||
{
|
||||
final List<String> lines = file.getLines();
|
||||
|
||||
if (lines.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
items.clear();
|
||||
|
||||
for (String line : lines)
|
||||
{
|
||||
line = line.trim();
|
||||
if (line.length() > 0 && line.charAt(0) == '#')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String[] parts = SPLIT.split(line);
|
||||
if (parts.length < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final long numeric = Integer.parseInt(parts[1]);
|
||||
|
||||
final long durability = parts.length > 2 && !(parts[2].length() == 1 && parts[2].charAt(0) == '0') ? Short.parseShort(parts[2]) : 0;
|
||||
items.put(parts[0].toLowerCase(Locale.ENGLISH), numeric | (durability << 32));
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack get(final String id, final IUser user) throws Exception
|
||||
{
|
||||
final ItemStack stack = get(id.toLowerCase(Locale.ENGLISH));
|
||||
|
||||
@Cleanup
|
||||
com.earth2me.essentials.api.ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
|
||||
final int defaultStackSize = settings.getData().getGeneral().getDefaultStacksize();
|
||||
|
||||
if (defaultStackSize > 0)
|
||||
{
|
||||
stack.setAmount(defaultStackSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
final int oversizedStackSize = settings.getData().getGeneral().getOversizedStacksize();
|
||||
if (oversizedStackSize > 0 && Permissions.OVERSIZEDSTACKS.isAuthorized(user))
|
||||
{
|
||||
stack.setAmount(oversizedStackSize);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public ItemStack get(final String id, final int quantity) throws Exception
|
||||
{
|
||||
final ItemStack retval = get(id.toLowerCase(Locale.ENGLISH));
|
||||
retval.setAmount(quantity);
|
||||
return retval;
|
||||
}
|
||||
|
||||
public ItemStack get(final String id) throws Exception
|
||||
{
|
||||
int itemid = 0;
|
||||
String itemname = null;
|
||||
short metaData = 0;
|
||||
if (id.matches("^\\d+[:+',;.]\\d+$"))
|
||||
{
|
||||
itemid = Integer.parseInt(id.split("[:+',;.]")[0]);
|
||||
metaData = Short.parseShort(id.split("[:+',;.]")[1]);
|
||||
}
|
||||
else if (id.matches("^\\d+$"))
|
||||
{
|
||||
itemid = Integer.parseInt(id);
|
||||
}
|
||||
else if (id.matches("^[^:+',;.]+[:+',;.]\\d+$"))
|
||||
{
|
||||
itemname = id.split("[:+',;.]")[0].toLowerCase(Locale.ENGLISH);
|
||||
metaData = Short.parseShort(id.split("[:+',;.]")[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemname = id.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
if (itemname != null)
|
||||
{
|
||||
if (items.containsKey(itemname))
|
||||
{
|
||||
long item = items.get(itemname);
|
||||
itemid = (int)(item & 0xffffffffL);
|
||||
if (metaData == 0)
|
||||
{
|
||||
metaData = (short)((item >> 32) & 0xffffL);
|
||||
}
|
||||
}
|
||||
else if (Material.getMaterial(itemname) != null)
|
||||
{
|
||||
itemid = Material.getMaterial(itemname).getId();
|
||||
metaData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(_("unknownItemName", id));
|
||||
}
|
||||
}
|
||||
|
||||
final Material mat = Material.getMaterial(itemid);
|
||||
if (mat == null)
|
||||
{
|
||||
throw new Exception(_("unknownItemId", itemid));
|
||||
}
|
||||
final ItemStack retval = new ItemStack(mat);
|
||||
retval.setAmount(mat.getMaxStackSize());
|
||||
retval.setDurability(metaData);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.IJails;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.storage.AsyncStorageObjectHolder;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import lombok.Cleanup;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockDamageEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
@@ -25,277 +23,242 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.settings.Jails> implements IJails
|
||||
{
|
||||
private static final transient Logger LOGGER = Bukkit.getLogger();
|
||||
|
||||
public Jails(final IEssentials ess)
|
||||
{
|
||||
super(ess, com.earth2me.essentials.settings.Jails.class);
|
||||
onReload();
|
||||
registerListeners();
|
||||
}
|
||||
|
||||
private void registerListeners()
|
||||
{
|
||||
final PluginManager pluginManager = ess.getServer().getPluginManager();
|
||||
final JailBlockListener blockListener = new JailBlockListener();
|
||||
final JailPlayerListener playerListener = new JailPlayerListener();
|
||||
pluginManager.registerEvents(blockListener, ess);
|
||||
pluginManager.registerEvents(playerListener, ess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile()
|
||||
{
|
||||
return new File(ess.getDataFolder(), "jail.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getJail(final String jailName) throws Exception
|
||||
{
|
||||
acquireReadLock();
|
||||
try
|
||||
{
|
||||
if (getData().getJails() == null || jailName == null
|
||||
|| !getData().getJails().containsKey(jailName.toLowerCase(Locale.ENGLISH)))
|
||||
{
|
||||
throw new Exception(_("jailNotExist"));
|
||||
}
|
||||
Location loc = getData().getJails().get(jailName.toLowerCase(Locale.ENGLISH)).getBukkitLocation();
|
||||
if (loc == null || loc.getWorld() == null)
|
||||
{
|
||||
throw new Exception(_("jailNotExist"));
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getList() throws Exception
|
||||
{
|
||||
acquireReadLock();
|
||||
try
|
||||
{
|
||||
if (getData().getJails() == null)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<String>(getData().getJails().keySet());
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeJail(final String jail) throws Exception
|
||||
{
|
||||
acquireWriteLock();
|
||||
try
|
||||
{
|
||||
if (getData().getJails() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
getData().getJails().remove(jail.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToJail(final IUser user, final String jail) throws Exception
|
||||
{
|
||||
acquireReadLock();
|
||||
try
|
||||
{
|
||||
if (!(user.isOnline()))
|
||||
{
|
||||
Location loc = getJail(jail);
|
||||
user.getTeleport().now(loc, false, TeleportCause.COMMAND);
|
||||
}
|
||||
user.acquireWriteLock();
|
||||
try
|
||||
{
|
||||
user.getData().setJail(jail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJail(final String jailName, final Location loc) throws Exception
|
||||
{
|
||||
acquireWriteLock();
|
||||
try
|
||||
{
|
||||
if (getData().getJails() == null)
|
||||
{
|
||||
getData().setJails(new HashMap<String, com.earth2me.essentials.storage.Location>());
|
||||
}
|
||||
getData().getJails().put(jailName.toLowerCase(Locale.ENGLISH), new com.earth2me.essentials.storage.Location(loc));
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
private class JailBlockListener implements Listener
|
||||
{
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onBlockBreak(final BlockBreakEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (user.getData().isJailed())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.settings.Jails> implements net.ess3.api.IJails {
|
||||
private static final transient Logger LOGGER = Bukkit.getLogger();
|
||||
private static transient boolean enabled = false;
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onBlockPlace(final BlockPlaceEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (user.getData().isJailed())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
public Jails(final IEssentials ess) {
|
||||
super(ess, com.earth2me.essentials.settings.Jails.class);
|
||||
reloadConfig();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onBlockDamage(final BlockDamageEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (user.getData().isJailed())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void registerListeners() {
|
||||
enabled = true;
|
||||
final PluginManager pluginManager = ess.getServer().getPluginManager();
|
||||
final JailListener blockListener = new JailListener();
|
||||
pluginManager.registerEvents(blockListener, ess);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, "Registering Jail listener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() {
|
||||
return new File(ess.getDataFolder(), "jail.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishRead() {
|
||||
checkRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishWrite() {
|
||||
checkRegister();
|
||||
}
|
||||
|
||||
public void resetListener() {
|
||||
enabled = false;
|
||||
checkRegister();
|
||||
}
|
||||
|
||||
private void checkRegister() {
|
||||
if (enabled == false && getCount() > 0) {
|
||||
registerListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getJail(final String jailName) throws Exception {
|
||||
acquireReadLock();
|
||||
try {
|
||||
if (getData().getJails() == null || jailName == null || !getData().getJails().containsKey(jailName.toLowerCase(Locale.ENGLISH))) {
|
||||
throw new Exception(tl("jailNotExist"));
|
||||
}
|
||||
Location loc = getData().getJails().get(jailName.toLowerCase(Locale.ENGLISH));
|
||||
if (loc == null || loc.getWorld() == null) {
|
||||
throw new Exception(tl("jailNotExist"));
|
||||
}
|
||||
return loc;
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getList() throws Exception {
|
||||
acquireReadLock();
|
||||
try {
|
||||
if (getData().getJails() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<String>(getData().getJails().keySet());
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeJail(final String jail) throws Exception {
|
||||
acquireWriteLock();
|
||||
try {
|
||||
if (getData().getJails() == null) {
|
||||
return;
|
||||
}
|
||||
getData().getJails().remove(jail.toLowerCase(Locale.ENGLISH));
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToJail(final IUser user, final String jail) throws Exception {
|
||||
acquireReadLock();
|
||||
try {
|
||||
if (user.getBase().isOnline()) {
|
||||
Location loc = getJail(jail);
|
||||
user.getTeleport().now(loc, false, TeleportCause.COMMAND);
|
||||
}
|
||||
user.setJail(jail);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJail(final String jailName, final Location loc) throws Exception {
|
||||
acquireWriteLock();
|
||||
try {
|
||||
if (getData().getJails() == null) {
|
||||
getData().setJails(new HashMap<String, Location>());
|
||||
}
|
||||
getData().getJails().put(jailName.toLowerCase(Locale.ENGLISH), loc);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
try {
|
||||
return getList().size();
|
||||
} catch (Exception ex) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class JailPlayerListener implements Listener
|
||||
{
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerInteract(final PlayerInteractEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (user.getData().isJailed())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
private class JailListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockBreak(final BlockBreakEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerRespawn(final PlayerRespawnEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (!user.getData().isJailed() || user.getData().getJail() == null || user.getData().getJail().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockPlace(final BlockPlaceEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
event.setRespawnLocation(getJail(user.getData().getJail()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ess.getSettings().isDebug())
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockDamage(final BlockDamageEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerTeleport(final PlayerTeleportEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (!user.getData().isJailed() || user.getData().getJail() == null || user.getData().getJail().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailEntityDamageByEntity(final EntityDamageByEntityEvent event) {
|
||||
if (event.getCause() != DamageCause.ENTITY_ATTACK || event.getEntity().getType() != EntityType.PLAYER) {
|
||||
return;
|
||||
}
|
||||
final Entity damager = event.getDamager();
|
||||
if (damager.getType() == EntityType.PLAYER) {
|
||||
final User user = ess.getUser((Player) damager);
|
||||
if (user != null && user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
event.setTo(getJail(user.getData().getJail()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ess.getSettings().isDebug())
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
user.sendMessage(_("jailMessage"));
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailPlayerInteract(final PlayerInteractEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event)
|
||||
{
|
||||
@Cleanup
|
||||
final IUser user = ess.getUser(event.getPlayer());
|
||||
user.acquireReadLock();
|
||||
if (!user.getData().isJailed() || user.getData().getJail() == null || user.getData().getJail().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJailPlayerRespawn(final PlayerRespawnEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!user.isJailed() || user.getJail() == null || user.getJail().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sendToJail(user, user.getData().getJail());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ess.getSettings().isDebug())
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.log(Level.INFO, _("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
user.sendMessage(_("jailMessage"));
|
||||
}
|
||||
}
|
||||
try {
|
||||
event.setRespawnLocation(getJail(user.getJail()));
|
||||
} catch (Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
} else {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onJailPlayerTeleport(final PlayerTeleportEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!user.isJailed() || user.getJail() == null || user.getJail().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
event.setTo(getJail(user.getJail()));
|
||||
} catch (Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
} else {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
user.sendMessage(tl("jailMessage"));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJailPlayerJoin(final PlayerJoinEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
user.checkJailTimeout(currentTime);
|
||||
if (!user.isJailed() || user.getJail() == null || user.getJail().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sendToJail(user, user.getJail());
|
||||
} catch (Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
} else {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
}
|
||||
user.sendMessage(tl("jailMessage"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.Trade.OverflowType;
|
||||
import com.earth2me.essentials.commands.NoChargeException;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class Kit {
|
||||
final IEssentials ess;
|
||||
final String kitName;
|
||||
final Map<String, Object> kit;
|
||||
final Trade charge;
|
||||
|
||||
public Kit(final String kitName, final IEssentials ess) throws Exception {
|
||||
this.kitName = kitName;
|
||||
this.ess = ess;
|
||||
this.kit = ess.getKits().getKit(kitName);
|
||||
this.charge = new Trade("kit-" + kitName, new Trade("kit-kit", ess), ess);
|
||||
|
||||
if (kit == null) {
|
||||
throw new Exception(tl("kitNotFound"));
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return kitName;
|
||||
}
|
||||
|
||||
public void checkPerms(final User user) throws Exception {
|
||||
if (!user.isAuthorized("essentials.kits." + kitName)) {
|
||||
throw new Exception(tl("noKitPermission", "essentials.kits." + kitName));
|
||||
}
|
||||
}
|
||||
|
||||
public void checkDelay(final User user) throws Exception {
|
||||
long nextUse = getNextUse(user);
|
||||
|
||||
if (nextUse == 0L) {
|
||||
return;
|
||||
} else if (nextUse < 0L) {
|
||||
user.sendMessage(tl("kitOnce"));
|
||||
throw new NoChargeException();
|
||||
} else {
|
||||
user.sendMessage(tl("kitTimed", DateUtil.formatDateDiff(nextUse)));
|
||||
throw new NoChargeException();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAffordable(final User user) throws Exception {
|
||||
charge.isAffordableFor(user);
|
||||
}
|
||||
|
||||
public void setTime(final User user) throws Exception {
|
||||
final Calendar time = new GregorianCalendar();
|
||||
user.setKitTimestamp(kitName, time.getTimeInMillis());
|
||||
}
|
||||
|
||||
public void chargeUser(final User user) throws Exception {
|
||||
charge.charge(user);
|
||||
}
|
||||
|
||||
public long getNextUse(final User user) throws Exception {
|
||||
if (user.isAuthorized("essentials.kit.exemptdelay")) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
final Calendar time = new GregorianCalendar();
|
||||
|
||||
double delay = 0;
|
||||
try {
|
||||
// Make sure delay is valid
|
||||
delay = kit.containsKey("delay") ? ((Number) kit.get("delay")).doubleValue() : 0.0d;
|
||||
} catch (Exception e) {
|
||||
throw new Exception(tl("kitError2"));
|
||||
}
|
||||
|
||||
// When was the last kit used?
|
||||
final long lastTime = user.getKitTimestamp(kitName);
|
||||
|
||||
// When can be use the kit again?
|
||||
final Calendar delayTime = new GregorianCalendar();
|
||||
delayTime.setTimeInMillis(lastTime);
|
||||
delayTime.add(Calendar.SECOND, (int) delay);
|
||||
delayTime.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
|
||||
|
||||
if (lastTime == 0L || lastTime > time.getTimeInMillis()) {
|
||||
// If we have no record of kit use, or its corrupted, give them benefit of the doubt.
|
||||
return 0L;
|
||||
} else if (delay < 0d) {
|
||||
// If the kit has a negative kit time, it can only be used once.
|
||||
return -1;
|
||||
} else if (delayTime.before(time)) {
|
||||
// If the kit was used in the past, but outside the delay time, it can be used.
|
||||
return 0L;
|
||||
} else {
|
||||
// If the kit has been used recently, return the next time it can be used.
|
||||
return delayTime.getTimeInMillis();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<String> getItems(final User user) throws Exception {
|
||||
return getItems();
|
||||
}
|
||||
|
||||
public List<String> getItems() throws Exception {
|
||||
if (kit == null) {
|
||||
throw new Exception(tl("kitNotFound"));
|
||||
}
|
||||
try {
|
||||
final List<String> itemList = new ArrayList<String>();
|
||||
final Object kitItems = kit.get("items");
|
||||
if (kitItems instanceof List) {
|
||||
for (Object item : (List) kitItems) {
|
||||
if (item instanceof String) {
|
||||
itemList.add(item.toString());
|
||||
continue;
|
||||
}
|
||||
throw new Exception("Invalid kit item: " + item.toString());
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
throw new Exception("Invalid item list");
|
||||
} catch (Exception e) {
|
||||
ess.getLogger().log(Level.WARNING, "Error parsing kit " + kitName + ": " + e.getMessage());
|
||||
throw new Exception(tl("kitError2"), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void expandItems(final User user) throws Exception {
|
||||
expandItems(user, getItems(user));
|
||||
}
|
||||
|
||||
public void expandItems(final User user, final List<String> items) throws Exception {
|
||||
try {
|
||||
IText input = new SimpleTextInput(items);
|
||||
IText output = new KeywordReplacer(input, user.getSource(), ess, true, true);
|
||||
|
||||
boolean spew = false;
|
||||
final boolean allowUnsafe = ess.getSettings().allowUnsafeEnchantments();
|
||||
for (String kitItem : output.getLines()) {
|
||||
if (kitItem.startsWith(ess.getSettings().getCurrencySymbol())) {
|
||||
BigDecimal value = new BigDecimal(kitItem.substring(ess.getSettings().getCurrencySymbol().length()).trim());
|
||||
Trade t = new Trade(value, ess);
|
||||
t.pay(user, OverflowType.DROP);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kitItem.startsWith("/")) {
|
||||
String command = kitItem.substring(1);
|
||||
String name = user.getName();
|
||||
command = command.replace("{player}", name);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||
continue;
|
||||
}
|
||||
|
||||
final String[] parts = kitItem.split(" +");
|
||||
final ItemStack parseStack = ess.getItemDb().get(parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);
|
||||
|
||||
if (parseStack.getType() == Material.AIR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final MetaItemStack metaStack = new MetaItemStack(parseStack);
|
||||
|
||||
if (parts.length > 2) {
|
||||
// We pass a null sender here because kits should not do perm checks
|
||||
metaStack.parseStringMeta(null, allowUnsafe, parts, 2, ess);
|
||||
}
|
||||
|
||||
final Map<Integer, ItemStack> overfilled;
|
||||
final boolean allowOversizedStacks = user.isAuthorized("essentials.oversizedstacks");
|
||||
if (allowOversizedStacks) {
|
||||
overfilled = InventoryWorkaround.addOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), metaStack.getItemStack());
|
||||
} else {
|
||||
overfilled = InventoryWorkaround.addItems(user.getBase().getInventory(), metaStack.getItemStack());
|
||||
}
|
||||
for (ItemStack itemStack : overfilled.values()) {
|
||||
int spillAmount = itemStack.getAmount();
|
||||
if (!allowOversizedStacks) {
|
||||
itemStack.setAmount(spillAmount < itemStack.getMaxStackSize() ? spillAmount : itemStack.getMaxStackSize());
|
||||
}
|
||||
while (spillAmount > 0) {
|
||||
user.getWorld().dropItemNaturally(user.getLocation(), itemStack);
|
||||
spillAmount -= itemStack.getAmount();
|
||||
}
|
||||
spew = true;
|
||||
}
|
||||
}
|
||||
user.getBase().updateInventory();
|
||||
if (spew) {
|
||||
user.sendMessage(tl("kitInvFull"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
user.getBase().updateInventory();
|
||||
ess.getLogger().log(Level.WARNING, e.getMessage());
|
||||
throw new Exception(tl("kitError2"), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,114 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.IKits;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.settings.Kit;
|
||||
import com.earth2me.essentials.storage.AsyncStorageObjectHolder;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.earth2me.essentials.I18n.capitalCase;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Kits extends AsyncStorageObjectHolder<com.earth2me.essentials.settings.Kits> implements IKits
|
||||
{
|
||||
public Kits(final IEssentials ess)
|
||||
{
|
||||
super(ess, com.earth2me.essentials.settings.Kits.class);
|
||||
onReload();
|
||||
}
|
||||
public class Kits implements IConf {
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getDataFolder(), "kits.yml");
|
||||
}
|
||||
private final EssentialsConf config;
|
||||
private ConfigurationSection kits;
|
||||
|
||||
@Override
|
||||
public Kit getKit(String kitName) throws Exception
|
||||
{
|
||||
acquireReadLock();
|
||||
try
|
||||
{
|
||||
if (getData().getKits() == null || kitName == null
|
||||
|| !getData().getKits().containsKey(kitName.toLowerCase(Locale.ENGLISH)))
|
||||
{
|
||||
throw new Exception(_("kitError2"));
|
||||
}
|
||||
final Kit kit = getData().getKits().get(kitName.toLowerCase(Locale.ENGLISH));
|
||||
if (kit == null)
|
||||
{
|
||||
throw new Exception(_("kitError2"));
|
||||
}
|
||||
return kit;
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
public Kits(final IEssentials essentials) {
|
||||
config = new EssentialsConf(new File(essentials.getDataFolder(), "kits.yml"));
|
||||
config.setTemplateName("/kits.yml");
|
||||
|
||||
@Override
|
||||
public void sendKit(IUser user, String kitName) throws Exception
|
||||
{
|
||||
final Kit kit = getKit(kitName);
|
||||
sendKit(user, kit);
|
||||
}
|
||||
reloadConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendKit(IUser user, Kit kit) throws Exception
|
||||
{
|
||||
final List<ItemStack> itemList = kit.getItems();
|
||||
user.giveItems(itemList, true);
|
||||
}
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
config.load();
|
||||
kits = _getKits();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getList() throws Exception
|
||||
{
|
||||
acquireReadLock();
|
||||
try
|
||||
{
|
||||
if (getData().getKits() == null)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return new ArrayList<String>(getData().getKits().keySet());
|
||||
}
|
||||
finally
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
private ConfigurationSection _getKits() {
|
||||
if (config.isConfigurationSection("kits")) {
|
||||
final ConfigurationSection section = config.getConfigurationSection("kits");
|
||||
final ConfigurationSection newSection = new MemoryConfiguration();
|
||||
for (String kitItem : section.getKeys(false)) {
|
||||
if (section.isConfigurationSection(kitItem)) {
|
||||
newSection.set(kitItem.toLowerCase(Locale.ENGLISH), section.getConfigurationSection(kitItem));
|
||||
}
|
||||
}
|
||||
return newSection;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return getData().getKits().isEmpty();
|
||||
}
|
||||
public EssentialsConf getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public ConfigurationSection getKits() {
|
||||
return kits;
|
||||
}
|
||||
|
||||
public Map<String, Object> getKit(String name) {
|
||||
name = name.replace('.', '_').replace('/', '_');
|
||||
if (getKits() != null) {
|
||||
final ConfigurationSection kits = getKits();
|
||||
// For some reason, YAML doesn't sees keys as always lowercase even if they aren't defined like that.
|
||||
// Workaround is to toLowercase when getting from the config, but showing normally elsewhere.
|
||||
// ODDLY ENOUGH when you get the configuration section for ALL kits, it will return the proper
|
||||
// case of each kit. But when you check for each kit's configuration section, it won't return the kit
|
||||
// you just found if you don't toLowercase it.
|
||||
if (kits.isConfigurationSection(name.toLowerCase())) {
|
||||
return kits.getConfigurationSection(name.toLowerCase()).getValues(true);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addKit(String name, List<String> lines, long delay) {
|
||||
// Will overwrite but w/e
|
||||
config.set("kits." + name + ".delay", delay);
|
||||
config.set("kits." + name + ".items", lines);
|
||||
kits = _getKits();
|
||||
config.save();
|
||||
}
|
||||
|
||||
public String listKits(final net.ess3.api.IEssentials ess, final User user) throws Exception {
|
||||
try {
|
||||
final ConfigurationSection kits = config.getConfigurationSection("kits");
|
||||
final StringBuilder list = new StringBuilder();
|
||||
for (String kitItem : kits.getKeys(false)) {
|
||||
if (user == null) {
|
||||
list.append(" ").append(capitalCase(kitItem));
|
||||
} else if (user.isAuthorized("essentials.kits." + kitItem.toLowerCase(Locale.ENGLISH))) {
|
||||
String cost = "";
|
||||
String name = capitalCase(kitItem);
|
||||
BigDecimal costPrice = new Trade("kit-" + kitItem.toLowerCase(Locale.ENGLISH), ess).getCommandCost(user);
|
||||
if (costPrice.signum() > 0) {
|
||||
cost = tl("kitCost", NumberUtil.displayCurrency(costPrice, ess));
|
||||
}
|
||||
|
||||
Kit kit = new Kit(kitItem, ess);
|
||||
double nextUse = kit.getNextUse(user);
|
||||
if (nextUse == -1 && ess.getSettings().isSkippingUsedOneTimeKitsFromKitList()) {
|
||||
continue;
|
||||
} else if (nextUse != 0) {
|
||||
name = tl("kitDelay", name);
|
||||
}
|
||||
|
||||
list.append(" ").append(name).append(cost);
|
||||
}
|
||||
}
|
||||
return list.toString().trim();
|
||||
} catch (Exception ex) {
|
||||
throw new Exception(tl("kitError"), ex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
|
||||
public class LocationTarget implements ITarget {
|
||||
private final Location location;
|
||||
|
||||
LocationTarget(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class ManagedFile {
|
||||
private static final int BUFFERSIZE = 1024 * 8;
|
||||
private final transient File file;
|
||||
|
||||
public ManagedFile(final String filename, final IEssentials ess) {
|
||||
file = new File(ess.getDataFolder(), filename);
|
||||
|
||||
if (file.exists()) {
|
||||
try {
|
||||
if (checkForVersion(file, ess.getDescription().getVersion()) && !file.delete()) {
|
||||
throw new IOException("Could not delete file " + file.toString());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
copyResourceAscii("/" + filename, file);
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, tl("itemsCsvNotLoaded"), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyResourceAscii(final String resourceName, final File file) throws IOException {
|
||||
final InputStreamReader reader = new InputStreamReader(ManagedFile.class.getResourceAsStream(resourceName));
|
||||
try {
|
||||
final MessageDigest digest = getDigest();
|
||||
final DigestOutputStream digestStream = new DigestOutputStream(new FileOutputStream(file), digest);
|
||||
try {
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(digestStream);
|
||||
try {
|
||||
final char[] buffer = new char[BUFFERSIZE];
|
||||
do {
|
||||
final int length = reader.read(buffer);
|
||||
if (length >= 0) {
|
||||
writer.write(buffer, 0, length);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
writer.write("\n");
|
||||
writer.flush();
|
||||
final BigInteger hashInt = new BigInteger(1, digest.digest());
|
||||
digestStream.on(false);
|
||||
digestStream.write('#');
|
||||
digestStream.write(hashInt.toString(16).getBytes());
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
} finally {
|
||||
digestStream.close();
|
||||
}
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkForVersion(final File file, final String version) throws IOException {
|
||||
if (file.length() < 33) {
|
||||
return false;
|
||||
}
|
||||
final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
||||
try {
|
||||
final byte[] buffer = new byte[(int) file.length()];
|
||||
int position = 0;
|
||||
do {
|
||||
final int length = bis.read(buffer, position, Math.min((int) file.length() - position, BUFFERSIZE));
|
||||
if (length < 0) {
|
||||
break;
|
||||
}
|
||||
position += length;
|
||||
} while (position < file.length());
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
|
||||
if (bais.skip(file.length() - 33) != file.length() - 33) {
|
||||
return false;
|
||||
}
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(bais));
|
||||
try {
|
||||
String hash = reader.readLine();
|
||||
if (hash != null && hash.matches("#[a-f0-9]{32}")) {
|
||||
hash = hash.substring(1);
|
||||
bais.reset();
|
||||
final String versionline = reader.readLine();
|
||||
if (versionline != null && versionline.matches("#version: .+")) {
|
||||
final String versioncheck = versionline.substring(10);
|
||||
if (!versioncheck.equalsIgnoreCase(version)) {
|
||||
bais.reset();
|
||||
final MessageDigest digest = getDigest();
|
||||
final DigestInputStream digestStream = new DigestInputStream(bais, digest);
|
||||
try {
|
||||
final byte[] bytes = new byte[(int) file.length() - 33];
|
||||
digestStream.read(bytes);
|
||||
final BigInteger correct = new BigInteger(hash, 16);
|
||||
final BigInteger test = new BigInteger(1, digest.digest());
|
||||
if (correct.equals(test)) {
|
||||
return true;
|
||||
} else {
|
||||
Bukkit.getLogger().warning("File " + file.toString() + " has been modified by user and file version differs, please update the file manually.");
|
||||
}
|
||||
} finally {
|
||||
digestStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
} finally {
|
||||
bis.close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static MessageDigest getDigest() throws IOException {
|
||||
try {
|
||||
return MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getLines() {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
try {
|
||||
final List<String> lines = new ArrayList<String>();
|
||||
do {
|
||||
final String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
} else {
|
||||
lines.add(line);
|
||||
}
|
||||
} while (true);
|
||||
return lines;
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,581 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.textreader.BookInput;
|
||||
import com.earth2me.essentials.textreader.BookPager;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.google.common.base.Joiner;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Banner;
|
||||
import org.bukkit.block.banner.PatternType;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.*;
|
||||
import org.bukkit.potion.Potion;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class MetaItemStack {
|
||||
private static final Map<String, DyeColor> colorMap = new HashMap<>();
|
||||
private static final Map<String, FireworkEffect.Type> fireworkShape = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (DyeColor color : DyeColor.values()) {
|
||||
colorMap.put(color.name(), color);
|
||||
}
|
||||
for (FireworkEffect.Type type : FireworkEffect.Type.values()) {
|
||||
fireworkShape.put(type.name(), type);
|
||||
}
|
||||
}
|
||||
|
||||
private final transient Pattern splitPattern = Pattern.compile("[:+',;.]");
|
||||
private ItemStack stack;
|
||||
private FireworkEffect.Builder builder = FireworkEffect.builder();
|
||||
private PotionEffectType pEffectType;
|
||||
private PotionEffect pEffect;
|
||||
private boolean validFirework = false;
|
||||
private boolean validPotionEffect = false;
|
||||
private boolean validPotionDuration = false;
|
||||
private boolean validPotionPower = false;
|
||||
private boolean isSplashPotion = false;
|
||||
private boolean completePotion = false;
|
||||
private int power = 1;
|
||||
private int duration = 120;
|
||||
|
||||
public MetaItemStack(final ItemStack stack) {
|
||||
this.stack = stack.clone();
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public boolean isValidFirework() {
|
||||
return validFirework;
|
||||
}
|
||||
|
||||
public boolean isValidPotion() {
|
||||
return validPotionEffect && validPotionDuration && validPotionPower;
|
||||
}
|
||||
|
||||
public FireworkEffect.Builder getFireworkBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public PotionEffect getPotionEffect() {
|
||||
return pEffect;
|
||||
}
|
||||
|
||||
public boolean completePotion() {
|
||||
return completePotion;
|
||||
}
|
||||
|
||||
private void resetPotionMeta() {
|
||||
pEffect = null;
|
||||
pEffectType = null;
|
||||
validPotionEffect = false;
|
||||
validPotionDuration = false;
|
||||
validPotionPower = false;
|
||||
isSplashPotion = false;
|
||||
completePotion = true;
|
||||
}
|
||||
|
||||
public boolean canSpawn(final IEssentials ess) {
|
||||
try {
|
||||
ess.getServer().getUnsafe().modifyItemStack(stack.clone(), "{}");
|
||||
return true;
|
||||
} catch (NullPointerException npe) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
|
||||
}
|
||||
return false;
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
return true;
|
||||
} catch (Throwable throwable) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Itemstack is invalid", throwable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void parseStringMeta(final CommandSource sender, final boolean allowUnsafe, String[] string, int fromArg, final IEssentials ess) throws Exception {
|
||||
if (string[fromArg].startsWith("{") && hasMetaPermission(sender, "vanilla", false, true, ess)) {
|
||||
try {
|
||||
stack = ess.getServer().getUnsafe().modifyItemStack(stack, Joiner.on(' ').join(Arrays.asList(string).subList(fromArg, string.length)));
|
||||
} catch (NullPointerException npe) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Itemstack is invalid", npe);
|
||||
}
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
throw new Exception(tl("noMetaJson"), nsme);
|
||||
} catch (Throwable throwable) {
|
||||
throw new Exception(throwable.getMessage(), throwable);
|
||||
}
|
||||
} else {
|
||||
for (int i = fromArg; i < string.length; i++) {
|
||||
addStringMeta(sender, allowUnsafe, string[i], ess);
|
||||
}
|
||||
if (validFirework) {
|
||||
if (!hasMetaPermission(sender, "firework", true, true, ess)) {
|
||||
throw new Exception(tl("noMetaFirework"));
|
||||
}
|
||||
FireworkEffect effect = builder.build();
|
||||
FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
|
||||
fmeta.addEffect(effect);
|
||||
if (fmeta.getEffects().size() > 1 && !hasMetaPermission(sender, "firework-multiple", true, true, ess)) {
|
||||
throw new Exception(tl("multipleCharges"));
|
||||
}
|
||||
stack.setItemMeta(fmeta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addStringMeta(final CommandSource sender, final boolean allowUnsafe, final String string, final IEssentials ess) throws Exception {
|
||||
final String[] split = splitPattern.split(string, 2);
|
||||
if (split.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
|
||||
|
||||
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
|
||||
final String displayName = FormatUtil.replaceFormat(split[1].replace('_', ' '));
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
meta.setDisplayName(displayName);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && (split[0].equalsIgnoreCase("lore") || split[0].equalsIgnoreCase("desc")) && hasMetaPermission(sender, "lore", false, true, ess)) {
|
||||
final List<String> lore = new ArrayList<String>();
|
||||
for (String line : split[1].split("\\|")) {
|
||||
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ')));
|
||||
}
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
meta.setLore(lore);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split[0].equalsIgnoreCase("unbreakable") && hasMetaPermission(sender, "unbreakable", false, true, ess)) {
|
||||
boolean value = split.length > 1 ? Boolean.valueOf(split[1]) : true;
|
||||
setUnbreakable(stack, value);
|
||||
} else if (split.length > 1 && (split[0].equalsIgnoreCase("player") || split[0].equalsIgnoreCase("owner")) && hasMetaPermission(sender, "head", false, true, ess)) {
|
||||
if (MaterialUtil.isPlayerHead(stack.getType(), stack.getDurability())) {
|
||||
final String owner = split[1];
|
||||
final SkullMeta meta = (SkullMeta) stack.getItemMeta();
|
||||
meta.setOwningPlayer(ess.getServer().getOfflinePlayer(owner));
|
||||
stack.setItemMeta(meta);
|
||||
} else {
|
||||
throw new Exception(tl("onlyPlayerSkulls"));
|
||||
}
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("book") && stack.getType() == WRITTEN_BOOK && (hasMetaPermission(sender, "book", true, true, ess) || hasMetaPermission(sender, "chapter-" + split[1].toLowerCase(Locale.ENGLISH), true, true, ess))) {
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
final IText input = new BookInput("book", true, ess);
|
||||
final BookPager pager = new BookPager(input);
|
||||
|
||||
List<String> pages = pager.getPages(split[1]);
|
||||
meta.setPages(pages);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("author") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "author", false, true, ess)) {
|
||||
final String author = FormatUtil.replaceFormat(split[1]);
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
meta.setAuthor(author);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
|
||||
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
meta.setTitle(title);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("power") && (MaterialUtil.isFirework(stack.getType()))&& hasMetaPermission(sender, "firework-power", false, true, ess)) {
|
||||
final int power = NumberUtil.isInt(split[1]) ? Integer.parseInt(split[1]) : 0;
|
||||
final FireworkMeta meta = (FireworkMeta) stack.getItemMeta();
|
||||
meta.setPower(power > 3 ? 4 : power);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("itemflags") && hasMetaPermission(sender, "itemflags", false, true, ess)) {
|
||||
addItemFlags(string);
|
||||
} else if (MaterialUtil.isFirework(stack.getType())) {//WARNING - Meta for fireworks will be ignored after this point.
|
||||
addFireworkMeta(sender, false, string, ess);
|
||||
} else if (MaterialUtil.isPotion(stack.getType())) { //WARNING - Meta for potions will be ignored after this point.
|
||||
addPotionMeta(sender, false, string, ess);
|
||||
} else if (MaterialUtil.isBanner(stack.getType())) {
|
||||
//WARNING - Meta for banners will be ignored after this point.
|
||||
addBannerMeta(sender, false, string, ess);
|
||||
} else if (split.length > 1 && (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour")) && MaterialUtil.isLeatherArmor(stack.getType())) {
|
||||
final String[] color = split[1].split("(\\||,)");
|
||||
if (color.length == 1 && (NumberUtil.isInt(color[0]) || color[0].startsWith("#"))) {
|
||||
// Either integer or hexadecimal
|
||||
final LeatherArmorMeta meta = (LeatherArmorMeta) stack.getItemMeta();
|
||||
String input = color[0];
|
||||
if (input.startsWith("#")) { // Hex
|
||||
meta.setColor(Color.fromRGB(
|
||||
Integer.valueOf(input.substring(1, 3), 16),
|
||||
Integer.valueOf(input.substring(3, 5), 16),
|
||||
Integer.valueOf(input.substring(5, 7), 16)));
|
||||
} else { // Int
|
||||
meta.setColor(Color.fromRGB(Integer.parseInt(input)));
|
||||
}
|
||||
stack.setItemMeta(meta);
|
||||
} else if (color.length == 3) { // r,g,b
|
||||
final int red = NumberUtil.isInt(color[0]) ? Integer.parseInt(color[0]) : 0;
|
||||
final int green = NumberUtil.isInt(color[1]) ? Integer.parseInt(color[1]) : 0;
|
||||
final int blue = NumberUtil.isInt(color[2]) ? Integer.parseInt(color[2]) : 0;
|
||||
final LeatherArmorMeta meta = (LeatherArmorMeta) stack.getItemMeta();
|
||||
meta.setColor(Color.fromRGB(red, green, blue));
|
||||
stack.setItemMeta(meta);
|
||||
} else {
|
||||
throw new Exception(tl("leatherSyntax"));
|
||||
}
|
||||
} else {
|
||||
parseEnchantmentStrings(sender, allowUnsafe, split, ess);
|
||||
}
|
||||
}
|
||||
|
||||
public void addItemFlags(final String string) throws Exception {
|
||||
String[] separate = splitPattern.split(string, 2);
|
||||
if (separate.length != 2) {
|
||||
throw new Exception(tl("invalidItemFlagMeta", string));
|
||||
}
|
||||
|
||||
String[] split = separate[1].split(",");
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
|
||||
for (String s : split) {
|
||||
for (ItemFlag flag : ItemFlag.values()) {
|
||||
if (s.equalsIgnoreCase(flag.name())) {
|
||||
meta.addItemFlags(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (meta.getItemFlags().isEmpty()) {
|
||||
throw new Exception(tl("invalidItemFlagMeta", string));
|
||||
}
|
||||
|
||||
stack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
public void addFireworkMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
|
||||
if (MaterialUtil.isFirework(stack.getType())) {
|
||||
final String[] split = splitPattern.split(string, 2);
|
||||
if (split.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour") || (allowShortName && split[0].equalsIgnoreCase("c"))) {
|
||||
if (validFirework) {
|
||||
if (!hasMetaPermission(sender, "firework", true, true, ess)) {
|
||||
throw new Exception(tl("noMetaFirework"));
|
||||
}
|
||||
FireworkEffect effect = builder.build();
|
||||
FireworkMeta fmeta = (FireworkMeta) stack.getItemMeta();
|
||||
fmeta.addEffect(effect);
|
||||
if (fmeta.getEffects().size() > 1 && !hasMetaPermission(sender, "firework-multiple", true, true, ess)) {
|
||||
throw new Exception(tl("multipleCharges"));
|
||||
}
|
||||
stack.setItemMeta(fmeta);
|
||||
builder = FireworkEffect.builder();
|
||||
}
|
||||
|
||||
List<Color> primaryColors = new ArrayList<Color>();
|
||||
String[] colors = split[1].split(",");
|
||||
for (String color : colors) {
|
||||
if (colorMap.containsKey(color.toUpperCase())) {
|
||||
validFirework = true;
|
||||
primaryColors.add(colorMap.get(color.toUpperCase()).getFireworkColor());
|
||||
} else {
|
||||
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
|
||||
}
|
||||
}
|
||||
builder.withColor(primaryColors);
|
||||
} else if (split[0].equalsIgnoreCase("shape") || split[0].equalsIgnoreCase("type") || (allowShortName && (split[0].equalsIgnoreCase("s") || split[0].equalsIgnoreCase("t")))) {
|
||||
FireworkEffect.Type finalEffect = null;
|
||||
split[1] = (split[1].equalsIgnoreCase("large") ? "BALL_LARGE" : split[1]);
|
||||
if (fireworkShape.containsKey(split[1].toUpperCase())) {
|
||||
finalEffect = fireworkShape.get(split[1].toUpperCase());
|
||||
} else {
|
||||
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
|
||||
}
|
||||
if (finalEffect != null) {
|
||||
builder.with(finalEffect);
|
||||
}
|
||||
} else if (split[0].equalsIgnoreCase("fade") || (allowShortName && split[0].equalsIgnoreCase("f"))) {
|
||||
List<Color> fadeColors = new ArrayList<Color>();
|
||||
String[] colors = split[1].split(",");
|
||||
for (String color : colors) {
|
||||
if (colorMap.containsKey(color.toUpperCase())) {
|
||||
fadeColors.add(colorMap.get(color.toUpperCase()).getFireworkColor());
|
||||
} else {
|
||||
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
|
||||
}
|
||||
}
|
||||
if (!fadeColors.isEmpty()) {
|
||||
builder.withFade(fadeColors);
|
||||
}
|
||||
} else if (split[0].equalsIgnoreCase("effect") || (allowShortName && split[0].equalsIgnoreCase("e"))) {
|
||||
String[] effects = split[1].split(",");
|
||||
for (String effect : effects) {
|
||||
if (effect.equalsIgnoreCase("twinkle")) {
|
||||
builder.flicker(true);
|
||||
} else if (effect.equalsIgnoreCase("trail")) {
|
||||
builder.trail(true);
|
||||
} else {
|
||||
throw new Exception(tl("invalidFireworkFormat", split[1], split[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addPotionMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
|
||||
if (MaterialUtil.isPotion(stack.getType())) {
|
||||
final String[] split = splitPattern.split(string, 2);
|
||||
|
||||
if (split.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (split[0].equalsIgnoreCase("effect") || (allowShortName && split[0].equalsIgnoreCase("e"))) {
|
||||
pEffectType = Potions.getByName(split[1]);
|
||||
if (pEffectType != null && pEffectType.getName() != null) {
|
||||
if (hasMetaPermission(sender, "potions." + pEffectType.getName().toLowerCase(Locale.ENGLISH), true, false, ess)) {
|
||||
validPotionEffect = true;
|
||||
} else {
|
||||
throw new Exception(tl("noPotionEffectPerm", pEffectType.getName().toLowerCase(Locale.ENGLISH)));
|
||||
}
|
||||
} else {
|
||||
throw new Exception(tl("invalidPotionMeta", split[1]));
|
||||
}
|
||||
} else if (split[0].equalsIgnoreCase("power") || (allowShortName && split[0].equalsIgnoreCase("p"))) {
|
||||
if (NumberUtil.isInt(split[1])) {
|
||||
validPotionPower = true;
|
||||
power = Integer.parseInt(split[1]);
|
||||
if (power > 0 && power < 4) {
|
||||
power -= 1;
|
||||
}
|
||||
} else {
|
||||
throw new Exception(tl("invalidPotionMeta", split[1]));
|
||||
}
|
||||
} else if (split[0].equalsIgnoreCase("duration") || (allowShortName && split[0].equalsIgnoreCase("d"))) {
|
||||
if (NumberUtil.isInt(split[1])) {
|
||||
validPotionDuration = true;
|
||||
duration = Integer.parseInt(split[1]) * 20; //Duration is in ticks by default, converted to seconds
|
||||
} else {
|
||||
throw new Exception(tl("invalidPotionMeta", split[1]));
|
||||
}
|
||||
} else if (split[0].equalsIgnoreCase("splash") || (allowShortName && split[0].equalsIgnoreCase("s"))) {
|
||||
isSplashPotion = Boolean.valueOf(split[1]);
|
||||
}
|
||||
|
||||
if (isValidPotion()) {
|
||||
PotionMeta pmeta = (PotionMeta) stack.getItemMeta();
|
||||
pEffect = pEffectType.createEffect(duration, power);
|
||||
if (pmeta.getCustomEffects().size() > 1 && !hasMetaPermission(sender, "potions.multiple", true, false, ess)) {
|
||||
throw new Exception(tl("multiplePotionEffects"));
|
||||
}
|
||||
pmeta.addCustomEffect(pEffect, true);
|
||||
stack.setItemMeta(pmeta);
|
||||
if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_9_R1)) {
|
||||
if (isSplashPotion && stack.getType() != Material.SPLASH_POTION) {
|
||||
stack.setType(Material.SPLASH_POTION);
|
||||
} else if (!isSplashPotion && stack.getType() != Material.POTION) {
|
||||
stack.setType(Material.POTION);
|
||||
}
|
||||
} else {
|
||||
Potion potion = Potion.fromItemStack(stack);
|
||||
potion.setSplash(isSplashPotion);
|
||||
potion.apply(stack);
|
||||
}
|
||||
resetPotionMeta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseEnchantmentStrings(final CommandSource sender, final boolean allowUnsafe, final String[] split, final IEssentials ess) throws Exception {
|
||||
final Enchantment enchantment = Enchantments.getByName(split[0]);
|
||||
if (enchantment == null || !hasMetaPermission(sender, "enchantments." + enchantment.getName().toLowerCase(Locale.ENGLISH), false, false, ess)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int level = -1;
|
||||
if (split.length > 1) {
|
||||
try {
|
||||
level = Integer.parseInt(split[1]);
|
||||
} catch (NumberFormatException ex) {
|
||||
level = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (level < 0 || (!allowUnsafe && level > enchantment.getMaxLevel())) {
|
||||
level = enchantment.getMaxLevel();
|
||||
}
|
||||
addEnchantment(sender, allowUnsafe, enchantment, level);
|
||||
}
|
||||
|
||||
public void addEnchantment(final CommandSource sender, final boolean allowUnsafe, final Enchantment enchantment, final int level) throws Exception {
|
||||
if (enchantment == null) {
|
||||
throw new Exception(tl("enchantmentNotFound"));
|
||||
}
|
||||
try {
|
||||
if (stack.getType().equals(Material.ENCHANTED_BOOK)) {
|
||||
EnchantmentStorageMeta meta = (EnchantmentStorageMeta) stack.getItemMeta();
|
||||
if (level == 0) {
|
||||
meta.removeStoredEnchant(enchantment);
|
||||
} else {
|
||||
meta.addStoredEnchant(enchantment, level, allowUnsafe);
|
||||
}
|
||||
stack.setItemMeta(meta);
|
||||
} else // all other material types besides ENCHANTED_BOOK
|
||||
{
|
||||
if (level == 0) {
|
||||
stack.removeEnchantment(enchantment);
|
||||
} else {
|
||||
if (allowUnsafe) {
|
||||
stack.addUnsafeEnchantment(enchantment, level);
|
||||
} else {
|
||||
stack.addEnchantment(enchantment, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Enchantment " + enchantment.getName() + ": " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Enchantment getEnchantment(final User user, final String name) throws Exception {
|
||||
final Enchantment enchantment = Enchantments.getByName(name);
|
||||
if (enchantment == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String enchantmentName = enchantment.getName().toLowerCase(Locale.ENGLISH);
|
||||
|
||||
if (!hasMetaPermission(user, "enchantments." + enchantmentName, true, false)) {
|
||||
throw new Exception(tl("enchantmentPerm", enchantmentName));
|
||||
}
|
||||
return enchantment;
|
||||
}
|
||||
|
||||
public void addBannerMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception {
|
||||
if (MaterialUtil.isBanner(stack.getType()) && !stack.getType().toString().equals("SHIELD") && string != null) {
|
||||
final String[] split = splitPattern.split(string, 2);
|
||||
|
||||
if (split.length < 2) {
|
||||
throw new Exception(tl("invalidBanner", split[1]));
|
||||
}
|
||||
|
||||
PatternType patternType = null;
|
||||
try {
|
||||
patternType = PatternType.valueOf(split[0]);
|
||||
} catch (Exception ignored ) {}
|
||||
|
||||
final BannerMeta meta = (BannerMeta) stack.getItemMeta();
|
||||
if (split[0].equalsIgnoreCase("basecolor")) {
|
||||
Color color = Color.fromRGB(Integer.valueOf(split[1]));
|
||||
meta.setBaseColor(DyeColor.getByColor(color));
|
||||
} else if (patternType != null) {
|
||||
PatternType type = PatternType.valueOf(split[0]);
|
||||
DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.valueOf(split[1])));
|
||||
org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
|
||||
meta.addPattern(pattern);
|
||||
}
|
||||
|
||||
stack.setItemMeta(meta);
|
||||
} else if (stack.getType().toString().equals("SHIELD") && string != null) {
|
||||
final String[] split = splitPattern.split(string, 2);
|
||||
|
||||
if (split.length < 2) {
|
||||
throw new Exception(tl("invalidBanner", split[1]));
|
||||
}
|
||||
|
||||
PatternType patternType = null;
|
||||
try {
|
||||
patternType = PatternType.valueOf(split[0]);
|
||||
} catch (Exception ignored ) {}
|
||||
|
||||
// Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795
|
||||
BlockStateMeta meta = (BlockStateMeta) stack.getItemMeta();
|
||||
Banner banner = (Banner) meta.getBlockState();
|
||||
if (split[0].equalsIgnoreCase("basecolor")) {
|
||||
Color color = Color.fromRGB(Integer.valueOf(split[1]));
|
||||
banner.setBaseColor(DyeColor.getByColor(color));
|
||||
} else if (patternType != null) {
|
||||
PatternType type = PatternType.valueOf(split[0]);
|
||||
DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.valueOf(split[1])));
|
||||
org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type);
|
||||
banner.addPattern(pattern);
|
||||
}
|
||||
banner.update();
|
||||
meta.setBlockState(banner);
|
||||
stack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasMetaPermission(final CommandSource sender, final String metaPerm, final boolean graceful, final boolean includeBase, final IEssentials ess) throws Exception {
|
||||
final User user = sender != null && sender.isPlayer() ? ess.getUser(sender.getPlayer()) : null;
|
||||
return hasMetaPermission(user, metaPerm, graceful, includeBase);
|
||||
}
|
||||
|
||||
private boolean hasMetaPermission(final User user, final String metaPerm, final boolean graceful, final boolean includeBase) throws Exception {
|
||||
final String permBase = includeBase ? "essentials.itemspawn.meta-" : "essentials.";
|
||||
if (user == null || user.isAuthorized(permBase + metaPerm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (graceful) {
|
||||
return false;
|
||||
} else {
|
||||
throw new Exception(tl("noMetaPerm", metaPerm));
|
||||
}
|
||||
}
|
||||
|
||||
private static int bukkitUnbreakableSupport = -1;
|
||||
private static Method spigotMethod;
|
||||
private static Method setUnbreakableMethod;
|
||||
|
||||
private void setUnbreakable(ItemStack is, boolean unbreakable) {
|
||||
ItemMeta meta = is.getItemMeta();
|
||||
try {
|
||||
if (bukkitUnbreakableSupport == -1) {
|
||||
try {
|
||||
ItemMeta.class.getDeclaredMethod("setUnbreakable", boolean.class);
|
||||
bukkitUnbreakableSupport = 1;
|
||||
} catch (NoSuchMethodException | SecurityException ex) {
|
||||
bukkitUnbreakableSupport = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bukkitUnbreakableSupport == 1) {
|
||||
meta.setUnbreakable(unbreakable);
|
||||
} else {
|
||||
if (spigotMethod == null) {
|
||||
spigotMethod = meta.getClass().getDeclaredMethod("spigot");
|
||||
spigotMethod.setAccessible(true);
|
||||
}
|
||||
Object itemStackSpigot = spigotMethod.invoke(meta);
|
||||
if (setUnbreakableMethod == null) {
|
||||
setUnbreakableMethod = itemStackSpigot.getClass().getDeclaredMethod("setUnbreakable", Boolean.TYPE);
|
||||
setUnbreakableMethod.setAccessible(true);
|
||||
}
|
||||
setUnbreakableMethod.invoke(itemStackSpigot, unbreakable);
|
||||
}
|
||||
is.setItemMeta(meta);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +1,173 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.CreatureType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public enum Mob
|
||||
{
|
||||
CHICKEN("Chicken", Enemies.FRIENDLY, CreatureType.CHICKEN),
|
||||
COW("Cow", Enemies.FRIENDLY, CreatureType.COW),
|
||||
CREEPER("Creeper", Enemies.ENEMY, CreatureType.CREEPER),
|
||||
GHAST("Ghast", Enemies.ENEMY, CreatureType.GHAST),
|
||||
GIANT("Giant", Enemies.ENEMY, CreatureType.GIANT),
|
||||
PIG("Pig", Enemies.FRIENDLY, CreatureType.PIG),
|
||||
PIGZOMB("PigZombie", Enemies.NEUTRAL, CreatureType.PIG_ZOMBIE),
|
||||
SHEEP("Sheep", Enemies.FRIENDLY, "", CreatureType.SHEEP),
|
||||
SKELETON("Skeleton", Enemies.ENEMY, CreatureType.SKELETON),
|
||||
SLIME("Slime", Enemies.ENEMY, CreatureType.SLIME),
|
||||
SPIDER("Spider", Enemies.ENEMY, CreatureType.SPIDER),
|
||||
SQUID("Squid", Enemies.FRIENDLY, CreatureType.SQUID),
|
||||
ZOMBIE("Zombie", Enemies.ENEMY, CreatureType.ZOMBIE),
|
||||
WOLF("Wolf", Enemies.NEUTRAL, CreatureType.WOLF),
|
||||
CAVESPIDER("CaveSpider", Enemies.ENEMY, CreatureType.CAVE_SPIDER),
|
||||
ENDERMAN("Enderman", Enemies.ENEMY, "", CreatureType.ENDERMAN),
|
||||
SILVERFISH("Silverfish", Enemies.ENEMY, "", CreatureType.SILVERFISH),
|
||||
ENDERDRAGON("EnderDragon", Enemies.ENEMY, CreatureType.ENDER_DRAGON),
|
||||
VILLAGER("Villager", Enemies.FRIENDLY, CreatureType.VILLAGER),
|
||||
BLAZE("Blaze", Enemies.ENEMY, CreatureType.BLAZE),
|
||||
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, CreatureType.MUSHROOM_COW),
|
||||
MAGMACUBE("MagmaCube", Enemies.ENEMY, CreatureType.MAGMA_CUBE),
|
||||
SNOWMAN("Snowman", Enemies.FRIENDLY, "", CreatureType.SNOWMAN);
|
||||
|
||||
public static final Logger logger = Logger.getLogger("Minecraft");
|
||||
// Suffixes can be appended on the end of a mob name to make it plural
|
||||
// Entities without a suffix, will default to 's'
|
||||
public enum Mob {
|
||||
CHICKEN("Chicken", Enemies.FRIENDLY, EntityType.CHICKEN),
|
||||
COW("Cow", Enemies.FRIENDLY, EntityType.COW),
|
||||
CREEPER("Creeper", Enemies.ENEMY, EntityType.CREEPER),
|
||||
GHAST("Ghast", Enemies.ENEMY, EntityType.GHAST),
|
||||
GIANT("Giant", Enemies.ENEMY, EntityType.GIANT),
|
||||
HORSE("Horse", Enemies.FRIENDLY, EntityType.HORSE),
|
||||
PIG("Pig", Enemies.FRIENDLY, EntityType.PIG),
|
||||
PIGZOMB("PigZombie", Enemies.NEUTRAL, EntityType.PIG_ZOMBIE),
|
||||
SHEEP("Sheep", Enemies.FRIENDLY, "", EntityType.SHEEP),
|
||||
SKELETON("Skeleton", Enemies.ENEMY, EntityType.SKELETON),
|
||||
SLIME("Slime", Enemies.ENEMY, EntityType.SLIME),
|
||||
SPIDER("Spider", Enemies.ENEMY, EntityType.SPIDER),
|
||||
SQUID("Squid", Enemies.FRIENDLY, EntityType.SQUID),
|
||||
ZOMBIE("Zombie", Enemies.ENEMY, EntityType.ZOMBIE),
|
||||
WOLF("Wolf", Enemies.NEUTRAL, "", EntityType.WOLF),
|
||||
CAVESPIDER("CaveSpider", Enemies.ENEMY, EntityType.CAVE_SPIDER),
|
||||
ENDERMAN("Enderman", Enemies.ENEMY, "", EntityType.ENDERMAN),
|
||||
SILVERFISH("Silverfish", Enemies.ENEMY, "", EntityType.SILVERFISH),
|
||||
ENDERDRAGON("EnderDragon", Enemies.ENEMY, EntityType.ENDER_DRAGON),
|
||||
VILLAGER("Villager", Enemies.FRIENDLY, EntityType.VILLAGER),
|
||||
BLAZE("Blaze", Enemies.ENEMY, EntityType.BLAZE),
|
||||
MUSHROOMCOW("MushroomCow", Enemies.FRIENDLY, EntityType.MUSHROOM_COW),
|
||||
MAGMACUBE("MagmaCube", Enemies.ENEMY, EntityType.MAGMA_CUBE),
|
||||
SNOWMAN("Snowman", Enemies.FRIENDLY, "", EntityType.SNOWMAN),
|
||||
OCELOT("Ocelot", Enemies.NEUTRAL, EntityType.OCELOT),
|
||||
IRONGOLEM("IronGolem", Enemies.NEUTRAL, EntityType.IRON_GOLEM),
|
||||
WITHER("Wither", Enemies.ENEMY, EntityType.WITHER),
|
||||
BAT("Bat", Enemies.FRIENDLY, EntityType.BAT),
|
||||
WITCH("Witch", Enemies.ENEMY, EntityType.WITCH),
|
||||
BOAT("Boat", Enemies.NEUTRAL, EntityType.BOAT),
|
||||
MINECART("Minecart", Enemies.NEUTRAL, EntityType.MINECART),
|
||||
MINECART_CHEST("ChestMinecart", Enemies.NEUTRAL, EntityType.MINECART_CHEST),
|
||||
MINECART_FURNACE("FurnaceMinecart", Enemies.NEUTRAL, EntityType.MINECART_FURNACE),
|
||||
MINECART_TNT("TNTMinecart", Enemies.NEUTRAL, EntityType.MINECART_TNT),
|
||||
MINECART_HOPPER("HopperMinecart", Enemies.NEUTRAL, EntityType.MINECART_HOPPER),
|
||||
MINECART_MOB_SPAWNER("SpawnerMinecart", Enemies.NEUTRAL, EntityType.MINECART_MOB_SPAWNER),
|
||||
ENDERCRYSTAL("EnderCrystal", Enemies.NEUTRAL, EntityType.ENDER_CRYSTAL),
|
||||
EXPERIENCEORB("ExperienceOrb", Enemies.NEUTRAL, "EXPERIENCE_ORB"),
|
||||
ARMOR_STAND("ArmorStand", Enemies.NEUTRAL, "ARMOR_STAND"),
|
||||
ENDERMITE("Endermite", Enemies.ENEMY, "ENDERMITE"),
|
||||
GUARDIAN("Guardian", Enemies.ENEMY, "GUARDIAN"),
|
||||
ELDER_GUARDIAN("ElderGuardian", Enemies.ENEMY, "ELDER_GUARDIAN"),
|
||||
RABBIT("Rabbit", Enemies.FRIENDLY, "RABBIT"),
|
||||
SHULKER("Shulker", Enemies.ENEMY, "SHULKER"),
|
||||
POLAR_BEAR("PolarBear", Enemies.NEUTRAL, "POLAR_BEAR"),
|
||||
WITHER_SKELETON("WitherSkeleton", Enemies.ENEMY, "WITHER_SKELETON"),
|
||||
STRAY_SKELETON("StraySkeleton", Enemies.ENEMY, "STRAY"),
|
||||
ZOMBIE_VILLAGER("ZombieVillager", Enemies.FRIENDLY, "ZOMBIE_VILLAGER"),
|
||||
SKELETON_HORSE("SkeletonHorse", Enemies.FRIENDLY, "SKELETON_HORSE"),
|
||||
ZOMBIE_HORSE("ZombieHorse", Enemies.FRIENDLY, "ZOMBIE_HORSE"),
|
||||
DONKEY("Donkey", Enemies.FRIENDLY, "DONKEY"),
|
||||
MULE("Mule", Enemies.FRIENDLY, "MULE"),
|
||||
EVOKER("Evoker", Enemies.ENEMY, "EVOKER"),
|
||||
VEX("Vex", Enemies.ENEMY, "VEX"),
|
||||
VINDICATOR("Vindicator", Enemies.ENEMY, "VINDICATOR"),
|
||||
LLAMA("Llama", Enemies.NEUTRAL, "LLAMA"),
|
||||
HUSK("Husk", Enemies.ENEMY, "HUSK"),
|
||||
ILLUSIONER("Illusioner", Enemies.ENEMY, "ILLUSIONER"),
|
||||
PARROT("Parrot", Enemies.NEUTRAL, "PARROT"),
|
||||
TURTLE("Turtle", Enemies.NEUTRAL, "TURTLE"),
|
||||
PHANTOM("Phantom", Enemies.ENEMY, "PHANTOM"),
|
||||
COD("Cod", Enemies.NEUTRAL, "COD"),
|
||||
SALMON("Salmon", Enemies.NEUTRAL, "SALMON"),
|
||||
PUFFERFISH("Pufferfish", Enemies.NEUTRAL, "PUFFERFISH"),
|
||||
TROPICAL_FISH("TropicalFish", Enemies.NEUTRAL, "TROPICAL_FISH"),
|
||||
DROWNED("Drowned", Enemies.ENEMY, "DROWNED"),
|
||||
DOLPHIN("Dolphin", Enemies.NEUTRAL, "DOLPHIN"),
|
||||
;
|
||||
|
||||
private Mob(String n, Enemies en, String s, CreatureType type)
|
||||
{
|
||||
this.suffix = s;
|
||||
this.name = n;
|
||||
this.type = en;
|
||||
this.bukkitType = type;
|
||||
}
|
||||
public static final Logger logger = Logger.getLogger("Essentials");
|
||||
|
||||
private Mob(String n, Enemies en, CreatureType type)
|
||||
{
|
||||
this.name = n;
|
||||
this.type = en;
|
||||
this.bukkitType = type;
|
||||
}
|
||||
public String suffix = "s";
|
||||
final public String name;
|
||||
final public Enemies type;
|
||||
final private CreatureType bukkitType;
|
||||
private static final Map<String, Mob> hashMap = new HashMap<String, Mob>();
|
||||
Mob(String n, Enemies en, String s, EntityType type) {
|
||||
this.suffix = s;
|
||||
this.name = n;
|
||||
this.type = en;
|
||||
this.bukkitType = type;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for (Mob mob : Mob.values())
|
||||
{
|
||||
hashMap.put(mob.name.toLowerCase(Locale.ENGLISH), mob);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getMobList() {
|
||||
return hashMap.keySet();
|
||||
}
|
||||
Mob(String n, Enemies en, EntityType type) {
|
||||
this.name = n;
|
||||
this.type = en;
|
||||
this.bukkitType = type;
|
||||
}
|
||||
|
||||
public LivingEntity spawn(final Player player, final Server server, final Location loc) throws MobException
|
||||
{
|
||||
final LivingEntity entity = player.getWorld().spawn(loc, (Class<? extends LivingEntity>)this.bukkitType.getEntityClass());
|
||||
if (entity == null)
|
||||
{
|
||||
logger.log(Level.WARNING, _("unableToSpawnMob"));
|
||||
throw new MobException();
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
Mob(String n, Enemies en, String typeName) {
|
||||
this.name = n;
|
||||
this.type = en;
|
||||
EntityType entityType;
|
||||
try {
|
||||
entityType = EntityType.valueOf(typeName);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
entityType = null;
|
||||
}
|
||||
bukkitType = entityType;
|
||||
}
|
||||
|
||||
public String suffix = "s";
|
||||
final public String name;
|
||||
final public Enemies type;
|
||||
final private EntityType bukkitType;
|
||||
private static final Map<String, Mob> hashMap = new HashMap<>();
|
||||
private static final Map<EntityType, Mob> bukkitMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Mob mob : Mob.values()) {
|
||||
hashMap.put(mob.name.toLowerCase(Locale.ENGLISH), mob);
|
||||
if (mob.bukkitType != null) {
|
||||
bukkitMap.put(mob.bukkitType, mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getMobList() {
|
||||
return Collections.unmodifiableSet(hashMap.keySet());
|
||||
}
|
||||
|
||||
public Entity spawn(final World world, final Server server, final Location loc) throws MobException {
|
||||
final Entity entity = world.spawn(loc, this.bukkitType.getEntityClass());
|
||||
if (entity == null) {
|
||||
logger.log(Level.WARNING, tl("unableToSpawnMob"));
|
||||
throw new MobException();
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
public enum Enemies
|
||||
{
|
||||
FRIENDLY("friendly"),
|
||||
NEUTRAL("neutral"),
|
||||
ENEMY("enemy");
|
||||
public enum Enemies {
|
||||
FRIENDLY("friendly"),
|
||||
NEUTRAL("neutral"),
|
||||
ENEMY("enemy");
|
||||
|
||||
private Enemies(final String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
final protected String type;
|
||||
}
|
||||
Enemies(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public CreatureType getType()
|
||||
{
|
||||
return bukkitType;
|
||||
}
|
||||
final protected String type;
|
||||
}
|
||||
|
||||
public static Mob fromName(final String name)
|
||||
{
|
||||
return hashMap.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
public EntityType getType() {
|
||||
return bukkitType;
|
||||
}
|
||||
|
||||
public static Mob fromName(final String name) {
|
||||
return hashMap.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
public static Mob fromBukkitType(final EntityType type) {
|
||||
return bukkitMap.get(type);
|
||||
}
|
||||
|
||||
|
||||
public static class MobException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
public static class MobException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.Colorable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public enum MobData {
|
||||
BABY_AGEABLE("baby", Ageable.class, Data.BABY, true),
|
||||
ADULT_AGEABLE("adult", Ageable.class, Data.ADULT, true),
|
||||
BABY_PIG("piglet", EntityType.PIG, Data.BABY, false),
|
||||
BABY_WOLF("puppy", EntityType.WOLF, Data.BABY, false),
|
||||
BABY_CHICKEN("chick", EntityType.CHICKEN, Data.BABY, false),
|
||||
BABY_HORSE("colt", EntityType.HORSE, Data.BABY, false),
|
||||
BABY_OCELOT("kitten", EntityType.OCELOT, Data.BABY, false),
|
||||
BABY_SHEEP("lamb", EntityType.SHEEP, Data.BABY, false),
|
||||
BABY_COW("calf", EntityType.COW.getEntityClass(), Data.BABY, false),
|
||||
BABY_VILLAGER("child", EntityType.VILLAGER, Data.BABY, false),
|
||||
TAMED_TAMEABLE("tamed", Tameable.class, Data.TAMED, true),
|
||||
TAME_TAMEABLE("tame", Tameable.class, Data.TAMED, false),
|
||||
RANDOM_SHEEP("random", EntityType.SHEEP, Data.COLORABLE, true),
|
||||
COLORABLE_SHEEP("", StringUtil.joinList(DyeColor.values()).toLowerCase(Locale.ENGLISH), EntityType.SHEEP, Data.COLORABLE, true),
|
||||
POLKA_HORSE("polka", EntityType.HORSE, Horse.Style.BLACK_DOTS, true),
|
||||
SOOTY_HORSE("sooty", EntityType.HORSE, Horse.Style.BLACK_DOTS, false),
|
||||
BLAZE_HORSE("blaze", EntityType.HORSE, Horse.Style.WHITE, true),
|
||||
SOCKS_HORSE("socks", EntityType.HORSE, Horse.Style.WHITE, false),
|
||||
LEOPARD_HORSE("leopard", EntityType.HORSE, Horse.Style.WHITE_DOTS, true),
|
||||
APPALOOSA_HORSE("appaloosa", EntityType.HORSE, Horse.Style.WHITE_DOTS, false),
|
||||
PAINT_HORSE("paint", EntityType.HORSE, Horse.Style.WHITEFIELD, true),
|
||||
MILKY_HORSE("milky", EntityType.HORSE, Horse.Style.WHITEFIELD, false),
|
||||
SPLOTCHY_HORSE("splotchy", EntityType.HORSE, Horse.Style.WHITEFIELD, false),
|
||||
BLACK_HORSE("black", EntityType.HORSE, Horse.Color.BLACK, true),
|
||||
CHESTNUT_HORSE("chestnut", EntityType.HORSE, Horse.Color.CHESTNUT, true),
|
||||
LIVER_HORSE("liver", EntityType.HORSE, Horse.Color.CHESTNUT, false),
|
||||
CREAMY_HORSE("creamy", EntityType.HORSE, Horse.Color.CREAMY, true),
|
||||
FLAXEN_HORSE("flaxen", EntityType.HORSE, Horse.Color.CREAMY, false),
|
||||
GRAY_HORSE("gray", EntityType.HORSE, Horse.Color.GRAY, true),
|
||||
DAPPLE_HORSE("dapple", EntityType.HORSE, Horse.Color.GRAY, false),
|
||||
BUCKSKIN_HORSE("buckskin", EntityType.HORSE, Horse.Color.DARK_BROWN, true),
|
||||
DARKBROWN_HORSE("darkbrown", EntityType.HORSE, Horse.Color.DARK_BROWN, false),
|
||||
DARK_HORSE("dark", EntityType.HORSE, Horse.Color.DARK_BROWN, false),
|
||||
DBROWN_HORSE("dbrown", EntityType.HORSE, Horse.Color.DARK_BROWN, false),
|
||||
BAY_HORSE("bay", EntityType.HORSE, Horse.Color.BROWN, true),
|
||||
BROWN_HORSE("brown", EntityType.HORSE, Horse.Color.BROWN, false),
|
||||
SADDLE_HORSE("saddle", EntityType.HORSE, Data.HORSESADDLE, true),
|
||||
GOLD_ARMOR_HORSE("goldarmor", EntityType.HORSE, EnumUtil.getMaterial("GOLDEN_HORSE_ARMOR", "GOLD_BARDING"), true),
|
||||
DIAMOND_ARMOR_HORSE("diamondarmor", EntityType.HORSE, EnumUtil.getMaterial("DIAMOND_HORSE_ARMOR", "DIAMOND_BARDING"), true),
|
||||
ARMOR_HORSE("armor", EntityType.HORSE, EnumUtil.getMaterial("IRON_HORSE_ARMOR", "IRON_BARDING"), true),
|
||||
SIAMESE_CAT("siamese", EntityType.OCELOT, Ocelot.Type.SIAMESE_CAT, true),
|
||||
WHITE_CAT("white", EntityType.OCELOT, Ocelot.Type.SIAMESE_CAT, false),
|
||||
RED_CAT("red", EntityType.OCELOT, Ocelot.Type.RED_CAT, true),
|
||||
ORANGE_CAT("orange", EntityType.OCELOT, Ocelot.Type.RED_CAT, false),
|
||||
TABBY_CAT("tabby", EntityType.OCELOT, Ocelot.Type.RED_CAT, false),
|
||||
BLACK_CAT("black", EntityType.OCELOT, Ocelot.Type.BLACK_CAT, true),
|
||||
TUXEDO_CAT("tuxedo", EntityType.OCELOT, Ocelot.Type.BLACK_CAT, false),
|
||||
BABY_ZOMBIE("baby", EntityType.ZOMBIE.getEntityClass(), Data.BABYZOMBIE, true),
|
||||
ADULT_ZOMBIE("adult", EntityType.ZOMBIE.getEntityClass(), Data.ADULTZOMBIE, true),
|
||||
DIAMOND_SWORD_ZOMBIE("diamondsword", EntityType.ZOMBIE.getEntityClass(), Material.DIAMOND_SWORD, true),
|
||||
GOLD_SWORD_ZOMBIE("goldsword", EntityType.ZOMBIE.getEntityClass(), EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD"), true),
|
||||
IRON_SWORD_ZOMBIE("ironsword", EntityType.ZOMBIE.getEntityClass(), Material.IRON_SWORD, true),
|
||||
STONE_SWORD_ZOMBIE("stonesword", EntityType.ZOMBIE.getEntityClass(), Material.STONE_SWORD, false),
|
||||
SWORD_ZOMBIE("sword", EntityType.ZOMBIE.getEntityClass(), Material.STONE_SWORD, true),
|
||||
DIAMOND_SWORD_SKELETON("diamondsword", EntityType.SKELETON, Material.DIAMOND_SWORD, true),
|
||||
GOLD_SWORD_SKELETON("goldsword", EntityType.SKELETON, EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD"), true),
|
||||
IRON_SWORD_SKELETON("ironsword", EntityType.SKELETON, Material.IRON_SWORD, true),
|
||||
STONE_SWORD_SKELETON("stonesword", EntityType.SKELETON, Material.STONE_SWORD, false),
|
||||
SWORD_SKELETON("sword", EntityType.SKELETON, Material.STONE_SWORD, true),
|
||||
BOW_SKELETON("bow", EntityType.SKELETON, Material.BOW, true),
|
||||
POWERED_CREEPER("powered", EntityType.CREEPER, Data.ELECTRIFIED, true),
|
||||
ELECTRIC_CREEPER("electric", EntityType.CREEPER, Data.ELECTRIFIED, false),
|
||||
CHARGED_CREEPER("charged", EntityType.CREEPER, Data.ELECTRIFIED, false),
|
||||
SADDLE_PIG("saddle", EntityType.PIG, Data.PIGSADDLE, true),
|
||||
ANGRY_WOLF("angry", EntityType.WOLF, Data.ANGRY, true),
|
||||
RABID_WOLF("rabid", EntityType.WOLF, Data.ANGRY, false),
|
||||
FARMER_VILLAGER("farmer", EntityType.VILLAGER, Villager.Profession.FARMER, true),
|
||||
LIBRARIAN_VILLAGER("librarian", EntityType.VILLAGER, Villager.Profession.LIBRARIAN, true),
|
||||
PRIEST_VILLAGER("priest", EntityType.VILLAGER, Villager.Profession.PRIEST, true),
|
||||
FATHER_VILLAGER("father", EntityType.VILLAGER, Villager.Profession.PRIEST, false),
|
||||
SMITH_VILLAGER("smith", EntityType.VILLAGER, Villager.Profession.BLACKSMITH, true),
|
||||
BUTCHER_VILLAGER("butcher", EntityType.VILLAGER, Villager.Profession.BUTCHER, true),
|
||||
SIZE_SLIME("", "<1-100>", EntityType.SLIME.getEntityClass(), Data.SIZE, true),
|
||||
NUM_EXPERIENCE_ORB("", "<1-2000000000>", EntityType.EXPERIENCE_ORB, Data.EXP, true),
|
||||
RED_PARROT("red", EntityType.PARROT, Parrot.Variant.RED, true),
|
||||
GREEN_PARROT("green", EntityType.PARROT, Parrot.Variant.GREEN, true),
|
||||
BLUE_PARROT("blue", EntityType.PARROT, Parrot.Variant.BLUE, true),
|
||||
CYAN_PARROT("cyan", EntityType.PARROT, Parrot.Variant.CYAN, true),
|
||||
GRAY_PARROT("gray", EntityType.PARROT, Parrot.Variant.GRAY, true),
|
||||
KOB_TROPICAL_FISH("kob", EntityType.TROPICAL_FISH, TropicalFish.Pattern.KOB, true),
|
||||
SUNSTREAK_TROPICAL_FISH("sunstreak", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SUNSTREAK, true),
|
||||
SNOOPER_TROPICAL_FISH("snooper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SNOOPER, true),
|
||||
DASHER_TROPICAL_FISH("dasher", EntityType.TROPICAL_FISH, TropicalFish.Pattern.DASHER, true),
|
||||
BRINELY_TROPICAL_FISH("brinely", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BRINELY, true),
|
||||
SPOTTY_TROPICAL_FISH("spotty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SPOTTY, true),
|
||||
FLOPPER_TROPICAL_FISH("flopper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.FLOPPER, true),
|
||||
STRIPEY_TROPICAL_FISH("stripey", EntityType.TROPICAL_FISH, TropicalFish.Pattern.STRIPEY, true),
|
||||
GLITTER_TROPICAL_FISH("glitter", EntityType.TROPICAL_FISH, TropicalFish.Pattern.GLITTER, true),
|
||||
BLOCKFISH_TROPICAL_FISH("blockfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BLOCKFISH, true),
|
||||
BETTY_TROPICAL_FISH("betty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BETTY, true),
|
||||
CLAYFISH_TROPICAL_FISH("clayfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.CLAYFISH, true);
|
||||
;
|
||||
|
||||
|
||||
public enum Data {
|
||||
ADULT,
|
||||
BABY,
|
||||
CHEST,
|
||||
ADULTZOMBIE,
|
||||
BABYZOMBIE,
|
||||
HORSESADDLE,
|
||||
PIGSADDLE,
|
||||
ELECTRIFIED,
|
||||
ANGRY,
|
||||
TAMED,
|
||||
COLORABLE,
|
||||
EXP,
|
||||
SIZE
|
||||
}
|
||||
|
||||
public static final Logger logger = Logger.getLogger("Essentials");
|
||||
|
||||
MobData(String n, Object type, Object value, boolean isPublic) {
|
||||
this.nickname = n;
|
||||
this.matched = n;
|
||||
this.helpMessage = n;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
MobData(String n, String h, Object type, Object value, boolean isPublic) {
|
||||
this.nickname = n;
|
||||
this.matched = n;
|
||||
this.helpMessage = h;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
final private String nickname;
|
||||
final private String helpMessage;
|
||||
final private Object type;
|
||||
final private Object value;
|
||||
final private boolean isPublic;
|
||||
private String matched;
|
||||
|
||||
public static LinkedHashMap<String, MobData> getPossibleData(final Entity spawned, boolean publicOnly) {
|
||||
LinkedHashMap<String, MobData> mobList = new LinkedHashMap<String, MobData>();
|
||||
for (MobData data : MobData.values()) {
|
||||
if (data.type instanceof EntityType && spawned.getType().equals(data.type) && ((publicOnly && data.isPublic) || !publicOnly)) {
|
||||
mobList.put(data.nickname.toLowerCase(Locale.ENGLISH), data);
|
||||
} else if (data.type instanceof Class && ((Class) data.type).isAssignableFrom(spawned.getClass()) && ((publicOnly && data.isPublic) || !publicOnly)) {
|
||||
mobList.put(data.nickname.toLowerCase(Locale.ENGLISH), data);
|
||||
}
|
||||
}
|
||||
|
||||
return mobList;
|
||||
}
|
||||
|
||||
public static List<String> getValidHelp(final Entity spawned) {
|
||||
List<String> output = new ArrayList<String>();
|
||||
LinkedHashMap<String, MobData> posData = getPossibleData(spawned, true);
|
||||
|
||||
for (MobData data : posData.values()) {
|
||||
output.add(data.helpMessage);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static MobData fromData(final Entity spawned, final String name) {
|
||||
if (name.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LinkedHashMap<String, MobData> posData = getPossibleData(spawned, false);
|
||||
for (String data : posData.keySet()) {
|
||||
if (name.contains(data)) {
|
||||
return posData.get(data);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMatched() {
|
||||
return this.matched;
|
||||
}
|
||||
|
||||
public void setData(final Entity spawned, final Player target, final String rawData) throws Exception {
|
||||
if (this.value.equals(Data.ANGRY)) {
|
||||
((Wolf) spawned).setAngry(true);
|
||||
} else if (this.value.equals(Data.ADULT)) {
|
||||
((Ageable) spawned).setAdult();
|
||||
} else if (this.value.equals(Data.BABY)) {
|
||||
((Ageable) spawned).setBaby();
|
||||
} else if (this.value.equals(Data.ADULTZOMBIE)) {
|
||||
((Zombie) spawned).setBaby(false);
|
||||
} else if (this.value.equals(Data.BABYZOMBIE)) {
|
||||
((Zombie) spawned).setBaby(true);
|
||||
} else if (this.value.equals(Data.ELECTRIFIED)) {
|
||||
((Creeper) spawned).setPowered(true);
|
||||
} else if (this.value.equals(Data.HORSESADDLE)) {
|
||||
final Horse horse = ((Horse) spawned);
|
||||
horse.setTamed(true);
|
||||
horse.setOwner(target);
|
||||
horse.getInventory().setSaddle(new ItemStack(Material.SADDLE, 1));
|
||||
} else if (this.value.equals(Data.PIGSADDLE)) {
|
||||
((Pig) spawned).setSaddle(true);
|
||||
} else if (this.value.equals(Data.TAMED)) {
|
||||
final Tameable tameable = ((Tameable) spawned);
|
||||
tameable.setTamed(true);
|
||||
tameable.setOwner(target);
|
||||
} else if (this.value.equals(Data.COLORABLE)) {
|
||||
final String color = rawData.toUpperCase(Locale.ENGLISH);
|
||||
try {
|
||||
if (color.equals("RANDOM")) {
|
||||
final Random rand = new Random();
|
||||
((Colorable) spawned).setColor(DyeColor.values()[rand.nextInt(DyeColor.values().length)]);
|
||||
} else if (!color.isEmpty()) {
|
||||
((Colorable) spawned).setColor(DyeColor.valueOf(color));
|
||||
}
|
||||
this.matched = rawData;
|
||||
} catch (Exception e) {
|
||||
throw new Exception(tl("sheepMalformedColor"), e);
|
||||
}
|
||||
} else if (this.value.equals(Data.EXP)) {
|
||||
try {
|
||||
((ExperienceOrb) spawned).setExperience(Integer.parseInt(rawData));
|
||||
this.matched = rawData;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new Exception(tl("invalidNumber"), e);
|
||||
}
|
||||
} else if (this.value.equals(Data.SIZE)) {
|
||||
try {
|
||||
((Slime) spawned).setSize(Integer.parseInt(rawData));
|
||||
this.matched = rawData;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new Exception(tl("slimeMalformedSize"), e);
|
||||
}
|
||||
} else if (this.value instanceof Horse.Color) {
|
||||
((Horse) spawned).setColor((Horse.Color) this.value);
|
||||
} else if (this.value instanceof Horse.Style) {
|
||||
((Horse) spawned).setStyle((Horse.Style) this.value);
|
||||
} else if (this.value instanceof Ocelot.Type) {
|
||||
((Ocelot) spawned).setCatType((Ocelot.Type) this.value);
|
||||
} else if (this.value instanceof Villager.Profession) {
|
||||
((Villager) spawned).setProfession((Villager.Profession) this.value);
|
||||
} else if (this.value instanceof Material) {
|
||||
if (this.type.equals(EntityType.HORSE)) {
|
||||
((Horse) spawned).setTamed(true);
|
||||
((Horse) spawned).getInventory().setArmor(new ItemStack((Material) this.value, 1));
|
||||
} else if (this.type.equals(EntityType.ZOMBIE.getEntityClass()) || this.type.equals(EntityType.SKELETON)) {
|
||||
final EntityEquipment invent = ((LivingEntity) spawned).getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack((Material) this.value, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
}
|
||||
} else if (this.value instanceof Parrot.Variant) {
|
||||
((Parrot) spawned).setVariant((Parrot.Variant) this.value);
|
||||
} else if (this.value instanceof TropicalFish.Pattern) {
|
||||
((TropicalFish) spawned).setPattern((TropicalFish.Pattern) this.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,35 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public class PlayerExtension {
|
||||
protected Player base;
|
||||
|
||||
public PlayerExtension(final Player base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public final Player getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public final Player setBase(final Player base) {
|
||||
return this.base = base;
|
||||
}
|
||||
|
||||
public Server getServer() {
|
||||
return base.getServer();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return base.getWorld();
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return base.getLocation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class PlayerList {
|
||||
// Cosmetic list formatting
|
||||
public static String listUsers(final IEssentials ess, final List<User> users, final String seperator) {
|
||||
final StringBuilder groupString = new StringBuilder();
|
||||
Collections.sort(users);
|
||||
boolean needComma = false;
|
||||
for (User user : users) {
|
||||
if (needComma) {
|
||||
groupString.append(seperator);
|
||||
}
|
||||
needComma = true;
|
||||
if (user.isAfk()) {
|
||||
groupString.append(tl("listAfkTag"));
|
||||
}
|
||||
if (user.isHidden()) {
|
||||
groupString.append(tl("listHiddenTag"));
|
||||
}
|
||||
user.setDisplayNick();
|
||||
groupString.append(user.getDisplayName());
|
||||
groupString.append("\u00a7f");
|
||||
}
|
||||
return groupString.toString();
|
||||
}
|
||||
|
||||
// Produce a user summary: There are 5 out of maximum 10 players online.
|
||||
public static String listSummary(final IEssentials ess, final User user, final boolean showHidden) {
|
||||
Server server = ess.getServer();
|
||||
int playerHidden = 0;
|
||||
int hiddenCount = 0;
|
||||
for (User onlinePlayer : ess.getOnlineUsers()) {
|
||||
if (onlinePlayer.isHidden() || (user != null && !user.getBase().canSee(onlinePlayer.getBase()))) {
|
||||
playerHidden++;
|
||||
if (showHidden || user.getBase().canSee(onlinePlayer.getBase())) {
|
||||
hiddenCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
String online;
|
||||
if (hiddenCount > 0) {
|
||||
online = tl("listAmountHidden", ess.getOnlinePlayers().size() - playerHidden, hiddenCount, server.getMaxPlayers());
|
||||
} else {
|
||||
online = tl("listAmount", ess.getOnlinePlayers().size() - playerHidden, server.getMaxPlayers());
|
||||
}
|
||||
return online;
|
||||
}
|
||||
|
||||
// Build the basic player list, divided by groups.
|
||||
public static Map<String, List<User>> getPlayerLists(final IEssentials ess, final User sender, final boolean showHidden) {
|
||||
Server server = ess.getServer();
|
||||
final Map<String, List<User>> playerList = new HashMap<String, List<User>>();
|
||||
for (User onlineUser : ess.getOnlineUsers()) {
|
||||
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && !sender.getBase().canSee(onlineUser.getBase()))) {
|
||||
continue;
|
||||
}
|
||||
final String group = FormatUtil.stripFormat(FormatUtil.stripEssentialsFormat(onlineUser.getGroup().toLowerCase()));
|
||||
List<User> list = playerList.get(group);
|
||||
if (list == null) {
|
||||
list = new ArrayList<User>();
|
||||
playerList.put(group, list);
|
||||
}
|
||||
list.add(onlineUser);
|
||||
}
|
||||
return playerList;
|
||||
}
|
||||
|
||||
// Handle the merging of groups
|
||||
public static List<User> getMergedList(final IEssentials ess, final Map<String, List<User>> playerList, final String groupName) {
|
||||
final Set<String> configGroups = ess.getSettings().getListGroupConfig().keySet();
|
||||
final List<User> users = new ArrayList<User>();
|
||||
for (String configGroup : configGroups) {
|
||||
if (configGroup.equalsIgnoreCase(groupName)) {
|
||||
String[] groupValues = ess.getSettings().getListGroupConfig().get(configGroup).toString().trim().split(" ");
|
||||
for (String groupValue : groupValues) {
|
||||
groupValue = groupValue.toLowerCase(Locale.ENGLISH);
|
||||
if (groupValue == null || groupValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
List<User> u = playerList.get(groupValue.trim());
|
||||
if (u == null || u.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
playerList.remove(groupValue);
|
||||
users.addAll(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
// Output a playerlist of just a single group, /list <groupname>
|
||||
public static String listGroupUsers(final IEssentials ess, final Map<String, List<User>> playerList, final String groupName) throws Exception {
|
||||
final List<User> users = getMergedList(ess, playerList, groupName);
|
||||
final List<User> groupUsers = playerList.get(groupName);
|
||||
if (groupUsers != null && !groupUsers.isEmpty()) {
|
||||
users.addAll(groupUsers);
|
||||
}
|
||||
if (users == null || users.isEmpty()) {
|
||||
throw new Exception(tl("groupDoesNotExist"));
|
||||
}
|
||||
final StringBuilder displayGroupName = new StringBuilder();
|
||||
displayGroupName.append(Character.toTitleCase(groupName.charAt(0)));
|
||||
displayGroupName.append(groupName.substring(1));
|
||||
return outputFormat(displayGroupName.toString(), listUsers(ess, users, ", "));
|
||||
}
|
||||
|
||||
// Build the output string
|
||||
public static String outputFormat(final String group, final String message) {
|
||||
final StringBuilder outputString = new StringBuilder();
|
||||
outputString.append(tl("listGroupTag", FormatUtil.replaceFormat(group)));
|
||||
outputString.append(message);
|
||||
return outputString.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public class PlayerTarget implements ITarget {
|
||||
private final String name;
|
||||
|
||||
public PlayerTarget(Player entity) {
|
||||
this.name = entity.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return Bukkit.getServer().getPlayerExact(name).getLocation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class Potions {
|
||||
private static final Map<String, PotionEffectType> POTIONS = new HashMap<>();
|
||||
private static final Map<String, PotionEffectType> ALIASPOTIONS = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
POTIONS.put("speed", PotionEffectType.SPEED);
|
||||
ALIASPOTIONS.put("fast", PotionEffectType.SPEED);
|
||||
ALIASPOTIONS.put("runfast", PotionEffectType.SPEED);
|
||||
ALIASPOTIONS.put("sprint", PotionEffectType.SPEED);
|
||||
ALIASPOTIONS.put("swift", PotionEffectType.SPEED);
|
||||
|
||||
POTIONS.put("slowness", PotionEffectType.SLOW);
|
||||
ALIASPOTIONS.put("slow", PotionEffectType.SLOW);
|
||||
ALIASPOTIONS.put("sluggish", PotionEffectType.SLOW);
|
||||
|
||||
POTIONS.put("haste", PotionEffectType.FAST_DIGGING);
|
||||
ALIASPOTIONS.put("superpick", PotionEffectType.FAST_DIGGING);
|
||||
ALIASPOTIONS.put("quickmine", PotionEffectType.FAST_DIGGING);
|
||||
ALIASPOTIONS.put("digspeed", PotionEffectType.FAST_DIGGING);
|
||||
ALIASPOTIONS.put("digfast", PotionEffectType.FAST_DIGGING);
|
||||
ALIASPOTIONS.put("sharp", PotionEffectType.FAST_DIGGING);
|
||||
|
||||
POTIONS.put("fatigue", PotionEffectType.SLOW_DIGGING);
|
||||
ALIASPOTIONS.put("slow", PotionEffectType.SLOW_DIGGING);
|
||||
ALIASPOTIONS.put("dull", PotionEffectType.SLOW_DIGGING);
|
||||
|
||||
POTIONS.put("strength", PotionEffectType.INCREASE_DAMAGE);
|
||||
ALIASPOTIONS.put("strong", PotionEffectType.INCREASE_DAMAGE);
|
||||
ALIASPOTIONS.put("bull", PotionEffectType.INCREASE_DAMAGE);
|
||||
ALIASPOTIONS.put("attack", PotionEffectType.INCREASE_DAMAGE);
|
||||
|
||||
POTIONS.put("heal", PotionEffectType.HEAL);
|
||||
ALIASPOTIONS.put("healthy", PotionEffectType.HEAL);
|
||||
ALIASPOTIONS.put("instaheal", PotionEffectType.HEAL);
|
||||
|
||||
POTIONS.put("harm", PotionEffectType.HARM);
|
||||
ALIASPOTIONS.put("harming", PotionEffectType.HARM);
|
||||
ALIASPOTIONS.put("injure", PotionEffectType.HARM);
|
||||
ALIASPOTIONS.put("damage", PotionEffectType.HARM);
|
||||
ALIASPOTIONS.put("inflict", PotionEffectType.HARM);
|
||||
|
||||
POTIONS.put("jump", PotionEffectType.JUMP);
|
||||
ALIASPOTIONS.put("leap", PotionEffectType.JUMP);
|
||||
|
||||
POTIONS.put("nausea", PotionEffectType.CONFUSION);
|
||||
ALIASPOTIONS.put("sick", PotionEffectType.CONFUSION);
|
||||
ALIASPOTIONS.put("sickness", PotionEffectType.CONFUSION);
|
||||
ALIASPOTIONS.put("confusion", PotionEffectType.CONFUSION);
|
||||
|
||||
POTIONS.put("regeneration", PotionEffectType.REGENERATION);
|
||||
ALIASPOTIONS.put("regen", PotionEffectType.REGENERATION);
|
||||
|
||||
POTIONS.put("resistance", PotionEffectType.DAMAGE_RESISTANCE);
|
||||
ALIASPOTIONS.put("dmgresist", PotionEffectType.DAMAGE_RESISTANCE);
|
||||
ALIASPOTIONS.put("armor", PotionEffectType.DAMAGE_RESISTANCE);
|
||||
|
||||
POTIONS.put("fireresist", PotionEffectType.FIRE_RESISTANCE);
|
||||
ALIASPOTIONS.put("fireresistance", PotionEffectType.FIRE_RESISTANCE);
|
||||
ALIASPOTIONS.put("resistfire", PotionEffectType.FIRE_RESISTANCE);
|
||||
|
||||
POTIONS.put("waterbreath", PotionEffectType.WATER_BREATHING);
|
||||
ALIASPOTIONS.put("waterbreathing", PotionEffectType.WATER_BREATHING);
|
||||
|
||||
POTIONS.put("invisibility", PotionEffectType.INVISIBILITY);
|
||||
ALIASPOTIONS.put("invisible", PotionEffectType.INVISIBILITY);
|
||||
ALIASPOTIONS.put("invis", PotionEffectType.INVISIBILITY);
|
||||
ALIASPOTIONS.put("vanish", PotionEffectType.INVISIBILITY);
|
||||
ALIASPOTIONS.put("disappear", PotionEffectType.INVISIBILITY);
|
||||
|
||||
POTIONS.put("blindness", PotionEffectType.BLINDNESS);
|
||||
ALIASPOTIONS.put("blind", PotionEffectType.BLINDNESS);
|
||||
|
||||
POTIONS.put("nightvision", PotionEffectType.NIGHT_VISION);
|
||||
ALIASPOTIONS.put("vision", PotionEffectType.NIGHT_VISION);
|
||||
|
||||
POTIONS.put("hunger", PotionEffectType.HUNGER);
|
||||
ALIASPOTIONS.put("hungry", PotionEffectType.HUNGER);
|
||||
ALIASPOTIONS.put("starve", PotionEffectType.HUNGER);
|
||||
|
||||
POTIONS.put("weakness", PotionEffectType.WEAKNESS);
|
||||
ALIASPOTIONS.put("weak", PotionEffectType.WEAKNESS);
|
||||
|
||||
POTIONS.put("poison", PotionEffectType.POISON);
|
||||
ALIASPOTIONS.put("venom", PotionEffectType.POISON);
|
||||
|
||||
POTIONS.put("wither", PotionEffectType.WITHER);
|
||||
ALIASPOTIONS.put("decay", PotionEffectType.WITHER);
|
||||
|
||||
POTIONS.put("healthboost", PotionEffectType.HEALTH_BOOST);
|
||||
ALIASPOTIONS.put("boost", PotionEffectType.HEALTH_BOOST);
|
||||
|
||||
POTIONS.put("absorption", PotionEffectType.ABSORPTION);
|
||||
ALIASPOTIONS.put("absorb", PotionEffectType.ABSORPTION);
|
||||
|
||||
POTIONS.put("saturation", PotionEffectType.SATURATION);
|
||||
ALIASPOTIONS.put("food", PotionEffectType.SATURATION);
|
||||
|
||||
POTIONS.put("waterbreathing", PotionEffectType.WATER_BREATHING);
|
||||
ALIASPOTIONS.put("underwaterbreathing", PotionEffectType.WATER_BREATHING);
|
||||
ALIASPOTIONS.put("waterbreath", PotionEffectType.WATER_BREATHING);
|
||||
ALIASPOTIONS.put("underwaterbreath", PotionEffectType.WATER_BREATHING);
|
||||
ALIASPOTIONS.put("air", PotionEffectType.WATER_BREATHING);
|
||||
|
||||
// 1.9
|
||||
try {
|
||||
POTIONS.put("glowing", PotionEffectType.GLOWING);
|
||||
ALIASPOTIONS.put("glow", PotionEffectType.GLOWING);
|
||||
|
||||
POTIONS.put("levitation", PotionEffectType.LEVITATION);
|
||||
ALIASPOTIONS.put("levitate", PotionEffectType.LEVITATION);
|
||||
|
||||
POTIONS.put("luck", PotionEffectType.LUCK);
|
||||
POTIONS.put("unluck", PotionEffectType.UNLUCK);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
public static PotionEffectType getByName(String name) {
|
||||
PotionEffectType peffect;
|
||||
if (NumberUtil.isInt(name)) {
|
||||
peffect = PotionEffectType.getById(Integer.parseInt(name));
|
||||
} else {
|
||||
peffect = PotionEffectType.getByName(name.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
if (peffect == null) {
|
||||
peffect = POTIONS.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
if (peffect == null) {
|
||||
peffect = ALIASPOTIONS.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
return peffect;
|
||||
}
|
||||
|
||||
public static Set<Entry<String, PotionEffectType>> entrySet() {
|
||||
return POTIONS.entrySet();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,276 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.Mob.MobException;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class SpawnMob {
|
||||
|
||||
private static final Material GOLDEN_HELMET = EnumUtil.getMaterial("GOLDEN_HELMET", "GOLD_HELMET");
|
||||
private static final Material GOLDEN_CHESTPLATE = EnumUtil.getMaterial("GOLDEN_CHESTPLATE", "GOLD_CHESTPLATE");
|
||||
private static final Material GOLDEN_LEGGINGS = EnumUtil.getMaterial("GOLDEN_LEGGINGS", "GOLD_LEGGINGS");
|
||||
private static final Material GOLDEN_BOOTS = EnumUtil.getMaterial("GOLDEN_BOOTS", "GOLD_BOOTS");
|
||||
private static final Material GOLDEN_SWORD = EnumUtil.getMaterial("GOLDEN_SWORD", "GOLD_SWORD");
|
||||
|
||||
public static String mobList(final User user) {
|
||||
final Set<String> mobList = Mob.getMobList();
|
||||
final Set<String> availableList = new HashSet<String>();
|
||||
for (String mob : mobList) {
|
||||
if (user.isAuthorized("essentials.spawnmob." + mob.toLowerCase(Locale.ENGLISH))) {
|
||||
availableList.add(mob);
|
||||
}
|
||||
}
|
||||
if (availableList.isEmpty()) {
|
||||
availableList.add(tl("none"));
|
||||
}
|
||||
return StringUtil.joinList(availableList);
|
||||
}
|
||||
|
||||
public static List<String> mobParts(final String mobString) {
|
||||
String[] mobParts = mobString.split(",");
|
||||
|
||||
List<String> mobs = new ArrayList<String>();
|
||||
|
||||
for (String mobPart : mobParts) {
|
||||
String[] mobDatas = mobPart.split(":");
|
||||
mobs.add(mobDatas[0]);
|
||||
}
|
||||
return mobs;
|
||||
}
|
||||
|
||||
public static List<String> mobData(final String mobString) {
|
||||
String[] mobParts = mobString.split(",");
|
||||
|
||||
List<String> mobData = new ArrayList<String>();
|
||||
|
||||
for (String mobPart : mobParts) {
|
||||
String[] mobDatas = mobPart.split(":");
|
||||
if (mobDatas.length == 1) {
|
||||
if (mobPart.contains(":")) {
|
||||
mobData.add("");
|
||||
} else {
|
||||
mobData.add(null);
|
||||
}
|
||||
} else {
|
||||
mobData.add(mobDatas[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return mobData;
|
||||
}
|
||||
|
||||
// This method spawns a mob where the user is looking, owned by user
|
||||
public static void spawnmob(final IEssentials ess, final Server server, final User user, final List<String> parts, final List<String> data, int mobCount) throws Exception {
|
||||
final Block block = LocationUtil.getTarget(user.getBase()).getBlock();
|
||||
if (block == null) {
|
||||
throw new Exception(tl("unableToSpawnMob"));
|
||||
}
|
||||
spawnmob(ess, server, user.getSource(), user, block.getLocation(), parts, data, mobCount);
|
||||
}
|
||||
|
||||
// This method spawns a mob at target, owned by target
|
||||
public static void spawnmob(final IEssentials ess, final Server server, final CommandSource sender, final User target, final List<String> parts, final List<String> data, int mobCount) throws Exception {
|
||||
spawnmob(ess, server, sender, target, target.getLocation(), parts, data, mobCount);
|
||||
}
|
||||
|
||||
// This method spawns a mob at loc, owned by target
|
||||
public static void spawnmob(final IEssentials ess, final Server server, final CommandSource sender, final User target, final Location loc, final List<String> parts, final List<String> data, int mobCount) throws Exception {
|
||||
final Location sloc = LocationUtil.getSafeDestination(loc);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
Mob mob = Mob.fromName(parts.get(i));
|
||||
checkSpawnable(ess, sender, mob);
|
||||
}
|
||||
|
||||
final int serverLimit = ess.getSettings().getSpawnMobLimit();
|
||||
int effectiveLimit = serverLimit / parts.size();
|
||||
|
||||
if (effectiveLimit < 1) {
|
||||
effectiveLimit = 1;
|
||||
while (parts.size() > serverLimit) {
|
||||
parts.remove(serverLimit);
|
||||
}
|
||||
}
|
||||
|
||||
if (mobCount > effectiveLimit) {
|
||||
mobCount = effectiveLimit;
|
||||
sender.sendMessage(tl("mobSpawnLimit"));
|
||||
}
|
||||
|
||||
Mob mob = Mob.fromName(parts.get(0)); // Get the first mob
|
||||
try {
|
||||
for (int i = 0; i < mobCount; i++) {
|
||||
spawnMob(ess, server, sender, target, sloc, parts, data);
|
||||
}
|
||||
sender.sendMessage(mobCount * parts.size() + " " + mob.name.toLowerCase(Locale.ENGLISH) + mob.suffix + " " + tl("spawned"));
|
||||
} catch (MobException e1) {
|
||||
throw new Exception(tl("unableToSpawnMob"), e1);
|
||||
} catch (NumberFormatException e2) {
|
||||
throw new Exception(tl("numberRequired"), e2);
|
||||
} catch (NullPointerException np) {
|
||||
throw new Exception(tl("soloMob"), np);
|
||||
}
|
||||
}
|
||||
|
||||
private static void spawnMob(final IEssentials ess, final Server server, final CommandSource sender, final User target, final Location sloc, List<String> parts, List<String> data) throws Exception {
|
||||
Mob mob;
|
||||
Entity spawnedMob = null;
|
||||
Entity spawnedMount;
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
if (i == 0) {
|
||||
mob = Mob.fromName(parts.get(i));
|
||||
spawnedMob = mob.spawn(sloc.getWorld(), server, sloc);
|
||||
defaultMobData(mob.getType(), spawnedMob);
|
||||
|
||||
if (data.get(i) != null) {
|
||||
changeMobData(sender, mob.getType(), spawnedMob, data.get(i).toLowerCase(Locale.ENGLISH), target);
|
||||
}
|
||||
}
|
||||
|
||||
int next = (i + 1);
|
||||
if (next < parts.size()) //If it's the last mob in the list, don't set the mount
|
||||
{
|
||||
Mob mMob = Mob.fromName(parts.get(next));
|
||||
spawnedMount = mMob.spawn(sloc.getWorld(), server, sloc);
|
||||
defaultMobData(mMob.getType(), spawnedMount);
|
||||
|
||||
if (data.get(next) != null) {
|
||||
changeMobData(sender, mMob.getType(), spawnedMount, data.get(next).toLowerCase(Locale.ENGLISH), target);
|
||||
}
|
||||
|
||||
spawnedMob.setPassenger(spawnedMount);
|
||||
|
||||
spawnedMob = spawnedMount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSpawnable(IEssentials ess, CommandSource sender, Mob mob) throws Exception {
|
||||
if (mob == null || mob.getType() == null) {
|
||||
throw new Exception(tl("invalidMob"));
|
||||
}
|
||||
|
||||
if (ess.getSettings().getProtectPreventSpawn(mob.getType().toString().toLowerCase(Locale.ENGLISH))) {
|
||||
throw new Exception(tl("disabledToSpawnMob"));
|
||||
}
|
||||
|
||||
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.spawnmob." + mob.name.toLowerCase(Locale.ENGLISH))) {
|
||||
throw new Exception(tl("noPermToSpawnMob"));
|
||||
}
|
||||
}
|
||||
|
||||
private static void changeMobData(final CommandSource sender, final EntityType type, final Entity spawned, final String inputData, final User target) throws Exception {
|
||||
String data = inputData;
|
||||
|
||||
if (data.isEmpty()) {
|
||||
sender.sendMessage(tl("mobDataList", StringUtil.joinList(MobData.getValidHelp(spawned))));
|
||||
}
|
||||
|
||||
if (spawned instanceof Zombie) {
|
||||
((Zombie) spawned).setBaby(false);
|
||||
} else if (spawned instanceof Ageable) {
|
||||
((Ageable) spawned).setAdult();
|
||||
}
|
||||
|
||||
if (spawned instanceof Zombie || type == EntityType.SKELETON) {
|
||||
if (inputData.contains("armor") || inputData.contains("armour")) {
|
||||
final EntityEquipment invent = ((LivingEntity) spawned).getEquipment();
|
||||
if (inputData.contains("noarmor") || inputData.contains("noarmour")) {
|
||||
invent.clear();
|
||||
} else if (inputData.contains("diamond")) {
|
||||
invent.setBoots(new ItemStack(Material.DIAMOND_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(Material.DIAMOND_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(Material.DIAMOND_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(Material.DIAMOND_HELMET, 1));
|
||||
} else if (inputData.contains("gold")) {
|
||||
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(GOLDEN_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(GOLDEN_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(GOLDEN_HELMET, 1));
|
||||
} else if (inputData.contains("leather")) {
|
||||
invent.setBoots(new ItemStack(Material.LEATHER_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(Material.LEATHER_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(Material.LEATHER_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(Material.LEATHER_HELMET, 1));
|
||||
} else if (inputData.contains("iron")) {
|
||||
invent.setBoots(new ItemStack(Material.IRON_BOOTS, 1));
|
||||
invent.setLeggings(new ItemStack(Material.IRON_LEGGINGS, 1));
|
||||
invent.setChestplate(new ItemStack(Material.IRON_CHESTPLATE, 1));
|
||||
invent.setHelmet(new ItemStack(Material.IRON_HELMET, 1));
|
||||
}
|
||||
invent.setBootsDropChance(0f);
|
||||
invent.setLeggingsDropChance(0f);
|
||||
invent.setChestplateDropChance(0f);
|
||||
invent.setHelmetDropChance(0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MobData newData = MobData.fromData(spawned, data);
|
||||
while (newData != null) {
|
||||
newData.setData(spawned, target.getBase(), data);
|
||||
data = data.replace(newData.getMatched(), "");
|
||||
newData = MobData.fromData(spawned, data);
|
||||
}
|
||||
}
|
||||
|
||||
private static void defaultMobData(final EntityType type, final Entity spawned) {
|
||||
if (type == EntityType.SKELETON) {
|
||||
final EntityEquipment invent = ((LivingEntity) spawned).getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(Material.BOW, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
|
||||
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
|
||||
invent.setBootsDropChance(0.0f);
|
||||
}
|
||||
|
||||
if (type == EntityType.PIG_ZOMBIE) {
|
||||
final PigZombie zombie = ((PigZombie) spawned);
|
||||
setVillager(zombie, false);
|
||||
|
||||
final EntityEquipment invent = zombie.getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(GOLDEN_SWORD, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
|
||||
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
|
||||
invent.setBootsDropChance(0.0f);
|
||||
}
|
||||
|
||||
if (type == EntityType.ZOMBIE) {
|
||||
final Zombie zombie = ((Zombie) spawned);
|
||||
setVillager(zombie, false);
|
||||
|
||||
final EntityEquipment invent = zombie.getEquipment();
|
||||
invent.setBoots(new ItemStack(GOLDEN_BOOTS, 1));
|
||||
invent.setBootsDropChance(0.0f);
|
||||
}
|
||||
|
||||
if (type == EntityType.HORSE) {
|
||||
((Horse) spawned).setJumpStrength(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static void setVillager(Zombie zombie, boolean villager) {
|
||||
try {
|
||||
zombie.setVillager(villager);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
|
||||
|
||||
public class TNTExplodeListener implements Listener, Runnable {
|
||||
private final transient IEssentials ess;
|
||||
private transient boolean enabled = false;
|
||||
private transient int timer = -1;
|
||||
|
||||
public TNTExplodeListener(final IEssentials ess) {
|
||||
super();
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if (!enabled) {
|
||||
enabled = true;
|
||||
timer = ess.scheduleSyncDelayedTask(this, 200);
|
||||
return;
|
||||
}
|
||||
if (timer != -1) {
|
||||
ess.getScheduler().cancelTask(timer);
|
||||
timer = ess.scheduleSyncDelayedTask(this, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onEntityExplode(final EntityExplodeEvent event) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
if (event.getEntity() instanceof LivingEntity) {
|
||||
return;
|
||||
}
|
||||
if (event.blockList().size() < 1) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
event.getLocation().getWorld().createExplosion(event.getLocation(), 0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -1,302 +1,299 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.ITeleport;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
|
||||
import com.earth2me.essentials.perm.Permissions;
|
||||
import com.earth2me.essentials.user.CooldownException;
|
||||
import com.earth2me.essentials.user.UserData.TimestampType;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.logging.Logger;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.ITeleport;
|
||||
import net.ess3.api.IUser;
|
||||
import net.ess3.api.events.UserWarpEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
public class Teleport implements Runnable, ITeleport
|
||||
{
|
||||
private static final double MOVE_CONSTANT = 0.3;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
private static class Target
|
||||
{
|
||||
private final Location location;
|
||||
private final Entity entity;
|
||||
public class Teleport implements ITeleport {
|
||||
private final IUser teleportOwner;
|
||||
private final IEssentials ess;
|
||||
private TimedTeleport timedTeleport;
|
||||
|
||||
public Target(Location location)
|
||||
{
|
||||
this.location = location;
|
||||
this.entity = null;
|
||||
}
|
||||
private TeleportType tpType;
|
||||
|
||||
public Target(Entity entity)
|
||||
{
|
||||
this.entity = entity;
|
||||
this.location = null;
|
||||
}
|
||||
public Teleport(IUser user, IEssentials ess) {
|
||||
this.teleportOwner = user;
|
||||
this.ess = ess;
|
||||
tpType = TeleportType.NORMAL;
|
||||
}
|
||||
|
||||
public Location getLocation()
|
||||
{
|
||||
if (this.entity != null)
|
||||
{
|
||||
return this.entity.getLocation();
|
||||
}
|
||||
return location;
|
||||
}
|
||||
}
|
||||
private IUser user;
|
||||
private int teleTimer = -1;
|
||||
private long started; // time this task was initiated
|
||||
private long delay; // how long to delay the teleport
|
||||
private int health;
|
||||
// note that I initially stored a clone of the location for reference, but...
|
||||
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
|
||||
// so, the X/Y/Z values are stored instead and rounded off
|
||||
private long initX;
|
||||
private long initY;
|
||||
private long initZ;
|
||||
private Target teleportTarget;
|
||||
private Trade chargeFor;
|
||||
private final IEssentials ess;
|
||||
private static final Logger logger = Logger.getLogger("Minecraft");
|
||||
private TeleportCause cause;
|
||||
public enum TeleportType {
|
||||
TPA,
|
||||
BACK,
|
||||
NORMAL
|
||||
}
|
||||
|
||||
private void initTimer(long delay, Target target, Trade chargeFor, TeleportCause cause)
|
||||
{
|
||||
this.started = System.currentTimeMillis();
|
||||
this.delay = delay;
|
||||
this.health = user.getHealth();
|
||||
this.initX = Math.round(user.getLocation().getX() * MOVE_CONSTANT);
|
||||
this.initY = Math.round(user.getLocation().getY() * MOVE_CONSTANT);
|
||||
this.initZ = Math.round(user.getLocation().getZ() * MOVE_CONSTANT);
|
||||
this.teleportTarget = target;
|
||||
this.chargeFor = chargeFor;
|
||||
this.cause = cause;
|
||||
}
|
||||
public void cooldown(boolean check) throws Exception {
|
||||
final Calendar time = new GregorianCalendar();
|
||||
if (teleportOwner.getLastTeleportTimestamp() > 0) {
|
||||
// Take the current time, and remove the delay from it.
|
||||
final double cooldown = ess.getSettings().getTeleportCooldown();
|
||||
final Calendar earliestTime = new GregorianCalendar();
|
||||
earliestTime.add(Calendar.SECOND, -(int) cooldown);
|
||||
earliestTime.add(Calendar.MILLISECOND, -(int) ((cooldown * 1000.0) % 1000.0));
|
||||
// This value contains the most recent time a teleportPlayer could have been used that would allow another use.
|
||||
final long earliestLong = earliestTime.getTimeInMillis();
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// When was the last teleportPlayer used?
|
||||
final long lastTime = teleportOwner.getLastTeleportTimestamp();
|
||||
|
||||
if (user == null || !user.isOnline() || user.getLocation() == null)
|
||||
{
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
if (Math.round(user.getLocation().getX() * MOVE_CONSTANT) != initX
|
||||
|| Math.round(user.getLocation().getY() * MOVE_CONSTANT) != initY
|
||||
|| Math.round(user.getLocation().getZ() * MOVE_CONSTANT) != initZ
|
||||
|| user.getHealth() < health)
|
||||
{ // user moved, cancel teleport
|
||||
cancel(true);
|
||||
return;
|
||||
}
|
||||
if (lastTime > time.getTimeInMillis()) {
|
||||
// This is to make sure time didn't get messed up on last teleportPlayer use.
|
||||
// If this happens, let's give the user the benifit of the doubt.
|
||||
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
|
||||
return;
|
||||
} else if (lastTime > earliestLong
|
||||
&& cooldownApplies()) {
|
||||
time.setTimeInMillis(lastTime);
|
||||
time.add(Calendar.SECOND, (int) cooldown);
|
||||
time.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
|
||||
throw new Exception(tl("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis())));
|
||||
}
|
||||
}
|
||||
// if justCheck is set, don't update lastTeleport; we're just checking
|
||||
if (!check) {
|
||||
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
|
||||
}
|
||||
}
|
||||
|
||||
health = user.getHealth(); // in case user healed, then later gets injured
|
||||
private boolean cooldownApplies() {
|
||||
boolean applies = true;
|
||||
String globalBypassPerm = "essentials.teleport.cooldown.bypass";
|
||||
switch (tpType) {
|
||||
case NORMAL:
|
||||
applies = !teleportOwner.isAuthorized(globalBypassPerm);
|
||||
break;
|
||||
case BACK:
|
||||
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
|
||||
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.back"));
|
||||
break;
|
||||
case TPA:
|
||||
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
|
||||
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.tpa"));
|
||||
break;
|
||||
}
|
||||
return applies;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (now > started + delay)
|
||||
{
|
||||
try
|
||||
{
|
||||
cooldown(false);
|
||||
user.sendMessage(_("teleportationCommencing"));
|
||||
try
|
||||
{
|
||||
private void warnUser(final IUser user, final double delay) {
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.add(Calendar.SECOND, (int) delay);
|
||||
c.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
|
||||
user.sendMessage(tl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis())));
|
||||
}
|
||||
|
||||
now(teleportTarget, cause);
|
||||
if (chargeFor != null)
|
||||
{
|
||||
chargeFor.charge(user);
|
||||
}
|
||||
}
|
||||
catch (Throwable ex)
|
||||
{
|
||||
ess.getCommandHandler().showCommandError(user.getBase(), "teleport", ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
user.sendMessage(_("cooldownWithMessage", ex.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
//The now function is used when you want to skip tp delay when teleporting someone to a location or player.
|
||||
@Override
|
||||
public void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception {
|
||||
if (cooldown) {
|
||||
cooldown(false);
|
||||
}
|
||||
final ITarget target = new LocationTarget(loc);
|
||||
now(teleportOwner, target, cause);
|
||||
}
|
||||
|
||||
public Teleport(IUser user, IEssentials ess)
|
||||
{
|
||||
this.user = user;
|
||||
this.ess = ess;
|
||||
}
|
||||
@Override
|
||||
public void now(Player entity, boolean cooldown, TeleportCause cause) throws Exception {
|
||||
if (cooldown) {
|
||||
cooldown(false);
|
||||
}
|
||||
final ITarget target = new PlayerTarget(entity);
|
||||
now(teleportOwner, target, cause);
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
|
||||
public void respawn(final Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
final Player player = user.getBase();
|
||||
final Location bed = player.getBedSpawnLocation();
|
||||
final PlayerRespawnEvent pre = new PlayerRespawnEvent(player, bed == null ? player.getWorld().getSpawnLocation() : bed, bed != null);
|
||||
ess.getServer().getPluginManager().callEvent(pre);
|
||||
teleport(new Target(pre.getRespawnLocation()), chargeFor, cause);
|
||||
}
|
||||
protected void now(IUser teleportee, ITarget target, TeleportCause cause) throws Exception {
|
||||
cancel(false);
|
||||
teleportee.setLastLocation();
|
||||
Location loc = target.getLocation();
|
||||
|
||||
public void warp(String warp, Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
final Location loc = ess.getWarps().getWarp(warp);
|
||||
teleport(new Target(loc), chargeFor, cause);
|
||||
user.sendMessage(_("warpingTo", warp));
|
||||
}
|
||||
if (LocationUtil.isBlockUnsafeForUser(teleportee, loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||
} else {
|
||||
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
|
||||
}
|
||||
} else {
|
||||
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
} else {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||
} else {
|
||||
if (ess.getSettings().isTeleportToCenterLocation()) {
|
||||
loc = LocationUtil.getRoundedDestination(loc);
|
||||
}
|
||||
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cooldown(boolean check) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
user.checkCooldown(TimestampType.LASTTELEPORT, ess.getGroups().getTeleportCooldown(user), !check, Permissions.TELEPORT_COOLDOWN_BYPASS);
|
||||
}
|
||||
catch (CooldownException ex)
|
||||
{
|
||||
throw new Exception(_("timeBeforeTeleport", ex.getMessage()));
|
||||
//The teleportPlayer function is used when you want to normally teleportPlayer someone to a location or player.
|
||||
//This method is nolonger used internally and will be removed.
|
||||
@Deprecated
|
||||
@Override
|
||||
public void teleport(Location loc, Trade chargeFor) throws Exception {
|
||||
teleport(loc, chargeFor, TeleportCause.PLUGIN);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void teleport(Location loc, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
teleport(teleportOwner, new LocationTarget(loc), chargeFor, cause);
|
||||
}
|
||||
|
||||
public void cancel(boolean notifyUser)
|
||||
{
|
||||
if (teleTimer == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
ess.getServer().getScheduler().cancelTask(teleTimer);
|
||||
if (notifyUser)
|
||||
{
|
||||
user.sendMessage(_("pendingTeleportCancelled"));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
teleTimer = -1;
|
||||
}
|
||||
}
|
||||
//This is used when teleporting to a player
|
||||
@Override
|
||||
public void teleport(Player entity, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
ITarget target = new PlayerTarget(entity);
|
||||
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
|
||||
teleport(teleportOwner, target, chargeFor, cause);
|
||||
}
|
||||
|
||||
public void cancel()
|
||||
{
|
||||
cancel(false);
|
||||
}
|
||||
//This is used when teleporting to stored location
|
||||
@Override
|
||||
public void teleportPlayer(IUser teleportee, Location loc, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
|
||||
}
|
||||
|
||||
public void teleport(Location loc, Trade chargeFor) throws Exception
|
||||
{
|
||||
teleport(new Target(loc), chargeFor, TeleportCause.PLUGIN);
|
||||
}
|
||||
//This is used on /tphere
|
||||
@Override
|
||||
public void teleportPlayer(IUser teleportee, Player entity, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
ITarget target = new PlayerTarget(entity);
|
||||
teleport(teleportee, target, chargeFor, cause);
|
||||
teleportee.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
|
||||
public void teleport(Location loc, Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
teleport(new Target(loc), chargeFor, cause);
|
||||
}
|
||||
private void teleport(IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
|
||||
public void teleport(Entity entity, Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
teleport(new Target(entity), chargeFor, cause);
|
||||
}
|
||||
Trade cashCharge = chargeFor;
|
||||
|
||||
private void teleport(Target target, Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
double delay = ess.getGroups().getTeleportDelay(user);
|
||||
if (chargeFor != null) {
|
||||
chargeFor.isAffordableFor(teleportOwner);
|
||||
|
||||
if (chargeFor != null)
|
||||
{
|
||||
chargeFor.isAffordableFor(user);
|
||||
}
|
||||
cooldown(true);
|
||||
if (delay <= 0 || Permissions.TELEPORT_TIMER_BYPASS.isAuthorized(user))
|
||||
{
|
||||
cooldown(false);
|
||||
now(target, cause);
|
||||
if (chargeFor != null)
|
||||
{
|
||||
chargeFor.charge(user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
|
||||
if (!chargeFor.getCommandCost(teleportOwner).equals(BigDecimal.ZERO)) {
|
||||
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
|
||||
cashCharge = new Trade(chargeFor.getCommandCost(teleportOwner), ess);
|
||||
}
|
||||
}
|
||||
|
||||
cancel();
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.add(Calendar.SECOND, (int)delay);
|
||||
c.add(Calendar.MILLISECOND, (int)((delay * 1000.0) % 1000.0));
|
||||
user.sendMessage(_("dontMoveMessage", Util.formatDateDiff(c.getTimeInMillis())));
|
||||
initTimer((long)(delay * 1000.0), target, chargeFor, cause);
|
||||
cooldown(true);
|
||||
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass") || teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
|
||||
cooldown(false);
|
||||
now(teleportee, target, cause);
|
||||
if (cashCharge != null) {
|
||||
cashCharge.charge(teleportOwner);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
teleTimer = ess.scheduleSyncRepeatingTask(this, 10, 10);
|
||||
}
|
||||
cancel(false);
|
||||
warnUser(teleportee, delay);
|
||||
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
|
||||
}
|
||||
|
||||
private void now(Target target, TeleportCause cause) throws Exception
|
||||
{
|
||||
cancel();
|
||||
user.setLastLocation();
|
||||
user.getBase().teleport(Util.getSafeDestination(target.getLocation()), cause);
|
||||
}
|
||||
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
|
||||
@Override
|
||||
public void respawn(final Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
if (chargeFor != null) {
|
||||
chargeFor.isAffordableFor(teleportOwner);
|
||||
}
|
||||
cooldown(true);
|
||||
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass")) {
|
||||
cooldown(false);
|
||||
respawnNow(teleportOwner, cause);
|
||||
if (chargeFor != null) {
|
||||
chargeFor.charge(teleportOwner);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception
|
||||
{
|
||||
if (cooldown)
|
||||
{
|
||||
cooldown(false);
|
||||
}
|
||||
now(new Target(loc), cause);
|
||||
}
|
||||
cancel(false);
|
||||
warnUser(teleportOwner, delay);
|
||||
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
||||
}
|
||||
|
||||
public void now(Location loc, Trade chargeFor, TeleportCause cause) throws Exception
|
||||
{
|
||||
cooldown(false);
|
||||
chargeFor.charge(user);
|
||||
now(new Target(loc), cause);
|
||||
}
|
||||
void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
|
||||
final Player player = teleportee.getBase();
|
||||
Location bed = player.getBedSpawnLocation();
|
||||
if (bed != null) {
|
||||
now(teleportee, new LocationTarget(bed), cause);
|
||||
} else {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Could not find bed spawn, forcing respawn event.");
|
||||
}
|
||||
final PlayerRespawnEvent pre = new PlayerRespawnEvent(player, player.getWorld().getSpawnLocation(), false);
|
||||
ess.getServer().getPluginManager().callEvent(pre);
|
||||
now(teleportee, new LocationTarget(pre.getRespawnLocation()), cause);
|
||||
}
|
||||
}
|
||||
|
||||
public void now(Entity entity, boolean cooldown, TeleportCause cause) throws Exception
|
||||
{
|
||||
if (cooldown)
|
||||
{
|
||||
cooldown(false);
|
||||
}
|
||||
now(new Target(entity), cause);
|
||||
}
|
||||
//The warp function is a wrapper used to teleportPlayer a player to a /warp
|
||||
@Override
|
||||
public void warp(IUser teleportee, String warp, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
UserWarpEvent event = new UserWarpEvent(teleportee, warp, chargeFor);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
public void back(Trade chargeFor) throws Exception
|
||||
{
|
||||
user.acquireReadLock();
|
||||
try
|
||||
{
|
||||
teleport(new Target(user.getData().getLastLocation().getBukkitLocation()), chargeFor, TeleportCause.COMMAND);
|
||||
}
|
||||
finally
|
||||
{
|
||||
user.unlock();
|
||||
}
|
||||
}
|
||||
if(event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
warp = event.getWarp();
|
||||
Location loc = ess.getWarps().getWarp(warp);
|
||||
teleportee.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
if (!teleportee.equals(teleportOwner)) {
|
||||
teleportOwner.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
|
||||
}
|
||||
|
||||
public void back() throws Exception
|
||||
{
|
||||
user.acquireReadLock();
|
||||
try
|
||||
{
|
||||
now(new Target(user.getData().getLastLocation().getBukkitLocation()), TeleportCause.COMMAND);
|
||||
}
|
||||
finally
|
||||
{
|
||||
user.unlock();
|
||||
}
|
||||
}
|
||||
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
|
||||
@Override
|
||||
public void back(Trade chargeFor) throws Exception {
|
||||
tpType = TeleportType.BACK;
|
||||
final Location loc = teleportOwner.getLastLocation();
|
||||
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
teleport(teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
|
||||
}
|
||||
|
||||
public void home(IUser user, String home, Trade chargeFor) throws Exception
|
||||
{
|
||||
final Location loc = user.getHome(home);
|
||||
if (loc == null)
|
||||
{
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
teleport(new Target(loc), chargeFor, TeleportCause.COMMAND);
|
||||
}
|
||||
//This function is used to throw a user back after a jail sentence
|
||||
@Override
|
||||
public void back() throws Exception {
|
||||
now(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND);
|
||||
}
|
||||
|
||||
public void setTpType(TeleportType tpType) {
|
||||
this.tpType = tpType;
|
||||
}
|
||||
|
||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||
private void cancel(boolean notifyUser) {
|
||||
if (timedTeleport != null) {
|
||||
timedTeleport.cancelTimer(notifyUser);
|
||||
timedTeleport = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initTimer(long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||
timedTeleport = new TimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class TimedTeleport implements Runnable {
|
||||
private static final double MOVE_CONSTANT = 0.3;
|
||||
private final IUser teleportOwner;
|
||||
private final IEssentials ess;
|
||||
private final Teleport teleport;
|
||||
private final UUID timer_teleportee;
|
||||
private int timer_task;
|
||||
private final long timer_started; // time this task was initiated
|
||||
private final long timer_delay; // how long to delay the teleportPlayer
|
||||
private double timer_health;
|
||||
// note that I initially stored a clone of the location for reference, but...
|
||||
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
|
||||
// so, the X/Y/Z values are stored instead and rounded off
|
||||
private final long timer_initX;
|
||||
private final long timer_initY;
|
||||
private final long timer_initZ;
|
||||
private final ITarget timer_teleportTarget;
|
||||
private final boolean timer_respawn;
|
||||
private final boolean timer_canMove;
|
||||
private final Trade timer_chargeFor;
|
||||
private final TeleportCause timer_cause;
|
||||
|
||||
TimedTeleport(IUser user, IEssentials ess, Teleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||
this.teleportOwner = user;
|
||||
this.ess = ess;
|
||||
this.teleport = teleport;
|
||||
this.timer_started = System.currentTimeMillis();
|
||||
this.timer_delay = delay;
|
||||
this.timer_health = teleportUser.getBase().getHealth();
|
||||
this.timer_initX = Math.round(teleportUser.getBase().getLocation().getX() * MOVE_CONSTANT);
|
||||
this.timer_initY = Math.round(teleportUser.getBase().getLocation().getY() * MOVE_CONSTANT);
|
||||
this.timer_initZ = Math.round(teleportUser.getBase().getLocation().getZ() * MOVE_CONSTANT);
|
||||
this.timer_teleportee = teleportUser.getBase().getUniqueId();
|
||||
this.timer_teleportTarget = target;
|
||||
this.timer_chargeFor = chargeFor;
|
||||
this.timer_cause = cause;
|
||||
this.timer_respawn = respawn;
|
||||
this.timer_canMove = user.isAuthorized("essentials.teleport.timer.move");
|
||||
|
||||
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20).getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (teleportOwner == null || !teleportOwner.getBase().isOnline() || teleportOwner.getBase().getLocation() == null) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final IUser teleportUser = ess.getUser(this.timer_teleportee);
|
||||
|
||||
if (teleportUser == null || !teleportUser.getBase().isOnline()) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final Location currLocation = teleportUser.getBase().getLocation();
|
||||
if (currLocation == null) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!timer_canMove && (Math.round(currLocation.getX() * MOVE_CONSTANT) != timer_initX || Math.round(currLocation.getY() * MOVE_CONSTANT) != timer_initY || Math.round(currLocation.getZ() * MOVE_CONSTANT) != timer_initZ || teleportUser.getBase().getHealth() < timer_health)) {
|
||||
// user moved, cancelTimer teleportPlayer
|
||||
cancelTimer(true);
|
||||
return;
|
||||
}
|
||||
|
||||
class DelayedTeleportTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
timer_health = teleportUser.getBase().getHealth(); // in case user healed, then later gets injured
|
||||
final long now = System.currentTimeMillis();
|
||||
if (now > timer_started + timer_delay) {
|
||||
try {
|
||||
teleport.cooldown(false);
|
||||
} catch (Exception ex) {
|
||||
teleportOwner.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
|
||||
if (teleportOwner != teleportUser) {
|
||||
teleportUser.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
|
||||
}
|
||||
}
|
||||
try {
|
||||
cancelTimer(false);
|
||||
teleportUser.sendMessage(tl("teleportationCommencing"));
|
||||
|
||||
try {
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.isAffordableFor(teleportOwner);
|
||||
}
|
||||
if (timer_respawn) {
|
||||
teleport.respawnNow(teleportUser, timer_cause);
|
||||
} else {
|
||||
teleport.now(teleportUser, timer_teleportTarget, timer_cause);
|
||||
}
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.charge(teleportOwner);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new DelayedTeleportTask());
|
||||
}
|
||||
|
||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||
void cancelTimer(boolean notifyUser) {
|
||||
if (timer_task == -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ess.getServer().getScheduler().cancelTask(timer_task);
|
||||
if (notifyUser) {
|
||||
teleportOwner.sendMessage(tl("pendingTeleportCancelled"));
|
||||
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
|
||||
ess.getUser(timer_teleportee).sendMessage(tl("pendingTeleportCancelled"));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
timer_task = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,337 +1,359 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.ChargeException;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.ISettings;
|
||||
import com.earth2me.essentials.api.IUser;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.SetExpFix;
|
||||
import com.earth2me.essentials.perm.NoCommandCostPermissions;
|
||||
import com.earth2me.essentials.perm.Permissions;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import lombok.Cleanup;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class Trade
|
||||
{
|
||||
private final transient String command;
|
||||
private final transient Double money;
|
||||
private final transient ItemStack itemStack;
|
||||
private final transient Integer exp;
|
||||
private final transient IEssentials ess;
|
||||
public class Trade {
|
||||
private final transient String command;
|
||||
private final transient Trade fallbackTrade;
|
||||
private final transient BigDecimal money;
|
||||
private final transient ItemStack itemStack;
|
||||
private final transient Integer exp;
|
||||
private final transient IEssentials ess;
|
||||
|
||||
public Trade(final String command, final IEssentials ess)
|
||||
{
|
||||
this(command, null, null, null, ess);
|
||||
}
|
||||
|
||||
public Trade(final double money, final IEssentials ess)
|
||||
{
|
||||
this(null, money, null, null, ess);
|
||||
}
|
||||
public enum TradeType {
|
||||
MONEY,
|
||||
EXP,
|
||||
ITEM
|
||||
}
|
||||
|
||||
public Trade(final ItemStack items, final IEssentials ess)
|
||||
{
|
||||
this(null, null, items, null, ess);
|
||||
}
|
||||
|
||||
public Trade(final int exp, final IEssentials ess)
|
||||
{
|
||||
this(null, null, null, exp, ess);
|
||||
}
|
||||
public enum OverflowType {
|
||||
ABORT,
|
||||
DROP,
|
||||
RETURN
|
||||
}
|
||||
|
||||
private Trade(final String command, final Double money, final ItemStack item, final Integer exp, final IEssentials ess)
|
||||
{
|
||||
this.command = command;
|
||||
this.money = money;
|
||||
this.itemStack = item;
|
||||
this.exp = exp;
|
||||
this.ess = ess;
|
||||
}
|
||||
public Trade(final String command, final IEssentials ess) {
|
||||
this(command, null, null, null, null, ess);
|
||||
}
|
||||
|
||||
public void isAffordableFor(final IUser user) throws ChargeException
|
||||
{
|
||||
final double mon = user.getMoney();
|
||||
if (getMoney() != null
|
||||
&& mon < getMoney()
|
||||
&& getMoney() > 0
|
||||
&& !Permissions.ECO_LOAN.isAuthorized(user))
|
||||
{
|
||||
throw new ChargeException(_("notEnoughMoney"));
|
||||
}
|
||||
public Trade(final String command, final Trade fallback, final IEssentials ess) {
|
||||
this(command, fallback, null, null, null, ess);
|
||||
}
|
||||
|
||||
if (getItemStack() != null
|
||||
&& !InventoryWorkaround.containsItem(user.getInventory(), true, true, itemStack))
|
||||
{
|
||||
throw new ChargeException(_("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
|
||||
}
|
||||
@Deprecated
|
||||
public Trade(final double money, final com.earth2me.essentials.IEssentials ess) {
|
||||
this(null, null, BigDecimal.valueOf(money), null, null, (IEssentials) ess);
|
||||
}
|
||||
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
public Trade(final BigDecimal money, final IEssentials ess) {
|
||||
this(null, null, money, null, null, ess);
|
||||
}
|
||||
|
||||
if (command != null && !command.isEmpty()
|
||||
&& !NoCommandCostPermissions.getPermission(command).isAuthorized(user)
|
||||
&& mon < settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command)
|
||||
&& 0 < settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command)
|
||||
&& !Permissions.ECO_LOAN.isAuthorized(user))
|
||||
{
|
||||
throw new ChargeException(_("notEnoughMoney"));
|
||||
}
|
||||
public Trade(final ItemStack items, final IEssentials ess) {
|
||||
this(null, null, null, items, null, ess);
|
||||
}
|
||||
|
||||
if (exp != null && exp > 0
|
||||
&& SetExpFix.getTotalExperience(user) < exp)
|
||||
{
|
||||
throw new ChargeException(_("notEnoughExperience"));
|
||||
}
|
||||
}
|
||||
public Trade(final int exp, final IEssentials ess) {
|
||||
this(null, null, null, null, exp, ess);
|
||||
}
|
||||
|
||||
public void pay(final IUser user)
|
||||
{
|
||||
pay(user, true);
|
||||
}
|
||||
private Trade(final String command, final Trade fallback, final BigDecimal money, final ItemStack item, final Integer exp, final IEssentials ess) {
|
||||
this.command = command;
|
||||
this.fallbackTrade = fallback;
|
||||
this.money = money;
|
||||
this.itemStack = item;
|
||||
this.exp = exp;
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
public boolean pay(final IUser user, final boolean dropItems)
|
||||
{
|
||||
boolean success = true;
|
||||
if (getMoney() != null && getMoney() > 0)
|
||||
{
|
||||
user.giveMoney(getMoney());
|
||||
}
|
||||
if (getItemStack() != null)
|
||||
{
|
||||
if (dropItems)
|
||||
{
|
||||
final Map<Integer, ItemStack> leftOver = InventoryWorkaround.addItem(user.getInventory(), true, getItemStack());
|
||||
final Location loc = user.getLocation();
|
||||
for (ItemStack dropStack : leftOver.values())
|
||||
{
|
||||
final int maxStackSize = dropStack.getType().getMaxStackSize();
|
||||
final int stacks = dropStack.getAmount() / maxStackSize;
|
||||
final int leftover = dropStack.getAmount() % maxStackSize;
|
||||
final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
|
||||
for (int i = 0; i < stacks; i++)
|
||||
{
|
||||
final ItemStack stack = dropStack.clone();
|
||||
stack.setAmount(maxStackSize);
|
||||
itemStacks[i] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
if (leftover > 0)
|
||||
{
|
||||
final ItemStack stack = dropStack.clone();
|
||||
stack.setAmount(leftover);
|
||||
itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = InventoryWorkaround.addAllItems(user.getInventory(), true, getItemStack());
|
||||
}
|
||||
user.updateInventory();
|
||||
}
|
||||
if (getExperience() != null)
|
||||
{
|
||||
SetExpFix.setTotalExperience(user, SetExpFix.getTotalExperience(user) + getExperience());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
public void isAffordableFor(final IUser user) throws ChargeException {
|
||||
|
||||
public void charge(final IUser user) throws ChargeException
|
||||
{
|
||||
if (getMoney() != null)
|
||||
{
|
||||
final double mon = user.getMoney();
|
||||
if (mon < getMoney() && getMoney() > 0 && !Permissions.ECO_LOAN.isAuthorized(user))
|
||||
{
|
||||
throw new ChargeException(_("notEnoughMoney"));
|
||||
}
|
||||
user.takeMoney(getMoney());
|
||||
}
|
||||
if (getItemStack() != null)
|
||||
{
|
||||
if (!InventoryWorkaround.containsItem(user.getInventory(), true, true, itemStack))
|
||||
{
|
||||
throw new ChargeException(_("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
|
||||
}
|
||||
InventoryWorkaround.removeItem(user.getInventory(), true, true, getItemStack());
|
||||
user.updateInventory();
|
||||
}
|
||||
if (command != null && !command.isEmpty()
|
||||
&& !NoCommandCostPermissions.getPermission(command).isAuthorized(user))
|
||||
{
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
final double mon = user.getMoney();
|
||||
final double cost = settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command);
|
||||
if (mon < cost && cost > 0 && !Permissions.ECO_LOAN.isAuthorized(user))
|
||||
{
|
||||
throw new ChargeException(_("notEnoughMoney"));
|
||||
}
|
||||
user.takeMoney(cost);
|
||||
}
|
||||
if (getExperience() != null)
|
||||
{
|
||||
final int experience = SetExpFix.getTotalExperience(user);
|
||||
if (experience < getExperience() && getExperience() > 0)
|
||||
{
|
||||
throw new ChargeException(_("notEnoughExperience"));
|
||||
}
|
||||
SetExpFix.setTotalExperience(user, experience - getExperience());
|
||||
}
|
||||
}
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + user.getName() + " can afford charge.");
|
||||
}
|
||||
|
||||
public Double getMoney()
|
||||
{
|
||||
return money;
|
||||
}
|
||||
if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
}
|
||||
|
||||
public ItemStack getItemStack()
|
||||
{
|
||||
return itemStack;
|
||||
}
|
||||
if (getItemStack() != null && !user.getBase().getInventory().containsAtLeast(itemStack, itemStack.getAmount())) {
|
||||
throw new ChargeException(tl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack())));
|
||||
}
|
||||
|
||||
public Integer getExperience()
|
||||
{
|
||||
return exp;
|
||||
}
|
||||
private static FileWriter fw = null;
|
||||
BigDecimal money;
|
||||
if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(money, ess)));
|
||||
}
|
||||
|
||||
public static void log(String type, String subtype, String event, String sender, Trade charge, String receiver, Trade pay, Location loc, IEssentials ess)
|
||||
{
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
if (!settings.getData().getEconomy().isLogEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fw == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fw = new FileWriter(new File(ess.getDataFolder(), "trade.log"), true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(type).append(",").append(subtype).append(",").append(event).append(",\"");
|
||||
sb.append(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date()));
|
||||
sb.append("\",\"");
|
||||
if (sender != null)
|
||||
{
|
||||
sb.append(sender);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (charge == null)
|
||||
{
|
||||
sb.append("\"\",\"\",\"\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (charge.getItemStack() != null)
|
||||
{
|
||||
sb.append(charge.getItemStack().getAmount()).append(",");
|
||||
sb.append(charge.getItemStack().getType().toString()).append(",");
|
||||
sb.append(charge.getItemStack().getDurability());
|
||||
}
|
||||
if (charge.getMoney() != null)
|
||||
{
|
||||
sb.append(charge.getMoney()).append(",");
|
||||
sb.append("money").append(",");
|
||||
sb.append(settings.getData().getEconomy().getCurrencySymbol());
|
||||
}
|
||||
if (charge.getExperience() != null)
|
||||
{
|
||||
sb.append(charge.getExperience()).append(",");
|
||||
sb.append("exp").append(",");
|
||||
sb.append("\"\"");
|
||||
}
|
||||
}
|
||||
sb.append(",\"");
|
||||
if (receiver != null)
|
||||
{
|
||||
sb.append(receiver);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (pay == null)
|
||||
{
|
||||
sb.append("\"\",\"\",\"\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pay.getItemStack() != null)
|
||||
{
|
||||
sb.append(pay.getItemStack().getAmount()).append(",");
|
||||
sb.append(pay.getItemStack().getType().toString()).append(",");
|
||||
sb.append(pay.getItemStack().getDurability());
|
||||
}
|
||||
if (pay.getMoney() != null)
|
||||
{
|
||||
sb.append(pay.getMoney()).append(",");
|
||||
sb.append("money").append(",");
|
||||
sb.append(settings.getData().getEconomy().getCurrencySymbol());
|
||||
}
|
||||
if (pay.getExperience() != null)
|
||||
{
|
||||
sb.append(pay.getExperience()).append(",");
|
||||
sb.append("exp").append(",");
|
||||
sb.append("\"\"");
|
||||
}
|
||||
}
|
||||
if (loc == null)
|
||||
{
|
||||
sb.append(",\"\",\"\",\"\",\"\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(",\"");
|
||||
sb.append(loc.getWorld().getName()).append("\",");
|
||||
sb.append(loc.getBlockX()).append(",");
|
||||
sb.append(loc.getBlockY()).append(",");
|
||||
sb.append(loc.getBlockZ()).append(",");
|
||||
}
|
||||
sb.append("\n");
|
||||
try
|
||||
{
|
||||
fw.write(sb.toString());
|
||||
fw.flush();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
if (exp != null && exp > 0 && SetExpFix.getTotalExperience(user.getBase()) < exp) {
|
||||
throw new ChargeException(tl("notEnoughExperience"));
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeLog()
|
||||
{
|
||||
if (fw != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fw.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger("Minecraft").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
fw = null;
|
||||
}
|
||||
}
|
||||
public boolean pay(final IUser user) throws MaxMoneyException {
|
||||
return pay(user, OverflowType.ABORT) == null;
|
||||
}
|
||||
|
||||
public Map<Integer, ItemStack> pay(final IUser user, final OverflowType type) throws MaxMoneyException {
|
||||
if (getMoney() != null && getMoney().signum() > 0) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying user " + user.getName() + " via trade " + getMoney().toPlainString());
|
||||
}
|
||||
user.giveMoney(getMoney());
|
||||
}
|
||||
if (getItemStack() != null) {
|
||||
// This stores the would be overflow
|
||||
Map<Integer, ItemStack> overFlow = InventoryWorkaround.addAllItems(user.getBase().getInventory(), getItemStack());
|
||||
|
||||
if (overFlow != null) {
|
||||
switch (type) {
|
||||
case ABORT:
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "abort paying " + user.getName() + " itemstack " + getItemStack().toString() + " due to lack of inventory space ");
|
||||
}
|
||||
|
||||
return overFlow;
|
||||
|
||||
case RETURN:
|
||||
// Pay the user the items, and return overflow
|
||||
final Map<Integer, ItemStack> returnStack = InventoryWorkaround.addItems(user.getBase().getInventory(), getItemStack());
|
||||
user.getBase().updateInventory();
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " with overflow " + returnStack.get(0).toString());
|
||||
}
|
||||
|
||||
return returnStack;
|
||||
|
||||
case DROP:
|
||||
// Pay the users the items directly, and drop the rest, will always return no overflow.
|
||||
final Map<Integer, ItemStack> leftOver = InventoryWorkaround.addItems(user.getBase().getInventory(), getItemStack());
|
||||
final Location loc = user.getBase().getLocation();
|
||||
for (ItemStack loStack : leftOver.values()) {
|
||||
final int maxStackSize = loStack.getType().getMaxStackSize();
|
||||
final int stacks = loStack.getAmount() / maxStackSize;
|
||||
final int leftover = loStack.getAmount() % maxStackSize;
|
||||
final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
|
||||
for (int i = 0; i < stacks; i++) {
|
||||
final ItemStack stack = loStack.clone();
|
||||
stack.setAmount(maxStackSize);
|
||||
itemStacks[i] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
if (leftover > 0) {
|
||||
final ItemStack stack = loStack.clone();
|
||||
stack.setAmount(leftover);
|
||||
itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
}
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " and dropping overflow " + leftOver.get(0).toString());
|
||||
}
|
||||
}
|
||||
} else if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " itemstack " + getItemStack().toString());
|
||||
}
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
if (getExperience() != null) {
|
||||
SetExpFix.setTotalExperience(user.getBase(), SetExpFix.getTotalExperience(user.getBase()) + getExperience());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void charge(final IUser user) throws ChargeException {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "attempting to charge user " + user.getName());
|
||||
}
|
||||
if (getMoney() != null) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString());
|
||||
}
|
||||
if (!user.canAfford(getMoney()) && getMoney().signum() > 0) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
}
|
||||
user.takeMoney(getMoney());
|
||||
}
|
||||
if (getItemStack() != null) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
|
||||
}
|
||||
if (!user.getBase().getInventory().containsAtLeast(getItemStack(), getItemStack().getAmount())) {
|
||||
throw new ChargeException(tl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
|
||||
}
|
||||
user.getBase().getInventory().removeItem(getItemStack());
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
if (command != null) {
|
||||
final BigDecimal cost = getCommandCost(user);
|
||||
if (!user.canAfford(cost) && cost.signum() > 0) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(cost, ess)));
|
||||
}
|
||||
user.takeMoney(cost);
|
||||
}
|
||||
if (getExperience() != null) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " exp " + getExperience());
|
||||
}
|
||||
final int experience = SetExpFix.getTotalExperience(user.getBase());
|
||||
if (experience < getExperience() && getExperience() > 0) {
|
||||
throw new ChargeException(tl("notEnoughExperience"));
|
||||
}
|
||||
SetExpFix.setTotalExperience(user.getBase(), experience - getExperience());
|
||||
}
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "charge user " + user.getName() + " completed");
|
||||
}
|
||||
}
|
||||
|
||||
public BigDecimal getMoney() {
|
||||
return money;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public Integer getExperience() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
public TradeType getType() {
|
||||
if (getExperience() != null) {
|
||||
return TradeType.EXP;
|
||||
}
|
||||
|
||||
if (getItemStack() != null) {
|
||||
return TradeType.ITEM;
|
||||
}
|
||||
|
||||
return TradeType.MONEY;
|
||||
}
|
||||
|
||||
public BigDecimal getCommandCost(final IUser user) {
|
||||
BigDecimal cost = BigDecimal.ZERO;
|
||||
if (command != null && !command.isEmpty()) {
|
||||
cost = ess.getSettings().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command);
|
||||
if (cost.signum() == 0 && fallbackTrade != null) {
|
||||
cost = fallbackTrade.getCommandCost(user);
|
||||
}
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "calculated command (" + command + ") cost for " + user.getName() + " as " + cost);
|
||||
}
|
||||
}
|
||||
if (cost.signum() != 0 && (user.isAuthorized("essentials.nocommandcost.all") || user.isAuthorized("essentials.nocommandcost." + command))) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private static FileWriter fw = null;
|
||||
|
||||
public static void log(String type, String subtype, String event, String sender, Trade charge, String receiver, Trade pay, Location loc, IEssentials ess) {
|
||||
//isEcoLogUpdateEnabled() - This refers to log entries with no location, ie API updates #EasterEgg
|
||||
//isEcoLogEnabled() - This refers to log entries with with location, ie /pay /sell and eco signs.
|
||||
|
||||
if ((loc == null && !ess.getSettings().isEcoLogUpdateEnabled()) || (loc != null && !ess.getSettings().isEcoLogEnabled())) {
|
||||
return;
|
||||
}
|
||||
if (fw == null) {
|
||||
try {
|
||||
fw = new FileWriter(new File(ess.getDataFolder(), "trade.log"), true);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(type).append(",").append(subtype).append(",").append(event).append(",\"");
|
||||
sb.append(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date()));
|
||||
sb.append("\",\"");
|
||||
if (sender != null) {
|
||||
sb.append(sender);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (charge == null) {
|
||||
sb.append("\"\",\"\",\"\"");
|
||||
} else {
|
||||
if (charge.getItemStack() != null) {
|
||||
sb.append(charge.getItemStack().getAmount()).append(",");
|
||||
sb.append(charge.getItemStack().getType().toString()).append(",");
|
||||
sb.append(charge.getItemStack().getDurability());
|
||||
}
|
||||
if (charge.getMoney() != null) {
|
||||
sb.append(charge.getMoney()).append(",");
|
||||
sb.append("money").append(",");
|
||||
sb.append(ess.getSettings().getCurrencySymbol());
|
||||
}
|
||||
if (charge.getExperience() != null) {
|
||||
sb.append(charge.getExperience()).append(",");
|
||||
sb.append("exp").append(",");
|
||||
sb.append("\"\"");
|
||||
}
|
||||
}
|
||||
sb.append(",\"");
|
||||
if (receiver != null) {
|
||||
sb.append(receiver);
|
||||
}
|
||||
sb.append("\",");
|
||||
if (pay == null) {
|
||||
sb.append("\"\",\"\",\"\"");
|
||||
} else {
|
||||
if (pay.getItemStack() != null) {
|
||||
sb.append(pay.getItemStack().getAmount()).append(",");
|
||||
sb.append(pay.getItemStack().getType().toString()).append(",");
|
||||
sb.append(pay.getItemStack().getDurability());
|
||||
}
|
||||
if (pay.getMoney() != null) {
|
||||
sb.append(pay.getMoney()).append(",");
|
||||
sb.append("money").append(",");
|
||||
sb.append(ess.getSettings().getCurrencySymbol());
|
||||
}
|
||||
if (pay.getExperience() != null) {
|
||||
sb.append(pay.getExperience()).append(",");
|
||||
sb.append("exp").append(",");
|
||||
sb.append("\"\"");
|
||||
}
|
||||
}
|
||||
if (loc == null) {
|
||||
sb.append(",\"\",\"\",\"\",\"\"");
|
||||
} else {
|
||||
sb.append(",\"");
|
||||
sb.append(loc.getWorld().getName()).append("\",");
|
||||
sb.append(loc.getBlockX()).append(",");
|
||||
sb.append(loc.getBlockY()).append(",");
|
||||
sb.append(loc.getBlockZ()).append(",");
|
||||
}
|
||||
sb.append("\n");
|
||||
try {
|
||||
fw.write(sb.toString());
|
||||
fw.flush();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeLog() {
|
||||
if (fw != null) {
|
||||
try {
|
||||
fw.close();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger("Essentials").log(Level.SEVERE, null, ex);
|
||||
}
|
||||
fw = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class UUIDMap {
|
||||
private final transient net.ess3.api.IEssentials ess;
|
||||
private File userList;
|
||||
private final transient Pattern splitPattern = Pattern.compile(",");
|
||||
|
||||
private static boolean pendingWrite;
|
||||
private static final ScheduledExecutorService writeScheduler = Executors.newScheduledThreadPool(1);
|
||||
private final Runnable writeTaskRunnable;
|
||||
|
||||
private static boolean loading = false;
|
||||
|
||||
public UUIDMap(final net.ess3.api.IEssentials ess) {
|
||||
this.ess = ess;
|
||||
userList = new File(ess.getDataFolder(), "usermap.csv");
|
||||
pendingWrite = false;
|
||||
writeTaskRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (pendingWrite) {
|
||||
try {
|
||||
new WriteRunner(ess.getDataFolder(), userList, ess.getUserMap().getNames()).run();
|
||||
} catch (Throwable t) { // bad code to prevent task from being suppressed
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
writeScheduler.scheduleWithFixedDelay(writeTaskRunnable, 5, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void loadAllUsers(final ConcurrentSkipListMap<String, UUID> names, final ConcurrentSkipListMap<UUID, ArrayList<String>> history) {
|
||||
try {
|
||||
if (!userList.exists()) {
|
||||
userList.createNewFile();
|
||||
}
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Reading usermap from disk");
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
names.clear();
|
||||
history.clear();
|
||||
loading = true;
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(userList))) {
|
||||
while (true) {
|
||||
final String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
} else {
|
||||
final String[] values = splitPattern.split(line);
|
||||
if (values.length == 2) {
|
||||
final String name = values[0];
|
||||
final UUID uuid = UUID.fromString(values[1]);
|
||||
names.put(name, uuid);
|
||||
if (!history.containsKey(uuid)) {
|
||||
final ArrayList<String> list = new ArrayList<>();
|
||||
list.add(name);
|
||||
history.put(uuid, list);
|
||||
} else {
|
||||
final ArrayList<String> list = history.get(uuid);
|
||||
if (!list.contains(name)) {
|
||||
list.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loading = false;
|
||||
} catch (IOException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeUUIDMap() {
|
||||
pendingWrite = true;
|
||||
}
|
||||
|
||||
public void forceWriteUUIDMap() {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Forcing usermap write to disk");
|
||||
}
|
||||
pendingWrite = true;
|
||||
writeTaskRunnable.run();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
writeScheduler.submit(writeTaskRunnable);
|
||||
writeScheduler.shutdown();
|
||||
}
|
||||
|
||||
private static class WriteRunner implements Runnable {
|
||||
private final File location;
|
||||
private final File endFile;
|
||||
private final Map<String, UUID> names;
|
||||
|
||||
private WriteRunner(final File location, final File endFile, final Map<String, UUID> names) {
|
||||
this.location = location;
|
||||
this.endFile = endFile;
|
||||
this.names = new HashMap<>(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
pendingWrite = false;
|
||||
if (loading || names.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
File configFile = null;
|
||||
|
||||
try {
|
||||
configFile = File.createTempFile("usermap", ".tmp.csv", location);
|
||||
|
||||
final BufferedWriter bWriter = new BufferedWriter(new FileWriter(configFile));
|
||||
for (Map.Entry<String, UUID> entry : names.entrySet()) {
|
||||
bWriter.write(entry.getKey() + "," + entry.getValue().toString());
|
||||
bWriter.newLine();
|
||||
}
|
||||
|
||||
bWriter.close();
|
||||
Files.move(configFile, endFile);
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
if (configFile != null && configFile.exists()) {
|
||||
Files.move(configFile, new File(endFile.getParentFile(), "usermap.bak.csv"));
|
||||
}
|
||||
} catch (Exception ex2) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex2.getMessage(), ex2);
|
||||
}
|
||||
Bukkit.getLogger().log(Level.WARNING, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,900 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
import com.earth2me.essentials.messaging.SimpleMessageRecipient;
|
||||
import com.earth2me.essentials.register.payment.Method;
|
||||
import com.earth2me.essentials.register.payment.Methods;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||
import net.ess3.api.events.JailStatusChangeEvent;
|
||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||
import net.ess3.api.events.UserBalanceUpdateEvent;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class User extends UserData implements Comparable<User>, IMessageRecipient, net.ess3.api.IUser {
|
||||
private static final Logger logger = Logger.getLogger("Essentials");
|
||||
private IMessageRecipient messageRecipient;
|
||||
private transient UUID teleportRequester;
|
||||
private transient boolean teleportRequestHere;
|
||||
private transient Location teleportLocation;
|
||||
private transient boolean vanished;
|
||||
private transient final Teleport teleport;
|
||||
private transient long teleportRequestTime;
|
||||
private transient long lastOnlineActivity;
|
||||
private transient long lastThrottledAction;
|
||||
private transient long lastActivity = System.currentTimeMillis();
|
||||
private boolean hidden = false;
|
||||
private boolean rightClickJump = false;
|
||||
private transient Location afkPosition = null;
|
||||
private boolean invSee = false;
|
||||
private boolean recipeSee = false;
|
||||
private boolean enderSee = false;
|
||||
private transient long teleportInvulnerabilityTimestamp = 0;
|
||||
private boolean ignoreMsg = false;
|
||||
private String afkMessage;
|
||||
private long afkSince;
|
||||
private Map<User, BigDecimal> confirmingPayments = new WeakHashMap<>();
|
||||
private String confirmingClearCommand;
|
||||
private long lastNotifiedAboutMailsMs;
|
||||
|
||||
public User(final Player base, final IEssentials ess) {
|
||||
super(base, ess);
|
||||
teleport = new Teleport(this, ess);
|
||||
if (isAfk()) {
|
||||
afkPosition = this.getLocation();
|
||||
}
|
||||
if (this.getBase().isOnline()) {
|
||||
lastOnlineActivity = System.currentTimeMillis();
|
||||
}
|
||||
this.messageRecipient = new SimpleMessageRecipient(ess, this);
|
||||
}
|
||||
|
||||
User update(final Player base) {
|
||||
setBase(base);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(final IEssentialsCommand cmd) {
|
||||
return isAuthorized(cmd, "essentials.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(final IEssentialsCommand cmd, final String permissionPrefix) {
|
||||
return isAuthorized(permissionPrefix + (cmd.getName().equals("r") ? "msg" : cmd.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(final String node) {
|
||||
final boolean result = isAuthorizedCheck(node);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " has " + node + " - " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isAuthorizedCheck(final String node) {
|
||||
|
||||
if (base instanceof OfflinePlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return ess.getPermissionsHandler().hasPermission(base, node);
|
||||
} catch (Exception ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage(), ex);
|
||||
} else {
|
||||
ess.getLogger().log(Level.SEVERE, "Permission System Error: " + ess.getPermissionsHandler().getName() + " returned: " + ex.getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void healCooldown() throws Exception {
|
||||
final Calendar now = new GregorianCalendar();
|
||||
if (getLastHealTimestamp() > 0) {
|
||||
final double cooldown = ess.getSettings().getHealCooldown();
|
||||
final Calendar cooldownTime = new GregorianCalendar();
|
||||
cooldownTime.setTimeInMillis(getLastHealTimestamp());
|
||||
cooldownTime.add(Calendar.SECOND, (int) cooldown);
|
||||
cooldownTime.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
|
||||
if (cooldownTime.after(now) && !isAuthorized("essentials.heal.cooldown.bypass")) {
|
||||
throw new Exception(tl("timeBeforeHeal", DateUtil.formatDateDiff(cooldownTime.getTimeInMillis())));
|
||||
}
|
||||
}
|
||||
setLastHealTimestamp(now.getTimeInMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveMoney(final BigDecimal value) throws MaxMoneyException {
|
||||
giveMoney(value, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveMoney(final BigDecimal value, final CommandSource initiator) throws MaxMoneyException {
|
||||
if (value.signum() == 0) {
|
||||
return;
|
||||
}
|
||||
setMoney(getMoney().add(value));
|
||||
sendMessage(tl("addedToAccount", NumberUtil.displayCurrency(value, ess)));
|
||||
if (initiator != null) {
|
||||
initiator.sendMessage(tl("addedToOthersAccount", NumberUtil.displayCurrency(value, ess), this.getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void payUser(final User reciever, final BigDecimal value) throws Exception {
|
||||
if (value.compareTo(BigDecimal.ZERO) < 1) {
|
||||
throw new Exception(tl("payMustBePositive"));
|
||||
}
|
||||
|
||||
if (canAfford(value)) {
|
||||
setMoney(getMoney().subtract(value));
|
||||
reciever.setMoney(reciever.getMoney().add(value));
|
||||
sendMessage(tl("moneySentTo", NumberUtil.displayCurrency(value, ess), reciever.getDisplayName()));
|
||||
reciever.sendMessage(tl("moneyRecievedFrom", NumberUtil.displayCurrency(value, ess), getDisplayName()));
|
||||
} else {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(value, ess)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void takeMoney(final BigDecimal value) {
|
||||
takeMoney(value, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void takeMoney(final BigDecimal value, final CommandSource initiator) {
|
||||
if (value.signum() == 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setMoney(getMoney().subtract(value));
|
||||
} catch (MaxMoneyException ex) {
|
||||
ess.getLogger().log(Level.WARNING, "Invalid call to takeMoney, total balance can't be more than the max-money limit.", ex);
|
||||
}
|
||||
sendMessage(tl("takenFromAccount", NumberUtil.displayCurrency(value, ess)));
|
||||
if (initiator != null) {
|
||||
initiator.sendMessage(tl("takenFromOthersAccount", NumberUtil.displayCurrency(value, ess), this.getDisplayName(), NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAfford(final BigDecimal cost) {
|
||||
return canAfford(cost, true);
|
||||
}
|
||||
|
||||
public boolean canAfford(final BigDecimal cost, final boolean permcheck) {
|
||||
if (cost.signum() <= 0) {
|
||||
return true;
|
||||
}
|
||||
final BigDecimal remainingBalance = getMoney().subtract(cost);
|
||||
if (!permcheck || isAuthorized("essentials.eco.loan")) {
|
||||
return (remainingBalance.compareTo(ess.getSettings().getMinMoney()) >= 0);
|
||||
}
|
||||
return (remainingBalance.signum() >= 0);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
_dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void _dispose() {
|
||||
if (!base.isOnline()) {
|
||||
this.base = new OfflinePlayer(getConfigUUID(), ess.getServer());
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean canSpawnItem(final Material material) {
|
||||
if (ess.getSettings().permissionBasedItemSpawn()) {
|
||||
final String name = material.toString().toLowerCase(Locale.ENGLISH).replace("_", "");
|
||||
|
||||
if (isAuthorized("essentials.itemspawn.item-all") || isAuthorized("essentials.itemspawn.item-" + name)) return true;
|
||||
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01)) {
|
||||
final int id = material.getId();
|
||||
if (isAuthorized("essentials.itemspawn.item-" + id)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return isAuthorized("essentials.itemspawn.exempt") || !ess.getSettings().itemSpawnBlacklist().contains(material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastLocation() {
|
||||
setLastLocation(this.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogoutLocation() {
|
||||
setLogoutLocation(this.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestTeleport(final User player, final boolean here) {
|
||||
teleportRequestTime = System.currentTimeMillis();
|
||||
teleportRequester = player == null ? null : player.getBase().getUniqueId();
|
||||
teleportRequestHere = here;
|
||||
if (player == null) {
|
||||
teleportLocation = null;
|
||||
} else {
|
||||
teleportLocation = here ? player.getLocation() : this.getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOutstandingTeleportRequest() {
|
||||
if (getTeleportRequest() != null) { // Player has outstanding teleport request.
|
||||
long timeout = ess.getSettings().getTpaAcceptCancellation();
|
||||
if (timeout != 0) {
|
||||
if ((System.currentTimeMillis() - getTeleportRequestTime()) / 1000 <= timeout) { // Player has outstanding request
|
||||
return true;
|
||||
} else { // outstanding request expired.
|
||||
requestTeleport(null, false);
|
||||
return false;
|
||||
}
|
||||
} else { // outstanding request does not expire
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public UUID getTeleportRequest() {
|
||||
return teleportRequester;
|
||||
}
|
||||
|
||||
public boolean isTpRequestHere() {
|
||||
return teleportRequestHere;
|
||||
}
|
||||
|
||||
public Location getTpRequestLocation() {
|
||||
return teleportLocation;
|
||||
}
|
||||
|
||||
public String getNick(final boolean longnick) {
|
||||
return getNick(longnick, true, true);
|
||||
}
|
||||
|
||||
public String getNick(final boolean longnick, final boolean withPrefix, final boolean withSuffix) {
|
||||
final StringBuilder prefix = new StringBuilder();
|
||||
String nickname;
|
||||
String suffix = "";
|
||||
final String nick = getNickname();
|
||||
if (ess.getSettings().isCommandDisabled("nick") || nick == null || nick.isEmpty() || nick.equals(getName())) {
|
||||
nickname = getName();
|
||||
} else if (nick.equalsIgnoreCase(getName())) {
|
||||
nickname = nick;
|
||||
} else {
|
||||
nickname = FormatUtil.replaceFormat(ess.getSettings().getNicknamePrefix()) + nick;
|
||||
suffix = "§r";
|
||||
}
|
||||
|
||||
if (this.getBase().isOp()) {
|
||||
try {
|
||||
final ChatColor opPrefix = ess.getSettings().getOperatorColor();
|
||||
if (opPrefix != null && opPrefix.toString().length() > 0) {
|
||||
prefix.insert(0, opPrefix.toString());
|
||||
suffix = "§r";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ess.getSettings().addPrefixSuffix()) {
|
||||
//These two extra toggles are not documented, because they are mostly redundant #EasterEgg
|
||||
if (withPrefix || !ess.getSettings().disablePrefix()) {
|
||||
final String ptext = ess.getPermissionsHandler().getPrefix(base).replace('&', '§');
|
||||
prefix.insert(0, ptext);
|
||||
suffix = "§r";
|
||||
}
|
||||
if (withSuffix || !ess.getSettings().disableSuffix()) {
|
||||
final String stext = ess.getPermissionsHandler().getSuffix(base).replace('&', '§');
|
||||
suffix = stext + "§r";
|
||||
suffix = suffix.replace("§f§f", "§f").replace("§f§r", "§r").replace("§r§r", "§r");
|
||||
}
|
||||
}
|
||||
final String strPrefix = prefix.toString();
|
||||
String output = strPrefix + nickname + suffix;
|
||||
if (!longnick && output.length() > 16) {
|
||||
output = strPrefix + nickname;
|
||||
}
|
||||
if (!longnick && output.length() > 16) {
|
||||
output = FormatUtil.lastCode(strPrefix) + nickname;
|
||||
}
|
||||
if (!longnick && output.length() > 16) {
|
||||
output = FormatUtil.lastCode(strPrefix) + nickname.substring(0, 14);
|
||||
}
|
||||
if (output.charAt(output.length() - 1) == '§') {
|
||||
output = output.substring(0, output.length() - 1);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public void setDisplayNick() {
|
||||
if (base.isOnline() && ess.getSettings().changeDisplayName()) {
|
||||
this.getBase().setDisplayName(getNick(true));
|
||||
if (isAfk()) {
|
||||
updateAfkListName();
|
||||
} else if (ess.getSettings().changePlayerListName()) {
|
||||
// 1.8 enabled player list-names longer than 16 characters.
|
||||
// If the server is on 1.8 or higher, provide that functionality. Otherwise, keep prior functionality.
|
||||
boolean higherOrEqualTo1_8 = ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_8_R1);
|
||||
String name = getNick(higherOrEqualTo1_8, ess.getSettings().isAddingPrefixInPlayerlist(), ess.getSettings().isAddingSuffixInPlayerlist());
|
||||
try {
|
||||
this.getBase().setPlayerListName(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
logger.log(Level.INFO, "Playerlist for " + name + " was not updated. Name clashed with another online player.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return super.getBase().getDisplayName() == null || (ess.getSettings().hideDisplayNameInVanish() && isHidden()) ? super.getBase().getName() : super.getBase().getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Teleport getTeleport() {
|
||||
return teleport;
|
||||
}
|
||||
|
||||
public long getLastOnlineActivity() {
|
||||
return lastOnlineActivity;
|
||||
}
|
||||
|
||||
public void setLastOnlineActivity(final long timestamp) {
|
||||
lastOnlineActivity = timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getMoney() {
|
||||
final long start = System.nanoTime();
|
||||
final BigDecimal value = _getMoney();
|
||||
final long elapsed = System.nanoTime() - start;
|
||||
if (elapsed > ess.getSettings().getEconomyLagWarning()) {
|
||||
ess.getLogger().log(Level.INFO, "Lag Notice - Slow Economy Response - Request took over {0}ms!", elapsed / 1000000.0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private BigDecimal _getMoney() {
|
||||
if (ess.getSettings().isEcoDisabled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Internal economy functions disabled, aborting balance check.");
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (Methods.hasMethod()) {
|
||||
try {
|
||||
final Method method = Methods.getMethod();
|
||||
if (!method.hasAccount(this.getName())) {
|
||||
throw new Exception();
|
||||
}
|
||||
final Method.MethodAccount account = Methods.getMethod().getAccount(this.getName());
|
||||
return BigDecimal.valueOf(account.balance());
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
return super.getMoney();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMoney(final BigDecimal value) throws MaxMoneyException {
|
||||
if (ess.getSettings().isEcoDisabled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Internal economy functions disabled, aborting balance change.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
final BigDecimal oldBalance = _getMoney();
|
||||
|
||||
UserBalanceUpdateEvent updateEvent = new UserBalanceUpdateEvent(this.getBase(), oldBalance, value);
|
||||
ess.getServer().getPluginManager().callEvent(updateEvent);
|
||||
BigDecimal newBalance = updateEvent.getNewBalance();
|
||||
|
||||
if (Methods.hasMethod()) {
|
||||
try {
|
||||
final Method method = Methods.getMethod();
|
||||
if (!method.hasAccount(this.getName())) {
|
||||
throw new Exception();
|
||||
}
|
||||
final Method.MethodAccount account = Methods.getMethod().getAccount(this.getName());
|
||||
account.set(newBalance.doubleValue());
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
super.setMoney(newBalance, true);
|
||||
Trade.log("Update", "Set", "API", getName(), new Trade(newBalance, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
public void updateMoneyCache(final BigDecimal value) {
|
||||
if (ess.getSettings().isEcoDisabled()) {
|
||||
return;
|
||||
}
|
||||
if (Methods.hasMethod() && super.getMoney() != value) {
|
||||
try {
|
||||
super.setMoney(value, false);
|
||||
} catch (MaxMoneyException ex) {
|
||||
// We don't want to throw any errors here, just updating a cache
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAfk(final boolean set) {
|
||||
final AfkStatusChangeEvent afkEvent = new AfkStatusChangeEvent(this, set);
|
||||
ess.getServer().getPluginManager().callEvent(afkEvent);
|
||||
if (afkEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.getBase().setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") ? true : set);
|
||||
if (set && !isAfk()) {
|
||||
afkPosition = this.getLocation();
|
||||
this.afkSince = System.currentTimeMillis();
|
||||
} else if (!set && isAfk()) {
|
||||
afkPosition = null;
|
||||
this.afkMessage = null;
|
||||
this.afkSince = 0;
|
||||
}
|
||||
_setAfk(set);
|
||||
updateAfkListName();
|
||||
}
|
||||
|
||||
private void updateAfkListName() {
|
||||
if (ess.getSettings().isAfkListName()) {
|
||||
if(isAfk()) {
|
||||
String afkName = ess.getSettings().getAfkListName().replace("{PLAYER}", getDisplayName()).replace("{USERNAME}", getName());
|
||||
getBase().setPlayerListName(afkName);
|
||||
} else {
|
||||
getBase().setPlayerListName(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean toggleAfk() {
|
||||
setAfk(!isAfk());
|
||||
return isAfk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public boolean isHidden(final Player player) {
|
||||
return hidden || !player.canSee(getBase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHidden(final boolean hidden) {
|
||||
this.hidden = hidden;
|
||||
if (hidden == true) {
|
||||
setLastLogout(getLastOnlineActivity());
|
||||
}
|
||||
}
|
||||
|
||||
//Returns true if status expired during this check
|
||||
public boolean checkJailTimeout(final long currentTime) {
|
||||
if (getJailTimeout() > 0 && getJailTimeout() < currentTime && isJailed()) {
|
||||
final JailStatusChangeEvent event = new JailStatusChangeEvent(this, null, false);
|
||||
ess.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
setJailTimeout(0);
|
||||
setJailed(false);
|
||||
sendMessage(tl("haveBeenReleased"));
|
||||
setJail(null);
|
||||
try {
|
||||
getTeleport().back();
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
getTeleport().respawn(null, TeleportCause.PLUGIN);
|
||||
} catch (Exception ex1) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Returns true if status expired during this check
|
||||
public boolean checkMuteTimeout(final long currentTime) {
|
||||
if (getMuteTimeout() > 0 && getMuteTimeout() < currentTime && isMuted()) {
|
||||
final MuteStatusChangeEvent event = new MuteStatusChangeEvent(this, null, false);
|
||||
ess.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
setMuteTimeout(0);
|
||||
sendMessage(tl("canTalkAgain"));
|
||||
setMuted(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateActivity(final boolean broadcast) {
|
||||
if (isAfk()) {
|
||||
setAfk(false);
|
||||
if (broadcast && !isHidden()) {
|
||||
setDisplayNick();
|
||||
final String msg = tl("userIsNotAway", getDisplayName());
|
||||
if (!msg.isEmpty()) {
|
||||
ess.broadcastMessage(this, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void updateActivityOnMove(final boolean broadcast) {
|
||||
if(ess.getSettings().cancelAfkOnMove()) {
|
||||
updateActivity(broadcast);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateActivityOnInteract(final boolean broadcast) {
|
||||
if(ess.getSettings().cancelAfkOnInteract()) {
|
||||
updateActivity(broadcast);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkActivity() {
|
||||
// Graceful time before the first afk check call.
|
||||
if (System.currentTimeMillis() - lastActivity <= 10000) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long autoafkkick = ess.getSettings().getAutoAfkKick();
|
||||
if (autoafkkick > 0
|
||||
&& lastActivity > 0 && (lastActivity + (autoafkkick * 1000)) < System.currentTimeMillis()
|
||||
&& !isAuthorized("essentials.kick.exempt")
|
||||
&& !isAuthorized("essentials.afk.kickexempt")) {
|
||||
final String kickReason = tl("autoAfkKickReason", autoafkkick / 60.0);
|
||||
lastActivity = 0;
|
||||
this.getBase().kickPlayer(kickReason);
|
||||
|
||||
|
||||
for (User user : ess.getOnlineUsers()) {
|
||||
if (user.isAuthorized("essentials.kick.notify")) {
|
||||
user.sendMessage(tl("playerKicked", Console.NAME, getName(), kickReason));
|
||||
}
|
||||
}
|
||||
}
|
||||
final long autoafk = ess.getSettings().getAutoAfk();
|
||||
if (!isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk.auto")) {
|
||||
setAfk(true);
|
||||
if (!isHidden()) {
|
||||
setDisplayNick();
|
||||
final String msg = tl("userIsAway", getDisplayName());
|
||||
if (!msg.isEmpty()) {
|
||||
ess.broadcastMessage(this, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Location getAfkPosition() {
|
||||
return afkPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGodModeEnabled() {
|
||||
if (super.isGodModeEnabled()) {
|
||||
// This enables the no-god-in-worlds functionality where the actual player god mode state is never modified in disabled worlds,
|
||||
// but this method gets called every time the player takes damage. In the case that the world has god-mode disabled then this method
|
||||
// will return false and the player will take damage, even though they are in god mode (isGodModeEnabledRaw()).
|
||||
if (!ess.getSettings().getNoGodWorlds().contains(this.getLocation().getWorld().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (isAfk()) {
|
||||
// Protect AFK players by representing them in a god mode state to render them invulnerable to damage.
|
||||
if (ess.getSettings().getFreezeAfkPlayers()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGodModeEnabledRaw() {
|
||||
return super.isGodModeEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
final String result = ess.getPermissionsHandler().getGroup(base);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "looking up groupname of " + base.getName() + " - " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inGroup(final String group) {
|
||||
final boolean result = ess.getPermissionsHandler().inGroup(base, group);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + base.getName() + " is in group " + group + " - " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBuild() {
|
||||
if (this.getBase().isOp()) {
|
||||
return true;
|
||||
}
|
||||
return ess.getPermissionsHandler().canBuild(base, getGroup());
|
||||
}
|
||||
|
||||
public long getTeleportRequestTime() {
|
||||
return teleportRequestTime;
|
||||
}
|
||||
|
||||
public boolean isInvSee() {
|
||||
return invSee;
|
||||
}
|
||||
|
||||
public void setInvSee(final boolean set) {
|
||||
invSee = set;
|
||||
}
|
||||
|
||||
public boolean isEnderSee() {
|
||||
return enderSee;
|
||||
}
|
||||
|
||||
public void setEnderSee(final boolean set) {
|
||||
enderSee = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableInvulnerabilityAfterTeleport() {
|
||||
final long time = ess.getSettings().getTeleportInvulnerability();
|
||||
if (time > 0) {
|
||||
teleportInvulnerabilityTimestamp = System.currentTimeMillis() + time;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetInvulnerabilityAfterTeleport() {
|
||||
if (teleportInvulnerabilityTimestamp != 0 && teleportInvulnerabilityTimestamp < System.currentTimeMillis()) {
|
||||
teleportInvulnerabilityTimestamp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInvulnerabilityAfterTeleport() {
|
||||
return teleportInvulnerabilityTimestamp != 0 && teleportInvulnerabilityTimestamp >= System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean canInteractVanished() {
|
||||
return isAuthorized("essentials.vanish.interact");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoreMsg() {
|
||||
return ignoreMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIgnoreMsg(boolean ignoreMsg) {
|
||||
this.ignoreMsg = ignoreMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanished() {
|
||||
return vanished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVanished(final boolean set) {
|
||||
vanished = set;
|
||||
if (set) {
|
||||
for (User user : ess.getOnlineUsers()) {
|
||||
if (!user.isAuthorized("essentials.vanish.see")) {
|
||||
user.getBase().hidePlayer(getBase());
|
||||
}
|
||||
}
|
||||
setHidden(true);
|
||||
ess.getVanishedPlayersNew().add(getName());
|
||||
if (isAuthorized("essentials.vanish.effect")) {
|
||||
this.getBase().addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 1, false));
|
||||
}
|
||||
} else {
|
||||
for (Player p : ess.getOnlinePlayers()) {
|
||||
p.showPlayer(getBase());
|
||||
}
|
||||
setHidden(false);
|
||||
ess.getVanishedPlayersNew().remove(getName());
|
||||
if (isAuthorized("essentials.vanish.effect")) {
|
||||
this.getBase().removePotionEffect(PotionEffectType.INVISIBILITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkSignThrottle() {
|
||||
if (isSignThrottled()) {
|
||||
return true;
|
||||
}
|
||||
updateThrottle();
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSignThrottled() {
|
||||
final long minTime = lastThrottledAction + (1000 / ess.getSettings().getSignUsePerSecond());
|
||||
return (System.currentTimeMillis() < minTime);
|
||||
}
|
||||
|
||||
public void updateThrottle() {
|
||||
lastThrottledAction = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean isFlyClickJump() {
|
||||
return rightClickJump;
|
||||
}
|
||||
|
||||
public void setRightClickJump(boolean rightClickJump) {
|
||||
this.rightClickJump = rightClickJump;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoreExempt() {
|
||||
return this.isAuthorized("essentials.chat.ignoreexempt");
|
||||
}
|
||||
|
||||
public boolean isRecipeSee() {
|
||||
return recipeSee;
|
||||
}
|
||||
|
||||
public void setRecipeSee(boolean recipeSee) {
|
||||
this.recipeSee = recipeSee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if (!message.isEmpty()) {
|
||||
base.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final User other) {
|
||||
return FormatUtil.stripFormat(getDisplayName()).compareToIgnoreCase(FormatUtil.stripFormat(other.getDisplayName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (!(object instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
return this.getName().equalsIgnoreCase(((User) object).getName());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSource getSource() {
|
||||
return new CommandSource(getBase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.getBase().getName();
|
||||
}
|
||||
|
||||
@Override public boolean isReachable() {
|
||||
return getBase().isOnline();
|
||||
}
|
||||
|
||||
@Override public MessageResponse sendMessage(IMessageRecipient recipient, String message) {
|
||||
return this.messageRecipient.sendMessage(recipient, message);
|
||||
}
|
||||
|
||||
@Override public MessageResponse onReceiveMessage(IMessageRecipient sender, String message) {
|
||||
return this.messageRecipient.onReceiveMessage(sender, message);
|
||||
}
|
||||
|
||||
@Override public IMessageRecipient getReplyRecipient() {
|
||||
return this.messageRecipient.getReplyRecipient();
|
||||
}
|
||||
|
||||
@Override public void setReplyRecipient(IMessageRecipient recipient) {
|
||||
this.messageRecipient.setReplyRecipient(recipient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAfkMessage() {
|
||||
return this.afkMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAfkMessage(String message) {
|
||||
if (isAfk()) {
|
||||
this.afkMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAfkSince() {
|
||||
return afkSince;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<User, BigDecimal> getConfirmingPayments() {
|
||||
return confirmingPayments;
|
||||
}
|
||||
|
||||
public String getConfirmingClearCommand() {
|
||||
return confirmingClearCommand;
|
||||
}
|
||||
|
||||
public void setConfirmingClearCommand(String command) {
|
||||
this.confirmingClearCommand = command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ItemStack} in the main hand or off-hand. If the main hand is empty then the offhand item is returned - also nullable.
|
||||
*/
|
||||
public ItemStack getItemInHand() {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
|
||||
return getBase().getInventory().getItemInHand();
|
||||
} else {
|
||||
PlayerInventory inventory = getBase().getInventory();
|
||||
return inventory.getItemInMainHand() != null ? inventory.getItemInMainHand() : inventory.getItemInOffHand();
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyOfMail() {
|
||||
List<String> mails = getMails();
|
||||
if (mails != null && !mails.isEmpty()) {
|
||||
int notifyPlayerOfMailCooldown = ess.getSettings().getNotifyPlayerOfMailCooldown() * 1000;
|
||||
if (System.currentTimeMillis() - lastNotifiedAboutMailsMs >= notifyPlayerOfMailCooldown) {
|
||||
sendMessage(tl("youHaveNewMail", mails.size()));
|
||||
lastNotifiedAboutMailsMs = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,959 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.InvalidWorldException;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public abstract class UserData extends PlayerExtension implements IConf {
|
||||
protected final transient IEssentials ess;
|
||||
private final EssentialsUserConf config;
|
||||
private final File folder;
|
||||
|
||||
protected UserData(Player base, IEssentials ess) {
|
||||
super(base);
|
||||
this.ess = ess;
|
||||
folder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs();
|
||||
}
|
||||
|
||||
String filename;
|
||||
try {
|
||||
filename = base.getUniqueId().toString();
|
||||
} catch (Throwable ex) {
|
||||
ess.getLogger().warning("Falling back to old username system for " + base.getName());
|
||||
filename = base.getName();
|
||||
}
|
||||
|
||||
config = new EssentialsUserConf(base.getName(), base.getUniqueId(), new File(folder, filename + ".yml"));
|
||||
reloadConfig();
|
||||
}
|
||||
|
||||
public final void reset() {
|
||||
config.forceSave();
|
||||
config.getFile().delete();
|
||||
if (config.username != null) {
|
||||
ess.getUserMap().removeUser(config.username);
|
||||
}
|
||||
}
|
||||
|
||||
public final void cleanup() {
|
||||
config.cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void reloadConfig() {
|
||||
config.load();
|
||||
money = _getMoney();
|
||||
unlimited = _getUnlimited();
|
||||
powertools = _getPowertools();
|
||||
homes = _getHomes();
|
||||
lastLocation = _getLastLocation();
|
||||
lastTeleportTimestamp = _getLastTeleportTimestamp();
|
||||
lastHealTimestamp = _getLastHealTimestamp();
|
||||
jail = _getJail();
|
||||
mails = _getMails();
|
||||
teleportEnabled = _getTeleportEnabled();
|
||||
godmode = _getGodModeEnabled();
|
||||
muted = _getMuted();
|
||||
muteTimeout = _getMuteTimeout();
|
||||
jailed = _getJailed();
|
||||
jailTimeout = _getJailTimeout();
|
||||
lastLogin = _getLastLogin();
|
||||
lastLogout = _getLastLogout();
|
||||
lastLoginAddress = _getLastLoginAddress();
|
||||
afk = _getAfk();
|
||||
geolocation = _getGeoLocation();
|
||||
isSocialSpyEnabled = _isSocialSpyEnabled();
|
||||
isNPC = _isNPC();
|
||||
arePowerToolsEnabled = _arePowerToolsEnabled();
|
||||
kitTimestamps = _getKitTimestamps();
|
||||
nickname = _getNickname();
|
||||
ignoredPlayers = _getIgnoredPlayers();
|
||||
logoutLocation = _getLogoutLocation();
|
||||
lastAccountName = _getLastAccountName();
|
||||
commandCooldowns = _getCommandCooldowns();
|
||||
acceptingPay = _getAcceptingPay();
|
||||
confirmPay = _getConfirmPay();
|
||||
confirmClear = _getConfirmClear();
|
||||
}
|
||||
|
||||
private BigDecimal money;
|
||||
|
||||
private BigDecimal _getMoney() {
|
||||
BigDecimal result = ess.getSettings().getStartingBalance();
|
||||
BigDecimal maxMoney = ess.getSettings().getMaxMoney();
|
||||
BigDecimal minMoney = ess.getSettings().getMinMoney();
|
||||
|
||||
// NPC banks are not actual player banks, as such they do not have player starting balance.
|
||||
if (isNPC()) {
|
||||
result = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
if (config.hasProperty("money")) {
|
||||
result = config.getBigDecimal("money", result);
|
||||
}
|
||||
if (result.compareTo(maxMoney) > 0) {
|
||||
result = maxMoney;
|
||||
}
|
||||
if (result.compareTo(minMoney) < 0) {
|
||||
result = minMoney;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public BigDecimal getMoney() {
|
||||
return money;
|
||||
}
|
||||
|
||||
public void setMoney(BigDecimal value, boolean throwError) throws MaxMoneyException {
|
||||
BigDecimal maxMoney = ess.getSettings().getMaxMoney();
|
||||
BigDecimal minMoney = ess.getSettings().getMinMoney();
|
||||
if (value.compareTo(maxMoney) > 0) {
|
||||
if (throwError) {
|
||||
throw new MaxMoneyException();
|
||||
}
|
||||
money = maxMoney;
|
||||
} else {
|
||||
money = value;
|
||||
}
|
||||
if (money.compareTo(minMoney) < 0) {
|
||||
money = minMoney;
|
||||
}
|
||||
config.setProperty("money", money);
|
||||
stopTransaction();
|
||||
}
|
||||
|
||||
private Map<String, Object> homes;
|
||||
|
||||
private Map<String, Object> _getHomes() {
|
||||
if (config.isConfigurationSection("homes")) {
|
||||
return config.getConfigurationSection("homes").getValues(false);
|
||||
}
|
||||
return new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
private String getHomeName(String search) {
|
||||
if (NumberUtil.isInt(search)) {
|
||||
try {
|
||||
search = getHomes().get(Integer.parseInt(search) - 1);
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
}
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
public Location getHome(String name) throws Exception {
|
||||
String search = getHomeName(name);
|
||||
return config.getLocation("homes." + search, this.getBase().getServer());
|
||||
}
|
||||
|
||||
public Location getHome(final Location world) {
|
||||
try {
|
||||
if (getHomes().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Location loc;
|
||||
for (String home : getHomes()) {
|
||||
loc = config.getLocation("homes." + home, this.getBase().getServer());
|
||||
if (world.getWorld() == loc.getWorld()) {
|
||||
return loc;
|
||||
}
|
||||
|
||||
}
|
||||
loc = config.getLocation("homes." + getHomes().get(0), this.getBase().getServer());
|
||||
return loc;
|
||||
} catch (InvalidWorldException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getHomes() {
|
||||
return new ArrayList<String>(homes.keySet());
|
||||
}
|
||||
|
||||
public void setHome(String name, Location loc) {
|
||||
//Invalid names will corrupt the yaml
|
||||
name = StringUtil.safeString(name);
|
||||
homes.put(name, loc);
|
||||
config.setProperty("homes." + name, loc);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public void delHome(String name) throws Exception {
|
||||
String search = getHomeName(name);
|
||||
if (!homes.containsKey(search)) {
|
||||
search = StringUtil.safeString(search);
|
||||
}
|
||||
if (homes.containsKey(search)) {
|
||||
homes.remove(search);
|
||||
config.removeProperty("homes." + search);
|
||||
config.save();
|
||||
} else {
|
||||
throw new Exception(tl("invalidHome", search));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasHome() {
|
||||
return config.hasProperty("home");
|
||||
}
|
||||
|
||||
private String nickname;
|
||||
|
||||
public String _getNickname() {
|
||||
return config.getString("nickname");
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nick) {
|
||||
nickname = nick;
|
||||
config.setProperty("nickname", nick);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private List<Material> unlimited;
|
||||
|
||||
private List<Material> _getUnlimited() {
|
||||
List<Material> retlist = new ArrayList<>();
|
||||
List<String> configList = config.getStringList("unlimited");
|
||||
for(String s : configList) {
|
||||
Material mat = Material.matchMaterial(s);
|
||||
if(mat != null) {
|
||||
retlist.add(mat);
|
||||
}
|
||||
}
|
||||
|
||||
return retlist;
|
||||
}
|
||||
|
||||
public List<Material> getUnlimited() {
|
||||
return unlimited;
|
||||
}
|
||||
|
||||
public boolean hasUnlimited(ItemStack stack) {
|
||||
return unlimited.contains(stack.getType());
|
||||
}
|
||||
|
||||
public void setUnlimited(ItemStack stack, boolean state) {
|
||||
if (unlimited.contains(stack.getType())) {
|
||||
unlimited.remove(stack.getType());
|
||||
}
|
||||
if (state) {
|
||||
unlimited.add(stack.getType());
|
||||
}
|
||||
config.setProperty("unlimited", unlimited);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private Map<String, Object> powertools;
|
||||
|
||||
private Map<String, Object> _getPowertools() {
|
||||
if (config.isConfigurationSection("powertools")) {
|
||||
return config.getConfigurationSection("powertools").getValues(false);
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public void clearAllPowertools() {
|
||||
powertools.clear();
|
||||
config.setProperty("powertools", powertools);
|
||||
config.save();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> getPowertool(ItemStack stack) {
|
||||
return (List<String>) powertools.get(stack.getType().name().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> getPowertool(Material material) {
|
||||
return (List<String>) powertools.get(material.name().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
public void setPowertool(ItemStack stack, List<String> commandList) {
|
||||
if (commandList == null || commandList.isEmpty()) {
|
||||
powertools.remove(stack.getType().name().toLowerCase(Locale.ENGLISH));
|
||||
} else {
|
||||
powertools.put(stack.getType().name().toLowerCase(Locale.ENGLISH), commandList);
|
||||
}
|
||||
config.setProperty("powertools", powertools);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean hasPowerTools() {
|
||||
return !powertools.isEmpty();
|
||||
}
|
||||
|
||||
private Location lastLocation;
|
||||
|
||||
private Location _getLastLocation() {
|
||||
try {
|
||||
return config.getLocation("lastlocation", this.getBase().getServer());
|
||||
} catch (InvalidWorldException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Location getLastLocation() {
|
||||
return lastLocation;
|
||||
}
|
||||
|
||||
public void setLastLocation(Location loc) {
|
||||
if (loc == null || loc.getWorld() == null) {
|
||||
return;
|
||||
}
|
||||
lastLocation = loc;
|
||||
config.setProperty("lastlocation", loc);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private Location logoutLocation;
|
||||
|
||||
private Location _getLogoutLocation() {
|
||||
try {
|
||||
return config.getLocation("logoutlocation", this.getBase().getServer());
|
||||
} catch (InvalidWorldException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Location getLogoutLocation() {
|
||||
return logoutLocation;
|
||||
}
|
||||
|
||||
public void setLogoutLocation(Location loc) {
|
||||
if (loc == null || loc.getWorld() == null) {
|
||||
return;
|
||||
}
|
||||
logoutLocation = loc;
|
||||
config.setProperty("logoutlocation", loc);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private long lastTeleportTimestamp;
|
||||
|
||||
private long _getLastTeleportTimestamp() {
|
||||
return config.getLong("timestamps.lastteleport", 0);
|
||||
}
|
||||
|
||||
public long getLastTeleportTimestamp() {
|
||||
return lastTeleportTimestamp;
|
||||
}
|
||||
|
||||
public void setLastTeleportTimestamp(long time) {
|
||||
lastTeleportTimestamp = time;
|
||||
config.setProperty("timestamps.lastteleport", time);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private long lastHealTimestamp;
|
||||
|
||||
private long _getLastHealTimestamp() {
|
||||
return config.getLong("timestamps.lastheal", 0);
|
||||
}
|
||||
|
||||
public long getLastHealTimestamp() {
|
||||
return lastHealTimestamp;
|
||||
}
|
||||
|
||||
public void setLastHealTimestamp(long time) {
|
||||
lastHealTimestamp = time;
|
||||
config.setProperty("timestamps.lastheal", time);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private String jail;
|
||||
|
||||
private String _getJail() {
|
||||
return config.getString("jail");
|
||||
}
|
||||
|
||||
public String getJail() {
|
||||
return jail;
|
||||
}
|
||||
|
||||
public void setJail(String jail) {
|
||||
if (jail == null || jail.isEmpty()) {
|
||||
this.jail = null;
|
||||
config.removeProperty("jail");
|
||||
} else {
|
||||
this.jail = jail;
|
||||
config.setProperty("jail", jail);
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
private List<String> mails;
|
||||
|
||||
private List<String> _getMails() {
|
||||
return config.getStringList("mail");
|
||||
}
|
||||
|
||||
public List<String> getMails() {
|
||||
return mails;
|
||||
}
|
||||
|
||||
public void setMails(List<String> mails) {
|
||||
if (mails == null) {
|
||||
config.removeProperty("mail");
|
||||
mails = _getMails();
|
||||
} else {
|
||||
config.setProperty("mail", mails);
|
||||
}
|
||||
this.mails = mails;
|
||||
config.save();
|
||||
}
|
||||
|
||||
public void addMail(String mail) {
|
||||
mails.add(mail);
|
||||
setMails(mails);
|
||||
}
|
||||
|
||||
private boolean teleportEnabled;
|
||||
|
||||
private boolean _getTeleportEnabled() {
|
||||
return config.getBoolean("teleportenabled", true);
|
||||
}
|
||||
|
||||
public boolean isTeleportEnabled() {
|
||||
return teleportEnabled;
|
||||
}
|
||||
|
||||
public void setTeleportEnabled(boolean set) {
|
||||
teleportEnabled = set;
|
||||
config.setProperty("teleportenabled", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private List<String> ignoredPlayers;
|
||||
|
||||
public List<String> _getIgnoredPlayers() {
|
||||
return Collections.synchronizedList(config.getStringList("ignore"));
|
||||
}
|
||||
|
||||
public void setIgnoredPlayers(List<String> players) {
|
||||
if (players == null || players.isEmpty()) {
|
||||
ignoredPlayers = Collections.synchronizedList(new ArrayList<String>());
|
||||
config.removeProperty("ignore");
|
||||
} else {
|
||||
ignoredPlayers = players;
|
||||
config.setProperty("ignore", players);
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean isIgnoredPlayer(final String userName) {
|
||||
final IUser user = ess.getUser(userName);
|
||||
if (user == null || !user.getBase().isOnline()) {
|
||||
return false;
|
||||
}
|
||||
return isIgnoredPlayer(user);
|
||||
}
|
||||
|
||||
public boolean isIgnoredPlayer(IUser user) {
|
||||
return (ignoredPlayers.contains(user.getName().toLowerCase(Locale.ENGLISH)) && !user.isIgnoreExempt());
|
||||
}
|
||||
|
||||
public void setIgnoredPlayer(IUser user, boolean set) {
|
||||
final String entry = user.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (set) {
|
||||
if (!ignoredPlayers.contains(entry)) ignoredPlayers.add(entry);
|
||||
} else {
|
||||
ignoredPlayers.remove(entry);
|
||||
}
|
||||
setIgnoredPlayers(ignoredPlayers);
|
||||
}
|
||||
|
||||
private boolean godmode;
|
||||
|
||||
private boolean _getGodModeEnabled() {
|
||||
return config.getBoolean("godmode", false);
|
||||
}
|
||||
|
||||
public boolean isGodModeEnabled() {
|
||||
return godmode;
|
||||
}
|
||||
|
||||
public void setGodModeEnabled(boolean set) {
|
||||
godmode = set;
|
||||
config.setProperty("godmode", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean muted;
|
||||
|
||||
public boolean _getMuted() {
|
||||
return config.getBoolean("muted", false);
|
||||
}
|
||||
|
||||
public boolean getMuted() {
|
||||
return muted;
|
||||
}
|
||||
|
||||
public boolean isMuted() {
|
||||
return muted;
|
||||
}
|
||||
|
||||
public void setMuted(boolean set) {
|
||||
muted = set;
|
||||
config.setProperty("muted", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private long muteTimeout;
|
||||
|
||||
private long _getMuteTimeout() {
|
||||
return config.getLong("timestamps.mute", 0);
|
||||
}
|
||||
|
||||
public long getMuteTimeout() {
|
||||
return muteTimeout;
|
||||
}
|
||||
|
||||
public void setMuteTimeout(long time) {
|
||||
muteTimeout = time;
|
||||
config.setProperty("timestamps.mute", time);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean jailed;
|
||||
|
||||
private boolean _getJailed() {
|
||||
return config.getBoolean("jailed", false);
|
||||
}
|
||||
|
||||
public boolean isJailed() {
|
||||
return jailed;
|
||||
}
|
||||
|
||||
public void setJailed(boolean set) {
|
||||
jailed = set;
|
||||
config.setProperty("jailed", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean toggleJailed() {
|
||||
boolean ret = !isJailed();
|
||||
setJailed(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private long jailTimeout;
|
||||
|
||||
private long _getJailTimeout() {
|
||||
return config.getLong("timestamps.jail", 0);
|
||||
}
|
||||
|
||||
public long getJailTimeout() {
|
||||
return jailTimeout;
|
||||
}
|
||||
|
||||
public void setJailTimeout(long time) {
|
||||
jailTimeout = time;
|
||||
config.setProperty("timestamps.jail", time);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private long lastLogin;
|
||||
|
||||
private long _getLastLogin() {
|
||||
return config.getLong("timestamps.login", 0);
|
||||
}
|
||||
|
||||
public long getLastLogin() {
|
||||
return lastLogin;
|
||||
}
|
||||
|
||||
private void _setLastLogin(long time) {
|
||||
lastLogin = time;
|
||||
config.setProperty("timestamps.login", time);
|
||||
}
|
||||
|
||||
public void setLastLogin(long time) {
|
||||
_setLastLogin(time);
|
||||
if (base.getAddress() != null && base.getAddress().getAddress() != null) {
|
||||
_setLastLoginAddress(base.getAddress().getAddress().getHostAddress());
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
private long lastLogout;
|
||||
|
||||
private long _getLastLogout() {
|
||||
return config.getLong("timestamps.logout", 0);
|
||||
}
|
||||
|
||||
public long getLastLogout() {
|
||||
return lastLogout;
|
||||
}
|
||||
|
||||
public void setLastLogout(long time) {
|
||||
lastLogout = time;
|
||||
config.setProperty("timestamps.logout", time);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private String lastLoginAddress;
|
||||
|
||||
private String _getLastLoginAddress() {
|
||||
return config.getString("ipAddress", "");
|
||||
}
|
||||
|
||||
public String getLastLoginAddress() {
|
||||
return lastLoginAddress;
|
||||
}
|
||||
|
||||
private void _setLastLoginAddress(String address) {
|
||||
lastLoginAddress = address;
|
||||
config.setProperty("ipAddress", address);
|
||||
}
|
||||
|
||||
private boolean afk;
|
||||
|
||||
private boolean _getAfk() {
|
||||
return config.getBoolean("afk", false);
|
||||
}
|
||||
|
||||
public boolean isAfk() {
|
||||
return afk;
|
||||
}
|
||||
|
||||
public void _setAfk(boolean set) {
|
||||
afk = set;
|
||||
config.setProperty("afk", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean newplayer;
|
||||
private String geolocation;
|
||||
|
||||
private String _getGeoLocation() {
|
||||
return config.getString("geolocation");
|
||||
}
|
||||
|
||||
public String getGeoLocation() {
|
||||
return geolocation;
|
||||
}
|
||||
|
||||
public void setGeoLocation(String geolocation) {
|
||||
if (geolocation == null || geolocation.isEmpty()) {
|
||||
this.geolocation = null;
|
||||
config.removeProperty("geolocation");
|
||||
} else {
|
||||
this.geolocation = geolocation;
|
||||
config.setProperty("geolocation", geolocation);
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean isSocialSpyEnabled;
|
||||
|
||||
private boolean _isSocialSpyEnabled() {
|
||||
return config.getBoolean("socialspy", false);
|
||||
}
|
||||
|
||||
public boolean isSocialSpyEnabled() {
|
||||
return isSocialSpyEnabled;
|
||||
}
|
||||
|
||||
public void setSocialSpyEnabled(boolean status) {
|
||||
isSocialSpyEnabled = status;
|
||||
config.setProperty("socialspy", status);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean isNPC;
|
||||
|
||||
private boolean _isNPC() {
|
||||
return config.getBoolean("npc", false);
|
||||
}
|
||||
|
||||
public boolean isNPC() {
|
||||
return isNPC;
|
||||
}
|
||||
|
||||
private String lastAccountName = null;
|
||||
|
||||
public String getLastAccountName() {
|
||||
return lastAccountName;
|
||||
}
|
||||
|
||||
public String _getLastAccountName() {
|
||||
return config.getString("lastAccountName", null);
|
||||
}
|
||||
|
||||
public void setLastAccountName(String lastAccountName) {
|
||||
this.lastAccountName = lastAccountName;
|
||||
config.setProperty("lastAccountName", lastAccountName);
|
||||
config.save();
|
||||
ess.getUserMap().trackUUID(getConfigUUID(), lastAccountName, true);
|
||||
}
|
||||
|
||||
public void setNPC(boolean set) {
|
||||
isNPC = set;
|
||||
config.setProperty("npc", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
private boolean arePowerToolsEnabled;
|
||||
|
||||
public boolean arePowerToolsEnabled() {
|
||||
return arePowerToolsEnabled;
|
||||
}
|
||||
|
||||
public void setPowerToolsEnabled(boolean set) {
|
||||
arePowerToolsEnabled = set;
|
||||
config.setProperty("powertoolsenabled", set);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean togglePowerToolsEnabled() {
|
||||
boolean ret = !arePowerToolsEnabled();
|
||||
setPowerToolsEnabled(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean _arePowerToolsEnabled() {
|
||||
return config.getBoolean("powertoolsenabled", true);
|
||||
}
|
||||
|
||||
private Map<String, Long> kitTimestamps;
|
||||
|
||||
private Map<String, Long> _getKitTimestamps() {
|
||||
|
||||
if (config.isConfigurationSection("timestamps.kits")) {
|
||||
final ConfigurationSection section = config.getConfigurationSection("timestamps.kits");
|
||||
final Map<String, Long> timestamps = new HashMap<String, Long>();
|
||||
for (String command : section.getKeys(false)) {
|
||||
if (section.isLong(command)) {
|
||||
timestamps.put(command.toLowerCase(Locale.ENGLISH), section.getLong(command));
|
||||
} else if (section.isInt(command)) {
|
||||
timestamps.put(command.toLowerCase(Locale.ENGLISH), (long) section.getInt(command));
|
||||
}
|
||||
}
|
||||
return timestamps;
|
||||
}
|
||||
return new HashMap<String, Long>();
|
||||
}
|
||||
|
||||
public long getKitTimestamp(String name) {
|
||||
name = name.replace('.', '_').replace('/', '_');
|
||||
if (kitTimestamps != null && kitTimestamps.containsKey(name)) {
|
||||
return kitTimestamps.get(name);
|
||||
}
|
||||
return 0l;
|
||||
}
|
||||
|
||||
public void setKitTimestamp(final String name, final long time) {
|
||||
kitTimestamps.put(name.toLowerCase(Locale.ENGLISH), time);
|
||||
config.setProperty("timestamps.kits", kitTimestamps);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public void setConfigProperty(String node, Object object) {
|
||||
final String prefix = "info.";
|
||||
node = prefix + node;
|
||||
if (object instanceof Map) {
|
||||
config.setProperty(node, (Map) object);
|
||||
} else if (object instanceof List) {
|
||||
config.setProperty(node, (List<String>) object);
|
||||
} else if (object instanceof Location) {
|
||||
config.setProperty(node, (Location) object);
|
||||
} else if (object instanceof ItemStack) {
|
||||
config.setProperty(node, (ItemStack) object);
|
||||
} else {
|
||||
config.setProperty(node, object);
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
public Set<String> getConfigKeys() {
|
||||
if (config.isConfigurationSection("info")) {
|
||||
return config.getConfigurationSection("info").getKeys(true);
|
||||
}
|
||||
return new HashSet<String>();
|
||||
}
|
||||
|
||||
public Map<String, Object> getConfigMap() {
|
||||
if (config.isConfigurationSection("info")) {
|
||||
return config.getConfigurationSection("info").getValues(true);
|
||||
}
|
||||
return new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public Map<String, Object> getConfigMap(String node) {
|
||||
if (config.isConfigurationSection("info." + node)) {
|
||||
return config.getConfigurationSection("info." + node).getValues(true);
|
||||
}
|
||||
return new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
// Pattern, Date. Pattern for less pattern creations
|
||||
private Map<Pattern, Long> commandCooldowns;
|
||||
|
||||
private Map<Pattern, Long> _getCommandCooldowns() {
|
||||
if (!config.isConfigurationSection("timestamps.command-cooldowns")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// See saveCommandCooldowns() for deserialization explanation
|
||||
List<Map<?, ?>> section = config.getMapList("timestamps.command-cooldowns");
|
||||
HashMap<Pattern, Long> result = new HashMap<>();
|
||||
for (Map<?, ?> map : section) {
|
||||
Pattern pattern = Pattern.compile(map.get("pattern").toString());
|
||||
long expiry = ((Number) map.get("expiry")).longValue();
|
||||
result.put(pattern, expiry);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<Pattern, Long> getCommandCooldowns() {
|
||||
if (this.commandCooldowns == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return Collections.unmodifiableMap(this.commandCooldowns);
|
||||
}
|
||||
|
||||
public Date getCommandCooldownExpiry(String label) {
|
||||
if (commandCooldowns != null) {
|
||||
for (Entry<Pattern, Long> entry : this.commandCooldowns.entrySet()) {
|
||||
if (entry.getKey().matcher(label).matches()) {
|
||||
return new Date(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addCommandCooldown(Pattern pattern, Date expiresAt, boolean save) {
|
||||
if (this.commandCooldowns == null) {
|
||||
this.commandCooldowns = new HashMap<>();
|
||||
}
|
||||
this.commandCooldowns.put(pattern, expiresAt.getTime());
|
||||
if (save) {
|
||||
saveCommandCooldowns();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean clearCommandCooldown(Pattern pattern) {
|
||||
if (this.commandCooldowns == null) {
|
||||
return false; // false for no modification
|
||||
}
|
||||
|
||||
if(this.commandCooldowns.remove(pattern) != null) {
|
||||
saveCommandCooldowns();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void saveCommandCooldowns() {
|
||||
// Serialization explanation:
|
||||
//
|
||||
// Serialization is done as a map list instead of a config section due to limitations.
|
||||
// When serializing patterns (which commonly include full stops .) Bukkit/Essentials config framework
|
||||
// interprets it as a path separator, thus it breaks up the regex into sub nodes causing invalid syntax.
|
||||
// Thus each command cooldown is instead stored as a Map of {pattern: .., expiry: ..} to work around this.
|
||||
List<Object> serialized = new ArrayList<>();
|
||||
for (Entry<Pattern, Long> entry : this.commandCooldowns.entrySet()) {
|
||||
// Don't save expired cooldowns
|
||||
if (entry.getValue() < System.currentTimeMillis()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<?, ?> map = ImmutableMap.builder()
|
||||
.put("pattern", entry.getKey().pattern())
|
||||
.put("expiry", entry.getValue())
|
||||
.build();
|
||||
serialized.add(map);
|
||||
}
|
||||
config.setProperty("timestamps.command-cooldowns", serialized);
|
||||
save();
|
||||
}
|
||||
|
||||
private boolean acceptingPay = true; // players accept pay by default
|
||||
|
||||
public boolean _getAcceptingPay() {
|
||||
return config.getBoolean("acceptingPay", true);
|
||||
}
|
||||
|
||||
public boolean isAcceptingPay() {
|
||||
return acceptingPay;
|
||||
}
|
||||
|
||||
public void setAcceptingPay(boolean acceptingPay) {
|
||||
this.acceptingPay = acceptingPay;
|
||||
config.setProperty("acceptingPay", acceptingPay);
|
||||
save();
|
||||
}
|
||||
|
||||
private Boolean confirmPay;
|
||||
|
||||
private Boolean _getConfirmPay() {
|
||||
return (Boolean) config.get("confirm-pay");
|
||||
}
|
||||
|
||||
public boolean isPromptingPayConfirm() {
|
||||
return confirmPay != null ? confirmPay : ess.getSettings().isConfirmCommandEnabledByDefault("pay");
|
||||
}
|
||||
|
||||
public void setPromptingPayConfirm(boolean prompt) {
|
||||
this.confirmPay = prompt;
|
||||
config.setProperty("confirm-pay", prompt);
|
||||
save();
|
||||
}
|
||||
|
||||
private Boolean confirmClear;
|
||||
|
||||
private Boolean _getConfirmClear() {
|
||||
return (Boolean) config.get("confirm-clear");
|
||||
}
|
||||
|
||||
public boolean isPromptingClearConfirm() {
|
||||
return confirmClear != null ? confirmClear : ess.getSettings().isConfirmCommandEnabledByDefault("clearinventory");
|
||||
}
|
||||
|
||||
public void setPromptingClearConfirm(boolean prompt) {
|
||||
this.confirmClear = prompt;
|
||||
config.setProperty("confirm-clear", prompt);
|
||||
save();
|
||||
}
|
||||
|
||||
public UUID getConfigUUID() {
|
||||
return config.uuid;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
config.save();
|
||||
}
|
||||
|
||||
public void startTransaction() {
|
||||
config.startTransaction();
|
||||
}
|
||||
|
||||
public void stopTransaction() {
|
||||
config.stopTransaction();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class UserMap extends CacheLoader<String, User> implements IConf {
|
||||
private final transient IEssentials ess;
|
||||
private final transient ConcurrentSkipListSet<UUID> keys = new ConcurrentSkipListSet<>();
|
||||
private final transient ConcurrentSkipListMap<String, UUID> names = new ConcurrentSkipListMap<>();
|
||||
private final transient ConcurrentSkipListMap<UUID, ArrayList<String>> history = new ConcurrentSkipListMap<>();
|
||||
private UUIDMap uuidMap;
|
||||
|
||||
private final transient Cache<String, User> users;
|
||||
private static boolean legacy = false;
|
||||
|
||||
public UserMap(final IEssentials ess) {
|
||||
super();
|
||||
this.ess = ess;
|
||||
uuidMap = new UUIDMap(ess);
|
||||
//RemovalListener<UUID, User> remListener = new UserMapRemovalListener();
|
||||
//users = CacheBuilder.newBuilder().maximumSize(ess.getSettings().getMaxUserCacheCount()).softValues().removalListener(remListener).build(this);
|
||||
CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
|
||||
int maxCount = ess.getSettings().getMaxUserCacheCount();
|
||||
try {
|
||||
cacheBuilder.maximumSize(maxCount);
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
legacy = true;
|
||||
legacyMaximumSize(cacheBuilder, maxCount);
|
||||
}
|
||||
cacheBuilder.softValues();
|
||||
if (!legacy) {
|
||||
users = cacheBuilder.build(this);
|
||||
} else {
|
||||
users = legacyBuild(cacheBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAllUsersAsync(final IEssentials ess) {
|
||||
ess.runTaskAsynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (users) {
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdir.exists()) {
|
||||
return;
|
||||
}
|
||||
keys.clear();
|
||||
users.invalidateAll();
|
||||
for (String string : userdir.list()) {
|
||||
if (!string.endsWith(".yml")) {
|
||||
continue;
|
||||
}
|
||||
final String name = string.substring(0, string.length() - 4);
|
||||
try {
|
||||
keys.add(UUID.fromString(name));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//Ignore these users till they rejoin.
|
||||
}
|
||||
}
|
||||
uuidMap.loadAllUsers(names, history);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean userExists(final UUID uuid) {
|
||||
return keys.contains(uuid);
|
||||
}
|
||||
|
||||
public User getUser(final String name) {
|
||||
try {
|
||||
final String sanitizedName = StringUtil.safeString(name);
|
||||
if (names.containsKey(sanitizedName)) {
|
||||
final UUID uuid = names.get(sanitizedName);
|
||||
return getUser(uuid);
|
||||
}
|
||||
|
||||
final File userFile = getUserFileFromString(sanitizedName);
|
||||
if (userFile.exists()) {
|
||||
ess.getLogger().info("Importing user " + name + " to usermap.");
|
||||
User user = new User(new OfflinePlayer(sanitizedName, ess.getServer()), ess);
|
||||
trackUUID(user.getBase().getUniqueId(), user.getName(), true);
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
} catch (UncheckedExecutionException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public User getUser(final UUID uuid) {
|
||||
try {
|
||||
if (!legacy) {
|
||||
return ((LoadingCache<String, User>) users).get(uuid.toString());
|
||||
} else {
|
||||
return legacyCacheGet(uuid);
|
||||
}
|
||||
} catch (ExecutionException ex) {
|
||||
return null;
|
||||
} catch (UncheckedExecutionException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void trackUUID(final UUID uuid, final String name, boolean replace) {
|
||||
if (uuid != null) {
|
||||
keys.add(uuid);
|
||||
if (name != null && name.length() > 0) {
|
||||
final String keyName = StringUtil.safeString(name);
|
||||
if (!names.containsKey(keyName)) {
|
||||
names.put(keyName, uuid);
|
||||
uuidMap.writeUUIDMap();
|
||||
} else if (!names.get(keyName).equals(uuid)) {
|
||||
if (replace) {
|
||||
ess.getLogger().info("Found new UUID for " + name + ". Replacing " + names.get(keyName).toString() + " with " + uuid.toString());
|
||||
names.put(keyName, uuid);
|
||||
uuidMap.writeUUIDMap();
|
||||
} else {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Found old UUID for " + name + " (" + uuid.toString() + "). Not adding to usermap.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User load(final String stringUUID) throws Exception {
|
||||
UUID uuid = UUID.fromString(stringUUID);
|
||||
Player player = ess.getServer().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
final User user = new User(player, ess);
|
||||
trackUUID(uuid, user.getName(), true);
|
||||
return user;
|
||||
}
|
||||
|
||||
final File userFile = getUserFileFromID(uuid);
|
||||
|
||||
if (userFile.exists()) {
|
||||
player = new OfflinePlayer(uuid, ess.getServer());
|
||||
final User user = new User(player, ess);
|
||||
((OfflinePlayer) player).setName(user.getLastAccountName());
|
||||
trackUUID(uuid, user.getName(), false);
|
||||
return user;
|
||||
}
|
||||
|
||||
throw new Exception("User not found!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
getUUIDMap().forceWriteUUIDMap();
|
||||
loadAllUsersAsync(ess);
|
||||
}
|
||||
|
||||
public void invalidateAll() {
|
||||
users.invalidateAll();
|
||||
}
|
||||
|
||||
public void removeUser(final String name) {
|
||||
if (names == null) {
|
||||
ess.getLogger().warning("Name collection is null, cannot remove user.");
|
||||
return;
|
||||
}
|
||||
UUID uuid = names.get(name);
|
||||
if (uuid != null) {
|
||||
keys.remove(uuid);
|
||||
users.invalidate(uuid.toString());
|
||||
}
|
||||
names.remove(name);
|
||||
names.remove(StringUtil.safeString(name));
|
||||
}
|
||||
|
||||
public Set<UUID> getAllUniqueUsers() {
|
||||
return Collections.unmodifiableSet(keys);
|
||||
}
|
||||
|
||||
public int getUniqueUsers() {
|
||||
return keys.size();
|
||||
}
|
||||
|
||||
protected ConcurrentSkipListMap<String, UUID> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
protected ConcurrentSkipListMap<UUID, ArrayList<String>> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public List<String> getUserHistory(final UUID uuid) {
|
||||
return history.get(uuid);
|
||||
}
|
||||
|
||||
public UUIDMap getUUIDMap() {
|
||||
return uuidMap;
|
||||
}
|
||||
|
||||
private File getUserFileFromID(final UUID uuid) {
|
||||
final File userFolder = new File(ess.getDataFolder(), "userdata");
|
||||
return new File(userFolder, uuid.toString() + ".yml");
|
||||
}
|
||||
|
||||
public File getUserFileFromString(final String name) {
|
||||
final File userFolder = new File(ess.getDataFolder(), "userdata");
|
||||
return new File(userFolder, StringUtil.sanitizeFileName(name) + ".yml");
|
||||
}
|
||||
// class UserMapRemovalListener implements RemovalListener
|
||||
// {
|
||||
// @Override
|
||||
// public void onRemoval(final RemovalNotification notification)
|
||||
// {
|
||||
// Object value = notification.getValue();
|
||||
// if (value != null)
|
||||
// {
|
||||
// ((User)value).cleanup();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private final Pattern validUserPattern = Pattern.compile("^[a-zA-Z0-9_]{2,16}$");
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public User getUserFromBukkit(String name) {
|
||||
name = StringUtil.safeString(name);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().warning("Using potentially blocking Bukkit UUID lookup for: " + name);
|
||||
}
|
||||
// Don't attempt to look up entirely invalid usernames
|
||||
if (name == null || !validUserPattern.matcher(name).matches()) {
|
||||
return null;
|
||||
}
|
||||
org.bukkit.OfflinePlayer offlinePlayer = ess.getServer().getOfflinePlayer(name);
|
||||
if (offlinePlayer == null) {
|
||||
return null;
|
||||
}
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = offlinePlayer.getUniqueId();
|
||||
} catch (UnsupportedOperationException | NullPointerException e) {
|
||||
return null;
|
||||
}
|
||||
// This is how Bukkit generates fake UUIDs
|
||||
if (UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)).equals(uuid)) {
|
||||
return null;
|
||||
} else {
|
||||
names.put(name, uuid);
|
||||
return getUser(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getLegacy;
|
||||
|
||||
private User legacyCacheGet(UUID uuid) {
|
||||
if (getLegacy == null) {
|
||||
Class<?> usersClass = users.getClass();
|
||||
for (Method m : usersClass.getDeclaredMethods()) {
|
||||
if (m.getName().equals("get")) {
|
||||
getLegacy = m;
|
||||
getLegacy.setAccessible(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (User) getLegacy.invoke(users, uuid.toString());
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void legacyMaximumSize(CacheBuilder builder, int maxCount) {
|
||||
try {
|
||||
Method maxSizeLegacy = builder.getClass().getDeclaredMethod("maximumSize", Integer.TYPE);
|
||||
maxSizeLegacy.setAccessible(true);
|
||||
maxSizeLegacy.invoke(builder, maxCount);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Cache<String, User> legacyBuild(CacheBuilder builder) {
|
||||
Method build = null;
|
||||
for (Method method : builder.getClass().getDeclaredMethods()) {
|
||||
if (method.getName().equals("build")) {
|
||||
build = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Cache<String, User> legacyUsers;
|
||||
try {
|
||||
assert build != null;
|
||||
build.setAccessible(true);
|
||||
legacyUsers = (Cache<String, User>) build.invoke(builder, this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
legacyUsers = null;
|
||||
}
|
||||
return legacyUsers;
|
||||
}
|
||||
}
|
||||
@@ -1,649 +0,0 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.ISettings;
|
||||
import com.earth2me.essentials.api.InvalidNameException;
|
||||
import com.earth2me.essentials.external.gnu.inet.encoding.Punycode;
|
||||
import com.earth2me.essentials.external.gnu.inet.encoding.PunycodeException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.Cleanup;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
|
||||
public final class Util
|
||||
{
|
||||
private Util()
|
||||
{
|
||||
}
|
||||
private final static Pattern INVALIDFILECHARS = Pattern.compile("[^\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFC]");
|
||||
private final static Pattern INVALIDCHARS = Pattern.compile("[^\t\n\r\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFC]");
|
||||
|
||||
public static String sanitizeFileName(String name) throws InvalidNameException
|
||||
{
|
||||
try
|
||||
{
|
||||
String r = name.toLowerCase(Locale.ENGLISH);
|
||||
r = r.replace('.', (char)('\ue200' + '.'));
|
||||
r = r.replace('\\', (char)('\ue200' + '\\'));
|
||||
r = r.replace('/', (char)('\ue200' + '/'));
|
||||
r = r.replace('"', (char)('\ue200' + '"'));
|
||||
r = r.replace('<', (char)('\ue200' + '<'));
|
||||
r = r.replace('>', (char)('\ue200' + '>'));
|
||||
r = r.replace('|', (char)('\ue200' + '|'));
|
||||
r = r.replace('?', (char)('\ue200' + '?'));
|
||||
r = r.replace('*', (char)('\ue200' + '*'));
|
||||
r = r.replace(':', (char)('\ue200' + ':'));
|
||||
r = r.replace('-', (char)('\ue200' + '-'));
|
||||
r = INVALIDFILECHARS.matcher(r).replaceAll("");
|
||||
return Punycode.encode(r);
|
||||
}
|
||||
catch (PunycodeException ex)
|
||||
{
|
||||
throw new InvalidNameException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static String decodeFileName(String name) throws InvalidNameException
|
||||
{
|
||||
try
|
||||
{
|
||||
String r = Punycode.decode(name);
|
||||
r = r.replace((char)('\ue200' + '.'), '.');
|
||||
r = r.replace((char)('\ue200' + '\\'), '\\');
|
||||
r = r.replace((char)('\ue200' + '/'), '/');
|
||||
r = r.replace((char)('\ue200' + '"'), '"');
|
||||
r = r.replace((char)('\ue200' + '<'), '<');
|
||||
r = r.replace((char)('\ue200' + '>'), '>');
|
||||
r = r.replace((char)('\ue200' + '|'), '|');
|
||||
r = r.replace((char)('\ue200' + '?'), '?');
|
||||
r = r.replace((char)('\ue200' + '*'), '*');
|
||||
r = r.replace((char)('\ue200' + ':'), ':');
|
||||
r = r.replace((char)('\ue200' + '-'), '-');
|
||||
return r;
|
||||
}
|
||||
catch (PunycodeException ex)
|
||||
{
|
||||
throw new InvalidNameException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static String sanitizeKey(String name)
|
||||
{
|
||||
return INVALIDCHARS.matcher(name.toLowerCase(Locale.ENGLISH)).replaceAll("_");
|
||||
}
|
||||
|
||||
public static String sanitizeString(final String string)
|
||||
{
|
||||
return INVALIDCHARS.matcher(string).replaceAll("");
|
||||
}
|
||||
|
||||
public static String formatDateDiff(long date)
|
||||
{
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.setTimeInMillis(date);
|
||||
Calendar now = new GregorianCalendar();
|
||||
return Util.formatDateDiff(now, c);
|
||||
}
|
||||
|
||||
public static String formatDateDiff(Calendar fromDate, Calendar toDate)
|
||||
{
|
||||
boolean future = false;
|
||||
if (toDate.equals(fromDate))
|
||||
{
|
||||
return _("now");
|
||||
}
|
||||
if (toDate.after(fromDate))
|
||||
{
|
||||
future = true;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int[] types = new int[]
|
||||
{
|
||||
Calendar.YEAR,
|
||||
Calendar.MONTH,
|
||||
Calendar.DAY_OF_MONTH,
|
||||
Calendar.HOUR_OF_DAY,
|
||||
Calendar.MINUTE,
|
||||
Calendar.SECOND
|
||||
};
|
||||
String[] names = new String[]
|
||||
{
|
||||
_("year"),
|
||||
_("years"),
|
||||
_("month"),
|
||||
_("months"),
|
||||
_("day"),
|
||||
_("days"),
|
||||
_("hour"),
|
||||
_("hours"),
|
||||
_("minute"),
|
||||
_("minutes"),
|
||||
_("second"),
|
||||
_("seconds")
|
||||
};
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
int diff = dateDiff(types[i], fromDate, toDate, future);
|
||||
if (diff > 0)
|
||||
{
|
||||
sb.append(" ").append(diff).append(" ").append(names[i * 2 + (diff > 1 ? 1 : 0)]);
|
||||
}
|
||||
}
|
||||
if (sb.length() == 0)
|
||||
{
|
||||
return "now";
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static int dateDiff(int type, Calendar fromDate, Calendar toDate, boolean future)
|
||||
{
|
||||
int diff = 0;
|
||||
long savedDate = fromDate.getTimeInMillis();
|
||||
while ((future && !fromDate.after(toDate)) || (!future && !fromDate.before(toDate)))
|
||||
{
|
||||
savedDate = fromDate.getTimeInMillis();
|
||||
fromDate.add(type, future ? 1 : -1);
|
||||
diff++;
|
||||
}
|
||||
diff--;
|
||||
fromDate.setTimeInMillis(savedDate);
|
||||
return diff;
|
||||
}
|
||||
|
||||
public static long parseDateDiff(String time, boolean future) throws Exception
|
||||
{
|
||||
Pattern timePattern = Pattern.compile(
|
||||
"(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?"
|
||||
+ "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = timePattern.matcher(time);
|
||||
int years = 0;
|
||||
int months = 0;
|
||||
int weeks = 0;
|
||||
int days = 0;
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
int seconds = 0;
|
||||
boolean found = false;
|
||||
while (m.find())
|
||||
{
|
||||
if (m.group() == null || m.group().isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < m.groupCount(); i++)
|
||||
{
|
||||
if (m.group(i) != null && !m.group(i).isEmpty())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
if (m.group(1) != null && !m.group(1).isEmpty())
|
||||
{
|
||||
years = Integer.parseInt(m.group(1));
|
||||
}
|
||||
if (m.group(2) != null && !m.group(2).isEmpty())
|
||||
{
|
||||
months = Integer.parseInt(m.group(2));
|
||||
}
|
||||
if (m.group(3) != null && !m.group(3).isEmpty())
|
||||
{
|
||||
weeks = Integer.parseInt(m.group(3));
|
||||
}
|
||||
if (m.group(4) != null && !m.group(4).isEmpty())
|
||||
{
|
||||
days = Integer.parseInt(m.group(4));
|
||||
}
|
||||
if (m.group(5) != null && !m.group(5).isEmpty())
|
||||
{
|
||||
hours = Integer.parseInt(m.group(5));
|
||||
}
|
||||
if (m.group(6) != null && !m.group(6).isEmpty())
|
||||
{
|
||||
minutes = Integer.parseInt(m.group(6));
|
||||
}
|
||||
if (m.group(7) != null && !m.group(7).isEmpty())
|
||||
{
|
||||
seconds = Integer.parseInt(m.group(7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
throw new Exception(_("illegalDate"));
|
||||
}
|
||||
Calendar c = new GregorianCalendar();
|
||||
if (years > 0)
|
||||
{
|
||||
c.add(Calendar.YEAR, years * (future ? 1 : -1));
|
||||
}
|
||||
if (months > 0)
|
||||
{
|
||||
c.add(Calendar.MONTH, months * (future ? 1 : -1));
|
||||
}
|
||||
if (weeks > 0)
|
||||
{
|
||||
c.add(Calendar.WEEK_OF_YEAR, weeks * (future ? 1 : -1));
|
||||
}
|
||||
if (days > 0)
|
||||
{
|
||||
c.add(Calendar.DAY_OF_MONTH, days * (future ? 1 : -1));
|
||||
}
|
||||
if (hours > 0)
|
||||
{
|
||||
c.add(Calendar.HOUR_OF_DAY, hours * (future ? 1 : -1));
|
||||
}
|
||||
if (minutes > 0)
|
||||
{
|
||||
c.add(Calendar.MINUTE, minutes * (future ? 1 : -1));
|
||||
}
|
||||
if (seconds > 0)
|
||||
{
|
||||
c.add(Calendar.SECOND, seconds * (future ? 1 : -1));
|
||||
}
|
||||
return c.getTimeInMillis();
|
||||
}
|
||||
// The player can stand inside these materials
|
||||
private static final Set<Integer> AIR_MATERIALS = new HashSet<Integer>();
|
||||
private static final HashSet<Byte> AIR_MATERIALS_TARGET = new HashSet<Byte>();
|
||||
|
||||
static
|
||||
{
|
||||
AIR_MATERIALS.add(Material.AIR.getId());
|
||||
AIR_MATERIALS.add(Material.SAPLING.getId());
|
||||
AIR_MATERIALS.add(Material.POWERED_RAIL.getId());
|
||||
AIR_MATERIALS.add(Material.DETECTOR_RAIL.getId());
|
||||
AIR_MATERIALS.add(Material.LONG_GRASS.getId());
|
||||
AIR_MATERIALS.add(Material.DEAD_BUSH.getId());
|
||||
AIR_MATERIALS.add(Material.YELLOW_FLOWER.getId());
|
||||
AIR_MATERIALS.add(Material.RED_ROSE.getId());
|
||||
AIR_MATERIALS.add(Material.BROWN_MUSHROOM.getId());
|
||||
AIR_MATERIALS.add(Material.RED_MUSHROOM.getId());
|
||||
AIR_MATERIALS.add(Material.TORCH.getId());
|
||||
AIR_MATERIALS.add(Material.REDSTONE_WIRE.getId());
|
||||
AIR_MATERIALS.add(Material.SEEDS.getId());
|
||||
AIR_MATERIALS.add(Material.SIGN_POST.getId());
|
||||
AIR_MATERIALS.add(Material.WOODEN_DOOR.getId());
|
||||
AIR_MATERIALS.add(Material.LADDER.getId());
|
||||
AIR_MATERIALS.add(Material.RAILS.getId());
|
||||
AIR_MATERIALS.add(Material.WALL_SIGN.getId());
|
||||
AIR_MATERIALS.add(Material.LEVER.getId());
|
||||
AIR_MATERIALS.add(Material.STONE_PLATE.getId());
|
||||
AIR_MATERIALS.add(Material.IRON_DOOR_BLOCK.getId());
|
||||
AIR_MATERIALS.add(Material.WOOD_PLATE.getId());
|
||||
AIR_MATERIALS.add(Material.REDSTONE_TORCH_OFF.getId());
|
||||
AIR_MATERIALS.add(Material.REDSTONE_TORCH_ON.getId());
|
||||
AIR_MATERIALS.add(Material.STONE_BUTTON.getId());
|
||||
AIR_MATERIALS.add(Material.SUGAR_CANE_BLOCK.getId());
|
||||
AIR_MATERIALS.add(Material.DIODE_BLOCK_OFF.getId());
|
||||
AIR_MATERIALS.add(Material.DIODE_BLOCK_ON.getId());
|
||||
AIR_MATERIALS.add(Material.TRAP_DOOR.getId());
|
||||
AIR_MATERIALS.add(Material.PUMPKIN_STEM.getId());
|
||||
AIR_MATERIALS.add(Material.MELON_STEM.getId());
|
||||
AIR_MATERIALS.add(Material.VINE.getId());
|
||||
AIR_MATERIALS.add(Material.NETHER_WARTS.getId());
|
||||
AIR_MATERIALS.add(Material.WATER_LILY.getId());
|
||||
|
||||
for (Integer integer : AIR_MATERIALS)
|
||||
{
|
||||
AIR_MATERIALS_TARGET.add(integer.byteValue());
|
||||
}
|
||||
AIR_MATERIALS_TARGET.add((byte)Material.WATER.getId());
|
||||
AIR_MATERIALS_TARGET.add((byte)Material.STATIONARY_WATER.getId());
|
||||
}
|
||||
|
||||
public static Location getTarget(final LivingEntity entity) throws Exception
|
||||
{
|
||||
final Block block = entity.getTargetBlock(AIR_MATERIALS_TARGET, 300);
|
||||
if (block == null)
|
||||
{
|
||||
throw new Exception("Not targeting a block");
|
||||
}
|
||||
return block.getLocation();
|
||||
}
|
||||
|
||||
public static Location getSafeDestination(final Location loc) throws Exception
|
||||
{
|
||||
if (loc == null || loc.getWorld() == null)
|
||||
{
|
||||
throw new Exception(_("destinationNotSet"));
|
||||
}
|
||||
final World world = loc.getWorld();
|
||||
int x = loc.getBlockX();
|
||||
int y = (int)Math.round(loc.getY());
|
||||
int z = loc.getBlockZ();
|
||||
|
||||
while (isBlockAboveAir(world, x, y, z))
|
||||
{
|
||||
y -= 1;
|
||||
if (y < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (isBlockUnsafe(world, x, y, z))
|
||||
{
|
||||
y += 1;
|
||||
if (y >= 127)
|
||||
{
|
||||
x += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (isBlockUnsafe(world, x, y, z))
|
||||
{
|
||||
y -= 1;
|
||||
if (y <= 1)
|
||||
{
|
||||
y = 127;
|
||||
x += 1;
|
||||
if (x - 32 > loc.getBlockX())
|
||||
{
|
||||
throw new Exception(_("holeInFloor"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Location(world, x + 0.5D, y, z + 0.5D, loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
|
||||
private static boolean isBlockAboveAir(final World world, final int x, final int y, final int z)
|
||||
{
|
||||
return AIR_MATERIALS.contains(world.getBlockAt(x, y - 1, z).getType().getId());
|
||||
}
|
||||
|
||||
public static boolean isBlockUnsafe(final World world, final int x, final int y, final int z)
|
||||
{
|
||||
final Block below = world.getBlockAt(x, y - 1, z);
|
||||
if (below.getType() == Material.LAVA || below.getType() == Material.STATIONARY_LAVA)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (below.getType() == Material.FIRE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!AIR_MATERIALS.contains(world.getBlockAt(x, y, z).getType().getId()))
|
||||
|| (!AIR_MATERIALS.contains(world.getBlockAt(x, y + 1, z).getType().getId())))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return isBlockAboveAir(world, x, y, z);
|
||||
}
|
||||
|
||||
public static ItemStack convertBlockToItem(final Block block)
|
||||
{
|
||||
final ItemStack is = new ItemStack(block.getType(), 1, (short)0, block.getData());
|
||||
switch (is.getType())
|
||||
{
|
||||
case WOODEN_DOOR:
|
||||
is.setType(Material.WOOD_DOOR);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case IRON_DOOR_BLOCK:
|
||||
is.setType(Material.IRON_DOOR);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case SIGN_POST:
|
||||
case WALL_SIGN:
|
||||
is.setType(Material.SIGN);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case CROPS:
|
||||
is.setType(Material.SEEDS);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case CAKE_BLOCK:
|
||||
is.setType(Material.CAKE);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case BED_BLOCK:
|
||||
is.setType(Material.BED);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case REDSTONE_WIRE:
|
||||
is.setType(Material.REDSTONE);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case REDSTONE_TORCH_OFF:
|
||||
case REDSTONE_TORCH_ON:
|
||||
is.setType(Material.REDSTONE_TORCH_ON);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case DIODE_BLOCK_OFF:
|
||||
case DIODE_BLOCK_ON:
|
||||
is.setType(Material.DIODE);
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case DOUBLE_STEP:
|
||||
is.setType(Material.STEP);
|
||||
break;
|
||||
case TORCH:
|
||||
case RAILS:
|
||||
case LADDER:
|
||||
case WOOD_STAIRS:
|
||||
case COBBLESTONE_STAIRS:
|
||||
case LEVER:
|
||||
case STONE_BUTTON:
|
||||
case FURNACE:
|
||||
case DISPENSER:
|
||||
case PUMPKIN:
|
||||
case JACK_O_LANTERN:
|
||||
case WOOD_PLATE:
|
||||
case STONE_PLATE:
|
||||
case PISTON_STICKY_BASE:
|
||||
case PISTON_BASE:
|
||||
case IRON_FENCE:
|
||||
case THIN_GLASS:
|
||||
case TRAP_DOOR:
|
||||
case FENCE:
|
||||
case FENCE_GATE:
|
||||
case NETHER_FENCE:
|
||||
is.setDurability((short)0);
|
||||
break;
|
||||
case FIRE:
|
||||
return null;
|
||||
case PUMPKIN_STEM:
|
||||
is.setType(Material.PUMPKIN_SEEDS);
|
||||
break;
|
||||
case MELON_STEM:
|
||||
is.setType(Material.MELON_SEEDS);
|
||||
break;
|
||||
}
|
||||
return is;
|
||||
}
|
||||
private static DecimalFormat df = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.US));
|
||||
|
||||
public static String formatCurrency(final double value, final IEssentials ess)
|
||||
{
|
||||
@Cleanup
|
||||
final ISettings settings = ess.getSettings();
|
||||
settings.acquireReadLock();
|
||||
String str = settings.getData().getEconomy().getCurrencySymbol() + df.format(value);
|
||||
if (str.endsWith(".00"))
|
||||
{
|
||||
str = str.substring(0, str.length() - 3);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static double roundDouble(final double d)
|
||||
{
|
||||
return Math.round(d * 100.0) / 100.0;
|
||||
}
|
||||
|
||||
public static boolean isInt(final String sInt)
|
||||
{
|
||||
try
|
||||
{
|
||||
Integer.parseInt(sInt);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String joinList(Object... list)
|
||||
{
|
||||
return joinList(", ", list);
|
||||
}
|
||||
|
||||
public static String joinList(String seperator, Object... list)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (Object each : list)
|
||||
{
|
||||
if (buf.length() > 0)
|
||||
{
|
||||
buf.append(seperator);
|
||||
}
|
||||
|
||||
if (each instanceof Collection)
|
||||
{
|
||||
buf.append(joinList(seperator, ((Collection)each).toArray()));
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
buf.append(each.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
buf.append(each.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static void registerPermissions(String path, Collection<String> nodes, boolean hasDefault, IEssentials ess)
|
||||
{
|
||||
if (nodes == null || nodes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final PluginManager pluginManager = ess.getServer().getPluginManager();
|
||||
Permission basePerm = pluginManager.getPermission(path + ".*");
|
||||
if (basePerm != null && !basePerm.getChildren().isEmpty())
|
||||
{
|
||||
basePerm.getChildren().clear();
|
||||
}
|
||||
if (basePerm == null)
|
||||
{
|
||||
basePerm = new Permission(path + ".*", PermissionDefault.OP);
|
||||
pluginManager.addPermission(basePerm);
|
||||
Permission mainPerm = pluginManager.getPermission("essentials.*");
|
||||
if (mainPerm == null)
|
||||
{
|
||||
mainPerm = new Permission("essentials.*", PermissionDefault.OP);
|
||||
pluginManager.addPermission(mainPerm);
|
||||
}
|
||||
mainPerm.getChildren().put(basePerm.getName(), Boolean.TRUE);
|
||||
}
|
||||
|
||||
for (String nodeName : nodes)
|
||||
{
|
||||
final String permissionName = path + "." + nodeName;
|
||||
Permission perm = pluginManager.getPermission(permissionName);
|
||||
if (perm == null)
|
||||
{
|
||||
final PermissionDefault defaultPerm = hasDefault && nodeName.equalsIgnoreCase("default") ? PermissionDefault.TRUE : PermissionDefault.OP;
|
||||
perm = new Permission(permissionName, defaultPerm);
|
||||
pluginManager.addPermission(perm);
|
||||
}
|
||||
basePerm.getChildren().put(permissionName, Boolean.TRUE);
|
||||
}
|
||||
basePerm.recalculatePermissibles();
|
||||
}
|
||||
private static transient final Pattern DOT_PATTERN = Pattern.compile("\\.");
|
||||
|
||||
public static Permission registerPermission(String permission, PermissionDefault defaultPerm)
|
||||
{
|
||||
final PluginManager pluginManager = Bukkit.getServer().getPluginManager();
|
||||
final String[] parts = DOT_PATTERN.split(permission);
|
||||
final StringBuilder builder = new StringBuilder(permission.length());
|
||||
Permission parent = null;
|
||||
for (int i = 0; i < parts.length - 1; i++)
|
||||
{
|
||||
builder.append(parts[i]).append(".*");
|
||||
String permString = builder.toString();
|
||||
Permission perm = pluginManager.getPermission(permString);
|
||||
if (perm == null)
|
||||
{
|
||||
perm = new Permission(permString, PermissionDefault.FALSE);
|
||||
pluginManager.addPermission(perm);
|
||||
if (parent != null)
|
||||
{
|
||||
parent.getChildren().put(perm.getName(), Boolean.TRUE);
|
||||
}
|
||||
parent = perm;
|
||||
}
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
}
|
||||
Permission perm = pluginManager.getPermission(permission);
|
||||
if (perm == null)
|
||||
{
|
||||
perm = new Permission(permission, defaultPerm);
|
||||
pluginManager.addPermission(perm);
|
||||
if (parent != null)
|
||||
{
|
||||
parent.getChildren().put(perm.getName(), Boolean.TRUE);
|
||||
}
|
||||
parent = perm;
|
||||
}
|
||||
perm.recalculatePermissibles();
|
||||
return perm;
|
||||
}
|
||||
private static transient final Pattern VANILLA_COLOR_PATTERN = Pattern.compile("\u00A7+[0-9A-FKa-fk]");
|
||||
private static transient final Pattern EASY_COLOR_PATTERN = Pattern.compile("&([0-9a-fk])");
|
||||
|
||||
public static String stripColor(final String input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return VANILLA_COLOR_PATTERN.matcher(input).replaceAll("");
|
||||
}
|
||||
|
||||
public static String replaceColor(final String input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return EASY_COLOR_PATTERN.matcher(input).replaceAll("\u00a7$1");
|
||||
}
|
||||
}
|
||||
@@ -1,152 +1,167 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.IWarp;
|
||||
import com.earth2me.essentials.api.IWarps;
|
||||
import com.earth2me.essentials.api.InvalidNameException;
|
||||
import com.earth2me.essentials.commands.WarpNotFoundException;
|
||||
import com.earth2me.essentials.settings.WarpHolder;
|
||||
import com.earth2me.essentials.storage.StorageObjectMap;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import net.ess3.api.InvalidNameException;
|
||||
import net.ess3.api.InvalidWorldException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class Warps extends StorageObjectMap<IWarp> implements IWarps
|
||||
{
|
||||
private static final Logger logger = Bukkit.getLogger();
|
||||
public class Warps implements IConf, net.ess3.api.IWarps {
|
||||
private static final Logger logger = Logger.getLogger("Essentials");
|
||||
private final Map<StringIgnoreCase, EssentialsConf> warpPoints = new HashMap<StringIgnoreCase, EssentialsConf>();
|
||||
private final File warpsFolder;
|
||||
private final Server server;
|
||||
|
||||
public Warps(IEssentials ess)
|
||||
{
|
||||
super(ess, "warps");
|
||||
}
|
||||
public Warps(Server server, File dataFolder) {
|
||||
this.server = server;
|
||||
warpsFolder = new File(dataFolder, "warps");
|
||||
if (!warpsFolder.exists()) {
|
||||
warpsFolder.mkdirs();
|
||||
}
|
||||
reloadConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return getKeySize() == 0;
|
||||
}
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return warpPoints.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getList()
|
||||
{
|
||||
final List<String> names = new ArrayList<String>();
|
||||
for (String key : getAllKeys())
|
||||
{
|
||||
IWarp warp = getObject(key);
|
||||
if (warp == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
warp.acquireReadLock();
|
||||
try
|
||||
{
|
||||
names.add(warp.getData().getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
warp.unlock();
|
||||
}
|
||||
}
|
||||
Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
|
||||
return names;
|
||||
}
|
||||
@Override
|
||||
public Collection<String> getList() {
|
||||
final List<String> keys = new ArrayList<String>();
|
||||
for (StringIgnoreCase stringIgnoreCase : warpPoints.keySet()) {
|
||||
keys.add(stringIgnoreCase.getString());
|
||||
}
|
||||
Collections.sort(keys, String.CASE_INSENSITIVE_ORDER);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getWarp(final String name) throws Exception
|
||||
{
|
||||
IWarp warp = getObject(name);
|
||||
if (warp == null)
|
||||
{
|
||||
throw new WarpNotFoundException(_("warpNotExist"));
|
||||
}
|
||||
warp.acquireReadLock();
|
||||
try
|
||||
{
|
||||
return warp.getData().getLocation().getBukkitLocation();
|
||||
}
|
||||
finally
|
||||
{
|
||||
warp.unlock();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Location getWarp(String warp) throws WarpNotFoundException, InvalidWorldException {
|
||||
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(warp));
|
||||
if (conf == null) {
|
||||
throw new WarpNotFoundException();
|
||||
}
|
||||
return conf.getLocation(null, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWarp(final String name, final Location loc) throws Exception
|
||||
{
|
||||
setWarp(name, new com.earth2me.essentials.storage.Location(loc));
|
||||
}
|
||||
|
||||
public void setWarp(final String name, final com.earth2me.essentials.storage.Location loc) throws Exception
|
||||
{
|
||||
IWarp warp = getObject(name);
|
||||
if (warp == null)
|
||||
{
|
||||
warp = new WarpHolder(name, ess);
|
||||
}
|
||||
warp.acquireWriteLock();
|
||||
try
|
||||
{
|
||||
warp.getData().setLocation(loc);
|
||||
}
|
||||
finally
|
||||
{
|
||||
warp.unlock();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setWarp(String name, Location loc) throws Exception {
|
||||
setWarp(null, name, loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWarp(IUser user, String name, Location loc) throws Exception {
|
||||
String filename = StringUtil.sanitizeFileName(name);
|
||||
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(name));
|
||||
if (conf == null) {
|
||||
File confFile = new File(warpsFolder, filename + ".yml");
|
||||
if (confFile.exists()) {
|
||||
throw new Exception(tl("similarWarpExist"));
|
||||
}
|
||||
conf = new EssentialsConf(confFile);
|
||||
warpPoints.put(new StringIgnoreCase(name), conf);
|
||||
}
|
||||
conf.setProperty(null, loc);
|
||||
conf.setProperty("name", name);
|
||||
if (user != null) conf.setProperty("lastowner", user.getBase().getUniqueId().toString());
|
||||
try {
|
||||
conf.saveWithError();
|
||||
} catch (IOException ex) {
|
||||
throw new IOException(tl("invalidWarpName"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getLastOwner(String warp) throws WarpNotFoundException {
|
||||
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(warp));
|
||||
if (conf == null) {
|
||||
throw new WarpNotFoundException();
|
||||
}
|
||||
UUID uuid = null;
|
||||
try {
|
||||
uuid = UUID.fromString(conf.getString("lastowner"));
|
||||
}
|
||||
catch (Exception ex) {}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWarp(String name) throws Exception {
|
||||
EssentialsConf conf = warpPoints.get(new StringIgnoreCase(name));
|
||||
if (conf == null) {
|
||||
throw new Exception(tl("warpNotExist"));
|
||||
}
|
||||
if (!conf.getFile().delete()) {
|
||||
throw new Exception(tl("warpDeleteError"));
|
||||
}
|
||||
warpPoints.remove(new StringIgnoreCase(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWarp(final String name) throws Exception
|
||||
{
|
||||
removeObject(name);
|
||||
}
|
||||
@Override
|
||||
public final void reloadConfig() {
|
||||
warpPoints.clear();
|
||||
File[] listOfFiles = warpsFolder.listFiles();
|
||||
if (listOfFiles.length >= 1) {
|
||||
for (int i = 0; i < listOfFiles.length; i++) {
|
||||
String filename = listOfFiles[i].getName();
|
||||
if (listOfFiles[i].isFile() && filename.endsWith(".yml")) {
|
||||
try {
|
||||
EssentialsConf conf = new EssentialsConf(listOfFiles[i]);
|
||||
conf.load();
|
||||
String name = conf.getString("name");
|
||||
if (name != null) {
|
||||
warpPoints.put(new StringIgnoreCase(name), conf);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, tl("loadWarpError", filename), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWarpFile(String name) throws InvalidNameException
|
||||
{
|
||||
return getStorageFile(name);
|
||||
}
|
||||
//This is here for future 3.x api support. Not implemented here becasue storage is handled differently
|
||||
@Override
|
||||
public File getWarpFile(String name) throws InvalidNameException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWarp load(String name) throws Exception
|
||||
{
|
||||
final IWarp warp = new WarpHolder(name, ess);
|
||||
warp.onReload();
|
||||
return warp;
|
||||
}
|
||||
@Override
|
||||
public int getCount() {
|
||||
return getList().size();
|
||||
}
|
||||
|
||||
private static class StringIgnoreCase {
|
||||
private final String string;
|
||||
|
||||
private static class StringIgnoreCase
|
||||
{
|
||||
private final String string;
|
||||
public StringIgnoreCase(String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public StringIgnoreCase(String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getString().toLowerCase(Locale.ENGLISH).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getString().toLowerCase(Locale.ENGLISH).hashCode();
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof StringIgnoreCase) {
|
||||
return getString().equalsIgnoreCase(((StringIgnoreCase) o).getString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof StringIgnoreCase)
|
||||
{
|
||||
return getString().equalsIgnoreCase(((StringIgnoreCase)o).getString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
}
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +1,156 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IEssentials;
|
||||
import com.earth2me.essentials.api.IWorth;
|
||||
import com.earth2me.essentials.storage.AsyncStorageObjectHolder;
|
||||
import com.earth2me.essentials.storage.EnchantmentLevel;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class Worth extends AsyncStorageObjectHolder<com.earth2me.essentials.settings.Worth> implements IWorth
|
||||
{
|
||||
public Worth(final IEssentials ess)
|
||||
{
|
||||
super(ess, com.earth2me.essentials.settings.Worth.class);
|
||||
onReload(false);
|
||||
}
|
||||
public class Worth implements IConf {
|
||||
private final EssentialsConf config;
|
||||
|
||||
@Override
|
||||
public double getPrice(final ItemStack itemStack)
|
||||
{
|
||||
this.acquireReadLock();
|
||||
try
|
||||
{
|
||||
final Map<MaterialData, Double> prices = this.getData().getSell();
|
||||
if (prices == null || itemStack == null)
|
||||
{
|
||||
return Double.NaN;
|
||||
}
|
||||
final Double basePrice = prices.get(itemStack.getData());
|
||||
if (basePrice == null || Double.isNaN(basePrice))
|
||||
{
|
||||
return Double.NaN;
|
||||
}
|
||||
double multiplier = 1.0;
|
||||
if (itemStack.getType().getMaxDurability() > 0) {
|
||||
multiplier *= (double)itemStack.getDurability() / (double)itemStack.getType().getMaxDurability();
|
||||
}
|
||||
if (itemStack.getEnchantments() != null && !itemStack.getEnchantments().isEmpty())
|
||||
{
|
||||
final Map<EnchantmentLevel, Double> enchantmentMultipliers = this.getData().getEnchantmentMultiplier();
|
||||
if (enchantmentMultipliers != null)
|
||||
{
|
||||
for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet())
|
||||
{
|
||||
final Double enchMult = enchantmentMultipliers.get(new EnchantmentLevel(entry.getKey(), entry.getValue()));
|
||||
if (enchMult != null)
|
||||
{
|
||||
multiplier *= enchMult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return basePrice * multiplier;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.unlock();
|
||||
}
|
||||
}
|
||||
public Worth(File dataFolder) {
|
||||
config = new EssentialsConf(new File(dataFolder, "worth.yml"));
|
||||
config.setTemplateName("/worth.yml");
|
||||
config.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrice(final ItemStack itemStack, final double price)
|
||||
{
|
||||
acquireWriteLock();
|
||||
try {
|
||||
if (getData().getSell() == null) {
|
||||
getData().setSell(new HashMap<MaterialData, Double>());
|
||||
}
|
||||
getData().getSell().put(itemStack.getData(), price);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the value of an item stack from the config.
|
||||
*
|
||||
* @param ess The Essentials instance.
|
||||
* @param itemStack The item stack to look up in the config.
|
||||
* @return The price from the config.
|
||||
*/
|
||||
public BigDecimal getPrice(IEssentials ess, ItemStack itemStack) {
|
||||
BigDecimal result;
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getDataFolder(), "worth.yml");
|
||||
}
|
||||
String itemname = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
|
||||
|
||||
// Check for matches with data value from stack
|
||||
// Note that we always default to BigDecimal.ONE.negate(), equivalent to -1
|
||||
result = config.getBigDecimal("worth." + itemname + "." + itemStack.getDurability(), BigDecimal.ONE.negate());
|
||||
|
||||
// Check for matches with data value 0
|
||||
if (result.signum() < 0) {
|
||||
final ConfigurationSection itemNameMatch = config.getConfigurationSection("worth." + itemname);
|
||||
if (itemNameMatch != null && itemNameMatch.getKeys(false).size() == 1) {
|
||||
result = config.getBigDecimal("worth." + itemname + ".0", BigDecimal.ONE.negate());
|
||||
}
|
||||
}
|
||||
|
||||
// Check for matches with data value wildcard
|
||||
if (result.signum() < 0) {
|
||||
result = config.getBigDecimal("worth." + itemname + ".*", BigDecimal.ONE.negate());
|
||||
}
|
||||
|
||||
// Check for matches with item name alone
|
||||
if (result.signum() < 0) {
|
||||
result = config.getBigDecimal("worth." + itemname, BigDecimal.ONE.negate());
|
||||
}
|
||||
|
||||
if (result.signum() < 0) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of items to be sold from a player's inventory.
|
||||
*
|
||||
* @param ess The Essentials instance.
|
||||
* @param user The user attempting to sell the item.
|
||||
* @param is A stack of the item to search the inventory for.
|
||||
* @param args The amount to try to sell.
|
||||
* @param isBulkSell Whether or not to try and bulk sell all items.
|
||||
* @return The amount of items to sell from the player's inventory.
|
||||
* @throws Exception Thrown if trying to sell air or an invalid amount.
|
||||
*/
|
||||
public int getAmount(IEssentials ess, User user, ItemStack is, String[] args, boolean isBulkSell) throws Exception {
|
||||
if (is == null || is.getType() == Material.AIR) {
|
||||
throw new Exception(tl("itemSellAir"));
|
||||
}
|
||||
|
||||
int amount = 0;
|
||||
|
||||
if (args.length > 1) {
|
||||
try {
|
||||
amount = Integer.parseInt(args[1].replaceAll("[^0-9]", ""));
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new NotEnoughArgumentsException(ex);
|
||||
}
|
||||
if (args[1].startsWith("-")) {
|
||||
amount = -amount;
|
||||
}
|
||||
}
|
||||
|
||||
boolean stack = args.length > 1 && args[1].endsWith("s");
|
||||
boolean requireStack = ess.getSettings().isTradeInStacks(is.getType());
|
||||
|
||||
if (requireStack && !stack) {
|
||||
throw new Exception(tl("itemMustBeStacked"));
|
||||
}
|
||||
|
||||
int max = 0;
|
||||
for (ItemStack s : user.getBase().getInventory().getContents()) {
|
||||
if (s == null || !s.isSimilar(is)) {
|
||||
continue;
|
||||
}
|
||||
max += s.getAmount();
|
||||
}
|
||||
|
||||
if (stack) {
|
||||
amount *= is.getType().getMaxStackSize();
|
||||
}
|
||||
if (amount < 1) {
|
||||
amount += max;
|
||||
}
|
||||
|
||||
if (requireStack) {
|
||||
amount -= amount % is.getType().getMaxStackSize();
|
||||
}
|
||||
if (amount > max || amount < 1) {
|
||||
if (!isBulkSell) {
|
||||
user.sendMessage(tl("itemNotEnough2"));
|
||||
user.sendMessage(tl("itemNotEnough3"));
|
||||
throw new Exception(tl("itemNotEnough1"));
|
||||
} else {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the price of an item and save it to the config.
|
||||
*
|
||||
* @param ess The Essentials instance.
|
||||
* @param itemStack A stack of the item to save.
|
||||
* @param price The new price of the item.
|
||||
*/
|
||||
public void setPrice(IEssentials ess, ItemStack itemStack, double price) {
|
||||
String path = "worth." + itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replace("_", "");
|
||||
|
||||
// Spigot 1.13+ throws an exception if a 1.13+ plugin even *attempts* to do set data.
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01) && itemStack.getType().getData() == null) {
|
||||
// Bukkit-bug: getDurability still contains the correct value, while getData().getData() is 0.
|
||||
path = path + "." + itemStack.getDurability();
|
||||
}
|
||||
|
||||
config.setProperty(path, price);
|
||||
config.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
config.load();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public class ChargeException extends Exception
|
||||
{
|
||||
public ChargeException(final String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ChargeException(final String message, final Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.EssentialsUserConf;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* You should use Vault instead of directly using this class.
|
||||
*/
|
||||
public class Economy {
|
||||
public Economy() {
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger("Essentials");
|
||||
private static IEssentials ess;
|
||||
private static final String noCallBeforeLoad = "Essentials API is called before Essentials is loaded.";
|
||||
public static final MathContext MATH_CONTEXT = MathContext.DECIMAL128;
|
||||
|
||||
/**
|
||||
* @param aEss the ess to set
|
||||
*/
|
||||
public static void setEss(IEssentials aEss) {
|
||||
ess = aEss;
|
||||
}
|
||||
|
||||
private static void createNPCFile(String name) {
|
||||
File folder = new File(ess.getDataFolder(), "userdata");
|
||||
name = StringUtil.safeString(name);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs();
|
||||
}
|
||||
UUID npcUUID = UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8));
|
||||
EssentialsUserConf npcConfig = new EssentialsUserConf(name, npcUUID, new File(folder, npcUUID.toString() + ".yml"));
|
||||
npcConfig.load();
|
||||
npcConfig.setProperty("npc", true);
|
||||
npcConfig.setProperty("lastAccountName", name);
|
||||
npcConfig.setProperty("money", ess.getSettings().getStartingBalance());
|
||||
npcConfig.forceSave();
|
||||
ess.getUserMap().trackUUID(npcUUID, name, false);
|
||||
}
|
||||
|
||||
private static void deleteNPC(String name) {
|
||||
User user = ess.getUser(name);
|
||||
user.reset();
|
||||
}
|
||||
|
||||
private static User getUserByName(String name) {
|
||||
if (ess == null) {
|
||||
throw new RuntimeException(noCallBeforeLoad);
|
||||
}
|
||||
if (name == null) {
|
||||
throw new RuntimeException("Economy username cannot be null");
|
||||
}
|
||||
|
||||
User user = ess.getUser(name);
|
||||
if (user == null) {
|
||||
/*
|
||||
Attempt lookup using UUID - this prevents balance resets when accessing economy
|
||||
via Vault during player join.
|
||||
See: https://github.com/EssentialsX/Essentials/issues/2400
|
||||
*/
|
||||
Player player = ess.getServer().getPlayerExact(name);
|
||||
if (player != null) {
|
||||
user = ess.getUser(player.getUniqueId());
|
||||
if (user != null) {
|
||||
logger.info(String.format("[Economy] Found player %s by UUID %s but not by their actual name - they may have changed their username", name, player.getUniqueId().toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the balance of a user
|
||||
*
|
||||
* @param name Name of the user
|
||||
*
|
||||
* @return balance
|
||||
*
|
||||
* @throws UserDoesNotExistException
|
||||
*/
|
||||
@Deprecated
|
||||
public static double getMoney(String name) throws UserDoesNotExistException {
|
||||
BigDecimal exactAmount = getMoneyExact(name);
|
||||
double amount = exactAmount.doubleValue();
|
||||
if (new BigDecimal(amount).compareTo(exactAmount) > 0) {
|
||||
// closest double is bigger than the exact amount
|
||||
// -> get the previous double value to not return more money than the user has
|
||||
amount = Math.nextAfter(amount, Double.NEGATIVE_INFINITY);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
public static BigDecimal getMoneyExact(String name) throws UserDoesNotExistException {
|
||||
User user = getUserByName(name);
|
||||
if (user == null) {
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
return user.getMoney();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the balance of a user
|
||||
*
|
||||
* @param name Name of the user
|
||||
* @param balance The balance you want to set
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
@Deprecated
|
||||
public static void setMoney(String name, double balance) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
try {
|
||||
setMoney(name, BigDecimal.valueOf(balance));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to set balance of " + name + " to " + balance + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setMoney(String name, BigDecimal balance) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
User user = getUserByName(name);
|
||||
if (user == null) {
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
if (balance.compareTo(ess.getSettings().getMinMoney()) < 0) {
|
||||
throw new NoLoanPermittedException();
|
||||
}
|
||||
if (balance.signum() < 0 && !user.isAuthorized("essentials.eco.loan")) {
|
||||
throw new NoLoanPermittedException();
|
||||
}
|
||||
try {
|
||||
user.setMoney(balance);
|
||||
} catch (MaxMoneyException ex) {
|
||||
//TODO: Update API to show max balance errors
|
||||
}
|
||||
Trade.log("API", "Set", "API", name, new Trade(balance, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds money to the balance of a user
|
||||
*
|
||||
* @param name Name of the user
|
||||
* @param amount The money you want to add
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
@Deprecated
|
||||
public static void add(String name, double amount) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
try {
|
||||
add(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to add " + amount + " to balance of " + name + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void add(String name, BigDecimal amount) throws UserDoesNotExistException, NoLoanPermittedException, ArithmeticException {
|
||||
BigDecimal result = getMoneyExact(name).add(amount, MATH_CONTEXT);
|
||||
setMoney(name, result);
|
||||
Trade.log("API", "Add", "API", name, new Trade(amount, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Substracts money from the balance of a user
|
||||
*
|
||||
* @param name Name of the user
|
||||
* @param amount The money you want to substract
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
@Deprecated
|
||||
public static void subtract(String name, double amount) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
try {
|
||||
substract(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to substract " + amount + " of balance of " + name + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void substract(String name, BigDecimal amount) throws UserDoesNotExistException, NoLoanPermittedException, ArithmeticException {
|
||||
BigDecimal result = getMoneyExact(name).subtract(amount, MATH_CONTEXT);
|
||||
setMoney(name, result);
|
||||
Trade.log("API", "Subtract", "API", name, new Trade(amount, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the balance of a user by a value
|
||||
*
|
||||
* @param name Name of the user
|
||||
* @param amount The balance is divided by this value
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
@Deprecated
|
||||
public static void divide(String name, double amount) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
try {
|
||||
divide(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to divide balance of " + name + " by " + amount + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void divide(String name, BigDecimal amount) throws UserDoesNotExistException, NoLoanPermittedException, ArithmeticException {
|
||||
BigDecimal result = getMoneyExact(name).divide(amount, MATH_CONTEXT);
|
||||
setMoney(name, result);
|
||||
Trade.log("API", "Divide", "API", name, new Trade(amount, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the balance of a user by a value
|
||||
*
|
||||
* @param name Name of the user
|
||||
* @param amount The balance is multiplied by this value
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
@Deprecated
|
||||
public static void multiply(String name, double amount) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
try {
|
||||
multiply(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to multiply balance of " + name + " by " + amount + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void multiply(String name, BigDecimal amount) throws UserDoesNotExistException, NoLoanPermittedException, ArithmeticException {
|
||||
BigDecimal result = getMoneyExact(name).multiply(amount, MATH_CONTEXT);
|
||||
setMoney(name, result);
|
||||
Trade.log("API", "Multiply", "API", name, new Trade(amount, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the balance of a user to the starting balance
|
||||
*
|
||||
* @param name Name of the user
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
* @throws NoLoanPermittedException If the user is not allowed to have a negative balance
|
||||
*/
|
||||
public static void resetBalance(String name) throws UserDoesNotExistException, NoLoanPermittedException {
|
||||
if (ess == null) {
|
||||
throw new RuntimeException(noCallBeforeLoad);
|
||||
}
|
||||
setMoney(name, ess.getSettings().getStartingBalance());
|
||||
Trade.log("API", "Reset", "API", name, new Trade(BigDecimal.ZERO, ess), null, null, null, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of the user
|
||||
* @param amount The amount of money the user should have
|
||||
*
|
||||
* @return true, if the user has more or an equal amount of money
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasEnough(String name, double amount) throws UserDoesNotExistException {
|
||||
try {
|
||||
return hasEnough(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasEnough(String name, BigDecimal amount) throws UserDoesNotExistException, ArithmeticException {
|
||||
return amount.compareTo(getMoneyExact(name)) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of the user
|
||||
* @param amount The amount of money the user should have
|
||||
*
|
||||
* @return true, if the user has more money
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasMore(String name, double amount) throws UserDoesNotExistException {
|
||||
try {
|
||||
return hasMore(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasMore(String name, BigDecimal amount) throws UserDoesNotExistException, ArithmeticException {
|
||||
return amount.compareTo(getMoneyExact(name)) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of the user
|
||||
* @param amount The amount of money the user should not have
|
||||
*
|
||||
* @return true, if the user has less money
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasLess(String name, double amount) throws UserDoesNotExistException {
|
||||
try {
|
||||
return hasLess(name, BigDecimal.valueOf(amount));
|
||||
} catch (ArithmeticException e) {
|
||||
logger.log(Level.WARNING, "Failed to compare balance of " + name + " with " + amount + ": " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasLess(String name, BigDecimal amount) throws UserDoesNotExistException, ArithmeticException {
|
||||
return amount.compareTo(getMoneyExact(name)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the user has a negative balance
|
||||
*
|
||||
* @param name Name of the user
|
||||
*
|
||||
* @return true, if the user has a negative balance
|
||||
*
|
||||
* @throws UserDoesNotExistException If a user by that name does not exists
|
||||
*/
|
||||
public static boolean isNegative(String name) throws UserDoesNotExistException {
|
||||
return getMoneyExact(name).signum() < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the amount of money like all other Essentials functions. Example: $100000 or $12345.67
|
||||
*
|
||||
* @param amount The amount of money
|
||||
*
|
||||
* @return Formatted money
|
||||
*/
|
||||
@Deprecated
|
||||
public static String format(double amount) {
|
||||
try {
|
||||
return format(BigDecimal.valueOf(amount));
|
||||
} catch (NumberFormatException e) {
|
||||
logger.log(Level.WARNING, "Failed to display " + amount + ": " + e.getMessage(), e);
|
||||
return "NaN";
|
||||
}
|
||||
}
|
||||
|
||||
public static String format(BigDecimal amount) {
|
||||
if (ess == null) {
|
||||
throw new RuntimeException(noCallBeforeLoad);
|
||||
}
|
||||
return NumberUtil.displayCurrency(amount, ess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a player exists to avoid the UserDoesNotExistException
|
||||
*
|
||||
* @param name Name of the user
|
||||
*
|
||||
* @return true, if the user exists
|
||||
*/
|
||||
public static boolean playerExists(String name) {
|
||||
return getUserByName(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a player is a npc
|
||||
*
|
||||
* @param name Name of the player
|
||||
*
|
||||
* @return true, if it's a npc
|
||||
*
|
||||
* @throws UserDoesNotExistException
|
||||
*/
|
||||
public static boolean isNPC(String name) throws UserDoesNotExistException {
|
||||
User user = getUserByName(name);
|
||||
if (user == null) {
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
return user.isNPC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dummy files for a npc, if there is no player yet with that name.
|
||||
*
|
||||
* @param name Name of the player
|
||||
*
|
||||
* @return true, if a new npc was created
|
||||
*/
|
||||
public static boolean createNPC(String name) {
|
||||
User user = getUserByName(name);
|
||||
if (user == null) {
|
||||
createNPCFile(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user, if it is marked as npc.
|
||||
*
|
||||
* @param name Name of the player
|
||||
*
|
||||
* @throws UserDoesNotExistException
|
||||
*/
|
||||
public static void removeNPC(String name) throws UserDoesNotExistException {
|
||||
User user = getUserByName(name);
|
||||
if (user == null) {
|
||||
throw new UserDoesNotExistException(name);
|
||||
}
|
||||
deleteNPC(name);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public interface IBackup extends Runnable
|
||||
{
|
||||
public void startTask();
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import java.util.Map;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public interface ICommandHandler extends IReload
|
||||
{
|
||||
Map<String, String> disabledCommands();
|
||||
|
||||
public void removePlugin(Plugin plugin);
|
||||
|
||||
public void addPlugin(Plugin plugin);
|
||||
|
||||
boolean handleCommand(CommandSender sender, Command command, String commandLabel, String[] args);
|
||||
|
||||
void showCommandError(CommandSender sender, String commandLabel, Throwable exception);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public interface IEconomy extends IReload
|
||||
{
|
||||
public double getMoney(String name) throws UserDoesNotExistException;
|
||||
|
||||
public void setMoney(String name, double balance) throws UserDoesNotExistException, NoLoanPermittedException;
|
||||
|
||||
public void resetBalance(String name) throws UserDoesNotExistException, NoLoanPermittedException;
|
||||
|
||||
public String format(double amount);
|
||||
|
||||
public boolean playerExists(String name);
|
||||
|
||||
public boolean isNPC(String name) throws UserDoesNotExistException;
|
||||
|
||||
public boolean createNPC(String name);
|
||||
|
||||
public void removeNPC(String name) throws UserDoesNotExistException;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.listener.TntExplodeListener;
|
||||
import com.earth2me.essentials.register.payment.Methods;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public interface IEssentials extends Plugin
|
||||
{
|
||||
void addReloadListener(IReload listener);
|
||||
|
||||
IUser getUser(Player player);
|
||||
|
||||
IUser getUser(String playerName);
|
||||
|
||||
int broadcastMessage(IUser sender, String message);
|
||||
|
||||
II18n getI18n();
|
||||
|
||||
ISettings getSettings();
|
||||
|
||||
IGroups getGroups();
|
||||
|
||||
IJails getJails();
|
||||
|
||||
IKits getKits();
|
||||
|
||||
IWarps getWarps();
|
||||
|
||||
IWorth getWorth();
|
||||
|
||||
IItemDb getItemDb();
|
||||
|
||||
IUserMap getUserMap();
|
||||
|
||||
IBackup getBackup();
|
||||
|
||||
ICommandHandler getCommandHandler();
|
||||
|
||||
World getWorld(String name);
|
||||
|
||||
Methods getPaymentMethod();
|
||||
|
||||
int scheduleAsyncDelayedTask(Runnable run);
|
||||
|
||||
int scheduleSyncDelayedTask(Runnable run);
|
||||
|
||||
int scheduleSyncDelayedTask(Runnable run, long delay);
|
||||
|
||||
int scheduleSyncRepeatingTask(Runnable run, long delay, long period);
|
||||
|
||||
//IPermissionsHandler getPermissionsHandler();
|
||||
void reload();
|
||||
|
||||
TntExplodeListener getTNTListener();
|
||||
|
||||
void setGroups(IGroups groups);
|
||||
|
||||
void removeReloadListener(IReload groups);
|
||||
|
||||
IEconomy getEconomy();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public interface IEssentialsModule
|
||||
{
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
|
||||
public interface IGroups
|
||||
{
|
||||
String getMainGroup(IUser player);
|
||||
|
||||
boolean inGroup(IUser player, String groupname);
|
||||
|
||||
double getHealCooldown(IUser player);
|
||||
|
||||
double getTeleportCooldown(IUser player);
|
||||
|
||||
double getTeleportDelay(IUser player);
|
||||
|
||||
String getPrefix(IUser player);
|
||||
|
||||
String getSuffix(IUser player);
|
||||
|
||||
int getHomeLimit(IUser player);
|
||||
|
||||
MessageFormat getChatFormat(IUser player);
|
||||
}
|
||||
@@ -3,7 +3,11 @@ package com.earth2me.essentials.api;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public interface II18n
|
||||
{
|
||||
Locale getCurrentLocale();
|
||||
public interface II18n {
|
||||
/**
|
||||
* Gets the current locale setting
|
||||
*
|
||||
* @return the current locale, if not set it will return the default locale
|
||||
*/
|
||||
Locale getCurrentLocale();
|
||||
}
|
||||
@@ -1,13 +1,163 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public interface IItemDb extends IReload
|
||||
{
|
||||
ItemStack get(final String name, final IUser user) throws Exception;
|
||||
|
||||
ItemStack get(final String name, final int quantity) throws Exception;
|
||||
public interface IItemDb {
|
||||
|
||||
ItemStack get(final String name) throws Exception;
|
||||
/**
|
||||
* Create a stack from the given name with the given quantity.
|
||||
*
|
||||
* @param name Item name to look up in the database
|
||||
* @param quantity Quantity of the item stack
|
||||
* @return The requested item stack
|
||||
* @throws Exception if the item stack cannot be created
|
||||
*/
|
||||
default ItemStack get(final String name, final int quantity) throws Exception {
|
||||
final ItemStack stack = get(name.toLowerCase(Locale.ENGLISH));
|
||||
stack.setAmount(quantity);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a stack from the given name with the maximum stack size for that material.
|
||||
*
|
||||
* @param name Item name to look up in the database
|
||||
* @return The requested item stack with the maximum stack size
|
||||
* @throws Exception if the item stack cannot be created
|
||||
*/
|
||||
ItemStack get(final String name) throws Exception;
|
||||
|
||||
/**
|
||||
* Get a comma-separated string list of up to 15 aliases for the given stack.
|
||||
*
|
||||
* @param item Item stack whose names to find
|
||||
* @return Comma-separated list of up to 15 item names
|
||||
*/
|
||||
default String names(ItemStack item) {
|
||||
List<String> nameList = nameList(item);
|
||||
|
||||
if (nameList.size() > 15) {
|
||||
nameList = nameList.subList(0, 14);
|
||||
}
|
||||
return StringUtil.joinList(", ", nameList);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a List of all aliases for the given item stack.
|
||||
*
|
||||
* @param item Item stack whose names to find
|
||||
* @return List of all names
|
||||
*/
|
||||
List<String> nameList(ItemStack item);
|
||||
|
||||
/**
|
||||
* Get the primary name for the given item stack.
|
||||
*
|
||||
* @param item Item stack whose name to find
|
||||
* @return Primary name of the item
|
||||
*/
|
||||
String name(ItemStack item);
|
||||
|
||||
/**
|
||||
* Get all stacks in a given User's inventory that matches the given arguments.
|
||||
*
|
||||
* @param user The user with the player inventory to search
|
||||
* @param args Either an item name, or one of the following:
|
||||
* hand (default), inventory/invent/all, blocks
|
||||
* @return A List of all matching ItemStacks
|
||||
* @throws Exception if the given args are invalid or no blocks are found
|
||||
*/
|
||||
List<ItemStack> getMatching(User user, String[] args) throws Exception;
|
||||
|
||||
/**
|
||||
* Serialise an ItemStack into a format that can be decoded by
|
||||
* {@link #get(String) get} and
|
||||
* {@link com.earth2me.essentials.MetaItemStack#parseStringMeta(CommandSource, boolean, String[], int, IEssentials)} MetaItemStack#parseStringMeta}.
|
||||
* Used to encode items for kits.
|
||||
*
|
||||
* @param is Stack to serialise
|
||||
* @return Serialised stack
|
||||
*/
|
||||
String serialize(ItemStack is);
|
||||
|
||||
/**
|
||||
* Return names recognised by the database, intended for tab-completion.
|
||||
*
|
||||
* @return Collection of all item names
|
||||
*/
|
||||
Collection<String> listNames();
|
||||
|
||||
/**
|
||||
* Get the material matching the given legacy ID. Used for conversion from item IDs to
|
||||
* modern names.
|
||||
*
|
||||
* @param id Legacy ID of material to find
|
||||
* @return Updated material
|
||||
*/
|
||||
@Deprecated
|
||||
default Material getFromLegacyId(int id) {
|
||||
return getFromLegacy(id, (byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the legacy ID for the given material.
|
||||
*
|
||||
* @param material Material to look up
|
||||
* @return Legacy ID of given material
|
||||
* @throws Exception if the ID cannot be looked up
|
||||
* @deprecated Item IDs are no longer supported.
|
||||
*/
|
||||
@Deprecated
|
||||
int getLegacyId(Material material) throws Exception;
|
||||
|
||||
/**
|
||||
* Convert colon syntax (eg. "13", "1:5") legacy IDs to Material. Used for conversion from
|
||||
* item IDs to modern names.
|
||||
*
|
||||
* @param item Legacy ID in colon syntax.
|
||||
* @return
|
||||
*/
|
||||
default Material getFromLegacy(String item) {
|
||||
final String[] split = item.split(":");
|
||||
|
||||
final int id = Integer.parseInt(split[0]);
|
||||
byte damage = 0;
|
||||
|
||||
if (split.length > 1 && NumberUtil.isInt(split[1])) {
|
||||
damage = Byte.parseByte(split[1]);
|
||||
}
|
||||
|
||||
return getFromLegacy(id, damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert legacy ID and damage value to Material. Used for conversion from item IDs to
|
||||
* modern names.
|
||||
*
|
||||
* @param id Legacy ID
|
||||
* @param damage Damage value
|
||||
* @return Material
|
||||
*/
|
||||
default Material getFromLegacy(final int id, final byte damage) {
|
||||
return MaterialUtil.convertFromLegacy(id, damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the item database is loaded and ready for use.
|
||||
*
|
||||
* @return Whether items have finished loading
|
||||
*/
|
||||
boolean isReady();
|
||||
}
|
||||
@@ -1,18 +1,65 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface IJails extends IReload
|
||||
{
|
||||
Location getJail(String jailName) throws Exception;
|
||||
|
||||
Collection<String> getList() throws Exception;
|
||||
public interface IJails extends IReload {
|
||||
/**
|
||||
* Gets the location of the jail with the given name
|
||||
*
|
||||
* @param jailName The name of the jail
|
||||
*
|
||||
* @return the location of the jail
|
||||
*
|
||||
* @throws Exception if the jail does not exist
|
||||
*/
|
||||
Location getJail(String jailName) throws Exception;
|
||||
|
||||
void removeJail(String jail) throws Exception;
|
||||
/**
|
||||
* Gets a list of jails by names
|
||||
*
|
||||
* @return a list of jails, if there are none the list will be empty
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
Collection<String> getList() throws Exception;
|
||||
|
||||
void sendToJail(IUser user, String jail) throws Exception;
|
||||
/**
|
||||
* Gets the number of jails
|
||||
*
|
||||
* @return the size of the list of jails
|
||||
*/
|
||||
int getCount();
|
||||
|
||||
void setJail(String jailName, Location loc) throws Exception;
|
||||
/**
|
||||
* Remove the jail with the given name
|
||||
*
|
||||
* @param jail the jail to remove
|
||||
*
|
||||
* @throws Exception if the jail does not exist
|
||||
*/
|
||||
void removeJail(String jail) throws Exception;
|
||||
|
||||
/**
|
||||
* Attempts to send the given user to the given jail
|
||||
*
|
||||
* @param user the user to send to jail
|
||||
* @param jail the jail to send the user to
|
||||
*
|
||||
* @throws Exception if the user is offline or jail does not exist
|
||||
*/
|
||||
void sendToJail(IUser user, String jail) throws Exception;
|
||||
|
||||
/**
|
||||
* Set a new jail with the given name and location
|
||||
*
|
||||
* @param jailName the name of the jail being set
|
||||
* @param loc the location of the jail being set
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void setJail(String jailName, Location loc) throws Exception;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.settings.Kit;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface IKits extends IReload
|
||||
{
|
||||
Kit getKit(String kit) throws Exception;
|
||||
|
||||
void sendKit(IUser user, String kit) throws Exception;
|
||||
|
||||
void sendKit(IUser user, Kit kit) throws Exception;
|
||||
|
||||
Collection<String> getList() throws Exception;
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
|
||||
public interface IPermission
|
||||
{
|
||||
String getPermission();
|
||||
|
||||
boolean isAuthorized(CommandSender sender);
|
||||
|
||||
Permission getBukkitPermission();
|
||||
|
||||
PermissionDefault getPermissionDefault();
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public interface IReload
|
||||
{
|
||||
void onReload();
|
||||
public interface IReload {
|
||||
void onReload();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
||||
public interface IReplyTo
|
||||
{
|
||||
void setReplyTo(CommandSender user);
|
||||
|
||||
CommandSender getReplyTo();
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.settings.Settings;
|
||||
import com.earth2me.essentials.storage.IStorageObjectHolder;
|
||||
|
||||
|
||||
public interface ISettings extends IStorageObjectHolder<Settings>
|
||||
{
|
||||
public String getLocale();
|
||||
|
||||
public boolean isDebug();
|
||||
|
||||
public void setDebug(boolean b);
|
||||
}
|
||||
@@ -1,28 +1,120 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.Trade;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
|
||||
public interface ITeleport
|
||||
{
|
||||
void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception;
|
||||
public interface ITeleport {
|
||||
/**
|
||||
* Used to skip teleportPlayer delay when teleporting someone to a location or player.
|
||||
*
|
||||
* @param loc - Where should the player end up
|
||||
* @param cooldown - If cooldown should be enforced
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void now(Location loc, boolean cooldown, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void now(Entity entity, boolean cooldown, TeleportCause cause) throws Exception;
|
||||
/**
|
||||
* Used to skip teleportPlayer delay when teleporting someone to a location or player.
|
||||
*
|
||||
* @param entity - Where should the player end up
|
||||
* @param cooldown - If cooldown should be enforced
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void now(Player entity, boolean cooldown, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void back(Trade chargeFor) throws Exception;
|
||||
@Deprecated
|
||||
void teleport(Location loc, Trade chargeFor) throws Exception;
|
||||
|
||||
void teleport(Location bed, Trade charge, TeleportCause teleportCause) throws Exception;
|
||||
/**
|
||||
* Teleport a player to a specific location
|
||||
*
|
||||
* @param loc - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void teleport(Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void teleport(Entity entity, Trade chargeFor, TeleportCause cause) throws Exception;
|
||||
/**
|
||||
* Teleport a player to a specific player
|
||||
*
|
||||
* @param entity - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void teleport(Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void home(IUser player, String toLowerCase, Trade charge) throws Exception;
|
||||
/**
|
||||
* Teleport a player to a specific location
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param loc - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void teleportPlayer(IUser otherUser, Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void respawn(Trade charge, TeleportCause teleportCause) throws Exception;
|
||||
/**
|
||||
* Teleport a player to a specific player
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param entity - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void teleportPlayer(IUser otherUser, Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
void back() throws Exception;
|
||||
/**
|
||||
* Teleport wrapper used to handle tp fallback on /jail and /home
|
||||
*
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void respawn(final Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle /warp teleports
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param warp - The name of the warp the user will be teleported too.
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void warp(IUser otherUser, String warp, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle /back teleports
|
||||
*
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void back(Trade chargeFor) throws Exception;
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle throwing user home after a jail sentence
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void back() throws Exception;
|
||||
|
||||
public void warp(String name, Trade charge, TeleportCause teleportCause) throws Exception;
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.storage.IStorageObjectHolder;
|
||||
import com.earth2me.essentials.user.CooldownException;
|
||||
import com.earth2me.essentials.user.UserData;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
||||
public interface IUser extends Player, IStorageObjectHolder<UserData>, IReload, IReplyTo, Comparable<IUser>
|
||||
{
|
||||
Player getBase();
|
||||
|
||||
double getMoney();
|
||||
|
||||
void takeMoney(double value);
|
||||
|
||||
void takeMoney(double value, CommandSender initiator);
|
||||
|
||||
void giveMoney(double value);
|
||||
|
||||
void giveMoney(double value, CommandSender initiator);
|
||||
|
||||
void giveItems(ItemStack itemStack, Boolean canSpew) throws ChargeException;
|
||||
|
||||
void giveItems(List<ItemStack> itemStacks, Boolean canSpew) throws ChargeException;
|
||||
|
||||
void setMoney(double value);
|
||||
|
||||
void payUser(final IUser reciever, final double value) throws Exception;
|
||||
|
||||
void setLastLocation();
|
||||
|
||||
Location getHome(String name) throws Exception;
|
||||
|
||||
Location getHome(Location loc);
|
||||
|
||||
boolean isHidden();
|
||||
|
||||
ITeleport getTeleport();
|
||||
|
||||
void checkCooldown(UserData.TimestampType cooldownType, double cooldown, boolean set, IPermission bypassPermission) throws CooldownException;
|
||||
|
||||
boolean toggleAfk();
|
||||
|
||||
void updateActivity(boolean broadcast);
|
||||
|
||||
void updateDisplayName();
|
||||
|
||||
boolean checkJailTimeout(long currentTime);
|
||||
|
||||
boolean checkMuteTimeout(long currentTime);
|
||||
|
||||
boolean checkBanTimeout(long currentTime);
|
||||
|
||||
long getTimestamp(UserData.TimestampType name);
|
||||
|
||||
void setTimestamp(UserData.TimestampType name, long value);
|
||||
|
||||
void setLastOnlineActivity(long currentTime);
|
||||
|
||||
void checkActivity();
|
||||
|
||||
long getLastOnlineActivity();
|
||||
|
||||
boolean isGodModeEnabled();
|
||||
|
||||
boolean isIgnoringPlayer(String name);
|
||||
|
||||
void setIgnoredPlayer(String name, boolean set);
|
||||
|
||||
Location getAfkPosition();
|
||||
|
||||
boolean toggleGodModeEnabled();
|
||||
|
||||
void dispose();
|
||||
|
||||
void updateCompass();
|
||||
|
||||
List<String> getHomes();
|
||||
|
||||
void addMail(String string);
|
||||
|
||||
boolean toggleMuted();
|
||||
|
||||
boolean toggleSocialSpy();
|
||||
|
||||
void requestTeleport(IUser user, boolean b);
|
||||
|
||||
boolean isTeleportRequestHere();
|
||||
|
||||
IUser getTeleportRequester();
|
||||
|
||||
boolean toggleTeleportEnabled();
|
||||
|
||||
long getTeleportRequestTime();
|
||||
|
||||
boolean gotMailInfo();
|
||||
|
||||
List<String> getMails();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public interface IUserMap extends IReload
|
||||
{
|
||||
boolean userExists(final String name);
|
||||
|
||||
IUser getUser(final Player player);
|
||||
|
||||
IUser getUser(final String playerName);
|
||||
|
||||
void removeUser(final String name) throws InvalidNameException;
|
||||
|
||||
Set<String> getAllUniqueUsers();
|
||||
|
||||
int getUniqueUsers();
|
||||
|
||||
File getUserFile(final String name) throws InvalidNameException;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.settings.Warp;
|
||||
import com.earth2me.essentials.storage.IStorageObjectHolder;
|
||||
|
||||
|
||||
public interface IWarp extends IStorageObjectHolder<Warp>
|
||||
{
|
||||
}
|
||||
@@ -1,21 +1,95 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.IConf;
|
||||
import com.earth2me.essentials.IUser;
|
||||
import com.earth2me.essentials.commands.WarpNotFoundException;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.Location;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public interface IWarps extends IReload
|
||||
{
|
||||
Location getWarp(String warp) throws Exception;
|
||||
public interface IWarps extends IConf {
|
||||
/**
|
||||
* Get a warp by name
|
||||
*
|
||||
* @param warp - Warp name
|
||||
*
|
||||
* @return - Location the warp is set to
|
||||
*
|
||||
* @throws WarpNotFoundException When the warp is not found
|
||||
* @throws InvalidWorldException When the world the warp is in is not found
|
||||
*/
|
||||
Location getWarp(String warp) throws WarpNotFoundException, net.ess3.api.InvalidWorldException;
|
||||
|
||||
Collection<String> getList();
|
||||
/**
|
||||
* Gets a list of warps
|
||||
*
|
||||
* @return - A {@link Collection} of warps
|
||||
*/
|
||||
Collection<String> getList();
|
||||
|
||||
void removeWarp(String name) throws Exception;
|
||||
/**
|
||||
* Gets the number of warps
|
||||
*
|
||||
* @return the size of the list of warps
|
||||
*/
|
||||
int getCount();
|
||||
|
||||
void setWarp(String name, Location loc) throws Exception;
|
||||
/**
|
||||
* Delete a warp from the warp DB
|
||||
*
|
||||
* @param name - Name of warp
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void removeWarp(String name) throws Exception;
|
||||
|
||||
public boolean isEmpty();
|
||||
/**
|
||||
* Set a warp
|
||||
*
|
||||
* @param name - Name of warp
|
||||
* @param loc - Location of warp
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void setWarp(String name, Location loc) throws Exception;
|
||||
|
||||
public File getWarpFile(String name) throws InvalidNameException;
|
||||
/**
|
||||
* Set a warp
|
||||
*
|
||||
* @param user - User of warp
|
||||
* @param name - Name of warp
|
||||
* @param loc - Location of warp
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
void setWarp(IUser user, String name, Location loc) throws Exception;
|
||||
|
||||
/**
|
||||
* Gets Lastowner UUID
|
||||
*
|
||||
* @param name - Name of warp
|
||||
*
|
||||
* @throws WarpNotFoundException
|
||||
*/
|
||||
UUID getLastOwner(String warp) throws WarpNotFoundException;
|
||||
/**
|
||||
* Check to see if the file is empty
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Get a warp file note: this is not yet implemented, as 3.x uses different storage methods
|
||||
*
|
||||
* @param name - name of file
|
||||
*
|
||||
* @return - an instance of the file
|
||||
*
|
||||
* @throws InvalidNameException - When the file is not found
|
||||
*/
|
||||
File getWarpFile(String name) throws net.ess3.api.InvalidNameException;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
||||
public interface IWorth extends IReload
|
||||
{
|
||||
double getPrice(ItemStack itemStack);
|
||||
|
||||
void setPrice(ItemStack itemStack, double price);
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
|
||||
public class InvalidNameException extends Exception
|
||||
{
|
||||
public InvalidNameException(Throwable thrwbl)
|
||||
{
|
||||
super(thrwbl);
|
||||
}
|
||||
public class InvalidNameException extends Exception {
|
||||
/**
|
||||
* NOTE: This is not implemented yet, just here for future 3.x api support Allow serialization of the
|
||||
* InvalidNameException exception
|
||||
*/
|
||||
private static final long serialVersionUID = 1485321420293663139L;
|
||||
|
||||
public InvalidNameException(Throwable thrwbl) {
|
||||
super(thrwbl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class InvalidWorldException extends Exception {
|
||||
private final String world;
|
||||
|
||||
public InvalidWorldException(final String world) {
|
||||
super(tl("invalidWorld"));
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public String getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
|
||||
public class NoLoanPermittedException extends net.ess3.api.NoLoanPermittedException {
|
||||
|
||||
public class NoLoanPermittedException extends Exception
|
||||
{
|
||||
public NoLoanPermittedException()
|
||||
{
|
||||
super(_("negativeBalanceError"));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import static com.earth2me.essentials.I18n._;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class UserDoesNotExistException extends Exception
|
||||
{
|
||||
public UserDoesNotExistException(String name)
|
||||
{
|
||||
super(_("userDoesNotExist", name));
|
||||
}
|
||||
public class UserDoesNotExistException extends Exception {
|
||||
public UserDoesNotExistException(String name) {
|
||||
super(tl("userDoesNotExist", name));
|
||||
}
|
||||
}
|
||||
Loaded 100 of 814 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user