mirror of
https://github.com/md5sha256/AreaShop.git
synced 2026-11-06 17:32:43 -05:00
Compare commits
800
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7907498c9 | ||
|
|
afbdc6c009 | ||
|
|
cc3a0b32a4 | ||
|
|
aca6103b1c | ||
|
|
02c02dad8d | ||
|
|
822f300e65 | ||
|
|
1671dc8c26 | ||
|
|
72c4a76c6c | ||
|
|
c9e7e3cdbb | ||
|
|
4ceff1b80e | ||
|
|
8e88dc7b6b | ||
|
|
2762ebae1d | ||
|
|
5742dd623e | ||
|
|
e5d190d81e | ||
|
|
b631cfc89d | ||
|
|
399b166339 | ||
|
|
b556cb1bce | ||
|
|
105274b633 | ||
|
|
9b036dad93 | ||
|
|
628aa83089 | ||
|
|
11da15454d | ||
|
|
ff2e4e235d | ||
|
|
88c7b7a4bd | ||
|
|
cd3a7e97a7 | ||
|
|
d33739491a | ||
|
|
5488deb0d7 | ||
|
|
ff59fa7f70 | ||
|
|
219ba0335e | ||
|
|
724439da7d | ||
|
|
7bebca5dca | ||
|
|
5989ecbcbc | ||
|
|
a6a38be0a5 | ||
|
|
5034aa358a | ||
|
|
4f7982f5b2 | ||
|
|
92c8eea23a | ||
|
|
4ff5852a9d | ||
|
|
b30a292398 | ||
|
|
5640a55d73 | ||
|
|
cd79e071a4 | ||
|
|
49a4b1420d | ||
|
|
7ef50fbcba | ||
|
|
f9b1920678 | ||
|
|
a9d388a12c | ||
|
|
d66b79ba67 | ||
|
|
a33e25d83c | ||
|
|
1b1e0c7225 | ||
|
|
a977433a22 | ||
|
|
81ef7b08ba | ||
|
|
1528668f01 | ||
|
|
51487b476b | ||
|
|
a1a64d8eb4 | ||
|
|
e0a451511c | ||
|
|
1bc2523b95 | ||
|
|
dba63b7cdd | ||
|
|
fbef0006d1 | ||
|
|
c1572eb754 | ||
|
|
82ab8dbbbc | ||
|
|
0a1d27488b | ||
|
|
a92b38e664 | ||
|
|
4e1f8f685e | ||
|
|
e02f14b041 | ||
|
|
7687a9be77 | ||
|
|
745895cdae | ||
|
|
0305ec3f1f | ||
|
|
ec36996385 | ||
|
|
2800bf469b | ||
|
|
d25fc9fd45 | ||
|
|
1172b1b775 | ||
|
|
0ba567cf90 | ||
|
|
74f0a8ed3b | ||
|
|
4c6b7233eb | ||
|
|
e00cc2c191 | ||
|
|
73346d241c | ||
|
|
e8a9c6b3c7 | ||
|
|
6c6f9fc8ed | ||
|
|
284d915ca5 | ||
|
|
1494d3a3fd | ||
|
|
abaf960613 | ||
|
|
0ca301970b | ||
|
|
c7c1d9e4f6 | ||
|
|
5a61cee351 | ||
|
|
a4195eb556 | ||
|
|
ddc5145539 | ||
|
|
5daa99c938 | ||
|
|
3c2bd89c8d | ||
|
|
3c3e8965a3 | ||
|
|
6898efb7d7 | ||
|
|
030826d343 | ||
|
|
b8625237a7 | ||
|
|
b0df7ba98d | ||
|
|
a8938dc492 | ||
|
|
9f0a6ee196 | ||
|
|
cb7016264f | ||
|
|
feff1c6e24 | ||
|
|
02d1881f6d | ||
|
|
aa61bc58ca | ||
|
|
4d467e0d05 | ||
|
|
32a84dd4c8 | ||
|
|
f141f78529 | ||
|
|
96d490836e | ||
|
|
7f7f50a650 | ||
|
|
91efe92ccc | ||
|
|
d308420f30 | ||
|
|
22e3785a07 | ||
|
|
ed55641c8b | ||
|
|
b9653b7382 | ||
|
|
7021b50cbc | ||
|
|
894cc9b99c | ||
|
|
2b5d0c6bd0 | ||
|
|
867b50c1f5 | ||
|
|
d6fdcb05ef | ||
|
|
c347e8de59 | ||
|
|
81457b0d0b | ||
|
|
d7006267ca | ||
|
|
31b345ffe0 | ||
|
|
1336cb78b2 | ||
|
|
7c6b80e392 | ||
|
|
46baea2c0d | ||
|
|
d2e61545ea | ||
|
|
a12fb49832 | ||
|
|
08be336499 | ||
|
|
3051e8b402 | ||
|
|
52c3742a2a | ||
|
|
5b16f40335 | ||
|
|
6c6a67928f | ||
|
|
06dd185205 | ||
|
|
02389b7d1b | ||
|
|
bee7f18bd0 | ||
|
|
63dc36c3bd | ||
|
|
4723043e9a | ||
|
|
703bbc6668 | ||
|
|
b524b1c88f | ||
|
|
f1546f8482 | ||
|
|
29ec5a2e3b | ||
|
|
3a15e3d025 | ||
|
|
90e010494a | ||
|
|
7541af37f3 | ||
|
|
36c74a32f0 | ||
|
|
129b144cb1 | ||
|
|
a79b0067f2 | ||
|
|
5c2e4f8f0c | ||
|
|
d639f61e8f | ||
|
|
65b9ffed18 | ||
|
|
ee94a3d549 | ||
|
|
44d8999b3c | ||
|
|
a09d6f9370 | ||
|
|
105cc1033c | ||
|
|
c3daff0842 | ||
|
|
3456bc6a37 | ||
|
|
58269daa45 | ||
|
|
bac50ed5d5 | ||
|
|
8d50a0d1a7 | ||
|
|
bf5436284a | ||
|
|
592a1b24f4 | ||
|
|
aacf75c170 | ||
|
|
4bf598ac5d | ||
|
|
4b4521b002 | ||
|
|
cd262fdf5e | ||
|
|
5b283d503b | ||
|
|
b9d5a29629 | ||
|
|
0b0f4b0289 | ||
|
|
75915f2ebf | ||
|
|
1395220edb | ||
|
|
a318293bbe | ||
|
|
0cbf14183d | ||
|
|
4c636856aa | ||
|
|
7bb3ed1859 | ||
|
|
909f6c4b45 | ||
|
|
adfc4334cc | ||
|
|
f8ae27c3f3 | ||
|
|
d2b2ca2b83 | ||
|
|
6f8afea58e | ||
|
|
113a1a4f63 | ||
|
|
6e7a659c80 | ||
|
|
1336858316 | ||
|
|
7b7b5abf2c | ||
|
|
9fd8a740db | ||
|
|
88a23650a0 | ||
|
|
4e1f9e6875 | ||
|
|
4fdf9d787f | ||
|
|
413f16a2d4 | ||
|
|
3c21ac1eba | ||
|
|
7670d1b479 | ||
|
|
73e04ccc68 | ||
|
|
52256c83b8 | ||
|
|
794854e9c2 | ||
|
|
2c7fc16f8b | ||
|
|
b7fc4175a1 | ||
|
|
6e686f5a3f | ||
|
|
324dae03eb | ||
|
|
8a3122ba93 | ||
|
|
aada9a4624 | ||
|
|
b74736f23b | ||
|
|
c54c8b32ac | ||
|
|
63c1b7474a | ||
|
|
192f34099a | ||
|
|
b933dfea72 | ||
|
|
3d08c9f7be | ||
|
|
52d5b4632b | ||
|
|
7e03db8b10 | ||
|
|
913d1c9b59 | ||
|
|
f24a922fec | ||
|
|
5871b3ba24 | ||
|
|
9d3818906c | ||
|
|
ac69d18dc0 | ||
|
|
2c3a78517d | ||
|
|
04d42c5444 | ||
|
|
172762356d | ||
|
|
aeb201c221 | ||
|
|
788ba7e2b6 | ||
|
|
89114ee126 | ||
|
|
d316f2e914 | ||
|
|
74219ff75b | ||
|
|
e13a5f2bb0 | ||
|
|
c3bc9457ef | ||
|
|
6dc97b019e | ||
|
|
41944102b6 | ||
|
|
90fecd1085 | ||
|
|
e1b4df8f25 | ||
|
|
f0e4bd12ca | ||
|
|
27d832f05a | ||
|
|
1ca846f1ec | ||
|
|
2472a14cae | ||
|
|
c2bfe2158e | ||
|
|
745d1dd7d7 | ||
|
|
f6977061f4 | ||
|
|
c922b83de4 | ||
|
|
444a769f37 | ||
|
|
6b81be9cbb | ||
|
|
cd07b899c8 | ||
|
|
6bd916facd | ||
|
|
d16ea37269 | ||
|
|
56ab7ef52b | ||
|
|
6ef2d89cfc | ||
|
|
94a807d7c2 | ||
|
|
0d01cb956e | ||
|
|
55c4f7f369 | ||
|
|
3348e5b697 | ||
|
|
381c8b2ebe | ||
|
|
6bf344e6be | ||
|
|
e2bcc57128 | ||
|
|
6df08bc713 | ||
|
|
0e0b085000 | ||
|
|
4f9fc950f0 | ||
|
|
fe16d732a2 | ||
|
|
8cc44cf79f | ||
|
|
4fd478dbc3 | ||
|
|
fe77bf0318 | ||
|
|
e4b53982b2 | ||
|
|
3c953ad9a3 | ||
|
|
88f55bb6a9 | ||
|
|
4ba8326314 | ||
|
|
de81d92da0 | ||
|
|
f636a98314 | ||
|
|
e4df5a8cc9 | ||
|
|
56818bebdb | ||
|
|
7e1d7168f1 | ||
|
|
ff1ea3ae51 | ||
|
|
c9dc8dd840 | ||
|
|
c0794daeeb | ||
|
|
d40b9c660b | ||
|
|
f7b010b3f3 | ||
|
|
a06d9271c4 | ||
|
|
dd343aa587 | ||
|
|
e09d4ebd83 | ||
|
|
5f435941e4 | ||
|
|
86316cdd5b | ||
|
|
61828d3cfd | ||
|
|
54241d5ce3 | ||
|
|
d048665530 | ||
|
|
23de68431c | ||
|
|
95b4543f19 | ||
|
|
d058bb7271 | ||
|
|
63d26be369 | ||
|
|
1020388aae | ||
|
|
e56107ffd6 | ||
|
|
06fceb4643 | ||
|
|
e2077c3b32 | ||
|
|
fcb64c2ddb | ||
|
|
cc51109720 | ||
|
|
0b48f4dd2e | ||
|
|
4d7f00b0ce | ||
|
|
b27ea83982 | ||
|
|
66da717a77 | ||
|
|
7f779d2df8 | ||
|
|
ed3bd01f2a | ||
|
|
ef03501d1c | ||
|
|
feb35cfd37 | ||
|
|
b6a8dcc24c | ||
|
|
5619612a6e | ||
|
|
26ac52cc0a | ||
|
|
5f6bd55afe | ||
|
|
aba2e12c5d | ||
|
|
2906de11de | ||
|
|
436672f85b | ||
|
|
5ba8ed7ad8 | ||
|
|
00d97f1beb | ||
|
|
f530fa40af | ||
|
|
a804df2257 | ||
|
|
c96e0b464e | ||
|
|
13e52aa4f1 | ||
|
|
9aeb531d16 | ||
|
|
44f83473d1 | ||
|
|
d7260998f5 | ||
|
|
638382eacf | ||
|
|
e18fe99161 | ||
|
|
bdc9e32c13 | ||
|
|
9a46d5ae3b | ||
|
|
6795fc43d9 | ||
|
|
dd9bd2c434 | ||
|
|
9438166180 | ||
|
|
9e06b9f268 | ||
|
|
4562bf23f6 | ||
|
|
24edb01754 | ||
|
|
2739bf6ad4 | ||
|
|
2ce84186ab | ||
|
|
279fa001ea | ||
|
|
b56d5320a6 | ||
|
|
30665908b9 | ||
|
|
0fd384833a | ||
|
|
09634de4bf | ||
|
|
7fafee82a7 | ||
|
|
2899b2978c | ||
|
|
7afcba79c9 | ||
|
|
72084b38f8 | ||
|
|
6a291feedd | ||
|
|
b85566882c | ||
|
|
c14407e14b | ||
|
|
ae9bd60d1b | ||
|
|
c689c2fae0 | ||
|
|
728cfb6dfa | ||
|
|
3abb6c06e4 | ||
|
|
51c11738af | ||
|
|
172b5a99f1 | ||
|
|
4c5d025e54 | ||
|
|
e93a2d04de | ||
|
|
af5980d555 | ||
|
|
3f7249f4a1 | ||
|
|
73c6fc858e | ||
|
|
360c3e7e21 | ||
|
|
73d0115b78 | ||
|
|
baf7eaabf1 | ||
|
|
ca8c0487a8 | ||
|
|
24156a03c4 | ||
|
|
ec677766d2 | ||
|
|
ef6c8fbf9d | ||
|
|
4f52fe9e6e | ||
|
|
3ebe5a6fa9 | ||
|
|
3cebe5d2c7 | ||
|
|
c76415c4f3 | ||
|
|
b7bc02aef3 | ||
|
|
d75094e191 | ||
|
|
4045914b48 | ||
|
|
1fac002ee0 | ||
|
|
64301e74e0 | ||
|
|
5a5a7fc5ef | ||
|
|
b928caf0c2 | ||
|
|
111f629787 | ||
|
|
718474ca95 | ||
|
|
93b9df3e54 | ||
|
|
bad983a0b8 | ||
|
|
e2c8b06b68 | ||
|
|
7249e39c02 | ||
|
|
9d9a58a170 | ||
|
|
e64e884c2a | ||
|
|
6ad4ff9deb | ||
|
|
eec9806492 | ||
|
|
43b2ae8278 | ||
|
|
6d5a92e389 | ||
|
|
7d7a62ffa0 | ||
|
|
44456d87b6 | ||
|
|
d92c710b27 | ||
|
|
3dceaf98cd | ||
|
|
33c29a3756 | ||
|
|
771734360f | ||
|
|
539e908d32 | ||
|
|
088471aa3c | ||
|
|
5a95c95670 | ||
|
|
5a5d627d51 | ||
|
|
9b5434a4b2 | ||
|
|
e13717950b | ||
|
|
03ed2803bd | ||
|
|
b3f1225934 | ||
|
|
68651899b7 | ||
|
|
4a7a4ca4ee | ||
|
|
0d272c8fe9 | ||
|
|
6b2c905939 | ||
|
|
7ab782799b | ||
|
|
bea82eae88 | ||
|
|
4ac0e045bd | ||
|
|
e5061b218e | ||
|
|
40fdfba47d | ||
|
|
e9260cede6 | ||
|
|
bb297c9ff1 | ||
|
|
666742ad56 | ||
|
|
36eb8c3a5e | ||
|
|
06a9f7b28e | ||
|
|
e101780420 | ||
|
|
6abe99e807 | ||
|
|
a1d18521ee | ||
|
|
363b416c59 | ||
|
|
7bf516108b | ||
|
|
7567cb5fe4 | ||
|
|
d2ca54e8ea | ||
|
|
e47cda4254 | ||
|
|
98d4c6a778 | ||
|
|
2a44dd29cc | ||
|
|
c1665c33ff | ||
|
|
2cdab9b6db | ||
|
|
72faf76619 | ||
|
|
ad66ce00b1 | ||
|
|
edc7126b87 | ||
|
|
a7f0ac248c | ||
|
|
675dee2cd3 | ||
|
|
c7226750ab | ||
|
|
2ecbb61053 | ||
|
|
fc132558a3 | ||
|
|
b172413b62 | ||
|
|
dcbb1f5896 | ||
|
|
6e3855c0c3 | ||
|
|
27991d17a2 | ||
|
|
159221d53d | ||
|
|
557d11dfb4 | ||
|
|
b9547e2c67 | ||
|
|
221785ae55 | ||
|
|
0d04676bce | ||
|
|
c8cd68c17b | ||
|
|
539887449c | ||
|
|
4cda8a9292 | ||
|
|
fe131dc157 | ||
|
|
41ced9ee6c | ||
|
|
03de0ff252 | ||
|
|
b057271394 | ||
|
|
d7cdff0b22 | ||
|
|
1035b6b41b | ||
|
|
e0bad7397c | ||
|
|
b7124e8cdd | ||
|
|
f0952c32c9 | ||
|
|
d3dfa86a65 | ||
|
|
8f73b8af3c | ||
|
|
51b24c74b4 | ||
|
|
9beb1eb61b | ||
|
|
de5fdafca0 | ||
|
|
0aea914d20 | ||
|
|
b4efe7d5bf | ||
|
|
ec7983e126 | ||
|
|
e45c353030 | ||
|
|
44b1cb0fc8 | ||
|
|
c7299fa56c | ||
|
|
12bf467714 | ||
|
|
5b327db316 | ||
|
|
b4f33589a1 | ||
|
|
530c74ccd2 | ||
|
|
fa4857cbce | ||
|
|
93fd4e96cb | ||
|
|
a6863ae782 | ||
|
|
e5e2c4ca08 | ||
|
|
b0341e2a3e | ||
|
|
c8e1ebb068 | ||
|
|
39c8eb5f73 | ||
|
|
2483cf1614 | ||
|
|
769f8ee4ca | ||
|
|
2c04b87a9f | ||
|
|
8ce1ed0264 | ||
|
|
035f8e1932 | ||
|
|
4d3482994f | ||
|
|
45f1c510e5 | ||
|
|
5c13223b9e | ||
|
|
8c47ae9b3c | ||
|
|
28d03a6a3a | ||
|
|
aa585e9b11 | ||
|
|
36d2ce60b9 | ||
|
|
bdea9448a4 | ||
|
|
bd2f40f5c8 | ||
|
|
9e908cee73 | ||
|
|
0d326d973d | ||
|
|
27eaa27765 | ||
|
|
fb35153eb2 | ||
|
|
aec6295516 | ||
|
|
38cd77e487 | ||
|
|
6b9866a4c4 | ||
|
|
5aceb81cfd | ||
|
|
50f6bce64e | ||
|
|
f713edc5b5 | ||
|
|
012920a51c | ||
|
|
6154454f96 | ||
|
|
e34daeb5ff | ||
|
|
0a2dc22c59 | ||
|
|
2482bd88c2 | ||
|
|
e86281ab28 | ||
|
|
5a9ca74b75 | ||
|
|
d301be2304 | ||
|
|
a23c6fa66f | ||
|
|
cd63517041 | ||
|
|
e3043c476b | ||
|
|
3be7573863 | ||
|
|
51161fffee | ||
|
|
c82067ad0b | ||
|
|
46dbb8d22c | ||
|
|
cace086466 | ||
|
|
06a716b1fd | ||
|
|
4530717045 | ||
|
|
741bbd879f | ||
|
|
8474edd29d | ||
|
|
d4df691166 | ||
|
|
3e247e6cb1 | ||
|
|
f3527134e8 | ||
|
|
0e14b121b8 | ||
|
|
8cc632fc05 | ||
|
|
77c1b3f288 | ||
|
|
21339cbf7c | ||
|
|
0351188671 | ||
|
|
47e1d80821 | ||
|
|
1d0472b052 | ||
|
|
22dcfc76af | ||
|
|
6b59176048 | ||
|
|
5dc4d11408 | ||
|
|
00bd305381 | ||
|
|
9daa50b23b | ||
|
|
33b73a0369 | ||
|
|
591540af30 | ||
|
|
4e1e50e993 | ||
|
|
9a52ca3d9b | ||
|
|
858b019806 | ||
|
|
b1dfe93088 | ||
|
|
0bf2314f2a | ||
|
|
33ddb8ae88 | ||
|
|
234e4b6261 | ||
|
|
ed2ffaeaa3 | ||
|
|
e073438862 | ||
|
|
07194f07da | ||
|
|
dfa3e0be66 | ||
|
|
8eef029400 | ||
|
|
c8d869ce15 | ||
|
|
053d75181d | ||
|
|
f0128c221b | ||
|
|
ce6c01c5d0 | ||
|
|
b835c4dded | ||
|
|
07e6782714 | ||
|
|
4002956aeb | ||
|
|
0b96b9cb42 | ||
|
|
0c192c2444 | ||
|
|
2381aaeacc | ||
|
|
906b331758 | ||
|
|
f0f2e09be0 | ||
|
|
395cc6de07 | ||
|
|
3b9d6187ca | ||
|
|
9d1585f513 | ||
|
|
9d6955039a | ||
|
|
747b47057b | ||
|
|
a973e254e6 | ||
|
|
a5105af3ad | ||
|
|
0bb0a05b76 | ||
|
|
dad502ec0c | ||
|
|
f471b9bbf0 | ||
|
|
f69d1c41e6 | ||
|
|
4ea6f59c49 | ||
|
|
0b7158290f | ||
|
|
e6757d23de | ||
|
|
7cda35f4da | ||
|
|
ee293d14b9 | ||
|
|
2e0fce4955 | ||
|
|
7afdefc9ed | ||
|
|
11f80e7ed1 | ||
|
|
40d45c7786 | ||
|
|
6b8e161e43 | ||
|
|
e1b2f7391c | ||
|
|
89ae8b9b4a | ||
|
|
fab415bf19 | ||
|
|
c7aa92be81 | ||
|
|
705c8d6891 | ||
|
|
429d87c9ff | ||
|
|
1fdd8b32cc | ||
|
|
7900f78a8c | ||
|
|
3a65a88849 | ||
|
|
7b491d0389 | ||
|
|
fd02c51492 | ||
|
|
bb1f592807 | ||
|
|
16c7a044ea | ||
|
|
152f183670 | ||
|
|
09b6e4c584 | ||
|
|
aeb70196a3 | ||
|
|
62148ea577 | ||
|
|
fcc9fb0945 | ||
|
|
b525c5902c | ||
|
|
b18a7cc6d5 | ||
|
|
54b6e84558 | ||
|
|
bae3c0a199 | ||
|
|
508270a280 | ||
|
|
87b2cb9ecd | ||
|
|
271b17b6be | ||
|
|
1dfedea50c | ||
|
|
d9abe2e347 | ||
|
|
1ba2e21ae9 | ||
|
|
fcdfdc6094 | ||
|
|
8a7e2ba5c2 | ||
|
|
0950452692 | ||
|
|
293978f068 | ||
|
|
5efe14b8e9 | ||
|
|
839d510151 | ||
|
|
9180d9b8ee | ||
|
|
7aa786f4ce | ||
|
|
10ea8540e7 | ||
|
|
dba00769f6 | ||
|
|
44c70c6a33 | ||
|
|
570f7b4055 | ||
|
|
feafa012dd | ||
|
|
82b340ce1a | ||
|
|
93809f27fc | ||
|
|
f8ed3654fd | ||
|
|
58a1afccf3 | ||
|
|
d9c3573225 | ||
|
|
1577443203 | ||
|
|
ab7a92c57d | ||
|
|
2e09b0f60f | ||
|
|
6e5c35f95b | ||
|
|
066ceedafd | ||
|
|
c8ebe24bd3 | ||
|
|
ad7db5ee23 | ||
|
|
f80a8178ff | ||
|
|
05c8e1a7e4 | ||
|
|
9904805310 | ||
|
|
0df2f429c0 | ||
|
|
b3408a2648 | ||
|
|
e1f89e7904 | ||
|
|
064b129205 | ||
|
|
8111387f32 | ||
|
|
a4b23bebba | ||
|
|
7421e685fa | ||
|
|
374b68d8fa | ||
|
|
ca7a9664f3 | ||
|
|
e957b4fc73 | ||
|
|
6493bc4f78 | ||
|
|
2db1b6a243 | ||
|
|
864662a3c4 | ||
|
|
59b960b87c | ||
|
|
2de653d73f | ||
|
|
4feee59834 | ||
|
|
816d136a62 | ||
|
|
121de7dc7e | ||
|
|
f7c86881cc | ||
|
|
351d51b664 | ||
|
|
5a28476cf0 | ||
|
|
8143bdae27 | ||
|
|
b62744fe10 | ||
|
|
fe0b63c760 | ||
|
|
def774c7a1 | ||
|
|
7c5cb5f5aa | ||
|
|
8af6e1d6f1 | ||
|
|
e0e6c39dae | ||
|
|
dabe46bd47 | ||
|
|
ec478a05d1 | ||
|
|
e21c0aafde | ||
|
|
52bf88f4a5 | ||
|
|
e4de560a65 | ||
|
|
6481da29e4 | ||
|
|
f287cc91a6 | ||
|
|
95b7b50346 | ||
|
|
21db2ff440 | ||
|
|
36dd978a92 | ||
|
|
6cc3f2a52f | ||
|
|
852731b1ad | ||
|
|
30faa77da9 | ||
|
|
ec57b922b8 | ||
|
|
c2bcc6008b | ||
|
|
72a05bedce | ||
|
|
bc73a8b20d | ||
|
|
832e8218b6 | ||
|
|
6fcb629133 | ||
|
|
7d6a1f35c1 | ||
|
|
60257d45c2 | ||
|
|
2300227d87 | ||
|
|
b1852b10bb | ||
|
|
88fdb0c3fc | ||
|
|
491e55fc77 | ||
|
|
c7b0a2c663 | ||
|
|
868f4d6b58 | ||
|
|
0d4b034181 | ||
|
|
5f20689ba3 | ||
|
|
38b658fccf | ||
|
|
28ed20c0b5 | ||
|
|
aaff36b2eb | ||
|
|
49b536cab0 | ||
|
|
9a9969dea3 | ||
|
|
84e4b49bfd | ||
|
|
6daaf6997d | ||
|
|
c445a62334 | ||
|
|
0d205b0d9e | ||
|
|
8c33826c2c | ||
|
|
51e1dbafb7 | ||
|
|
6edad3faff | ||
|
|
f89e0f861b | ||
|
|
770b1d98df | ||
|
|
8e5baa47af | ||
|
|
367466735e | ||
|
|
ade6bc3971 | ||
|
|
05fd8c0156 | ||
|
|
5403472476 | ||
|
|
c4ee7bc7aa | ||
|
|
940f1969b6 | ||
|
|
07eb5477b8 | ||
|
|
a4112092b5 | ||
|
|
872d81b0a9 | ||
|
|
b04871c553 | ||
|
|
fd1b8fba4c | ||
|
|
991e7b1961 | ||
|
|
aac963325a | ||
|
|
3e7c7ce76b | ||
|
|
c858d30481 | ||
|
|
b090fd5577 | ||
|
|
8d132c66c4 | ||
|
|
50e3e59543 | ||
|
|
eb21b9567e | ||
|
|
4dba305f6d | ||
|
|
7481d8287f | ||
|
|
4d41decbe5 | ||
|
|
7fc5a5af81 | ||
|
|
d26fa99b95 | ||
|
|
39d755d2db | ||
|
|
48ab46ecf7 | ||
|
|
b3fa31e1cc | ||
|
|
783085fbf7 | ||
|
|
aa093b0c8a | ||
|
|
9c357fe929 | ||
|
|
4d70571a23 | ||
|
|
29a4105ece | ||
|
|
edc7136063 | ||
|
|
6fabc75be4 | ||
|
|
085507bf8b | ||
|
|
73ed3366ae | ||
|
|
9ca029176d | ||
|
|
bf181d69d7 | ||
|
|
68c57515da | ||
|
|
903d6c309f | ||
|
|
0a02eb3254 | ||
|
|
bf04589fab | ||
|
|
14dd094803 | ||
|
|
02df35304c | ||
|
|
4321667ec5 | ||
|
|
5cf5df78c8 | ||
|
|
8608d6ce1d | ||
|
|
614336862e | ||
|
|
a4ea175f1b | ||
|
|
c96043aa38 | ||
|
|
d5a29f6c32 | ||
|
|
5176a1c2c5 | ||
|
|
89569ea182 | ||
|
|
f349657a59 | ||
|
|
40d3d4d8af | ||
|
|
0d5db8fa4e | ||
|
|
25c56e8ecb | ||
|
|
9f436a7eb4 | ||
|
|
f76c1b8a9f | ||
|
|
d466658f36 | ||
|
|
04e02c4ce4 | ||
|
|
3bf493109c | ||
|
|
2f9b6d3987 | ||
|
|
93d5612513 | ||
|
|
937db4620d | ||
|
|
a0239b8837 | ||
|
|
401f52e687 | ||
|
|
2f6874a16e | ||
|
|
c95f4e1c6c | ||
|
|
1a2d755727 | ||
|
|
c489e6eba4 | ||
|
|
b1a56b5230 | ||
|
|
dfbc7805b5 | ||
|
|
8f2c95f5c4 | ||
|
|
0b9bffe68f | ||
|
|
7ac6e34c89 | ||
|
|
5231f6e86e | ||
|
|
791b696aff | ||
|
|
c92bc716dc | ||
|
|
463b34e952 | ||
|
|
ff6e69196d | ||
|
|
76ad952bb6 | ||
|
|
0cdff5e143 | ||
|
|
9dc3013215 | ||
|
|
796b95c9f9 | ||
|
|
2785a72457 | ||
|
|
c2df0cd912 | ||
|
|
4cd32a0792 | ||
|
|
354e70af57 | ||
|
|
fde60e2a27 | ||
|
|
d1a3027e0b | ||
|
|
4e57f03fc0 | ||
|
|
83d4efc3a8 | ||
|
|
1395afffe9 | ||
|
|
5094d39a96 | ||
|
|
e664c1efd9 | ||
|
|
871eeed29c | ||
|
|
0d56762bfc | ||
|
|
c08763883f | ||
|
|
efb534f131 | ||
|
|
d9405a9f49 | ||
|
|
684add89cd | ||
|
|
d1848c0728 | ||
|
|
9fd16290c0 | ||
|
|
3bbca11cc9 | ||
|
|
b1be87014f |
No files matched your search
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a problem in the plugin
|
||||
title: ''
|
||||
labels: 'NEW, Type: Bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Current behavior**
|
||||
<!--- Tell what happens currently and/or show the stacktrace if an error occured -->
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
<!--- Tell what you expected to happen instead -->
|
||||
|
||||
|
||||
**Steps to reproduce**
|
||||
<!--- Exactly show how this bug can be triggered -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
|
||||
**Your environment**
|
||||
<!--- Indicate which versions you use -->
|
||||
<!--- Attention: "LATEST" or "NEWEST" are invalid answers! -->
|
||||
<!--- Use '/version' for the Platform version and '/version <plugin>' for plugin versions -->
|
||||
* Server platform (Bukkit, Spigot, etc.):
|
||||
* Server version:
|
||||
* AreaShop version:
|
||||
* WorldEdit version:
|
||||
* WorldGuard version:
|
||||
* Vault version:
|
||||
|
||||
|
||||
**Your config files**
|
||||
<!--- Attach a '.zip' file of the '/plugins/AreaShop' and '/plugins/WorldGuard' directories to show your configuration setup -->
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea
|
||||
title: ''
|
||||
labels: 'NEW, Type: Feature'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the problem you are trying to solve with this feature request**
|
||||
<!-- When I know the problem you are trying to solve I can help you to think about the best solution -->
|
||||
|
||||
|
||||
**Describe the solution you'd like**
|
||||
<!-- Describe the config settings, commands and other features that should be added -->
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Support question
|
||||
about: Ask help with the setup or usage of the plugin
|
||||
title: ''
|
||||
labels: 'NEW, Type: Support'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Current behavior**
|
||||
<!--- Tell what happens currently -->
|
||||
|
||||
|
||||
**Desired behavior**
|
||||
<!--- Tell what you want to happen instead -->
|
||||
|
||||
|
||||
**Your environment**
|
||||
<!--- Indicate which versions you use -->
|
||||
<!--- Attention: "LATEST" or "NEWEST" are invalid answers! -->
|
||||
<!--- Use '/version' for the Platform version and '/version <plugin>' for plugin versions -->
|
||||
* Server platform (Bukkit, Spigot, etc.):
|
||||
* Server version:
|
||||
* AreaShop version:
|
||||
* WorldEdit version:
|
||||
* WorldGuard version:
|
||||
* Vault version:
|
||||
|
||||
|
||||
**Your config files**
|
||||
<!--- Attach a '.zip' file of the '/plugins/AreaShop' and '/plugins/WorldGuard' directories to show your configuration setup -->
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Java CI with Gradle
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Only run on PRs if the source branch is on someone else's repo
|
||||
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: ["ubuntu-latest", "windows-latest"]
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'zulu'
|
||||
cache: 'gradle'
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean build
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,maven
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,intellij+all,gradle,maven
|
||||
|
||||
### Intellij+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/*
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Maven ###
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# Eclipse m2e generated files
|
||||
# Eclipse Core
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
build/
|
||||
build-cache/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
### Gradle Patch ###
|
||||
**/build/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,maven
|
||||
|
||||
**/run
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>NLThijs48 - AreaShop</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>
|
||||
@@ -0,0 +1,144 @@
|
||||
plugins {
|
||||
id("io.github.goooler.shadow") version "8.1.7"
|
||||
id("xyz.jpenilla.run-paper") version "2.3.0"
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
isDownloadSources = true
|
||||
}
|
||||
}
|
||||
|
||||
description = "AreaShop"
|
||||
|
||||
dependencies {
|
||||
// Platform
|
||||
compileOnlyApi(libs.spigot)
|
||||
compileOnlyApi(libs.worldeditCore)
|
||||
compileOnlyApi(libs.worldeditBukkit)
|
||||
compileOnlyApi(libs.worldguardCore)
|
||||
compileOnlyApi(libs.worldguardBukkit)
|
||||
compileOnlyApi("com.github.MilkBowl:VaultAPI:1.7")
|
||||
|
||||
// 3rd party libraries
|
||||
api("io.papermc:paperlib:1.0.8")
|
||||
api("com.github.NLthijs48:InteractiveMessenger:e7749258ca")
|
||||
api("com.github.NLthijs48:BukkitDo:819d51ec2b")
|
||||
api("io.github.baked-libs:dough-data:1.2.0")
|
||||
api("com.google.inject:guice:7.0.0") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
api("com.google.inject.extensions:guice-assistedinject:7.0.0") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
implementation("org.incendo:cloud-paper:2.0.0-beta.10") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
implementation("org.incendo:cloud-processors-confirmation:1.0.0-beta.3") {
|
||||
exclude("com.google.guava")
|
||||
}
|
||||
implementation("net.kyori:adventure-text-minimessage:4.16.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
|
||||
implementation("org.spongepowered:configurate-yaml:4.1.2")
|
||||
|
||||
// Project submodules
|
||||
api(projects.areashopInterface)
|
||||
api(projects.adapters.platform.platformInterface)
|
||||
api(projects.adapters.platform.paper)
|
||||
|
||||
if (!providers.environmentVariable("JITPACK").isPresent) {
|
||||
// We don't need these adapters if we are only publishing an api jar
|
||||
runtimeOnly(projects.adapters.plugins.worldedit)
|
||||
runtimeOnly(projects.adapters.plugins.worldguard)
|
||||
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
|
||||
runtimeOnly(projects.adapters.plugins.essentials)
|
||||
}
|
||||
testImplementation("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
|
||||
testImplementation("com.github.seeseemelk:MockBukkit-v1.21:3.131.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
|
||||
}
|
||||
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
tasks {
|
||||
processResources {
|
||||
filesMatching("plugin.yml") {
|
||||
expand("version" to project.version)
|
||||
}
|
||||
}
|
||||
|
||||
assemble {
|
||||
if (!providers.environmentVariable("JITPACK").isPresent) {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName.set("AreaShop")
|
||||
if (!providers.environmentVariable("JITPACK").isPresent) {
|
||||
archiveClassifier.set("original")
|
||||
} else {
|
||||
archiveClassifier.set("")
|
||||
}
|
||||
}
|
||||
|
||||
if (providers.environmentVariable("JITPACK").isPresent) {
|
||||
artifacts {
|
||||
archives(jar)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
val javaComponent = project.components["java"] as AdhocComponentWithVariants
|
||||
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
|
||||
skip()
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set("")
|
||||
base {
|
||||
archiveBaseName.set("AreaShop")
|
||||
}
|
||||
val base = "me.wiefferink.areashop.libraries"
|
||||
relocate("org.incendo.cloud", "${base}.cloud")
|
||||
relocate("me.wiefferink.interactivemessenger", "${base}.interactivemessenger")
|
||||
relocate("me.wiefferink.bukkitdo", "${base}.bukkitdo")
|
||||
relocate("io.papermc.lib", "${base}.paperlib")
|
||||
relocate("io.github.bakedlibs.dough", "${base}.dough")
|
||||
relocate("com.google.inject", "${base}.inject")
|
||||
relocate("com.google.errorprone", "${base}.errorprone")
|
||||
relocate("org.aopalliance", "${base}.aopalliance")
|
||||
relocate("javax.annotation", "${base}.javax.annotation")
|
||||
relocate("jakarta.inject", "${base}.jakarta.inject")
|
||||
relocate("org.jetbrains.annotations", "${base}.jetbrains.annotations")
|
||||
relocate("io.leangen.geantyref", "${base}.geantyref")
|
||||
relocate("net.kyori", "${base}.kyori")
|
||||
relocate("org.checkerframework", "${base}.checkerframework")
|
||||
relocate("org.intellij", "${base}.intellij")
|
||||
relocate("org.spongepowered", "${base}.spongepowered")
|
||||
relocate("org.yaml.snakeyaml", "${base}.snakeyaml")
|
||||
}
|
||||
runServer {
|
||||
// Configure the Minecraft version for our task.
|
||||
// This is the only required configuration besides applying the plugin.
|
||||
// Your plugin's jar (or shadowJar if present) will be used automatically.
|
||||
minecraftVersion("1.21.1")
|
||||
|
||||
downloadPlugins {
|
||||
github("EssentialsX", "essentials", "2.20.1", "EssentialsX-2.20.1.jar")
|
||||
github("MilkBowl", "Vault", "1.7.3", "Vault.jar")
|
||||
// WorldEdit 7.3.9
|
||||
url("https://mediafilez.forgecdn.net/files/5935/693/worldedit-bukkit-7.3.9.jar")
|
||||
// WorldGuard 7.0.12
|
||||
url("https://mediafilez.forgecdn.net/files/5719/698/worldguard-bukkit-7.0.12-dist.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package me.wiefferink.areashop;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import me.wiefferink.interactivemessenger.Log;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import me.wiefferink.interactivemessenger.source.LanguageManager;
|
||||
import me.wiefferink.interactivemessenger.translation.Transifex;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Collections;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
|
||||
public class ASLanguageManager extends LanguageManager {
|
||||
private JavaPlugin plugin;
|
||||
private String jarLanguagePath;
|
||||
private File languageFolder;
|
||||
private String wgPrefix;
|
||||
private List<String> chatPrefix;
|
||||
private Map<String, List<String>> currentLanguage, defaultLanguage;
|
||||
|
||||
public ASLanguageManager(JavaPlugin plugin,
|
||||
String jarLanguagePath,
|
||||
String currentLanguageName,
|
||||
String defaultLanguageName,
|
||||
List<String> chatPrefix,
|
||||
String wgPrefix) {
|
||||
super(plugin, jarLanguagePath, currentLanguageName, defaultLanguageName, chatPrefix);
|
||||
this.plugin = plugin;
|
||||
this.jarLanguagePath = jarLanguagePath;
|
||||
this.chatPrefix = chatPrefix;
|
||||
this.languageFolder = new File(plugin.getDataFolder() + File.separator + jarLanguagePath);
|
||||
|
||||
Message.init(this, plugin.getLogger());
|
||||
saveDefaults();
|
||||
currentLanguage = loadLanguage(currentLanguageName);
|
||||
if (defaultLanguageName.equals(currentLanguageName)) {
|
||||
defaultLanguage = currentLanguage;
|
||||
} else {
|
||||
defaultLanguage = loadLanguage(defaultLanguageName);
|
||||
}
|
||||
this.wgPrefix = wgPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMessage(String key) {
|
||||
List<String> message;
|
||||
if (key.equalsIgnoreCase(Message.CHATLANGUAGEVARIABLE)) {
|
||||
message = chatPrefix;
|
||||
} else if (key.equalsIgnoreCase("wgPrefix")) {
|
||||
message = new ArrayList<>();
|
||||
message.add(wgPrefix);
|
||||
} else if (currentLanguage.containsKey(key)) {
|
||||
message = currentLanguage.get(key);
|
||||
} else {
|
||||
message = defaultLanguage.get(key);
|
||||
}
|
||||
if (message == null) {
|
||||
Log.warn("Did not find message '" + key + "' in the current or default language");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(message);
|
||||
}
|
||||
|
||||
private void saveDefaults() {
|
||||
// Create the language folder if it not exists
|
||||
if (!languageFolder.exists()) {
|
||||
if (!languageFolder.mkdirs()) {
|
||||
Log.warn("Could not create language directory: " + languageFolder.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
File jarPath;
|
||||
try {
|
||||
// Read jar as ZIP file
|
||||
jarPath = new File(plugin.getClass()
|
||||
.getProtectionDomain()
|
||||
.getCodeSource()
|
||||
.getLocation()
|
||||
.toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
Log.error("Failed to find location of jar file:", ExceptionUtils.getStackTrace(e));
|
||||
return;
|
||||
}
|
||||
try (ZipFile jar = new ZipFile(jarPath)) {
|
||||
Enumeration<? extends ZipEntry> entries = jar.entries();
|
||||
|
||||
// Each entry is a file or directory
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
|
||||
// Filter to YAML files in the language directory
|
||||
if (!entry.isDirectory() && entry.getName()
|
||||
.startsWith(jarLanguagePath + "/") && entry.getName()
|
||||
.endsWith(".yml")) {
|
||||
// Save the file to disk
|
||||
File targetFile = new File(languageFolder.getAbsolutePath() + File.separator + entry.getName()
|
||||
.substring(entry.getName().lastIndexOf("/")));
|
||||
try (
|
||||
InputStream input = jar.getInputStream(entry);
|
||||
OutputStream output = new FileOutputStream(targetFile)
|
||||
) {
|
||||
byte[] bytes = input.readAllBytes();
|
||||
output.write(bytes);
|
||||
} catch (IOException e) {
|
||||
Log.warn("Something went wrong saving a default language file: " + targetFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (
|
||||
IOException e) {
|
||||
Log.error("Failed to read zip file:", ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<String>> loadLanguage(String key) {
|
||||
return loadLanguage(key, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the specified language
|
||||
*
|
||||
* @param key The language to load
|
||||
* @param convert try conversion or not (infinite recursion prevention)
|
||||
* @return Map with the messages loaded from the file
|
||||
*/
|
||||
private Map<String, List<String>> loadLanguage(String key, boolean convert) {
|
||||
Map<String, List<String>> result = new HashMap<>();
|
||||
|
||||
// Load the language file
|
||||
boolean convertFromTransifex = false;
|
||||
File file = new File(languageFolder.getAbsolutePath() + File.separator + key + ".yml");
|
||||
try (
|
||||
InputStream inputStream = new FileInputStream(file);
|
||||
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)
|
||||
) {
|
||||
// Detect empty language files, happens when the YAML parsers prints an exception (it does return an empty YamlConfiguration though)
|
||||
YamlConfiguration ymlFile = YamlConfiguration.loadConfiguration(reader);
|
||||
if (ymlFile.getKeys(false).isEmpty()) {
|
||||
Log.warn("Language file " + key + ".yml has zero messages.");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Retrieve the messages from the YAML file and create the result
|
||||
if (convert && Transifex.needsConversion(ymlFile)) {
|
||||
convertFromTransifex = true;
|
||||
} else {
|
||||
for (String messageKey : ymlFile.getKeys(false)) {
|
||||
List<String> toPut;
|
||||
if (ymlFile.isList(messageKey)) {
|
||||
toPut = ymlFile.getStringList(messageKey);
|
||||
} else {
|
||||
toPut = Collections.singletonList(ymlFile.getString(messageKey));
|
||||
}
|
||||
result.put(messageKey, new ArrayList<>(toPut));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.warn("Could not load language file: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
// Do conversion (after block above closed the reader)
|
||||
if (convertFromTransifex) {
|
||||
if (!Transifex.convertFrom(file)) {
|
||||
Log.warn("Failed to convert " + file.getName() + " from the Transifex layout to the AreaShop layout, check the errors above");
|
||||
}
|
||||
return loadLanguage(key, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,858 @@
|
||||
package me.wiefferink.areashop;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Stage;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
|
||||
import me.wiefferink.areashop.adapters.platform.paper.PaperPlatform;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommands;
|
||||
import me.wiefferink.areashop.extensions.AreashopExtension;
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.interfaces.AreaShopInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
|
||||
import me.wiefferink.areashop.managers.CacheManager;
|
||||
import me.wiefferink.areashop.managers.FeatureManager;
|
||||
import me.wiefferink.areashop.managers.FileManager;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.managers.Manager;
|
||||
import me.wiefferink.areashop.managers.SignErrorLogger;
|
||||
import me.wiefferink.areashop.managers.SignLinkerManager;
|
||||
import me.wiefferink.areashop.modules.AreaShopModule;
|
||||
import me.wiefferink.areashop.modules.BukkitModule;
|
||||
import me.wiefferink.areashop.modules.DependencyModule;
|
||||
import me.wiefferink.areashop.modules.PlatformModule;
|
||||
import me.wiefferink.areashop.services.ServiceManager;
|
||||
import me.wiefferink.areashop.tools.GithubUpdateCheck;
|
||||
import me.wiefferink.areashop.tools.LanguageConverter;
|
||||
import me.wiefferink.areashop.tools.SimpleMessageBridge;
|
||||
import me.wiefferink.areashop.tools.SpigotPlatform;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.areashop.tools.version.Version;
|
||||
import me.wiefferink.areashop.tools.version.VersionUtil;
|
||||
import me.wiefferink.bukkitdo.Do;
|
||||
import me.wiefferink.interactivemessenger.source.LanguageManager;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Main class for the AreaShop plugin.
|
||||
* Contains methods to get parts of the plugins functionality and definitions for constants.
|
||||
*/
|
||||
public final class AreaShop extends JavaPlugin implements AreaShopApi {
|
||||
// Statically available instance
|
||||
private static AreaShop instance = null;
|
||||
|
||||
// General variables
|
||||
private Injector injector;
|
||||
private WorldGuardPlugin worldGuard = null;
|
||||
private WorldGuardInterface worldGuardInterface = null;
|
||||
private WorldEditPlugin worldEdit = null;
|
||||
private WorldEditInterface worldEditInterface = null;
|
||||
private MessageBridge messageBridge;
|
||||
private IFileManager fileManager = null;
|
||||
private LanguageManager languageManager = null;
|
||||
private CacheManager cacheManager = null;
|
||||
private SignLinkerManager signLinkerManager = null;
|
||||
private FeatureManager featureManager = null;
|
||||
private SignManager signManager;
|
||||
private SignErrorLogger signErrorLogger;
|
||||
private Set<Manager> managers = null;
|
||||
private boolean debug = false;
|
||||
private List<String> chatprefix = null;
|
||||
private boolean ready = false;
|
||||
private GithubUpdateCheck githubUpdateCheck = null;
|
||||
|
||||
private final ServiceManager serviceManager = new ServiceManager();
|
||||
|
||||
// Folders and file names
|
||||
public static final String languageFolder = "lang";
|
||||
public static final String schematicFolder = "schem";
|
||||
public static final String regionsFolder = "regions";
|
||||
public static final String groupsFile = "groups.yml";
|
||||
public static final String defaultFile = "default.yml";
|
||||
public static final String configFile = "config.yml";
|
||||
public static final String configFileHidden = "hiddenConfig.yml";
|
||||
public static final String signLogFile = "sign-errors.log";
|
||||
public static final String versionFile = "versions";
|
||||
|
||||
// Euro tag for in the config
|
||||
public static final String currencyEuro = "%euro%";
|
||||
|
||||
// Constants for handling file versions
|
||||
public static final String versionFiles = "files";
|
||||
public static final int versionFilesCurrent = 3;
|
||||
|
||||
// Keys for replacing parts of flags, commands, strings
|
||||
public static final String tagPlayerName = "player";
|
||||
public static final String tagPlayerUUID = "uuid";
|
||||
public static final String tagWorldName = "world";
|
||||
public static final String tagRegionName = "region";
|
||||
public static final String tagRegionType = "type";
|
||||
public static final String tagPrice = "price";
|
||||
public static final String tagRawPrice = "rawprice";
|
||||
public static final String tagDuration = "duration";
|
||||
public static final String tagRentedUntil = "until";
|
||||
public static final String tagRentedUntilShort = "untilshort";
|
||||
public static final String tagWidth = "width"; // x-axis
|
||||
public static final String tagHeight = "height"; // y-axis
|
||||
public static final String tagDepth = "depth"; // z-axis
|
||||
public static final String tagVolume = "volume"; // Number of blocks in the region (accounting for polygon regions)
|
||||
public static final String tagTimeLeft = "timeleft";
|
||||
public static final String tagClicker = "clicker";
|
||||
public static final String tagResellPrice = "resellprice";
|
||||
public static final String tagRawResellPrice = "rawresellprice";
|
||||
public static final String tagFriends = "friends";
|
||||
public static final String tagFriendsUUID = "friendsuuid";
|
||||
public static final String tagMoneyBackPercentage = "moneybackpercent";
|
||||
public static final String tagMoneyBackAmount = "moneyback";
|
||||
public static final String tagRawMoneyBackAmount = "rawmoneyback";
|
||||
public static final String tagTimesExtended = "timesExtended";
|
||||
public static final String tagMaxExtends = "maxextends";
|
||||
public static final String tagExtendsLeft = "extendsleft";
|
||||
public static final String tagMaxRentTime = "maxrenttime";
|
||||
public static final String tagMaxInactiveTime = "inactivetime";
|
||||
public static final String tagLandlord = "landlord";
|
||||
public static final String tagLandlordUUID = "landlorduuid";
|
||||
public static final String tagDateTime = "datetime";
|
||||
public static final String tagDateTimeShort = "datetimeshort";
|
||||
public static final String tagYear = "year";
|
||||
public static final String tagMonth = "month";
|
||||
public static final String tagDay = "day";
|
||||
public static final String tagHour = "hour";
|
||||
public static final String tagMinute = "minute";
|
||||
public static final String tagSecond = "second";
|
||||
public static final String tagMillisecond = "millisecond";
|
||||
public static final String tagEpoch = "epoch";
|
||||
public static final String tagTeleportX = "tpx";
|
||||
public static final String tagTeleportY = "tpy";
|
||||
public static final String tagTeleportZ = "tpz";
|
||||
public static final String tagTeleportBlockX = "tpblockx";
|
||||
public static final String tagTeleportBlockY = "tpblocky";
|
||||
public static final String tagTeleportBlockZ = "tpblockz";
|
||||
public static final String tagTeleportPitch = "tppitch";
|
||||
public static final String tagTeleportYaw = "tpyaw";
|
||||
public static final String tagTeleportPitchRound = "tppitchround";
|
||||
public static final String tagTeleportYawRound = "tpyawround";
|
||||
public static final String tagTeleportWorld = "tpworld";
|
||||
|
||||
public static AreaShop getInstance() {
|
||||
return AreaShop.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on start or reload of the server.
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
AreaShop.instance = this;
|
||||
Do.init(this);
|
||||
managers = new HashSet<>();
|
||||
messageBridge = new SimpleMessageBridge(this.serviceManager);
|
||||
signErrorLogger = new SignErrorLogger(new File(getDataFolder(), signLogFile));
|
||||
|
||||
// Setup NMS Impl
|
||||
Version currentServerVersion = VersionUtil.parseMinecraftVersion(Bukkit.getBukkitVersion());
|
||||
if (currentServerVersion.versionData().isOlderThan(VersionUtil.MC_1_21)) {
|
||||
error("Unsupported minecraft version: " + currentServerVersion + "! Minimum is 1.21");
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
final MinecraftPlatform platform;
|
||||
if (PaperLib.isPaper()) {
|
||||
platform = new PaperPlatform(this);
|
||||
info("Detected Paper; using the PaperPlatform impl");
|
||||
} else {
|
||||
platform = new SpigotPlatform(this);
|
||||
info("Detected Spigot; using the SpigotPlatform impl");
|
||||
}
|
||||
final PlatformModule platformModule = new PlatformModule(platform);
|
||||
|
||||
// Check if Vault is present
|
||||
if(getServer().getPluginManager().getPlugin("Vault") == null) {
|
||||
error("Vault plugin is not present or has not loaded correctly");
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find WorldEdit integration version to load
|
||||
String weHandlerVersion;
|
||||
Plugin plugin = getServer().getPluginManager().getPlugin("WorldEdit");
|
||||
if(!(plugin instanceof WorldEditPlugin) || !plugin.isEnabled()) {
|
||||
error("WorldEdit plugin is not present or has not loaded correctly");
|
||||
return;
|
||||
} else {
|
||||
this.worldEdit = (WorldEditPlugin) plugin;
|
||||
Plugin fawePlugin = getServer().getPluginManager().getPlugin("FastAsyncWorldEdit");
|
||||
if (fawePlugin != null && fawePlugin.isEnabled()) {
|
||||
weHandlerVersion = "FastAsyncWorldEditHandler";
|
||||
info("Detected FastAsyncWorldEdit, using the fawe handler");
|
||||
} else {
|
||||
weHandlerVersion = "WorldEditHandler";
|
||||
}
|
||||
}
|
||||
|
||||
plugin = getServer().getPluginManager().getPlugin("WorldGuard");
|
||||
if(!(plugin instanceof WorldGuardPlugin) || !plugin.isEnabled()) {
|
||||
error("WorldGuard plugin is not present or has not loaded correctly");
|
||||
shutdownOnError();
|
||||
return;
|
||||
} else {
|
||||
this.worldGuard = (WorldGuardPlugin) plugin;
|
||||
}
|
||||
|
||||
DependencyModule dependencyModule = new DependencyModule(this.worldEdit, this.worldGuard, getEconomy(), getPermissionProvider());
|
||||
|
||||
// Load WorldEdit
|
||||
try {
|
||||
Class<?> clazz = Class.forName("me.wiefferink.areashop.adapters.plugins." + weHandlerVersion);
|
||||
if(WorldEditInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldEditInterface
|
||||
worldEditInterface = (WorldEditInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
|
||||
}
|
||||
} catch(Exception e) {
|
||||
error("Could not load the handler for WorldEdit (tried to load " + weHandlerVersion + "), report this problem to the author: " + ExceptionUtils.getStackTrace(e));
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Load WorldGuard
|
||||
try {
|
||||
Class<?> clazz = Class.forName("me.wiefferink.areashop.adapters.plugins.WorldGuardHandler");
|
||||
// Check if we have a NMSHandler class at that location.
|
||||
if(WorldGuardInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldGuardInterface
|
||||
worldGuardInterface = (WorldGuardInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
|
||||
}
|
||||
} catch(Exception e) {
|
||||
error("Could not load the handler for WorldGuard, report this problem to the author:" + ExceptionUtils.getStackTrace(e));
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
AreaShopModule asModule = new AreaShopModule(this,
|
||||
this.messageBridge,
|
||||
this.worldEditInterface,
|
||||
this.worldGuardInterface,
|
||||
this.signErrorLogger,
|
||||
this.serviceManager,
|
||||
platformModule,
|
||||
dependencyModule
|
||||
);
|
||||
injector = Guice.createInjector(Stage.PRODUCTION, new BukkitModule(getServer()), asModule);
|
||||
|
||||
// Load all data from files and check versions
|
||||
fileManager = injector.getInstance(IFileManager.class);
|
||||
managers.add((FileManager) fileManager);
|
||||
boolean loadFilesResult = fileManager.loadFiles(false);
|
||||
if (!loadFilesResult) {
|
||||
shutdownOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
performLanguageMigrations();
|
||||
setupLanguageManager();
|
||||
|
||||
featureManager = injector.getInstance(FeatureManager.class);
|
||||
featureManager.initializeFeatures(injector);
|
||||
managers.add(featureManager);
|
||||
signManager = injector.getInstance(SignManager.class);
|
||||
managers.add(signManager);
|
||||
cacheManager = injector.getInstance(CacheManager.class);
|
||||
String rawExpiryDuration = fileManager.getConfig().getString("cacheExpiryDuration", "7d");
|
||||
long millis = Utils.durationStringToLong(rawExpiryDuration);
|
||||
cacheManager.initialize(new File(getDataFolder(), "uuid-cache.bin"), Duration.ofMillis(millis));
|
||||
cacheManager.loadCache();
|
||||
managers.add(cacheManager);
|
||||
|
||||
loadExtensions();
|
||||
|
||||
// Register the event listeners
|
||||
getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this, messageBridge, this.cacheManager), this);
|
||||
|
||||
setupTasks();
|
||||
|
||||
// Register commands
|
||||
AreashopCommands commands = injector.getInstance(AreashopCommands.class);
|
||||
commands.registerCommands();
|
||||
|
||||
// Create a signLinkerManager
|
||||
signLinkerManager = injector.getInstance(SignLinkerManager.class);
|
||||
managers.add(signLinkerManager);
|
||||
|
||||
// Register dynamic permission (things declared in config)
|
||||
registerDynamicPermissions();
|
||||
|
||||
// Don't initialize the updatechecker if disabled in the config
|
||||
if(getConfig().getBoolean("checkForUpdates")) {
|
||||
githubUpdateCheck = new GithubUpdateCheck(
|
||||
this,
|
||||
"md5sha256",
|
||||
"AreaShop"
|
||||
).withVersionComparator((latestVersion, currentVersion) -> {
|
||||
Version latest = Version.parse(cleanVersion(latestVersion));
|
||||
Version current = Version.parse(cleanVersion(currentVersion));
|
||||
return latest.versionData().isNewerThan(current.versionData());
|
||||
}
|
||||
).checkUpdate(result -> {
|
||||
AreaShop.debug("Update check result:", result);
|
||||
if(!result.hasUpdate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://github.com/md5sha256/AreaShop/releases");
|
||||
for(Player player : Utils.getOnlinePlayers()) {
|
||||
notifyUpdate(player);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify a player about an update if he wants notifications about it and an update is available.
|
||||
* @param sender CommandSender to notify
|
||||
*/
|
||||
public void notifyUpdate(CommandSender sender) {
|
||||
if(githubUpdateCheck != null && githubUpdateCheck.hasUpdate() && sender.hasPermission("areashop.notifyupdate")) {
|
||||
messageBridge.message(sender, "update-playerNotify", cleanVersion(githubUpdateCheck.getCurrentVersion()), cleanVersion(githubUpdateCheck.getLatestVersion()));
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdownOnError() {
|
||||
error("The plugin has not started, fix the errors listed above");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
private void loadExtensions() {
|
||||
if (this.getServer().getPluginManager().isPluginEnabled("Essentials")) {
|
||||
loadEssentialsExt().ifPresent(ext -> ext.init(this, this.injector));
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<AreashopExtension> loadEssentialsExt() {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("me.wiefferink.areashop.adapters.plugins.essentials.EssentialsExtension");
|
||||
Class<? extends AreashopExtension> extClass = clazz.asSubclass(AreashopExtension.class);
|
||||
AreashopExtension extension = extClass.getConstructor().newInstance();
|
||||
return Optional.of(extension);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
error("Failed to initialize the essentials extension!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a version number.
|
||||
* @param version Version to clean
|
||||
* @return Cleaned up version (removed prefixes and suffixes)
|
||||
*/
|
||||
private String cleanVersion(String version) {
|
||||
version = version.toLowerCase();
|
||||
|
||||
// Strip 'v' as used on Github tags
|
||||
if(version.startsWith("v")) {
|
||||
version = version.substring(1);
|
||||
}
|
||||
|
||||
// Strip build number as used by Jenkins
|
||||
if(version.contains("#")) {
|
||||
version = version.substring(0, version.indexOf("#"));
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public CacheManager getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on shutdown or reload of the server.
|
||||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
Bukkit.getServer().getScheduler().cancelTasks(this);
|
||||
|
||||
// Cleanup managers
|
||||
for(Manager manager : managers) {
|
||||
manager.shutdown();
|
||||
}
|
||||
signErrorLogger.saveIfDirty();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the plugin will be using MiniMessage or not
|
||||
* @return true if MiniMessage should be used, false otherwise
|
||||
*/
|
||||
public static boolean useMiniMessage() {
|
||||
return getInstance().getConfig().getBoolean("useMiniMessage");
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the plugin is ready to be used.
|
||||
* @return true if the plugin is ready, false otherwise
|
||||
*/
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the plugin is ready to be used or not (not to be used from another plugin!).
|
||||
* @param ready Indicate if the plugin is ready to be used
|
||||
*/
|
||||
public void setReady(boolean ready) {
|
||||
this.ready = ready;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the plugin should output debug messages (loaded from config normally).
|
||||
* @param debug Indicates if the plugin should output debug messages or not
|
||||
*/
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
private void performLanguageMigrations() {
|
||||
boolean migrateExisting = this.getConfig().getBoolean("migrateLanguages", false);
|
||||
if (!migrateExisting) {
|
||||
return;
|
||||
}
|
||||
getLogger().info("Performing language migration");
|
||||
List<String> chatPrefix = getConfig().getStringList("chatPrefix");
|
||||
List<String> convertedChatPrefix = LanguageConverter.convertRawList(chatPrefix);
|
||||
if (convertedChatPrefix.size() == 1) {
|
||||
getConfig().set("mmChatPrefix", convertedChatPrefix.getFirst());
|
||||
} else {
|
||||
getConfig().set("mmChatPrefix", convertedChatPrefix);
|
||||
}
|
||||
saveConfig();
|
||||
File existingLanguages = getDataFolder().toPath().resolve(languageFolder).toFile();
|
||||
File[] langFiles = existingLanguages.listFiles(file -> file.getName().endsWith(".yml"));
|
||||
if (langFiles == null) {
|
||||
return;
|
||||
}
|
||||
for (File file : langFiles) {
|
||||
String name = file.getName();
|
||||
String langName = name.substring(0, name.length() - 4);
|
||||
if (langName.endsWith("-MM")) {
|
||||
debug("Skipping migration for " + langName + " as it already exists.");
|
||||
continue;
|
||||
}
|
||||
File toMigrate = new File(existingLanguages, langName + "-MM.yml");
|
||||
try {
|
||||
LanguageConverter.performConversion(file, toMigrate);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.SEVERE, "Failed to perform migration for lang: " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
getLogger().info("Language migration complete!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a new LanguageManager.
|
||||
*/
|
||||
private void setupLanguageManager() {
|
||||
languageManager = new ASLanguageManager(
|
||||
this,
|
||||
languageFolder,
|
||||
useMiniMessage() ? getConfig().getString("mmLanguage") : getConfig().getString("language"),
|
||||
"EN",
|
||||
useMiniMessage() ? getConfig().getStringList("mmChatPrefix") : chatprefix,
|
||||
getConfig().getString("wgPrefix")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the chatprefix to use in the chat (loaded from config normally).
|
||||
* @param chatprefix The string to use in front of chat messages (supports formatting codes)
|
||||
*/
|
||||
public void setChatprefix(List<String> chatprefix) {
|
||||
this.chatprefix = chatprefix;
|
||||
}
|
||||
|
||||
public SignErrorLogger getSignErrorLogger() {
|
||||
return signErrorLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the WorldGuard plugin.
|
||||
* @return WorldGuardPlugin
|
||||
*/
|
||||
@Override
|
||||
public WorldGuardPlugin getWorldGuard() {
|
||||
return worldGuard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get WorldGuardInterface for version dependent things.
|
||||
* @return WorldGuardInterface
|
||||
*/
|
||||
public WorldGuardInterface getWorldGuardHandler() {
|
||||
return this.worldGuardInterface;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public SignManager getSignManager() {
|
||||
return signManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RegionManager.
|
||||
* @param world World to get the RegionManager for
|
||||
* @return RegionManager for the given world, if there is one, otherwise null
|
||||
*/
|
||||
public RegionManager getRegionManager(World world) {
|
||||
return this.worldGuardInterface.getRegionManager(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the WorldEdit plugin.
|
||||
* @return WorldEditPlugin
|
||||
*/
|
||||
@Override
|
||||
public WorldEditPlugin getWorldEdit() {
|
||||
return worldEdit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin pluginInstance() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get WorldGuardInterface for version dependent things.
|
||||
* @return WorldGuardInterface
|
||||
*/
|
||||
public WorldEditInterface getWorldEditHandler() {
|
||||
return this.worldEditInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the LanguageManager.
|
||||
* @return the LanguageManager
|
||||
*/
|
||||
public LanguageManager getLanguageManager() {
|
||||
return languageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SignLinkerManager.
|
||||
* Handles sign linking mode.
|
||||
* @return The SignLinkerManager
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public SignLinkerManager getSignlinkerManager() {
|
||||
return signLinkerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FeatureManager.
|
||||
* Manages region specific features.
|
||||
* @return The FeatureManager
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public FeatureManager getFeatureManager() {
|
||||
return featureManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ServiceManager getServiceManager() {
|
||||
return this.serviceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the Vault plugin.
|
||||
* @return Economy
|
||||
*/
|
||||
private Economy getEconomy() {
|
||||
RegisteredServiceProvider<Economy> economy = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
|
||||
if(economy == null) {
|
||||
error("There is no economy provider to support Vault, make sure you installed an economy plugin");
|
||||
return null;
|
||||
}
|
||||
return economy.getProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Vault permissions provider.
|
||||
* @return Vault permissions provider
|
||||
*/
|
||||
private net.milkbowl.vault.permission.Permission getPermissionProvider() {
|
||||
RegisteredServiceProvider<net.milkbowl.vault.permission.Permission> permissionProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class);
|
||||
if (permissionProvider == null) {
|
||||
return null;
|
||||
}
|
||||
return permissionProvider.getProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a permission of a (possibly offline) player.
|
||||
* @param offlinePlayer OfflinePlayer to check
|
||||
* @param permission Permission to check
|
||||
* @return true if the player has the permission, false if the player does not have permission or, is offline and there is not Vault-compatible permission plugin
|
||||
*/
|
||||
public boolean hasPermission(OfflinePlayer offlinePlayer, String permission) {
|
||||
// Online, return through Bukkit
|
||||
if(offlinePlayer.getPlayer() != null) {
|
||||
return offlinePlayer.getPlayer().hasPermission(permission);
|
||||
}
|
||||
|
||||
// Resolve while offline if possible
|
||||
net.milkbowl.vault.permission.Permission permissionProvider = getPermissionProvider();
|
||||
if(permissionProvider != null) {
|
||||
// TODO: Should we provide a world here?
|
||||
return permissionProvider.playerHas(null, offlinePlayer, permission);
|
||||
}
|
||||
|
||||
// Player offline and no offline permission provider available, safely say that there is no permission
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the FileManager (loads/save regions and can be used to get regions).
|
||||
* @return The fileManager
|
||||
*/
|
||||
public IFileManager getFileManager() {
|
||||
return fileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register dynamic permissions controlled by config settings.
|
||||
*/
|
||||
private void registerDynamicPermissions() {
|
||||
// Register limit groups of amount of regions a player can have
|
||||
ConfigurationSection section = getConfig().getConfigurationSection("limitGroups");
|
||||
if(section == null) {
|
||||
return;
|
||||
}
|
||||
for(String group : section.getKeys(false)) {
|
||||
if(!"default".equals(group)) {
|
||||
Permission perm = new Permission("areashop.limits." + group);
|
||||
try {
|
||||
Bukkit.getPluginManager().addPermission(perm);
|
||||
} catch(IllegalArgumentException e) {
|
||||
warn("Could not add the following permission to be used as limit: " + perm.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Bukkit.getPluginManager().recalculatePermissionDefaults(Bukkit.getPluginManager().getPermission("playerwarps.limits"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all required tasks.
|
||||
*/
|
||||
private void setupTasks() {
|
||||
|
||||
long signLogTicks = Utils.millisToTicks(TimeUnit.MINUTES.toMillis(5));
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(this,
|
||||
() -> signErrorLogger.saveIfDirty(),
|
||||
signLogTicks,
|
||||
signLogTicks);
|
||||
|
||||
// Rent expiration timer
|
||||
long expirationCheck = Utils.millisToTicks(Utils.getDurationFromSecondsOrString("expiration.delay"));
|
||||
final AreaShop finalPlugin = this;
|
||||
if(expirationCheck > 0) {
|
||||
Do.syncTimer(expirationCheck, () -> {
|
||||
if(isReady()) {
|
||||
finalPlugin.getFileManager().checkRents();
|
||||
AreaShop.debugTask("Checking rent expirations...");
|
||||
} else {
|
||||
AreaShop.debugTask("Skipped checking rent expirations, plugin not ready");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Inactive unrenting/selling timer
|
||||
long inactiveCheck = Utils.millisToTicks(Utils.getDurationFromMinutesOrString("inactive.delay"));
|
||||
if(inactiveCheck > 0) {
|
||||
Do.syncTimer(inactiveCheck, () -> {
|
||||
if(isReady()) {
|
||||
finalPlugin.getFileManager().checkForInactiveRegions();
|
||||
AreaShop.debugTask("Checking for regions with players that are inactive too long...");
|
||||
} else {
|
||||
AreaShop.debugTask("Skipped checking for regions of inactive players, plugin not ready");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Periodic updating of signs for timeleft tags
|
||||
long periodicUpdate = Utils.millisToTicks(Utils.getDurationFromSecondsOrString("signs.delay"));
|
||||
if(periodicUpdate > 0) {
|
||||
Do.syncTimer(periodicUpdate, () -> {
|
||||
if(isReady()) {
|
||||
finalPlugin.getFileManager().performPeriodicSignUpdate();
|
||||
AreaShop.debugTask("Performing periodic sign update...");
|
||||
} else {
|
||||
AreaShop.debugTask("Skipped performing periodic sign update, plugin not ready");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Saving regions and group settings
|
||||
long saveFiles = Utils.millisToTicks(Utils.getDurationFromMinutesOrString("saving.delay"));
|
||||
if(saveFiles > 0) {
|
||||
Do.syncTimer(saveFiles, () -> {
|
||||
if(isReady()) {
|
||||
finalPlugin.getFileManager().saveRequiredFiles();
|
||||
AreaShop.debugTask("Saving required files...");
|
||||
} else {
|
||||
AreaShop.debugTask("Skipped saving required files, plugin not ready");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Sending warnings about rent regions to online players
|
||||
long expireWarning = Utils.millisToTicks(Utils.getDurationFromMinutesOrString("expireWarning.delay"));
|
||||
if(expireWarning > 0) {
|
||||
Do.syncTimer(expireWarning, () -> {
|
||||
if(isReady()) {
|
||||
finalPlugin.getFileManager().sendRentExpireWarnings();
|
||||
AreaShop.debugTask("Sending rent expire warnings...");
|
||||
} else {
|
||||
AreaShop.debugTask("Skipped sending rent expire warnings, plugin not ready");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update all regions on startup
|
||||
if(getConfig().getBoolean("updateRegionsOnStartup")) {
|
||||
Do.syncLater(20, () -> {
|
||||
finalPlugin.getFileManager().updateAllRegions();
|
||||
AreaShop.debugTask("Updating all regions at startup...");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the config.
|
||||
*/
|
||||
@Override
|
||||
public YamlConfiguration getConfig() {
|
||||
return fileManager.getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an debug message to the console.
|
||||
* @param message The message that should be printed to the console
|
||||
*/
|
||||
public static void debug(Object... message) {
|
||||
if(AreaShop.getInstance().debug) {
|
||||
info("Debug: " + StringUtils.join(message, " "));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-static debug to use as implementation of the interface.
|
||||
* @param message Object parts of the message that should be logged, toString() will be used
|
||||
*/
|
||||
@Override
|
||||
public void debugI(Object... message) {
|
||||
AreaShop.debug(StringUtils.join(message, " "));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debugI(Supplier<String> message) {
|
||||
if (debug) {
|
||||
info("Debug: " + message.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an information message to the console.
|
||||
* @param message The message to print
|
||||
*/
|
||||
public static void info(Object... message) {
|
||||
AreaShop.getInstance().getLogger().info(() -> StringUtils.join(message, " "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a warning to the console.
|
||||
* @param message The message to print
|
||||
*/
|
||||
public static void warn(Object... message) {
|
||||
AreaShop.getInstance().getLogger().warning(() -> StringUtils.join(message, " "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error to the console.
|
||||
* @param message The message to print
|
||||
*/
|
||||
public static void error(Object... message) {
|
||||
AreaShop.getInstance().getLogger().severe(() -> StringUtils.join(message, " "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print debug message for periodic task.
|
||||
* @param message The message to print
|
||||
*/
|
||||
public static void debugTask(Object... message) {
|
||||
if(AreaShop.getInstance().getConfig().getBoolean("debugTask")) {
|
||||
AreaShop.debug(StringUtils.join(message, " "));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all files of the plugin and update all regions.
|
||||
* @param confirmationReceiver The CommandSender which should be notified when complete, null for nobody
|
||||
*/
|
||||
public void reload(final CommandSender confirmationReceiver) {
|
||||
setReady(false);
|
||||
fileManager.saveRequiredFilesAtOnce();
|
||||
fileManager.loadFiles(true);
|
||||
setupLanguageManager();
|
||||
messageBridge.message(confirmationReceiver, "reload-reloading");
|
||||
fileManager.checkRents();
|
||||
fileManager.updateAllRegions(confirmationReceiver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all files of the plugin and update all regions.
|
||||
*/
|
||||
public void reload() {
|
||||
reload(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package me.wiefferink.areashop;
|
||||
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.interfaces.AreaShopInterface;
|
||||
import me.wiefferink.areashop.managers.FeatureManager;
|
||||
import me.wiefferink.areashop.managers.SignLinkerManager;
|
||||
import me.wiefferink.areashop.services.ServiceManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface AreaShopApi extends AreaShopInterface {
|
||||
|
||||
/**
|
||||
* Get the SignLinkerManager.
|
||||
* Handles sign linking mode.
|
||||
*
|
||||
* @return The SignLinkerManager
|
||||
*/
|
||||
@Nonnull SignLinkerManager getSignlinkerManager();
|
||||
|
||||
/**
|
||||
* Get the FeatureManager.
|
||||
* Manages region specific features.
|
||||
*
|
||||
* @return The FeatureManager
|
||||
*/
|
||||
@Nonnull FeatureManager getFeatureManager();
|
||||
|
||||
|
||||
@Nonnull SignManager getSignManager();
|
||||
|
||||
@Nonnull
|
||||
ServiceManager getServiceManager();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package me.wiefferink.areashop;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface MessageBridge {
|
||||
/**
|
||||
* Send a message to a target without a prefix.
|
||||
*
|
||||
* @param target The target to send the message to
|
||||
* @param key The key of the language string
|
||||
* @param replacements The replacements to insert in the message
|
||||
*/
|
||||
void messageNoPrefix(Object target, String key, Object... replacements);
|
||||
|
||||
/**
|
||||
* Send a message to a target, prefixed by the default chat prefix.
|
||||
*
|
||||
* @param target The target to send the message to
|
||||
* @param key The key of the language string
|
||||
* @param replacements The replacements to insert in the message
|
||||
*/
|
||||
void message(Object target, String key, Object... replacements);
|
||||
|
||||
void messagePersistent(@Nonnull OfflinePlayer target,
|
||||
@Nonnull String key,
|
||||
@Nonnull Object... replacements);
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.WorldFlagUtil;
|
||||
import me.wiefferink.areashop.commands.util.WorldGuardRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.WorldSelection;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
|
||||
import me.wiefferink.areashop.events.ask.BuyingRegionEvent;
|
||||
import me.wiefferink.areashop.events.ask.RentingRegionEvent;
|
||||
import me.wiefferink.areashop.events.notify.BoughtRegionEvent;
|
||||
import me.wiefferink.areashop.events.notify.RentedRegionEvent;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.bukkitdo.Do;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class AddCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion.RegionType> KEY_REGION_TYPE = CloudKey.of("regionType",
|
||||
GeneralRegion.RegionType.class);
|
||||
private static final CloudKey<ProtectedRegion> KEY_REGION = CloudKey.of("region", ProtectedRegion.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final AreaShop plugin;
|
||||
private final WorldEditInterface worldEditInterface;
|
||||
private final WorldGuardInterface worldGuardInterface;
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
@Inject
|
||||
public AddCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull AreaShop plugin,
|
||||
@Nonnull WorldEditInterface worldEditInterface,
|
||||
@Nonnull WorldGuardInterface worldGuardInterface,
|
||||
@Nonnull RegionFactory regionFactory) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.plugin = plugin;
|
||||
this.worldEditInterface = worldEditInterface;
|
||||
this.worldGuardInterface = worldGuardInterface;
|
||||
this.regionFactory = regionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.createrent")
|
||||
|| target.hasPermission("areashop.createrent.member")
|
||||
|| target.hasPermission("areashop.createrent.owner")
|
||||
|
||||
|| target.hasPermission("areashop.createbuy")
|
||||
|| target.hasPermission("areashop.createbuy.member")
|
||||
|| target.hasPermission("areashop.createbuy.owner")) {
|
||||
return "help-add";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
// /as add <rent|buy> [region] [world]
|
||||
var wgRegionParser = WorldGuardRegionParser.worldGuardRegionParser(WorldFlagUtil.DEFAULT_WORLD_FLAG, this.worldGuardInterface);
|
||||
return builder
|
||||
.literal("add")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION_TYPE, EnumParser.enumParser(GeneralRegion.RegionType.class))
|
||||
.optional(KEY_REGION, wgRegionParser)
|
||||
.flag(WorldFlagUtil.DEFAULT_WORLD_FLAG)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
final GeneralRegion.RegionType regionType = context.get(KEY_REGION_TYPE);
|
||||
World world = WorldFlagUtil.parseOrDetectWorld(context, player);
|
||||
Map<String, ProtectedRegion> regions;
|
||||
Optional<ProtectedRegion> inputRegion = context.optional(KEY_REGION);
|
||||
if (inputRegion.isPresent()) {
|
||||
regions = new HashMap<>();
|
||||
regions.put(inputRegion.get().getId(), inputRegion.get());
|
||||
} else {
|
||||
WorldSelection selection = WorldSelection.fromPlayer(player, this.worldEditInterface);
|
||||
regions = Utils.getWorldEditRegionsInSelection(selection.selection()).stream()
|
||||
.collect(Collectors.toMap(ProtectedRegion::getId, region -> region));
|
||||
}
|
||||
if (regions.isEmpty()) {
|
||||
throw new AreaShopCommandException("cmd-noWERegionsFound");
|
||||
}
|
||||
AreaShop.debug("Starting add task with " + regions.size() + " regions");
|
||||
AddTaskState state = createState(player, regionType, world);
|
||||
int batchSize = plugin.getConfig().getInt("adding.regionsPerTick");
|
||||
Do.forAll(
|
||||
batchSize,
|
||||
regions.entrySet(),
|
||||
regionEntry -> processEntry(regionEntry, state),
|
||||
() -> onCompletion(state)
|
||||
);
|
||||
}
|
||||
|
||||
private AddTaskState createState(
|
||||
@Nonnull Player player,
|
||||
@Nonnull GeneralRegion.RegionType regionType,
|
||||
@Nonnull World world
|
||||
) {
|
||||
Set<GeneralRegion> regionsSuccess = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsAlready = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsAlreadyOtherWorld = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsRentCancelled = new TreeSet<>(); // Denied by an event listener
|
||||
Set<GeneralRegion> regionsBuyCancelled = new TreeSet<>(); // Denied by an event listener
|
||||
Set<String> namesBlacklisted = new TreeSet<>();
|
||||
Set<String> namesNoPermission = new TreeSet<>();
|
||||
Set<String> namesAddCancelled = new TreeSet<>(); // Denied by an event listener
|
||||
return new AddTaskState(
|
||||
player,
|
||||
regionType,
|
||||
regionsSuccess,
|
||||
regionsAlready,
|
||||
regionsAlreadyOtherWorld,
|
||||
regionsRentCancelled,
|
||||
regionsBuyCancelled,
|
||||
namesBlacklisted,
|
||||
namesNoPermission,
|
||||
namesAddCancelled,
|
||||
world
|
||||
);
|
||||
}
|
||||
|
||||
private void processEntry(@Nonnull Map.Entry<String, ProtectedRegion> regionEntry,
|
||||
@Nonnull AddTaskState taskState) {
|
||||
Player player = taskState.sender();
|
||||
Set<GeneralRegion> regionsAlready = taskState.regionsAlready();
|
||||
Set<GeneralRegion> regionsAlreadyOtherWorld = taskState.regionsAlreadyOtherWorld();
|
||||
Set<String> namesBlacklisted = taskState.namesBlacklisted();
|
||||
Set<String> namesNoPermission = taskState.namesNoPermission();
|
||||
GeneralRegion.RegionType regionType = taskState.regionType();
|
||||
World world = taskState.world();
|
||||
String regionName = regionEntry.getKey();
|
||||
ProtectedRegion region = regionEntry.getValue();
|
||||
// Determine if the player is an owner or member of the region
|
||||
boolean isMember = this.worldGuardInterface.containsMember(region, player.getUniqueId());
|
||||
boolean isOwner = this.worldGuardInterface.containsOwner(region, player.getUniqueId());
|
||||
String type = regionType.toString().toLowerCase(Locale.ENGLISH);
|
||||
IFileManager.AddResult result = this.plugin.getFileManager()
|
||||
.checkRegionAdd(
|
||||
player,
|
||||
region,
|
||||
world,
|
||||
regionType
|
||||
);
|
||||
switch (result) {
|
||||
case ALREADYADDED -> regionsAlready.add(plugin.getFileManager().getRegion(regionName));
|
||||
case ALREADYADDEDOTHERWORLD -> regionsAlreadyOtherWorld.add(plugin.getFileManager().getRegion(regionName));
|
||||
case BLACKLISTED -> namesBlacklisted.add(regionName);
|
||||
case NOPERMISSION -> namesNoPermission.add(regionName);
|
||||
default -> {
|
||||
// Check if the player should be landlord
|
||||
boolean landlord = (!player.hasPermission("areashop.create" + type)
|
||||
&& ((player.hasPermission("areashop.create" + type + ".owner") && isOwner)
|
||||
|| (player.hasPermission("areashop.create" + type + ".member") && isMember)));
|
||||
List<UUID> existing = new ArrayList<>();
|
||||
existing.addAll(worldGuardInterface.getOwners(region).asUniqueIdList());
|
||||
existing.addAll(worldGuardInterface.getMembers(region).asUniqueIdList());
|
||||
debugResult(player, regionName, landlord, existing, isMember, isOwner, regionType);
|
||||
if (regionType == GeneralRegion.RegionType.BUY) {
|
||||
proccessBuy(region, landlord, existing, taskState);
|
||||
} else if (regionType == GeneralRegion.RegionType.RENT) {
|
||||
processRent(region, landlord, existing, taskState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void debugResult(
|
||||
@Nonnull Player player,
|
||||
@Nonnull String regionName,
|
||||
boolean landlord,
|
||||
List<UUID> existing,
|
||||
boolean isMember,
|
||||
boolean isOwner,
|
||||
@Nonnull GeneralRegion.RegionType regionType
|
||||
) {
|
||||
String type = regionType.name().toLowerCase(Locale.ENGLISH);
|
||||
AreaShop.debug("regionAddLandlordStatus:",
|
||||
regionName,
|
||||
"landlord:",
|
||||
landlord,
|
||||
"existing:",
|
||||
existing,
|
||||
"isMember:",
|
||||
isMember,
|
||||
"isOwner:",
|
||||
isOwner,
|
||||
"createPermission:",
|
||||
player.hasPermission("areashop.create" + type),
|
||||
"ownerPermission:",
|
||||
player.hasPermission("areashop.create" + type + ".owner"),
|
||||
"memberPermission:",
|
||||
player.hasPermission("areashop.create" + type + ".member"));
|
||||
}
|
||||
|
||||
private void onCompletion(@Nonnull AddTaskState taskState) {
|
||||
CommandSender player = taskState.sender();
|
||||
GeneralRegion.RegionType regionType = taskState.regionType;
|
||||
Set<GeneralRegion> regionsSuccess = taskState.regionsSuccess();
|
||||
Set<GeneralRegion> regionsAlready = taskState.regionsAlready();
|
||||
Set<GeneralRegion> regionsAlreadyOtherWorld = taskState.regionsAlreadyOtherWorld();
|
||||
Set<GeneralRegion> regionsRentCancelled = taskState.regionsRentCancelled(); // Denied by an event listener
|
||||
Set<GeneralRegion> regionsBuyCancelled = taskState.regionsBuyCancelled(); // Denied by an event listener
|
||||
Set<String> namesBlacklisted = taskState.namesBlacklisted();
|
||||
Set<String> namesNoPermission = taskState.namesNoPermission();
|
||||
Set<String> namesAddCancelled = taskState.namesAddCancelled(); // Denied by an event listener
|
||||
if (!regionsSuccess.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-success",
|
||||
regionType.name().toLowerCase(Locale.ENGLISH),
|
||||
Utils.combinedMessage(regionsSuccess, "region"));
|
||||
}
|
||||
if (!regionsAlready.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-failed",
|
||||
Utils.combinedMessage(regionsAlready, "region"));
|
||||
}
|
||||
if (!regionsAlreadyOtherWorld.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-failedOtherWorld",
|
||||
Utils.combinedMessage(regionsAlreadyOtherWorld, "region"));
|
||||
}
|
||||
if (!regionsRentCancelled.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-rentCancelled",
|
||||
Utils.combinedMessage(regionsRentCancelled, "region"));
|
||||
}
|
||||
if (!regionsBuyCancelled.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-buyCancelled",
|
||||
Utils.combinedMessage(regionsBuyCancelled, "region"));
|
||||
}
|
||||
if (!namesBlacklisted.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-blacklisted",
|
||||
Utils.createCommaSeparatedList(namesBlacklisted));
|
||||
}
|
||||
if (!namesNoPermission.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-noPermissionRegions",
|
||||
Utils.createCommaSeparatedList(namesNoPermission));
|
||||
this.messageBridge.message(player, "add-noPermissionOwnerMember");
|
||||
}
|
||||
if (!namesAddCancelled.isEmpty()) {
|
||||
this.messageBridge.message(player,
|
||||
"add-rentCancelled",
|
||||
Utils.createCommaSeparatedList(namesAddCancelled));
|
||||
}
|
||||
}
|
||||
|
||||
private void processRent(
|
||||
@Nonnull ProtectedRegion region,
|
||||
boolean landlord,
|
||||
List<UUID> existing,
|
||||
@Nonnull AddTaskState taskState
|
||||
) {
|
||||
Player player = taskState.sender();
|
||||
Set<GeneralRegion> regionsSuccess = taskState.regionsSuccess();
|
||||
Set<GeneralRegion> regionsRentCancelled = taskState.regionsRentCancelled(); // Denied by an event listener
|
||||
Set<String> namesAddCancelled = taskState.namesAddCancelled(); // Denied by an event listener
|
||||
World world = taskState.world();
|
||||
String regionName = region.getId();
|
||||
RentRegion rent = regionFactory.createRentRegion(regionName, world);
|
||||
// Set landlord
|
||||
if (landlord) {
|
||||
rent.setLandlord(player.getUniqueId(), player.getName());
|
||||
}
|
||||
|
||||
AddingRegionEvent event = plugin.getFileManager().addRegion(rent);
|
||||
if (event.isCancelled()) {
|
||||
namesAddCancelled.add(rent.getName());
|
||||
return;
|
||||
}
|
||||
rent.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
|
||||
rent.update();
|
||||
|
||||
// Add existing owners/members if any
|
||||
if (!landlord && !existing.isEmpty()) {
|
||||
UUID rentBy = existing.removeFirst();
|
||||
OfflinePlayer rentByPlayer = Bukkit.getOfflinePlayer(rentBy);
|
||||
|
||||
RentingRegionEvent rentingRegionEvent = new RentingRegionEvent(rent,
|
||||
rentByPlayer,
|
||||
false);
|
||||
Bukkit.getPluginManager().callEvent(rentingRegionEvent);
|
||||
if (rentingRegionEvent.isCancelled()) {
|
||||
regionsRentCancelled.add(rent);
|
||||
} else {
|
||||
// Add values to the rent and send it to FileManager
|
||||
rent.setRentedUntil(Calendar.getInstance()
|
||||
.getTimeInMillis() + rent.getDuration());
|
||||
rent.setRenter(rentBy);
|
||||
rent.updateLastActiveTime();
|
||||
|
||||
// Fire schematic event and updated times extended
|
||||
rent.handleSchematicEvent(GeneralRegion.RegionEvent.RENTED);
|
||||
|
||||
// Add others as friends
|
||||
for (UUID friend : existing) {
|
||||
rent.getFriendsFeature().addFriend(friend, null);
|
||||
}
|
||||
|
||||
rent.notifyAndUpdate(new RentedRegionEvent(rent, false));
|
||||
}
|
||||
}
|
||||
|
||||
regionsSuccess.add(rent);
|
||||
}
|
||||
|
||||
private void proccessBuy(
|
||||
@Nonnull ProtectedRegion region,
|
||||
boolean landlord,
|
||||
List<UUID> existing,
|
||||
@Nonnull AddTaskState taskState
|
||||
) {
|
||||
Player player = taskState.sender();
|
||||
Set<GeneralRegion> regionsSuccess = taskState.regionsSuccess();
|
||||
Set<GeneralRegion> regionsBuyCancelled = taskState.regionsBuyCancelled(); // Denied by an event listener
|
||||
Set<String> namesAddCancelled = taskState.namesAddCancelled(); // Denied by an event listener
|
||||
World world = taskState.world();
|
||||
String regionName = region.getId();
|
||||
BuyRegion buy = regionFactory.createBuyRegion(regionName, world);
|
||||
// Set landlord
|
||||
if (landlord) {
|
||||
buy.setLandlord(player.getUniqueId(), player.getName());
|
||||
}
|
||||
|
||||
AddingRegionEvent event = plugin.getFileManager().addRegion(buy);
|
||||
if (event.isCancelled()) {
|
||||
namesAddCancelled.add(buy.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
buy.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
|
||||
buy.update();
|
||||
|
||||
// Add existing owners/members if any
|
||||
if (!landlord && !existing.isEmpty()) {
|
||||
UUID buyBy = existing.removeFirst();
|
||||
OfflinePlayer buyByPlayer = Bukkit.getOfflinePlayer(buyBy);
|
||||
|
||||
BuyingRegionEvent buyingRegionEvent = new BuyingRegionEvent(buy,
|
||||
buyByPlayer);
|
||||
Bukkit.getPluginManager().callEvent(buyingRegionEvent);
|
||||
if (buyingRegionEvent.isCancelled()) {
|
||||
regionsBuyCancelled.add(buy);
|
||||
} else {
|
||||
// Set the owner
|
||||
buy.setBuyer(buyBy);
|
||||
buy.updateLastActiveTime();
|
||||
|
||||
// Update everything
|
||||
buy.handleSchematicEvent(GeneralRegion.RegionEvent.BOUGHT);
|
||||
|
||||
// Add others as friends
|
||||
for (UUID friend : existing) {
|
||||
buy.getFriendsFeature().addFriend(friend, null);
|
||||
}
|
||||
|
||||
buy.notifyAndUpdate(new BoughtRegionEvent(buy));
|
||||
}
|
||||
}
|
||||
|
||||
regionsSuccess.add(buy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Add a region";
|
||||
}
|
||||
|
||||
public String getHelp(CommandSender target) {
|
||||
if (target.hasPermission("areashop.createrent")
|
||||
|| target.hasPermission("areashop.createrent.member")
|
||||
|| target.hasPermission("areashop.createrent.owner")
|
||||
|
||||
|| target.hasPermission("areashop.createbuy")
|
||||
|| target.hasPermission("areashop.createbuy.member")
|
||||
|| target.hasPermission("areashop.createbuy.owner")) {
|
||||
return "help-add";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("add");
|
||||
}
|
||||
|
||||
private record AddTaskState(
|
||||
@Nonnull Player sender,
|
||||
@Nonnull GeneralRegion.RegionType regionType,
|
||||
@Nonnull Set<GeneralRegion> regionsSuccess,
|
||||
@Nonnull Set<GeneralRegion> regionsAlready,
|
||||
@Nonnull Set<GeneralRegion> regionsAlreadyOtherWorld,
|
||||
@Nonnull Set<GeneralRegion> regionsRentCancelled,
|
||||
@Nonnull Set<GeneralRegion> regionsBuyCancelled,
|
||||
@Nonnull Set<String> namesBlacklisted,
|
||||
@Nonnull Set<String> namesNoPermission,
|
||||
@Nonnull Set<String> namesAddCancelled,
|
||||
@Nonnull World world) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class AddFriendCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_FRIEND = CloudKey.of("friend", String.class);
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
private final MessageBridge messageBridge;
|
||||
private final Plugin plugin;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
|
||||
@Inject
|
||||
public AddFriendCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull Plugin plugin,
|
||||
@Nonnull BukkitSchedulerExecutor executor,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.plugin = plugin;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
this.executor = executor;
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Allows you to add friends to your regions";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.addfriendall") || target.hasPermission("areashop.addfriend")) {
|
||||
return "help-addFriend";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("addfriend")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_FRIEND, OfflinePlayerParser.parser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.addfriend") && !sender.hasPermission("areashop.addfriendall")) {
|
||||
this.messageBridge.message(sender, "addfriend-noPermission");
|
||||
return;
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_FRIEND))
|
||||
.whenCompleteAsync((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
processWithFriend(sender, region, offlinePlayer);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
private void processWithFriend(@Nonnull Player sender,
|
||||
@Nonnull GeneralRegion region,
|
||||
@Nonnull OfflinePlayer friend
|
||||
) {
|
||||
if (sender.hasPermission("areashop.addfriendall") && ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
|
||||
|| (region instanceof BuyRegion buyRegion && !buyRegion.isSold()))) {
|
||||
this.messageBridge.message(sender, "addfriend-noOwner", region);
|
||||
return;
|
||||
|
||||
}
|
||||
if (!sender.hasPermission("areashop.addfriend")) {
|
||||
this.messageBridge.message(sender, "addfriend-noPermission", region);
|
||||
return;
|
||||
}
|
||||
if (!region.isOwner(sender)) {
|
||||
this.messageBridge.message(sender, "addfriend-noPermissionOther", region);
|
||||
return;
|
||||
}
|
||||
if (!friend.hasPlayedBefore() && !friend.isOnline() && !plugin.getConfig()
|
||||
.getBoolean("addFriendNotExistingPlayers")) {
|
||||
this.messageBridge.message(sender, "addfriend-notVisited", friend.getName(), region);
|
||||
} else if (region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
|
||||
this.messageBridge.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
|
||||
} else if (region.isOwner(friend.getUniqueId())) {
|
||||
this.messageBridge.message(sender, "addfriend-self", friend.getName(), region);
|
||||
} else if (region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "addfriend-success", friend.getName(), region);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("addfriend");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.SignProfileUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.features.signs.RegionSign;
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.tools.Materials;
|
||||
import me.wiefferink.areashop.tools.SignUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class AddSignCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
|
||||
private final SignManager signManager;
|
||||
private final Plugin plugin;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public AddSignCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull SignManager signManager,
|
||||
@Nonnull Plugin plugin
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.signManager = signManager;
|
||||
this.plugin = plugin;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Allows you to add signs to existing regions";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.addsign")) {
|
||||
return "help-addsign";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("addsign")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.optional(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.flag(SignProfileUtil.DEFAULT_FLAG)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.addsign")) {
|
||||
throw new AreaShopCommandException("addsign-noPermission");
|
||||
}
|
||||
// Get the sign
|
||||
Block block = null;
|
||||
BlockIterator blockIterator = new BlockIterator(sender, 100);
|
||||
while(blockIterator.hasNext() && block == null) {
|
||||
Block next = blockIterator.next();
|
||||
if(next.getType() != Material.AIR) {
|
||||
block = next;
|
||||
}
|
||||
}
|
||||
if(block == null || !Materials.isSign(block.getType())) {
|
||||
messageBridge.message(sender, "addsign-noSign");
|
||||
return;
|
||||
}
|
||||
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, KEY_REGION);
|
||||
String profile = SignProfileUtil.getOrParseProfile(context, this.plugin);
|
||||
Optional<RegionSign> optionalRegionSign = this.signManager.signFromLocation(block.getLocation());
|
||||
if(optionalRegionSign.isPresent()) {
|
||||
RegionSign regionSign = optionalRegionSign.get();
|
||||
messageBridge.message(sender, "addsign-alreadyRegistered", regionSign.getRegion());
|
||||
return;
|
||||
}
|
||||
|
||||
region.getSignsFeature().addSign(block.getLocation(), block.getType(), SignUtils.getSignFacing(block), profile);
|
||||
if(profile == null) {
|
||||
messageBridge.message(sender, "addsign-success", region);
|
||||
} else {
|
||||
messageBridge.message(sender, "addsign-successProfile", profile, region);
|
||||
}
|
||||
region.update();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("addsign");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class BuyCommand extends AreashopCommandBean {
|
||||
|
||||
private final CommandFlag<BuyRegion> buyRegionFlag;
|
||||
|
||||
@Inject
|
||||
public BuyCommand(@Nonnull IFileManager fileManager) {
|
||||
this.buyRegionFlag = RegionParseUtil.createDefaultBuy(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.buy")) {
|
||||
return "help-buy";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Allows you to buy a region";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("buy");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder
|
||||
.literal("buy")
|
||||
.flag(this.buyRegionFlag)
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
if (!context.hasPermission("areashop.buy")) {
|
||||
throw new AreaShopCommandException("buy-noPermission");
|
||||
}
|
||||
Player sender = context.sender().sender();
|
||||
BuyRegion region = RegionParseUtil.getOrParseBuyRegion(context, sender, this.buyRegionFlag);
|
||||
region.buy(sender);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.WorldSelection;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@Singleton
|
||||
public class DelCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
private final WorldEditInterface worldEditInterface;
|
||||
private final IFileManager fileManager;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public DelCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull WorldEditInterface worldEditInterface,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.worldEditInterface = worldEditInterface;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Allows you to delete regions";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.destroyrent") || target.hasPermission("areashop.destroybuy") || target.hasPermission(
|
||||
"areashop.destroyrent.landlord") || target.hasPermission("areashop.destroybuy.landlord")) {
|
||||
return "help-del";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("delete", "del");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("del", "delete")
|
||||
.optional(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
public void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.destroybuy")
|
||||
&& !sender.hasPermission("areashop.destroybuy.landlord")
|
||||
&& !sender.hasPermission("areashop.destroyrent")
|
||||
&& !sender.hasPermission("areashop.destroyrent.landlord")) {
|
||||
throw new AreaShopCommandException("del-noPermission");
|
||||
}
|
||||
Optional<GeneralRegion> inputRegion = context.optional(KEY_REGION);
|
||||
if (inputRegion.isPresent()) {
|
||||
handleSingleDeletion(sender, inputRegion.get());
|
||||
return;
|
||||
}
|
||||
List<GeneralRegion> regions;
|
||||
if (sender instanceof Player player) {
|
||||
WorldSelection selection = WorldSelection.fromPlayer(player, this.worldEditInterface);
|
||||
regions = Utils.getWorldEditRegionsInSelection(selection.selection()).stream()
|
||||
.map(ProtectedRegion::getId)
|
||||
.map(this.fileManager::getRegion)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
} else {
|
||||
throw new AreaShopCommandException("cmd-weOnlyByPlayer");
|
||||
}
|
||||
if (regions.isEmpty()) {
|
||||
throw new AreaShopCommandException("cmd-noWERegionsFound");
|
||||
}
|
||||
handleMassDeletion(player, regions);
|
||||
}
|
||||
|
||||
private void handleSingleDeletion(@Nonnull CommandSender sender, GeneralRegion region) {
|
||||
boolean isLandlord = sender instanceof Player player && region.isLandlord(player.getUniqueId());
|
||||
if (region instanceof RentRegion) {
|
||||
// Remove the rent if the player has permission
|
||||
if (sender.hasPermission("areashop.destroyrent") || (isLandlord && sender.hasPermission(
|
||||
"areashop.destroyrent.landlord"))) {
|
||||
DeletingRegionEvent event = fileManager.deleteRegion(region, true);
|
||||
if (event.isCancelled()) {
|
||||
this.messageBridge.message(sender, "general-cancelled", event.getReason());
|
||||
} else {
|
||||
this.messageBridge.message(sender, "destroy-successRent", region);
|
||||
}
|
||||
} else {
|
||||
this.messageBridge.message(sender, "destroy-noPermissionRent", region);
|
||||
}
|
||||
} else if (region instanceof BuyRegion) {
|
||||
// Remove the buy if the player has permission
|
||||
if (sender.hasPermission("areashop.destroybuy") || (isLandlord && sender.hasPermission(
|
||||
"areashop.destroybuy.landlord"))) {
|
||||
DeletingRegionEvent event = fileManager.deleteRegion(region, true);
|
||||
if (event.isCancelled()) {
|
||||
messageBridge.message(sender, "general-cancelled", event.getReason());
|
||||
} else {
|
||||
messageBridge.message(sender, "destroy-successBuy", region);
|
||||
}
|
||||
} else {
|
||||
messageBridge.message(sender, "destroy-noPermissionBuy", region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMassDeletion(@Nonnull Player sender, @Nonnull List<GeneralRegion> regions) {
|
||||
List<String> namesSuccess = new ArrayList<>();
|
||||
Set<GeneralRegion> regionsFailed = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsCancelled = new TreeSet<>();
|
||||
for (GeneralRegion region : regions) {
|
||||
if (cannotDelete(sender, region)) {
|
||||
regionsFailed.add(region);
|
||||
continue;
|
||||
}
|
||||
|
||||
DeletingRegionEvent event = this.fileManager.deleteRegion(region, true);
|
||||
if (event.isCancelled()) {
|
||||
regionsCancelled.add(region);
|
||||
} else {
|
||||
namesSuccess.add(region.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Send messages
|
||||
if (!namesSuccess.isEmpty()) {
|
||||
this.messageBridge.message(sender, "del-success", Utils.createCommaSeparatedList(namesSuccess));
|
||||
}
|
||||
if (!regionsFailed.isEmpty()) {
|
||||
this.messageBridge.message(sender, "del-failed", Utils.combinedMessage(regionsFailed, "region"));
|
||||
}
|
||||
if (!regionsCancelled.isEmpty()) {
|
||||
this.messageBridge.message(sender, "del-cancelled", Utils.combinedMessage(regionsCancelled, "region"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean cannotDelete(@Nonnull Player sender, @Nonnull GeneralRegion region) {
|
||||
boolean isLandlord = region.isLandlord(sender.getUniqueId());
|
||||
if (region instanceof RentRegion
|
||||
&& (!sender.hasPermission("areashop.destroyrent") && !(isLandlord && sender.hasPermission(
|
||||
"areashop.destroyrent.landlord")))) {
|
||||
return true;
|
||||
|
||||
}
|
||||
return region instanceof BuyRegion
|
||||
&& (!sender.hasPermission("areashop.destroybuy") && !(isLandlord && sender.hasPermission(
|
||||
"areashop.destroybuy.landlord")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.features.FriendsFeature;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class DelFriendCommand extends AreashopCommandBean {
|
||||
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
|
||||
@Inject
|
||||
public DelFriendCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
|
||||
@Nonnull BukkitSchedulerExecutor executor
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a person can remove friends.
|
||||
*
|
||||
* @param person The person to check
|
||||
* @param region The region to check for
|
||||
* @return true if the person can remove friends, otherwise false
|
||||
*/
|
||||
public static boolean canUse(CommandSender person, GeneralRegion region) {
|
||||
if (person.hasPermission("areashop.delfriendall")) {
|
||||
return true;
|
||||
}
|
||||
if (person instanceof Player player) {
|
||||
return region.isOwner(player) && player.hasPermission("areashop.delfriend");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.delfriendall") || target.hasPermission("areashop.delfriend")) {
|
||||
return "help-delFriend";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("deletefriend", "delfriend");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("delfriend", "deletefriend")
|
||||
.required(KEY_PLAYER, OfflinePlayerParser.parser(), this::suggestFriends)
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.delfriend") && !sender.hasPermission("areashop.delfriendall")) {
|
||||
throw new AreaShopCommandException("delfriend-noPermission");
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenCompleteAsync((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
processWithSender(sender, region, offlinePlayer);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
private void processWithSender(@Nonnull CommandSender sender,
|
||||
@Nonnull GeneralRegion region,
|
||||
@Nonnull OfflinePlayer friend) {
|
||||
FriendsFeature friendsFeature = region.getFriendsFeature();
|
||||
if (sender.hasPermission("areashop.delfriendall")) {
|
||||
if ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
|
||||
|| (region instanceof BuyRegion buyRegion && !buyRegion.isSold())) {
|
||||
throw new AreaShopCommandException("delfriend-noOwner", region);
|
||||
|
||||
}
|
||||
if (!friendsFeature.getFriends().contains(friend.getUniqueId())) {
|
||||
throw new AreaShopCommandException("delfriend-notAdded", friend.getName(), region);
|
||||
|
||||
}
|
||||
if (friendsFeature.deleteFriend(friend.getUniqueId(), sender)) {
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "delfriend-successOther", friend.getName(), region);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!sender.hasPermission("areashop.delfriend") || !(sender instanceof Player player)) {
|
||||
throw new AreaShopCommandException("delfriend-noPermission", region);
|
||||
}
|
||||
if (!region.isOwner(player)) {
|
||||
throw new AreaShopCommandException("delfriend-noPermissionOther", region);
|
||||
}
|
||||
if (!friendsFeature.getFriends().contains(friend.getUniqueId())) {
|
||||
throw new AreaShopCommandException("delfriend-notAdded", friend.getName(), region);
|
||||
} else if (friendsFeature.deleteFriend(friend.getUniqueId(), sender)) {
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "delfriend-success", friend.getName(), region);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestFriends(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.delfriend")) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
GeneralRegion region;
|
||||
try {
|
||||
region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
} catch (AreaShopCommandException ignored) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
if (!sender.hasPermission("areashop.delfriendall")
|
||||
&& sender instanceof Player player
|
||||
&& !region.isOwner(player)
|
||||
) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
String text = input.peekString();
|
||||
FriendsFeature friendsFeature = region.getFriendsFeature();
|
||||
Collection<Suggestion> suggestion = friendsFeature.getFriendNames().stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.features.signs.RegionSign;
|
||||
import me.wiefferink.areashop.features.signs.SignManager;
|
||||
import me.wiefferink.areashop.tools.Materials;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class DelSignCommand extends AreashopCommandBean {
|
||||
|
||||
private final SignManager signManager;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public DelSignCommand(@Nonnull MessageBridge messageBridge, @Nonnull SignManager signManager) {
|
||||
this.signManager = signManager;
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("deletesign", "delsign");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("delsign", "deletesign")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.delsign")) {
|
||||
return "help-delsign";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.delsign")) {
|
||||
throw new AreaShopCommandException("delsign-noPermission");
|
||||
}
|
||||
// Get the sign
|
||||
Block block = null;
|
||||
BlockIterator blockIterator = new BlockIterator(sender, 100);
|
||||
while (blockIterator.hasNext() && block == null) {
|
||||
Block next = blockIterator.next();
|
||||
if (!next.getType().isAir()) {
|
||||
block = next;
|
||||
}
|
||||
}
|
||||
if (block == null || !Materials.isSign(block.getType())) {
|
||||
throw new AreaShopCommandException("delsign-noSign");
|
||||
}
|
||||
Optional<RegionSign> optionalSign = signManager.removeSign(block.getLocation());
|
||||
if (optionalSign.isEmpty()) {
|
||||
throw new AreaShopCommandException("delsign-noRegion");
|
||||
}
|
||||
RegionSign regionSign = optionalSign.get();
|
||||
messageBridge.message(sender, "delsign-success", regionSign.getRegion());
|
||||
regionSign.remove();
|
||||
// Sometimes the RegionSign data is corrupted. Forcefully set the block to air
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionGroupParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.DoubleParser;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Singleton
|
||||
public class FindCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion.RegionType> KEY_REGION_TYPE = CloudKey.of("regionType",
|
||||
GeneralRegion.RegionType.class);
|
||||
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("maxPrice", Double.class);
|
||||
|
||||
private final Economy economy;
|
||||
private final IFileManager fileManager;
|
||||
private final CommandFlag<RegionGroup> regionGroupFlag;
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public FindCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull Economy economy,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.economy = economy;
|
||||
this.fileManager = fileManager;
|
||||
this.regionGroupFlag = CommandFlag.builder("region")
|
||||
.withComponent(ParserDescriptor.of(new RegionGroupParser<>(fileManager, "find-wrongGroup"),
|
||||
RegionGroup.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.find")) {
|
||||
return "help-find";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("find")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION_TYPE, EnumParser.enumParser(GeneralRegion.RegionType.class))
|
||||
.optional(KEY_PRICE, DoubleParser.doubleParser(0))
|
||||
.flag(this.regionGroupFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("find");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.find")) {
|
||||
throw new AreaShopCommandException("find-noPermission");
|
||||
}
|
||||
double balance;
|
||||
if (economy != null) {
|
||||
balance = economy.getBalance(sender);
|
||||
} else {
|
||||
balance = 0;
|
||||
}
|
||||
boolean maxPriceSet = context.contains(KEY_PRICE);
|
||||
double maxPrice = context.getOrDefault(KEY_PRICE, Double.MAX_VALUE);
|
||||
RegionGroup group = context.flags().get(this.regionGroupFlag);
|
||||
GeneralRegion.RegionType regionType = context.get(KEY_REGION_TYPE);
|
||||
Message onlyInGroup;
|
||||
if (group != null) {
|
||||
onlyInGroup = Message.fromKey("find-onlyInGroup").replacements(group.getName());
|
||||
} else {
|
||||
onlyInGroup = Message.empty();
|
||||
}
|
||||
switch (regionType) {
|
||||
case BUY -> handleBuy(sender, balance, maxPrice, maxPriceSet, onlyInGroup, group);
|
||||
case RENT -> handleRent(sender, balance, maxPrice, maxPriceSet, onlyInGroup, group);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBuy(@Nonnull Player sender,
|
||||
double balance,
|
||||
double maxPrice,
|
||||
boolean maxPriceSet,
|
||||
@Nonnull Message onlyInGroup,
|
||||
RegionGroup group
|
||||
) {
|
||||
Collection<BuyRegion> regions = fileManager.getBuysRef();
|
||||
List<BuyRegion> results = new LinkedList<>();
|
||||
for (BuyRegion region : regions) {
|
||||
if (!region.isSold()
|
||||
&& ((region.getPrice() <= balance && !maxPriceSet) || (region.getPrice() <= maxPrice && maxPriceSet))
|
||||
&& (group == null || group.isMember(region))
|
||||
&& (region.getBooleanSetting("general.findCrossWorld") || sender.getWorld()
|
||||
.equals(region.getWorld()))
|
||||
) {
|
||||
results.add(region);
|
||||
}
|
||||
}
|
||||
if (results.isEmpty()) {
|
||||
double currency = maxPriceSet ? maxPrice : balance;
|
||||
String key = maxPriceSet ? "find-noneFoundMax" : "find-noneFound";
|
||||
throw new AreaShopCommandException(key, "buy", Utils.formatCurrency(currency), onlyInGroup);
|
||||
}
|
||||
// Draw a random one
|
||||
BuyRegion region = results.get(ThreadLocalRandom.current().nextInt(results.size()));
|
||||
// Teleport
|
||||
double currency = maxPriceSet ? maxPrice : balance;
|
||||
String key = maxPriceSet ? "find-successMax" : "find-success";
|
||||
this.messageBridge.message(sender,
|
||||
key,
|
||||
"buy",
|
||||
Utils.formatCurrency(currency),
|
||||
onlyInGroup,
|
||||
region);
|
||||
boolean tpToSign = region.getBooleanSetting("general.findTeleportToSign");
|
||||
region.getTeleportFeature().teleportPlayer(sender, tpToSign, false);
|
||||
}
|
||||
|
||||
private void handleRent(
|
||||
@Nonnull Player sender,
|
||||
double balance,
|
||||
double maxPrice,
|
||||
boolean maxPriceSet,
|
||||
@Nonnull Message onlyInGroup,
|
||||
RegionGroup group
|
||||
) {
|
||||
Collection<RentRegion> regions = fileManager.getRentsRef();
|
||||
List<RentRegion> results = new LinkedList<>();
|
||||
for (RentRegion region : regions) {
|
||||
if (!region.isRented()
|
||||
&& ((region.getPrice() <= balance && !maxPriceSet) || (region.getPrice() <= maxPrice && maxPriceSet))
|
||||
&& (group == null || group.isMember(region))
|
||||
&& (region.getBooleanSetting("general.findCrossWorld") || sender.getWorld()
|
||||
.equals(region.getWorld()))
|
||||
) {
|
||||
results.add(region);
|
||||
}
|
||||
}
|
||||
if (results.isEmpty()) {
|
||||
double currency = maxPriceSet ? maxPrice : balance;
|
||||
String key = maxPriceSet ? "find-noneFoundMax" : "find-noneFound";
|
||||
throw new AreaShopCommandException(key, "rent", Utils.formatCurrency(currency), onlyInGroup);
|
||||
}
|
||||
// Draw a random one
|
||||
RentRegion region = results.get(ThreadLocalRandom.current().nextInt(results.size()));
|
||||
// Teleport
|
||||
double currency = maxPriceSet ? maxPrice : balance;
|
||||
String key = maxPriceSet ? "find-successMax" : "find-success";
|
||||
this.messageBridge.message(sender,
|
||||
key,
|
||||
"rent",
|
||||
Utils.formatCurrency(currency),
|
||||
onlyInGroup,
|
||||
region);
|
||||
boolean tpToSign = region.getBooleanSetting("general.findTeleportToSign");
|
||||
region.getTeleportFeature().teleportPlayer(sender, tpToSign, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class GroupAddCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_GROUP = CloudKey.of("group", String.class);
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final RegionFactory regionFactory;
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public GroupAddCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull RegionFactory regionFactory
|
||||
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.regionFactory = regionFactory;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.groupadd")) {
|
||||
return "help-groupadd";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("groupadd")
|
||||
.required(KEY_GROUP, StringParser.stringParser(), this::suggestGroupNames)
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("groupadd");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.groupadd")) {
|
||||
throw new AreaShopCommandException("groupadd-noPermission");
|
||||
}
|
||||
String rawGroup = context.get(KEY_GROUP);
|
||||
RegionGroup group = fileManager.getGroup(rawGroup);
|
||||
if (group == null) {
|
||||
group = regionFactory.createRegionGroup(rawGroup);
|
||||
fileManager.addGroup(group);
|
||||
}
|
||||
GeneralRegion declaredRegion = context.flags().get(this.regionFlag);
|
||||
if (declaredRegion != null) {
|
||||
if (!group.addMember(declaredRegion)) {
|
||||
throw new AreaShopCommandException("groupadd-failed", group.getName(), declaredRegion);
|
||||
}
|
||||
declaredRegion.update();
|
||||
this.messageBridge.message(sender,
|
||||
"groupadd-success",
|
||||
group.getName(),
|
||||
group.getMembers().size(),
|
||||
declaredRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<GeneralRegion> regions = RegionParseUtil.getOrParseRegionsInSel(context, sender, this.regionFlag);
|
||||
Set<GeneralRegion> regionsSuccess = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsFailed = new TreeSet<>();
|
||||
for (GeneralRegion region : regions) {
|
||||
if (group.addMember(region)) {
|
||||
regionsSuccess.add(region);
|
||||
} else {
|
||||
regionsFailed.add(region);
|
||||
}
|
||||
}
|
||||
if (!regionsSuccess.isEmpty()) {
|
||||
messageBridge.message(sender,
|
||||
"groupadd-weSuccess",
|
||||
group.getName(),
|
||||
Utils.combinedMessage(regionsSuccess, "region"));
|
||||
}
|
||||
if (!regionsFailed.isEmpty()) {
|
||||
messageBridge.message(sender,
|
||||
"groupadd-weFailed",
|
||||
group.getName(),
|
||||
Utils.combinedMessage(regionsFailed, "region"));
|
||||
}
|
||||
// Update all regions, this does it in a task, updating them without lag
|
||||
fileManager.updateRegions(List.copyOf(regionsSuccess), sender);
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestGroupNames(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getGroupNames().stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class GroupDelCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_GROUP = CloudKey.of("group", String.class);
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final RegionFactory regionFactory;
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public GroupDelCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull RegionFactory regionFactory
|
||||
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.regionFactory = regionFactory;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.groupdel")) {
|
||||
return "help-groupdel";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("groupdel")
|
||||
.required(KEY_GROUP, StringParser.stringParser(), this::suggestGroupNames)
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("groupdel");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("groupdel")) {
|
||||
throw new AreaShopCommandException("groupdel-noPermission");
|
||||
}
|
||||
String rawGroup = context.get(KEY_GROUP);
|
||||
RegionGroup group = fileManager.getGroup(rawGroup);
|
||||
if (group == null) {
|
||||
group = regionFactory.createRegionGroup(rawGroup);
|
||||
fileManager.addGroup(group);
|
||||
}
|
||||
GeneralRegion declaredRegion = context.flags().get(this.regionFlag);
|
||||
if (declaredRegion != null) {
|
||||
if (!group.removeMember(declaredRegion)) {
|
||||
throw new AreaShopCommandException("groupdel-failed", group.getName(), declaredRegion);
|
||||
}
|
||||
this.messageBridge.message(sender,
|
||||
"groupdel-success",
|
||||
group.getName(),
|
||||
group.getMembers().size(),
|
||||
declaredRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<GeneralRegion> regions = RegionParseUtil.getOrParseRegionsInSel(context, sender, this.regionFlag);
|
||||
Set<GeneralRegion> regionsSuccess = new TreeSet<>();
|
||||
Set<GeneralRegion> regionsFailed = new TreeSet<>();
|
||||
for (GeneralRegion region : regions) {
|
||||
if (group.removeMember(region)) {
|
||||
regionsSuccess.add(region);
|
||||
} else {
|
||||
regionsFailed.add(region);
|
||||
}
|
||||
}
|
||||
if (!regionsSuccess.isEmpty()) {
|
||||
messageBridge.message(sender,
|
||||
"groupdel-weSuccess",
|
||||
group.getName(),
|
||||
Utils.combinedMessage(regionsSuccess, "region"));
|
||||
}
|
||||
if (!regionsFailed.isEmpty()) {
|
||||
messageBridge.message(sender,
|
||||
"groupdel-weFailed",
|
||||
group.getName(),
|
||||
Utils.combinedMessage(regionsFailed, "region"));
|
||||
}
|
||||
// Update all regions, this does it in a task, updating them without lag
|
||||
fileManager.updateRegions(List.copyOf(regionsSuccess), sender);
|
||||
group.saveRequired();
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestGroupNames(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getGroupNames().stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionGroupParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
|
||||
@Singleton
|
||||
public class GroupInfoCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<RegionGroup> KEY_GROUP = CloudKey.of("group", RegionGroup.class);
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public GroupInfoCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.groupinfo")) {
|
||||
return "help-groupinfo";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
ParserDescriptor<CommandSource<?>, RegionGroup> regionGroupParser = ParserDescriptor.of(
|
||||
new RegionGroupParser<>(this.fileManager, "groupinfo-noGroup"),
|
||||
RegionGroup.class);
|
||||
return builder
|
||||
.literal("groupinfo")
|
||||
.required(KEY_GROUP, regionGroupParser)
|
||||
.handler(this::handleCommand);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("groupinfo");
|
||||
}
|
||||
|
||||
public void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
if (!context.hasPermission("groupinfo")) {
|
||||
throw new AreaShopCommandException("groupinfo-noPermission");
|
||||
}
|
||||
RegionGroup group = context.get(KEY_GROUP);
|
||||
Set<String> members = group.getMembers();
|
||||
if (members.isEmpty()) {
|
||||
throw new AreaShopCommandException("groupinfo-noMembers", group.getName());
|
||||
}
|
||||
String seperatedMembers = Utils.createCommaSeparatedList(members);
|
||||
this.messageBridge.message(context.sender().sender(), "groupinfo-members", group.getName(), seperatedMembers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class GroupListCommand extends AreashopCommandBean {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public GroupListCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if(target.hasPermission("areashop.grouplist")) {
|
||||
return "help-grouplist";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("grouplist", "groups")
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("grouplist", "groups");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
if (!context.hasPermission("areashop.grouplist")) {
|
||||
throw new AreaShopCommandException("grouplist-noPermission");
|
||||
}
|
||||
List<String> groups = this.fileManager.getGroupNames();
|
||||
CommandSender sender = context.sender().sender();
|
||||
if(groups.isEmpty()) {
|
||||
messageBridge.message(sender, "grouplist-noGroups");
|
||||
} else {
|
||||
messageBridge.message(sender, "grouplist-success", Utils.createCommaSeparatedList(groups));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommands;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class HelpCommand extends AreashopCommandBean {
|
||||
private final AreashopCommands commands;
|
||||
|
||||
@Inject
|
||||
public HelpCommand(@Nonnull AreashopCommands commands) {
|
||||
this.commands = commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.help")) {
|
||||
return "help-help";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("help")
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("help");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.help")) {
|
||||
throw new AreaShopCommandException("help-noPermission");
|
||||
}
|
||||
this.commands.showHelp(sender);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AcceptedValuesParser;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.regions.ImportJobFactory;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class ImportCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_SOURCE = CloudKey.of("source", String.class);
|
||||
|
||||
/* RegionGroup priority usage:
|
||||
0: Settings from /config.yml
|
||||
1: Settings from /worlds/<world>/config.yml
|
||||
2: Settings from /worlds/<world>/parent-regions.yml (if their priority is set it is added to this value)
|
||||
*/
|
||||
private final ImportJobFactory importJobFactory;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public ImportCommand(@Nonnull MessageBridge messageBridge, @Nonnull ImportJobFactory importJobFactory) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.importJobFactory = importJobFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.import")) {
|
||||
return "help-import";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
withConfirmation();
|
||||
var sourceParser = AcceptedValuesParser.ofConstant(List.of("RegionForSale"), "import-wrongSource", true);
|
||||
return builder.literal("import")
|
||||
.required(KEY_SOURCE, ParserDescriptor.of(sourceParser, String.class))
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("import");
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - Landlord?
|
||||
// - Friends
|
||||
// - Region flags?
|
||||
// - Settings from the 'permissions' section in RegionForSale/config.yml?
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.import")) {
|
||||
this.messageBridge.message(sender, "import-noPermission");
|
||||
return;
|
||||
}
|
||||
String importSource = context.get(KEY_SOURCE);
|
||||
if (!"RegionForSale".equalsIgnoreCase(importSource)) {
|
||||
throw new AreaShopCommandException("import-wrongSource");
|
||||
}
|
||||
importJobFactory.createImportJob(sender).execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class InfoBaseCommand extends AreashopCommandBean {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public InfoBaseCommand(
|
||||
@Nonnull MessageBridge messageBridge
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.info")) {
|
||||
return "help-info";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("info").handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("info");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.info")) {
|
||||
messageBridge.message(sender, "info-noPermission");
|
||||
return;
|
||||
}
|
||||
this.messageBridge.message(sender, "info-help");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionGroupParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.SimpleMessageBridge;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Singleton
|
||||
public class InfoCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CommandFlag<Integer> FLAG_PAGE = CommandFlag.builder("page")
|
||||
.withComponent(IntegerParser.integerParser(1))
|
||||
.build();
|
||||
private static final CloudKey<RegionStateFilterType> KEY_TYPE = CloudKey.of("type", RegionStateFilterType.class);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
private final CommandFlag<RegionGroup> filterGroupFlag;
|
||||
|
||||
@Inject
|
||||
public InfoCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.filterGroupFlag = CommandFlag.builder("group")
|
||||
.withComponent(ParserDescriptor.of(new RegionGroupParser<>(fileManager, "info-noFiltergroup"),
|
||||
RegionGroup.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("info")
|
||||
.required(KEY_TYPE, EnumParser.enumParser(RegionStateFilterType.class))
|
||||
.flag(FLAG_PAGE)
|
||||
.flag(this.filterGroupFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("info");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.info")) {
|
||||
messageBridge.message(sender, "info-noPermission");
|
||||
return;
|
||||
}
|
||||
RegionStateFilterType filterType = context.get(KEY_TYPE);
|
||||
processOtherFilters(context, filterType);
|
||||
}
|
||||
|
||||
private void processOtherFilters(@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull RegionStateFilterType filterType) {
|
||||
RegionGroup filterGroup = context.flags().get(this.filterGroupFlag);
|
||||
int page = context.flags().getValue(FLAG_PAGE).orElse(1);
|
||||
Stream<? extends GeneralRegion> toShow = switch (filterType) {
|
||||
case ALL -> fileManager.getRegionsRef().stream();
|
||||
case SOLD -> fileManager.getBuysRef().stream().filter(BuyRegion::isSold);
|
||||
case RENTED -> fileManager.getRentsRef().stream().filter(RentRegion::isRented);
|
||||
case FORRENT -> fileManager.getRentsRef().stream().filter(RentRegion::isAvailable);
|
||||
case FORSALE -> fileManager.getBuysRef().stream().filter(BuyRegion::isAvailable);
|
||||
case RESELLING -> fileManager.getBuysRef().stream().filter(BuyRegion::isInResellingMode);
|
||||
case NOGROUP -> {
|
||||
List<GeneralRegion> regions = new LinkedList<>(fileManager.getRegions());
|
||||
for (RegionGroup group : fileManager.getGroups()) {
|
||||
regions.removeAll(group.getMemberRegions());
|
||||
}
|
||||
yield regions.stream();
|
||||
}
|
||||
};
|
||||
String header = switch (filterType) {
|
||||
case ALL -> "info-allHeader";
|
||||
case SOLD -> "info-soldHeader";
|
||||
case RENTED -> "info-rentedHeader";
|
||||
case FORRENT -> "info-forrentHeader";
|
||||
case FORSALE -> "info-forsaleHeader";
|
||||
case RESELLING -> "info-resellingHeader";
|
||||
case NOGROUP -> "info-nogroupHeader";
|
||||
};
|
||||
String baseCommand = switch (filterType) {
|
||||
case ALL -> "info all";
|
||||
case SOLD -> "info sold";
|
||||
case RENTED -> "info rented";
|
||||
case FORRENT -> "info forrent";
|
||||
case FORSALE -> "info forsale";
|
||||
case RESELLING -> "info reselling";
|
||||
case NOGROUP -> "info nogroup";
|
||||
};
|
||||
showSortedPagedList(context.sender().sender(), toShow, filterGroup, header, page, baseCommand);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display a page of a list of regions.
|
||||
*
|
||||
* @param sender The CommandSender to send the messages to
|
||||
* @param regionStream The regions to display
|
||||
* @param filterGroup The group to filter the regions by
|
||||
* @param keyHeader The header to print above the page
|
||||
* @param pageInput The page number, if any
|
||||
* @param baseCommand The command to execute for next/previous page (/areashop will be added)
|
||||
*/
|
||||
private void showSortedPagedList(
|
||||
CommandSender sender,
|
||||
Stream<? extends GeneralRegion> regionStream,
|
||||
RegionGroup filterGroup,
|
||||
String keyHeader,
|
||||
int pageInput,
|
||||
String baseCommand
|
||||
) {
|
||||
int page = pageInput;
|
||||
int maximumItems = 20;
|
||||
int itemsPerPage = maximumItems - 2;
|
||||
List<? extends GeneralRegion> regions;
|
||||
if (filterGroup != null) {
|
||||
regions = regionStream.filter(generalRegion -> !filterGroup.isMember(generalRegion)).toList();
|
||||
} else {
|
||||
regions = regionStream.toList();
|
||||
}
|
||||
if (regions.isEmpty()) {
|
||||
messageBridge.message(sender, "info-noRegions");
|
||||
return;
|
||||
}
|
||||
// First sort by type, then by name
|
||||
regions = regions.stream().sorted((one, two) -> {
|
||||
int typeCompare = getTypeOrder(two).compareTo(getTypeOrder(one));
|
||||
if (typeCompare != 0) {
|
||||
return typeCompare;
|
||||
} else {
|
||||
return one.getName().compareTo(two.getName());
|
||||
}
|
||||
}).toList();
|
||||
// Header
|
||||
Message limitedToGroup = Message.empty();
|
||||
if (filterGroup != null) {
|
||||
limitedToGroup = Message.fromKey("info-limitedToGroup").replacements(filterGroup.getName());
|
||||
}
|
||||
messageBridge.message(sender, keyHeader, limitedToGroup);
|
||||
// Page entries
|
||||
int totalPages = (int) Math.ceil(regions.size() / (double) itemsPerPage); // Clip page to correct boundaries, not much need to tell the user
|
||||
if (regions.size() == itemsPerPage + 1) { // 19 total items is mapped to 1 page of 19
|
||||
itemsPerPage++;
|
||||
totalPages = 1;
|
||||
}
|
||||
page = Math.max(1, Math.min(totalPages, page));
|
||||
int linesPrinted = 1; // header
|
||||
for (int i = (page - 1) * itemsPerPage; i < page * itemsPerPage && i < regions.size(); i++) {
|
||||
String state;
|
||||
GeneralRegion region = regions.get(i);
|
||||
if (region.getType() == GeneralRegion.RegionType.RENT) {
|
||||
if (region.getOwner() == null) {
|
||||
state = "Forrent";
|
||||
} else {
|
||||
state = "Rented";
|
||||
}
|
||||
} else {
|
||||
if (region.getOwner() == null) {
|
||||
state = "Forsale";
|
||||
} else if (!((BuyRegion) region).isInResellingMode()) {
|
||||
state = "Sold";
|
||||
} else {
|
||||
state = "Reselling";
|
||||
}
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender, "info-entry" + state, region);
|
||||
linesPrinted++;
|
||||
}
|
||||
Message footer = Message.empty();
|
||||
// Previous button
|
||||
if (page > 1) {
|
||||
footer.append(Message.fromKey("info-pagePrevious").replacements(baseCommand + " --page " + (page - 1)));
|
||||
} else {
|
||||
footer.append(Message.fromKey("info-pageNoPrevious"));
|
||||
}
|
||||
// Page status
|
||||
if (totalPages > 1) {
|
||||
StringBuilder pageString = new StringBuilder("" + page);
|
||||
for (int i = pageString.length(); i < (totalPages + "").length(); i++) {
|
||||
pageString.insert(0, "0");
|
||||
}
|
||||
footer.append(Message.fromKey("info-pageStatus").replacements(page, totalPages));
|
||||
if (page < totalPages) {
|
||||
footer.append(Message.fromKey("info-pageNext").replacements(baseCommand + " --page " + (page + 1)));
|
||||
} else {
|
||||
footer.append(Message.fromKey("info-pageNoNext"));
|
||||
}
|
||||
// Fill up space if the page is not full (aligns header nicely)
|
||||
for (int i = linesPrinted; i < maximumItems - 1; i++) {
|
||||
sender.sendMessage(" ");
|
||||
}
|
||||
SimpleMessageBridge.send(footer, sender);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an integer to order by type, usable for Comparators.
|
||||
*
|
||||
* @param region The region to get the order for
|
||||
* @return An integer for sorting by type
|
||||
*/
|
||||
private Integer getTypeOrder(GeneralRegion region) {
|
||||
if (region.getType() == GeneralRegion.RegionType.RENT) {
|
||||
if (region.getOwner() == null) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
if (region.getOwner() == null) {
|
||||
return 3;
|
||||
} else if (!((BuyRegion) region).isInResellingMode()) {
|
||||
return 4;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum RegionStateFilterType {
|
||||
ALL,
|
||||
RENTED,
|
||||
FORRENT,
|
||||
SOLD,
|
||||
FORSALE,
|
||||
RESELLING,
|
||||
NOGROUP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionInfoUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class InfoPlayerCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
|
||||
@Inject
|
||||
public InfoPlayerCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
|
||||
@Nonnull BukkitSchedulerExecutor executor
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("info").literal("player")
|
||||
.required(KEY_PLAYER, OfflinePlayerParser.parser())
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("info region");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.info")) {
|
||||
messageBridge.message(sender, "info-noPermission");
|
||||
return;
|
||||
}
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenCompleteAsync((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, offlinePlayer);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import io.github.bakedlibs.dough.blocks.BlockPosition;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.SimpleMessageBridge;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class InfoRegionCommand extends AreashopCommandBean {
|
||||
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public InfoRegionCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("info").literal("region")
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("info region");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.info")) {
|
||||
messageBridge.message(sender, "info-noPermission");
|
||||
return;
|
||||
}
|
||||
// Region info
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
if (region instanceof RentRegion rent) {
|
||||
handleRent(sender, rent);
|
||||
} else if (region instanceof BuyRegion buy) {
|
||||
handleBuy(sender, buy);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBuy(@Nonnull CommandSender sender, @Nonnull BuyRegion buy) {
|
||||
messageBridge.message(sender, "info-regionHeaderBuy", buy);
|
||||
if (buy.isSold()) {
|
||||
if (buy.isInResellingMode()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionReselling", buy);
|
||||
messageBridge.messageNoPrefix(sender, "info-regionReselPrice", buy);
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionBought", buy);
|
||||
}
|
||||
// Money back
|
||||
if (!buy.getBooleanSetting("buy.sellDisabled")) {
|
||||
if (SellCommand.canUse(sender, buy)) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackBuyClick", buy);
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackBuy", buy);
|
||||
}
|
||||
}
|
||||
// Friends
|
||||
if (!buy.getFriendsFeature().getFriendNames().isEmpty()) {
|
||||
String messagePart = "info-friend";
|
||||
if (DelFriendCommand.canUse(sender, buy)) {
|
||||
messagePart = "info-friendRemove";
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender,
|
||||
"info-regionFriends",
|
||||
buy,
|
||||
Utils.combinedMessage(buy.getFriendsFeature().getFriendNames(), messagePart));
|
||||
}
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionCanBeBought", buy);
|
||||
}
|
||||
if (buy.getLandlord() != null) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionLandlord", buy);
|
||||
}
|
||||
if (buy.getInactiveTimeUntilSell() != -1) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionInactiveSell", buy);
|
||||
}
|
||||
// Restoring
|
||||
if (buy.isRestoreEnabled()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestoringBuy", buy);
|
||||
}
|
||||
// Restrictions
|
||||
if (!buy.isSold()) {
|
||||
if (buy.restrictedToRegion()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestrictedRegionBuy", buy);
|
||||
} else if (buy.restrictedToWorld()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestrictedWorldBuy", buy);
|
||||
}
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender, "info-regionFooterBuy", buy);
|
||||
}
|
||||
|
||||
private void handleRent(@Nonnull CommandSender sender, @Nonnull RentRegion rent) {
|
||||
messageBridge.message(sender, "info-regionHeaderRent", rent);
|
||||
if (rent.isRented()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRented", rent);
|
||||
messageBridge.messageNoPrefix(sender, "info-regionExtending", rent);
|
||||
// Money back
|
||||
if (UnrentCommand.canUse(sender, rent)) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackRentClick", rent);
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackRent", rent);
|
||||
}
|
||||
// Friends
|
||||
if (!rent.getFriendsFeature().getFriendNames().isEmpty()) {
|
||||
String messagePart = "info-friend";
|
||||
if (DelFriendCommand.canUse(sender, rent)) {
|
||||
messagePart = "info-friendRemove";
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender,
|
||||
"info-regionFriends",
|
||||
rent,
|
||||
Utils.combinedMessage(rent.getFriendsFeature().getFriendNames(), messagePart));
|
||||
}
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionCanBeRented", rent);
|
||||
}
|
||||
if (rent.getLandlordName() != null) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionLandlord", rent);
|
||||
}
|
||||
// Maximum extends
|
||||
if (rent.getMaxExtends() != -1) {
|
||||
if (rent.getMaxExtends() == 0) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionNoExtending", rent);
|
||||
} else if (rent.isRented()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionExtendsLeft", rent);
|
||||
} else {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMaxExtends", rent);
|
||||
}
|
||||
}
|
||||
// If maxExtends is zero it does not make sense to show this message
|
||||
if (rent.getMaxRentTime() != -1 && rent.getMaxExtends() != 0) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionMaxRentTime", rent);
|
||||
}
|
||||
if (rent.getInactiveTimeUntilUnrent() != -1) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionInactiveUnrent", rent);
|
||||
}
|
||||
displayMiscInfo(sender, rent);
|
||||
// Restoring
|
||||
if (rent.isRestoreEnabled()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestoringRent", rent);
|
||||
}
|
||||
// Restrictions
|
||||
if (!rent.isRented()) {
|
||||
if (rent.restrictedToRegion()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestrictedRegionRent", rent);
|
||||
} else if (rent.restrictedToWorld()) {
|
||||
messageBridge.messageNoPrefix(sender, "info-regionRestrictedWorldRent", rent);
|
||||
}
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender, "info-regionFooterRent", rent);
|
||||
}
|
||||
|
||||
private void displayMiscInfo(@Nonnull CommandSender sender, @Nonnull GeneralRegion region) {
|
||||
displayTeleportInfo(sender, region);
|
||||
displaySignInfo(sender, region);
|
||||
displayGroupInfo(sender, region);
|
||||
}
|
||||
|
||||
private void displayGroupInfo(@Nonnull CommandSender sender, @Nonnull GeneralRegion region) {// Groups
|
||||
if (sender.hasPermission("areashop.groupinfo") && !region.getGroupNames().isEmpty()) {
|
||||
messageBridge.messageNoPrefix(sender,
|
||||
"info-regionGroups",
|
||||
Utils.createCommaSeparatedList(region.getGroupNames()));
|
||||
}
|
||||
}
|
||||
|
||||
private void displaySignInfo(@Nonnull CommandSender sender, @Nonnull GeneralRegion region) {
|
||||
// Signs
|
||||
List<String> signLocations = new ArrayList<>();
|
||||
for (BlockPosition location : region.getSignsFeature().signManager().allSignLocations()) {
|
||||
signLocations.add(Message.fromKey("info-regionSignLocation")
|
||||
.replacements(location.getWorld().getName(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ())
|
||||
.getPlain());
|
||||
}
|
||||
if (!signLocations.isEmpty()) {
|
||||
messageBridge.messageNoPrefix(sender,
|
||||
"info-regionSigns",
|
||||
Utils.createCommaSeparatedList(signLocations));
|
||||
}
|
||||
}
|
||||
|
||||
private void displayTeleportInfo(@Nonnull CommandSender sender, @Nonnull GeneralRegion region) {
|
||||
// Teleport
|
||||
Message tp = Message.fromKey("info-prefix");
|
||||
boolean foundSomething = false;
|
||||
if (TeleportCommand.canUse(sender, region)) {
|
||||
foundSomething = true;
|
||||
tp.append(Message.fromKey("info-regionTeleport").replacements(region));
|
||||
}
|
||||
if (SetTeleportCommand.canUse(sender, region)) {
|
||||
if (foundSomething) {
|
||||
tp.append(", ");
|
||||
}
|
||||
foundSomething = true;
|
||||
tp.append(Message.fromKey("info-setRegionTeleport").replacements(region));
|
||||
}
|
||||
if (foundSomething) {
|
||||
tp.append(".");
|
||||
SimpleMessageBridge.send(tp, sender);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.SignProfileUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.SignLinkerManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class LinkSignsCommand extends AreashopCommandBean {
|
||||
|
||||
private final SignLinkerManager signLinkerManager;
|
||||
private final AreaShop plugin;
|
||||
|
||||
private final CommandFlag<String> profileFlag;
|
||||
|
||||
@Inject
|
||||
public LinkSignsCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull SignLinkerManager signLinkerManager,
|
||||
@Nonnull AreaShop plugin
|
||||
) {
|
||||
this.signLinkerManager = signLinkerManager;
|
||||
this.plugin = plugin;
|
||||
this.profileFlag = SignProfileUtil.createDefault(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("linksign")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.flag(this.profileFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("linksign");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.linksigns")) {
|
||||
return "help-linksigns";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("linksigns")) {
|
||||
throw new AreaShopCommandException("linksigns-noPermission");
|
||||
}
|
||||
if (signLinkerManager.isInSignLinkMode(player)) {
|
||||
signLinkerManager.exitSignLinkMode(player);
|
||||
return;
|
||||
}
|
||||
// Get the profile
|
||||
String profile = SignProfileUtil.getOrParseProfile(context, this.plugin);
|
||||
this.signLinkerManager.enterSignLinkMode(player, profile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionInfoUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class MeCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
private final IFileManager fileManager;
|
||||
private final MessageBridge messageBridge;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
|
||||
@Inject
|
||||
public MeCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
|
||||
@Nonnull BukkitSchedulerExecutor executor
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("me")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.optional(KEY_PLAYER, OfflinePlayerParser.parser())
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("me");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.me")) {
|
||||
return "help-me";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.me")) {
|
||||
throw new AreaShopCommandException("me-noPermission");
|
||||
}
|
||||
if (!context.contains(KEY_PLAYER)) {
|
||||
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, sender);
|
||||
return;
|
||||
}
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenCompleteAsync((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
RegionInfoUtil.showRegionInfo(this.messageBridge, this.fileManager, sender, offlinePlayer);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.tools.SimpleMessageBridge;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.bukkit.parser.PlayerParser;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class MessageCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Player> KEY_PLAYER = CloudKey.of("player", Player.class);
|
||||
private static final CloudKey<String> KEY_MESSAGE = CloudKey.of("message", String.class);
|
||||
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
// Internal command, no need to show in the help list
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("message")
|
||||
.required(KEY_PLAYER, PlayerParser.playerParser())
|
||||
.required(KEY_MESSAGE, StringParser.greedyStringParser())
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("message");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if(!sender.hasPermission("areashop.message")) {
|
||||
throw new AreaShopCommandException("message-noPermission");
|
||||
}
|
||||
Player player = context.get(KEY_PLAYER);
|
||||
String message = context.get(KEY_MESSAGE);
|
||||
Message m = Message.fromString(message);
|
||||
SimpleMessageBridge.send(m, player);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.ArgumentParseExceptionHandler;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionCreationUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.exception.CommandExecutionException;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.DoubleParser;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Singleton
|
||||
public class QuickBuyCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_REGION = CloudKey.of("region", String.class);
|
||||
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("price", Double.class);
|
||||
private static final CloudKey<String> KEY_LANDLORD = CloudKey.of("landlord", String.class);
|
||||
private final RegionFactory regionFactory;
|
||||
private final IFileManager fileManager;
|
||||
private final MessageBridge messageBridge;
|
||||
private final RegionCreationUtil regionCreationUtil;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
|
||||
@Inject
|
||||
public QuickBuyCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull RegionFactory regionFactory,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull RegionCreationUtil regionCreationUtil,
|
||||
@Nonnull BukkitSchedulerExecutor executor,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFactory = regionFactory;
|
||||
this.fileManager = fileManager;
|
||||
this.regionCreationUtil = regionCreationUtil;
|
||||
this.executor = executor;
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("quickbuy")
|
||||
.permission("permission")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION, StringParser.stringParser())
|
||||
.required(KEY_PRICE, DoubleParser.doubleParser(0))
|
||||
.required(KEY_LANDLORD, OfflinePlayerParser.parser())
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
// /as quickbuy <name> <price> <duration> <landlord>
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("areashop.quickbuy")) {
|
||||
player.sendMessage("Insufficient permission");
|
||||
return;
|
||||
}
|
||||
this.regionCreationUtil.createRegion(context, player, KEY_REGION)
|
||||
.exceptionally(throwable -> {
|
||||
if (throwable instanceof AreaShopCommandException exception) {
|
||||
ArgumentParseExceptionHandler.handleException(this.messageBridge, context.sender(), exception);
|
||||
} else {
|
||||
throw new CommandExecutionException(throwable, context);
|
||||
}
|
||||
return null;
|
||||
}).thenAcceptAsync(region -> {
|
||||
// Error handled previously
|
||||
if (region == null) {
|
||||
this.messageBridge.message(player, "quickadd-failedCreateWGRegion");
|
||||
return;
|
||||
}
|
||||
double price = context.get(KEY_PRICE);
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_LANDLORD))
|
||||
.whenCompleteAsync((landlord, exception) -> {
|
||||
if (exception != null) {
|
||||
player.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!landlord.isOnline() && !landlord.hasPlayedBefore()) {
|
||||
this.messageBridge.message(player, "me-noPlayer", landlord.getName());
|
||||
return;
|
||||
}
|
||||
String regionName = region.getId();
|
||||
World world = player.getWorld();
|
||||
|
||||
BuyRegion buyRegion = this.regionFactory.createBuyRegion(regionName, world);
|
||||
buyRegion.setPrice(price);
|
||||
buyRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
|
||||
this.fileManager.addRegion(buyRegion);
|
||||
this.messageBridge.message(player, "add-success", "buy", regionName);
|
||||
}, this.executor);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getHelpKey(@Nonnull CommandSender target) {
|
||||
if (target.hasPermission("areashop.quickbuy")) {
|
||||
return "help-quickbuy";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("quickbuy");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.description.Description;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Singleton
|
||||
public class QuickDeleteCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
|
||||
private static final CommandFlag<Void> FLAG_RETURN_MONEY = CommandFlag.builder("return-money")
|
||||
.withDescription(Description.of(
|
||||
"If this flag is present, money is returned to the player if someone is currently holding this region"))
|
||||
.build();
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final WorldGuardInterface worldGuardInterface;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public QuickDeleteCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull WorldGuardInterface worldGuardInterface
|
||||
) {
|
||||
this.fileManager = fileManager;
|
||||
this.worldGuardInterface = worldGuardInterface;
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("quickdelete", "quickdel")
|
||||
.permission("areashop.quickdelete")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
GeneralRegion region = context.get(KEY_REGION);
|
||||
boolean giveMoneyBack = context.flags().isPresent(FLAG_RETURN_MONEY);
|
||||
DeletingRegionEvent event = this.fileManager.deleteRegion(region, giveMoneyBack);
|
||||
if (event.isCancelled()) {
|
||||
throw new AreaShopCommandException("general-cancelled", event.getReason());
|
||||
}
|
||||
this.messageBridge.message(player, "destroy-successRent", region);
|
||||
RegionManager regionManager = this.worldGuardInterface.getRegionManager(region.getWorld());
|
||||
regionManager.removeRegion(region.getRegion().getId());
|
||||
this.messageBridge.message(player, "quickdelete-WGRegionDeleted", region.getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getHelpKey(@Nonnull CommandSender target) {
|
||||
return "help-quickdelete";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("quickdelete", "quickdel");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.ArgumentParseExceptionHandler;
|
||||
import me.wiefferink.areashop.commands.util.DurationInputParser;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionCreationUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import me.wiefferink.areashop.tools.DurationInput;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.exception.CommandExecutionException;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.DoubleParser;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Singleton
|
||||
public class QuickRentCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_REGION = CloudKey.of("region", String.class);
|
||||
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("price", Double.class);
|
||||
|
||||
private static final CloudKey<DurationInput> KEY_DURATION = CloudKey.of("duration", DurationInput.class);
|
||||
private static final CloudKey<String> KEY_LANDLORD = CloudKey.of("landlord", String.class);
|
||||
private final RegionFactory regionFactory;
|
||||
private final IFileManager fileManager;
|
||||
private final MessageBridge messageBridge;
|
||||
private final RegionCreationUtil regionCreationUtil;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
|
||||
@Inject
|
||||
public QuickRentCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull RegionFactory regionFactory,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull RegionCreationUtil regionCreationUtil,
|
||||
@Nonnull BukkitSchedulerExecutor executor,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFactory = regionFactory;
|
||||
this.fileManager = fileManager;
|
||||
this.regionCreationUtil = regionCreationUtil;
|
||||
this.executor = executor;
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("quickrent")
|
||||
.permission("permission")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION, StringParser.stringParser())
|
||||
.required(KEY_PRICE, DoubleParser.doubleParser(0))
|
||||
.required(KEY_DURATION, DurationInputParser.durationInputParser())
|
||||
.required(KEY_LANDLORD, OfflinePlayerParser.parser())
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
// /as quickrent <name> <price> <duration> <landlord>
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("areashop.quickrent")) {
|
||||
player.sendMessage("Insufficient permission");
|
||||
return;
|
||||
}
|
||||
this.regionCreationUtil.createRegion(context, player, KEY_REGION)
|
||||
.exceptionally(throwable -> {
|
||||
if (throwable instanceof AreaShopCommandException exception) {
|
||||
ArgumentParseExceptionHandler.handleException(this.messageBridge, context.sender(), exception);
|
||||
} else {
|
||||
throw new CommandExecutionException(throwable, context);
|
||||
}
|
||||
return null;
|
||||
}).thenAcceptAsync(region -> {
|
||||
// Error handled previously
|
||||
if (region == null) {
|
||||
this.messageBridge.message(player, "quickadd-failedCreateWGRegion");
|
||||
return;
|
||||
}
|
||||
double price = context.get(KEY_PRICE);
|
||||
DurationInput duration = context.get(KEY_DURATION);
|
||||
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_LANDLORD))
|
||||
.whenCompleteAsync((landlord, exception) -> {
|
||||
if (exception != null) {
|
||||
player.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!landlord.hasPlayedBefore() && !landlord.isOnline()) {
|
||||
this.messageBridge.message(player, "cmd-invalidPlayer", landlord.getName());
|
||||
return;
|
||||
}
|
||||
String regionName = region.getId();
|
||||
World world = player.getWorld();
|
||||
|
||||
RentRegion rentRegion = this.regionFactory.createRentRegion(regionName, world);
|
||||
rentRegion.setPrice(price);
|
||||
rentRegion.setLandlord(landlord.getUniqueId(), landlord.getName());
|
||||
rentRegion.setDuration(duration.toTinySpacedString());
|
||||
this.fileManager.addRegion(rentRegion);
|
||||
this.messageBridge.message(player, "add-success", "rent", regionName);
|
||||
}, this.executor);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getHelpKey(@Nonnull CommandSender target) {
|
||||
if (target.hasPermission("areashop.quickrent")) {
|
||||
return "help-quickrent";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("quickrent");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Commands
|
||||
|
||||
This module contains all AreaShop commands.
|
||||
AreaShop uses https://cloud.incendo.org/
|
||||
|
||||
* `util/AreashopCommandBean` is extended by all other classes, and implements some general functionality and defines which methods should be implemented.
|
||||
* Other classes implement specific sub-commands, supply their help messages and tab completion.
|
||||
* `util/AreashopCommands` class in handles all command registration
|
||||
@@ -0,0 +1,59 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.AreaShop;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class ReloadCommand extends AreashopCommandBean {
|
||||
private final AreaShop plugin;
|
||||
|
||||
@Inject
|
||||
public ReloadCommand(@Nonnull AreaShop plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("reload")
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("reload");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.reload")) {
|
||||
return "help-reload";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
if (!context.hasPermission("areashop.reload")) {
|
||||
throw new AreaShopCommandException("reload-noPermission");
|
||||
}
|
||||
this.plugin.reload(context.sender().sender());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class RentCommand extends AreashopCommandBean {
|
||||
|
||||
private final CommandFlag<RentRegion> rentRegionFlag;
|
||||
|
||||
@Inject
|
||||
public RentCommand(@Nonnull IFileManager fileManager) {
|
||||
this.rentRegionFlag = RegionParseUtil.createDefaultRent(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return "Allows you to rent a region";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if(target.hasPermission("areashop.rent")) {
|
||||
return "help-rent";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nonnull CommandProperties properties() {
|
||||
return CommandProperties.of("rent");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder
|
||||
.literal("rent")
|
||||
.flag(this.rentRegionFlag)
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
if (!context.hasPermission("areashop.rent")) {
|
||||
throw new AreaShopCommandException("rent-noPermission");
|
||||
}
|
||||
Player sender = context.sender().sender();
|
||||
RentRegion region = RegionParseUtil.getOrParseRentRegion(context, sender, this.rentRegionFlag);
|
||||
region.rent(sender);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.BuyRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.DoubleParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class ResellCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Double> KEY_PRICE = CloudKey.of("price", Double.class);
|
||||
private final CommandFlag<BuyRegion> regionFlag;
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public ResellCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
ParserDescriptor<CommandSource<?>, BuyRegion> regionParser = ParserDescriptor.of(
|
||||
new BuyRegionParser<>(fileManager, this::suggestBuyRegions),
|
||||
BuyRegion.class
|
||||
);
|
||||
this.regionFlag = CommandFlag.<CommandSource<?>>builder("region").withComponent(regionParser).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(@Nonnull Command.Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("resell")
|
||||
.required(KEY_PRICE, DoubleParser.doubleParser(0))
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("resell");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.resellall") || target.hasPermission("areashop.resell")) {
|
||||
return "help-resell";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.resell") && !sender.hasPermission("areashop.resellall")) {
|
||||
messageBridge.message(sender, "resell-noPermissionOther");
|
||||
return;
|
||||
}
|
||||
double price = context.get(KEY_PRICE);
|
||||
BuyRegion buy = RegionParseUtil.getOrParseBuyRegion(context, sender, this.regionFlag);
|
||||
if (!buy.isSold()) {
|
||||
messageBridge.message(sender, "resell-notBought", buy);
|
||||
return;
|
||||
}
|
||||
if (sender.hasPermission("areashop.resellall")) {
|
||||
buy.enableReselling(price);
|
||||
buy.update();
|
||||
messageBridge.message(sender, "resell-success", buy);
|
||||
} else if (sender.hasPermission("areashop.resell") && sender instanceof Player player) {
|
||||
if (!buy.isOwner(player)) {
|
||||
messageBridge.message(sender, "resell-noPermissionOther", buy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buy.getBooleanSetting("buy.resellDisabled")) {
|
||||
messageBridge.message(sender, "resell-disabled", buy);
|
||||
return;
|
||||
}
|
||||
|
||||
buy.enableReselling(price);
|
||||
buy.update();
|
||||
messageBridge.message(sender, "resell-success", buy);
|
||||
} else {
|
||||
messageBridge.message(sender, "resell-noPermission", buy);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestBuyRegions(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getBuysRef().stream()
|
||||
.filter(region -> region.isSold() && !region.isInResellingMode())
|
||||
.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SchematicEventCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
private static final CloudKey<GeneralRegion.RegionEvent> KEY_EVENT_TYPE = CloudKey.of("eventType",
|
||||
GeneralRegion.RegionEvent.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public SchematicEventCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("schemevent")
|
||||
.required(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.required(KEY_EVENT_TYPE, EnumParser.enumParser(GeneralRegion.RegionEvent.class))
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("schemevent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.schematicevents")) {
|
||||
return "help-schemevent";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.schematicevents")) {
|
||||
throw new AreaShopCommandException("schemevent-noPermission");
|
||||
}
|
||||
|
||||
GeneralRegion region = context.get(KEY_REGION);
|
||||
GeneralRegion.RegionEvent event = context.get(KEY_EVENT_TYPE);
|
||||
if (region.getRegion() == null) {
|
||||
throw new AreaShopCommandException("general-noRegion", region);
|
||||
}
|
||||
region.handleSchematicEvent(event);
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "schemevent-success", event.getValue(), region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.BuyRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class SellCommand extends AreashopCommandBean {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
private final CommandFlag<BuyRegion> buyRegionFlag;
|
||||
|
||||
@Inject
|
||||
public SellCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
ParserDescriptor<CommandSource<?>, BuyRegion> regionParser =
|
||||
ParserDescriptor.of(new BuyRegionParser<>(fileManager, this::suggestBuyRegions), BuyRegion.class);
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.buyRegionFlag = CommandFlag.<CommandSource<?>>builder("region").withComponent(regionParser).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a person can sell the region.
|
||||
*
|
||||
* @param person The person to check
|
||||
* @param region The region to check for
|
||||
* @return true if the person can sell it, otherwise false
|
||||
*/
|
||||
public static boolean canUse(CommandSender person, GeneralRegion region) {
|
||||
if (person.hasPermission("areashop.sell")) {
|
||||
return true;
|
||||
}
|
||||
if (person instanceof Player player) {
|
||||
return region.isOwner(player) && person.hasPermission("areashop.sellown");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("sell")
|
||||
.flag(this.buyRegionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("sell");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.sell") || target.hasPermission("areashop.sellown")) {
|
||||
return "help-sell";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.sell") && !sender.hasPermission("areashop.sellown")) {
|
||||
this.messageBridge.message(sender, "sell-noPermission");
|
||||
return;
|
||||
}
|
||||
BuyRegion buy = RegionParseUtil.getOrParseBuyRegion(context, sender, this.buyRegionFlag);
|
||||
if (!buy.isSold()) {
|
||||
messageBridge.message(sender, "sell-notBought", buy);
|
||||
return;
|
||||
}
|
||||
buy.sell(true, sender);
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestBuyRegions(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getBuysRef().stream()
|
||||
.filter(BuyRegion::isSold)
|
||||
.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.DurationInput;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class SetDurationCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_DURATION = CloudKey.of("duration", String.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<RentRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public SetDurationCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefaultRent(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setduration")) {
|
||||
return "help-setduration";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setduration")
|
||||
.required(KEY_DURATION, StringParser.stringParser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setduration");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setduration") && (!sender.hasPermission("areashop.setduration.landlord") && sender instanceof Player)) {
|
||||
this.messageBridge.message(sender, "setduration-noPermission");
|
||||
return;
|
||||
}
|
||||
RentRegion rent = RegionParseUtil.getOrParseRentRegion(context, sender, this.regionFlag);
|
||||
if (!sender.hasPermission("areashop.setduration")
|
||||
&& !(sender instanceof Player player
|
||||
&& rent.isLandlord(player.getUniqueId()))
|
||||
) {
|
||||
this.messageBridge.message(sender, "setduration-noLandlord", rent);
|
||||
return;
|
||||
}
|
||||
String rawDuration = context.get(KEY_DURATION);
|
||||
if ("default".equalsIgnoreCase(rawDuration) || "reset".equalsIgnoreCase(rawDuration)) {
|
||||
rent.setDuration(null);
|
||||
rent.update();
|
||||
this.messageBridge.message(sender, "setduration-successRemoved", rent);
|
||||
return;
|
||||
}
|
||||
DurationInput duration = parseInternalDuration(rawDuration);
|
||||
sender.sendMessage(duration.toTinySpacedString());
|
||||
rent.setDuration(duration.toTinySpacedString());
|
||||
rent.update();
|
||||
this.messageBridge.message(sender, "setduration-success", rent);
|
||||
}
|
||||
|
||||
private DurationInput parseInternalDuration(String rawDuration) {
|
||||
int start = 0;
|
||||
for (int i = 0; i < rawDuration.length(); i++) {
|
||||
if (Character.isAlphabetic(rawDuration.charAt(i))) {
|
||||
start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start == 0) {
|
||||
throw new AreaShopCommandException("setduration-wrongFormat", rawDuration);
|
||||
}
|
||||
String duration = rawDuration.substring(0, start);
|
||||
String durationUnit = rawDuration.substring(start);
|
||||
int durationInt;
|
||||
try {
|
||||
durationInt = Integer.parseInt(duration);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new AreaShopCommandException("setduration-wrongAmount", duration);
|
||||
}
|
||||
TimeUnit timeUnit = DurationInput.getTimeUnit(durationUnit)
|
||||
.orElseThrow(() -> new AreaShopCommandException("setduration-wrongFormat", durationUnit));
|
||||
|
||||
boolean invalid = !switch (timeUnit) {
|
||||
case DAYS, HOURS, MINUTES, SECONDS -> true;
|
||||
default -> false;
|
||||
};
|
||||
if (invalid) {
|
||||
throw new AreaShopCommandException("setduration-wrongFormat", durationUnit);
|
||||
}
|
||||
return new DurationInput(durationInt, timeUnit);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetLandlordCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
|
||||
@Inject
|
||||
public SetLandlordCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
|
||||
@Nonnull BukkitSchedulerExecutor executor
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setlandlord")) {
|
||||
return "help-setlandlord";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setlandlord")
|
||||
.required(KEY_PLAYER, OfflinePlayerParser.parser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setlandlord");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setlandlord")) {
|
||||
throw new AreaShopCommandException("setlandlord-noPermission");
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenCompleteAsync((landlord, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!landlord.hasPlayedBefore() && !landlord.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", landlord.getName());
|
||||
return;
|
||||
}
|
||||
String playerName = landlord.getName();
|
||||
region.setLandlord(landlord.getUniqueId(), playerName);
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "setlandlord-success", playerName, region);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetMaxExtends extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Integer> KEY_EXTENDS = CloudKey.of("extends", Integer.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<RentRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public SetMaxExtends(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefaultRent(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setmaxextends")) {
|
||||
return "help-setmaxextends";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setmaxextends")
|
||||
.required(KEY_EXTENDS, IntegerParser.integerParser(0))
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setmaxextends");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setmaxextends") && (!sender.hasPermission("areashop.setmaxextends.landlord") && sender instanceof Player)) {
|
||||
this.messageBridge.message(sender, "setmaxextends-noPermission");
|
||||
return;
|
||||
}
|
||||
RentRegion rent = RegionParseUtil.getOrParseRentRegion(context, sender, this.regionFlag);
|
||||
if (!sender.hasPermission("areashop.setmaxextends")
|
||||
&& !(sender instanceof Player player
|
||||
&& rent.isLandlord(player.getUniqueId()))
|
||||
) {
|
||||
this.messageBridge.message(sender, "setmaxextends-noLandlord", rent);
|
||||
return;
|
||||
}
|
||||
int extend = context.get(KEY_EXTENDS);
|
||||
|
||||
sender.sendMessage();
|
||||
rent.setMaxExtends(extend);
|
||||
rent.update();
|
||||
this.messageBridge.message(sender, "setmaxextends-success", rent);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
|
||||
@Singleton
|
||||
public class SetOwnerCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
private final BukkitSchedulerExecutor executor;
|
||||
|
||||
@Inject
|
||||
public SetOwnerCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper,
|
||||
@Nonnull BukkitSchedulerExecutor executor
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setownerrent") || target.hasPermission("areashop.setownerbuy")) {
|
||||
return "help-setowner";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setowner")
|
||||
.required(KEY_PLAYER, OfflinePlayerParser.parser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setowner");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setownerrent") && !sender.hasPermission("areashop.setownerbuy")) {
|
||||
this.messageBridge.message(sender, "setowner-noPermission");
|
||||
return;
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
if (region instanceof RentRegion && !sender.hasPermission("areashop.setownerrent")) {
|
||||
this.messageBridge.message(sender, "setowner-noPermissionRent", region);
|
||||
return;
|
||||
}
|
||||
if (region instanceof BuyRegion && !sender.hasPermission("areashop.setownerbuy")) {
|
||||
this.messageBridge.message(sender, "setowner-noPermissionBuy", region);
|
||||
return;
|
||||
}
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenCompleteAsync((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
setOwner(sender, offlinePlayer, region);
|
||||
}, this.executor);
|
||||
}
|
||||
|
||||
private void setOwner(@Nonnull CommandSender sender, @Nonnull OfflinePlayer player, GeneralRegion region) {
|
||||
final UUID uuid = player.getUniqueId();
|
||||
if (region instanceof RentRegion rent) {
|
||||
if (rent.isRenter(uuid)) {
|
||||
// extend
|
||||
rent.setRentedUntil(rent.getRentedUntil() + rent.getDuration());
|
||||
rent.setRenter(uuid);
|
||||
this.messageBridge.message(sender, "setowner-succesRentExtend", region);
|
||||
} else {
|
||||
// change
|
||||
if (!rent.isRented()) {
|
||||
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
|
||||
}
|
||||
rent.setRenter(uuid);
|
||||
this.messageBridge.message(sender, "setowner-succesRent", region);
|
||||
}
|
||||
} else if (region instanceof BuyRegion buy) {
|
||||
buy.setBuyer(uuid);
|
||||
this.messageBridge.message(sender, "setowner-succesBuy", region);
|
||||
}
|
||||
region.getFriendsFeature().deleteFriend(region.getOwner(), null);
|
||||
region.update();
|
||||
region.saveRequired();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetPriceCommand extends AreashopCommandBean {
|
||||
|
||||
|
||||
private static final CloudKey<String> KEY_PRICE = CloudKey.of("price", String.class);
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public SetPriceCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.setprice")) {
|
||||
return "help-setprice";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setprice")
|
||||
.required(KEY_PRICE, StringParser.stringParser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setprice");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setprice") && (!sender.hasPermission("areashop.setprice.landlord") && sender instanceof Player)) {
|
||||
this.messageBridge.message(sender, "setprice-noPermission");
|
||||
return;
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
if (!sender.hasPermission("areashop.setprice")
|
||||
&& !(sender instanceof Player player && region.isLandlord(player.getUniqueId()))) {
|
||||
this.messageBridge.message(sender, "setprice-noLandlord", region);
|
||||
return;
|
||||
}
|
||||
String rawPrice = context.get(KEY_PRICE);
|
||||
if ("default".equalsIgnoreCase(rawPrice) || "reset".equalsIgnoreCase(rawPrice)) {
|
||||
if (region instanceof RentRegion rentRegion) {
|
||||
rentRegion.setPrice(null);
|
||||
} else if (region instanceof BuyRegion buyRegion) {
|
||||
buyRegion.setPrice(null);
|
||||
}
|
||||
region.update();
|
||||
this.messageBridge.message(sender, "setprice-successRemoved", region);
|
||||
return;
|
||||
}
|
||||
double price;
|
||||
try {
|
||||
price = Double.parseDouble(rawPrice);
|
||||
} catch (NumberFormatException e) {
|
||||
this.messageBridge.message(sender, "setprice-wrongPrice", rawPrice, region);
|
||||
return;
|
||||
}
|
||||
if (region instanceof RentRegion rentRegion) {
|
||||
rentRegion.setPrice(price);
|
||||
this.messageBridge.message(sender, "setprice-successRent", region);
|
||||
} else if (region instanceof BuyRegion buyRegion) {
|
||||
buyRegion.setPrice(price);
|
||||
this.messageBridge.message(sender, "setprice-successBuy", region);
|
||||
}
|
||||
region.update();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class SetRestoreCommand extends AreashopCommandBean {
|
||||
|
||||
private static final List<String> RESTORE_TYPES = List.of("true", "false", "general");
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
private static final CloudKey<String> KEY_RESTORE = CloudKey.of("restore", String.class);
|
||||
|
||||
private static final CloudKey<String> KEY_PROFILE = CloudKey.of("profile", String.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public SetRestoreCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setrestore")) {
|
||||
return "help-setrestore";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("setrestore")
|
||||
.required(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.required(KEY_RESTORE, StringParser.stringParser(), this::suggestRestoreType)
|
||||
.optional(KEY_PROFILE, StringParser.stringParser(), this::suggestSchematicProfiles)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("setrestore");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.setrestore")) {
|
||||
throw new AreaShopCommandException("setrestore-noPermission");
|
||||
}
|
||||
GeneralRegion region = context.get(KEY_REGION);
|
||||
String restoreType = context.get(KEY_RESTORE);
|
||||
Optional<String> optionalProfile = context.optional(KEY_PROFILE);
|
||||
Boolean value = null;
|
||||
if (restoreType.equalsIgnoreCase("true")) {
|
||||
value = true;
|
||||
} else if (restoreType.equalsIgnoreCase("false")) {
|
||||
value = false;
|
||||
}
|
||||
region.setRestoreSetting(value);
|
||||
String valueString = "general";
|
||||
if (value != null) {
|
||||
valueString = value + "";
|
||||
}
|
||||
if (optionalProfile.isPresent()) {
|
||||
String profile = optionalProfile.get();
|
||||
region.setSchematicProfile(profile);
|
||||
this.messageBridge.message(sender, "setrestore-successProfile", valueString, profile, region);
|
||||
} else {
|
||||
this.messageBridge.message(sender, "setrestore-success", valueString, region);
|
||||
}
|
||||
region.update();
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestRestoreType(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = RESTORE_TYPES.stream()
|
||||
.filter(type -> type.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestSchematicProfiles(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
ConfigurationSection schemProfiles = fileManager.getConfig().getConfigurationSection("schematicProfiles");
|
||||
if (schemProfiles == null) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = schemProfiles.getKeys(false).stream()
|
||||
.filter(profile -> profile.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetTeleportCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CommandFlag<Void> FLAG_RESET = CommandFlag.builder("reset").build();
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
@Inject
|
||||
public SetTeleportCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a person can set the teleport location of the region.
|
||||
*
|
||||
* @param person The person to check
|
||||
* @param region The region to check for
|
||||
* @return true if the person can set the teleport location, otherwise false
|
||||
*/
|
||||
public static boolean canUse(CommandSender person, GeneralRegion region) {
|
||||
if (!(person instanceof Player player)) {
|
||||
return false;
|
||||
}
|
||||
return player.hasPermission("areashop.setteleportall")
|
||||
|| region.isOwner(player) && player.hasPermission("areashop.setteleport");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.setteleportall") || target.hasPermission("areashop.setteleport")) {
|
||||
return "help-setteleport";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("settp")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("settp");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("areashop.setteleport") && !player.hasPermission("areashop.setteleportall")) {
|
||||
this.messageBridge.message(player, "setteleport-noPermission");
|
||||
return;
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, player, this.regionFlag);
|
||||
|
||||
boolean owner;
|
||||
if (region instanceof RentRegion rentRegion) {
|
||||
owner = player.getUniqueId().equals(rentRegion.getRenter());
|
||||
} else if (region instanceof BuyRegion buyRegion) {
|
||||
owner = player.getUniqueId().equals(buyRegion.getBuyer());
|
||||
} else {
|
||||
// FIXME log error
|
||||
return;
|
||||
}
|
||||
if (!player.hasPermission("areashop.setteleport")) {
|
||||
throw new AreaShopCommandException("setteleport-noPermission", region);
|
||||
} else if (!owner && !player.hasPermission("areashop.setteleportall")) {
|
||||
throw new AreaShopCommandException("setteleport-noPermissionOther", region);
|
||||
}
|
||||
boolean reset = context.flags().contains(FLAG_RESET);
|
||||
if (reset) {
|
||||
region.getTeleportFeature().setTeleport(null);
|
||||
region.update();
|
||||
this.messageBridge.message(player, "setteleport-reset", region);
|
||||
}
|
||||
ProtectedRegion wgRegion = region.getRegion();
|
||||
Location location = player.getLocation();
|
||||
if (!player.hasPermission("areashop.setteleportoutsideregion") && (wgRegion == null || !wgRegion.contains(
|
||||
location.getBlockX(),
|
||||
location.getBlockY(),
|
||||
location.getBlockZ()))
|
||||
) {
|
||||
this.messageBridge.message(player, "setteleport-notInside", region);
|
||||
return;
|
||||
}
|
||||
region.getTeleportFeature().setTeleport(location);
|
||||
region.update();
|
||||
this.messageBridge.message(player, "setteleport-success", region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.BooleanParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class SetTransferCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Boolean> KEY_ENABLED = CloudKey.of("enabled", Boolean.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public SetTransferCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.regionFlag = RegionParseUtil.createDefault(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.settransfer")) {
|
||||
return "help-settransfer";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("settransfer")
|
||||
.required(KEY_ENABLED, BooleanParser.booleanParser(true))
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("settransfer");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.settransfer")) {
|
||||
throw new AreaShopCommandException("settransfer-noPermission");
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
boolean enabled = context.get(KEY_ENABLED);
|
||||
region.setTransferEnabled(enabled);
|
||||
messageBridge.message(sender, "settransfer-success", enabled, region);
|
||||
region.update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditSelection;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RegionFactory;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import me.wiefferink.interactivemessenger.processing.Message;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class StackCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<Integer> KEY_AMOUNT = CloudKey.of("amount", Integer.class);
|
||||
private static final CloudKey<Integer> KEY_GAP = CloudKey.of("gap", Integer.class);
|
||||
private static final CloudKey<String> KEY_NAME = CloudKey.of("name", String.class);
|
||||
private static final CloudKey<GeneralRegion.RegionType> KEY_TYPE = CloudKey.of("type",
|
||||
GeneralRegion.RegionType.class);
|
||||
private static final CommandFlag<String> FLAG_GROUP = CommandFlag.builder("group")
|
||||
.withComponent(StringParser.stringParser())
|
||||
.build();
|
||||
private final MessageBridge messageBridge;
|
||||
private final Plugin plugin;
|
||||
private final WorldEditInterface worldEditInterface;
|
||||
private final WorldGuardInterface worldGuardInterface;
|
||||
private final RegionFactory regionFactory;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public StackCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull Plugin plugin,
|
||||
@Nonnull WorldEditInterface worldEditInterface,
|
||||
@Nonnull WorldGuardInterface worldGuardInterface,
|
||||
@Nonnull RegionFactory regionFactory,
|
||||
@Nonnull IFileManager fileManager
|
||||
|
||||
) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.plugin = plugin;
|
||||
this.worldEditInterface = worldEditInterface;
|
||||
this.worldGuardInterface = worldGuardInterface;
|
||||
this.regionFactory = regionFactory;
|
||||
this.fileManager = fileManager;
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Vector calculateShift(BlockFace facing, WorldEditSelection selection, int gap) {
|
||||
Vector shift = new Vector(0, 0, 0);
|
||||
if (facing == BlockFace.SOUTH) {
|
||||
shift = shift.setZ(-selection.getLength() - gap);
|
||||
} else if (facing == BlockFace.WEST) {
|
||||
shift = shift.setX(selection.getWidth() + gap);
|
||||
} else if (facing == BlockFace.NORTH) {
|
||||
shift = shift.setZ(selection.getLength() + gap);
|
||||
} else if (facing == BlockFace.EAST) {
|
||||
shift = shift.setX(-selection.getWidth() - gap);
|
||||
} else if (facing == BlockFace.DOWN) {
|
||||
shift = shift.setY(-selection.getHeight() - gap);
|
||||
} else if (facing == BlockFace.UP) {
|
||||
shift = shift.setY(selection.getHeight() + gap);
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.stack")) {
|
||||
return "help-stack";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("stack")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_AMOUNT, IntegerParser.integerParser(0))
|
||||
.required(KEY_GAP, IntegerParser.integerParser(0))
|
||||
.required(KEY_NAME, StringParser.stringParser())
|
||||
.required(KEY_TYPE, EnumParser.enumParser(GeneralRegion.RegionType.class))
|
||||
.flag(FLAG_GROUP)
|
||||
.handler(this::handleCommand);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("stack");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("areashop.stack")) {
|
||||
throw new AreaShopCommandException("stack-noPermission");
|
||||
}
|
||||
int amount = context.get(KEY_AMOUNT);
|
||||
int gap = context.get(KEY_GAP);
|
||||
String name = context.get(KEY_NAME);
|
||||
GeneralRegion.RegionType regionType = context.get(KEY_TYPE);
|
||||
Optional<String> optionalGroup = context.flags().getValue(FLAG_GROUP);
|
||||
// Get WorldEdit selection
|
||||
final WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
|
||||
if (selection == null) {
|
||||
this.messageBridge.message(player, "stack-noSelection");
|
||||
return;
|
||||
}
|
||||
// Get or create group
|
||||
RegionGroup group = null;
|
||||
if (optionalGroup.isPresent()) {
|
||||
String groupName = optionalGroup.get();
|
||||
group = fileManager.getGroup(groupName);
|
||||
if (group == null) {
|
||||
group = regionFactory.createRegionGroup(groupName);
|
||||
fileManager.addGroup(group);
|
||||
}
|
||||
}
|
||||
// Get facing of the player (must be clearly one of the four directions to make sure it is no mistake)
|
||||
BlockFace facing = Utils.yawToFacing(player.getLocation().getYaw());
|
||||
if (player.getLocation().getPitch() > 45) {
|
||||
facing = BlockFace.DOWN;
|
||||
} else if (player.getLocation().getPitch() < -45) {
|
||||
facing = BlockFace.UP;
|
||||
}
|
||||
if (!(facing == BlockFace.NORTH || facing == BlockFace.EAST || facing == BlockFace.SOUTH || facing == BlockFace.WEST || facing == BlockFace.UP || facing == BlockFace.DOWN)) {
|
||||
this.messageBridge.message(player,
|
||||
"stack-unclearDirection",
|
||||
facing.toString().toLowerCase().replace('_', '-'));
|
||||
return;
|
||||
}
|
||||
Vector shift = calculateShift(facing, selection, gap);
|
||||
BukkitRunnable task = stackTask(player, name, amount, selection, regionType, shift, group);
|
||||
task.runTaskTimer(plugin, 1, 1);
|
||||
}
|
||||
|
||||
private BukkitRunnable stackTask(
|
||||
@Nonnull Player player,
|
||||
@Nonnull String name,
|
||||
int amount,
|
||||
@Nonnull WorldEditSelection selection,
|
||||
GeneralRegion.RegionType regionType,
|
||||
@Nonnull Vector shift,
|
||||
@Nullable RegionGroup group
|
||||
) {
|
||||
final int regionsPerTick = plugin.getConfig().getInt("adding.regionsPerTick");
|
||||
|
||||
Location minimumLocation = selection.getMinimumLocation();
|
||||
Vector minimumVector = new Vector(minimumLocation.getX(), minimumLocation.getY(), minimumLocation.getZ());
|
||||
Location maximumLocation = selection.getMaximumLocation();
|
||||
Vector maximumVector = new Vector(maximumLocation.getX(), maximumLocation.getY(), maximumLocation.getZ());
|
||||
return new BukkitRunnable() {
|
||||
private final RegionManager manager = worldGuardInterface.getRegionManager(selection.getWorld());
|
||||
private int current = -1;
|
||||
private int counter = 1;
|
||||
private int tooLow = 0;
|
||||
private int tooHigh = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < regionsPerTick; i++) {
|
||||
current++;
|
||||
if (current >= amount) {
|
||||
continue;
|
||||
}
|
||||
// Create the region name
|
||||
String regionName = countToName(name, counter);
|
||||
while (manager.getRegion(regionName) != null || fileManager.getRegion(regionName) != null) {
|
||||
counter++;
|
||||
regionName = countToName(name, counter);
|
||||
}
|
||||
|
||||
// Add the region to WorldGuard (at startposition shifted by the number of this region times the blocks it should shift)
|
||||
Vector minimum = minimumVector.clone().add(shift.clone().multiply(current));
|
||||
Vector maximum = maximumVector.clone().add(shift.clone().multiply(current));
|
||||
|
||||
// Check for out of bounds
|
||||
if (minimum.getBlockY() < 0) {
|
||||
tooLow++;
|
||||
continue;
|
||||
} else if (maximum.getBlockY() > 256) {
|
||||
tooHigh++;
|
||||
continue;
|
||||
}
|
||||
ProtectedCuboidRegion region = worldGuardInterface.createCuboidRegion(regionName, minimum, maximum);
|
||||
manager.addRegion(region);
|
||||
|
||||
// Add the region to AreaShop
|
||||
GeneralRegion newRegion;
|
||||
if (regionType == GeneralRegion.RegionType.BUY) {
|
||||
newRegion = regionFactory.createRentRegion(regionName, selection.getWorld());
|
||||
} else {
|
||||
newRegion = regionFactory.createBuyRegion(regionName, selection.getWorld());
|
||||
}
|
||||
|
||||
if (group != null) {
|
||||
group.addMember(newRegion);
|
||||
}
|
||||
AddingRegionEvent event = fileManager.addRegion(newRegion);
|
||||
if (event.isCancelled()) {
|
||||
messageBridge.message(player, "general-cancelled", event.getReason());
|
||||
continue;
|
||||
}
|
||||
newRegion.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
|
||||
newRegion.update();
|
||||
}
|
||||
if (current >= amount) {
|
||||
if (player.isOnline()) {
|
||||
int added = amount - tooLow - tooHigh;
|
||||
Message wrong = Message.empty();
|
||||
if (tooHigh > 0) {
|
||||
wrong.append(Message.fromKey("stack-tooHigh").replacements(tooHigh));
|
||||
}
|
||||
if (tooLow > 0) {
|
||||
wrong.append(Message.fromKey("stack-tooLow").replacements(tooLow));
|
||||
}
|
||||
messageBridge.message(player, "stack-addComplete", added, wrong);
|
||||
}
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a name from a count, with the right length.
|
||||
*
|
||||
* @param template Template to put the name in (# to put the count there, otherwise count is appended)
|
||||
* @param count Number to use
|
||||
* @return name with prepended 0's
|
||||
*/
|
||||
private String countToName(String template, int count) {
|
||||
StringBuilder counterName = new StringBuilder().append(count);
|
||||
int minimumLength = plugin.getConfig().getInt("stackRegionNumberLength");
|
||||
while (counterName.length() < minimumLength) {
|
||||
counterName.insert(0, "0");
|
||||
}
|
||||
|
||||
if (template.contains("#")) {
|
||||
return template.replace("#", counterName);
|
||||
} else {
|
||||
return template + counterName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.BuyRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class StopResellCommand extends AreashopCommandBean {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
|
||||
private final CommandFlag<BuyRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public StopResellCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
ParserDescriptor<CommandSource<?>, BuyRegion> regionParser =
|
||||
ParserDescriptor.of(new BuyRegionParser<>(fileManager, this::suggestBuyRegions), BuyRegion.class);
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.regionFlag = CommandFlag.<CommandSource<?>>builder("region")
|
||||
.withComponent(regionParser)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.stopresellall") || target.hasPermission("areashop.stopresell")) {
|
||||
return "help-stopResell";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("stopresell")
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("stopresell");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.stopresell") && !sender.hasPermission("areashop.stopresellall")) {
|
||||
this.messageBridge.message(sender, "stopresell-noPermissionOther");
|
||||
return;
|
||||
}
|
||||
|
||||
BuyRegion buy = RegionParseUtil.getOrParseBuyRegion(context, sender, this.regionFlag);
|
||||
if (!buy.isInResellingMode()) {
|
||||
this.messageBridge.message(sender, "stopresell-notResell", buy);
|
||||
return;
|
||||
}
|
||||
if (sender.hasPermission("areashop.stopresellall")) {
|
||||
buy.disableReselling();
|
||||
buy.update();
|
||||
this.messageBridge.message(sender, "stopresell-success", buy);
|
||||
} else if (sender.hasPermission("areashop.stopresell") && sender instanceof Player player) {
|
||||
if (buy.isOwner(player)) {
|
||||
buy.disableReselling();
|
||||
buy.update();
|
||||
this.messageBridge.message(sender, "stopresell-success", buy);
|
||||
} else {
|
||||
this.messageBridge.message(sender, "stopresell-noPermissionOther", buy);
|
||||
}
|
||||
} else {
|
||||
this.messageBridge.message(sender, "stopresell-noPermission", buy);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestBuyRegions(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getBuysRef().stream()
|
||||
.filter(region -> region.isSold() && region.isInResellingMode())
|
||||
.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Singleton
|
||||
public class TeleportCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<GeneralRegion> KEY_REGION = CloudKey.of("region", GeneralRegion.class);
|
||||
private static final CommandFlag<Void> KEY_TO_SIGN = CommandFlag.builder("to-sign").build();
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
private final IFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
public TeleportCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a person can teleport to the region (assuming he is not teleporting to a sign).
|
||||
*
|
||||
* @param person The person to check
|
||||
* @param region The region to check for
|
||||
* @return true if the person can teleport to it, otherwise false
|
||||
*/
|
||||
public static boolean canUse(CommandSender person, GeneralRegion region) {
|
||||
if (!(person instanceof Player player)) {
|
||||
return false;
|
||||
}
|
||||
return player.hasPermission("areashop.teleportall")
|
||||
|| region.isOwner(player) && player.hasPermission("areashop.teleport")
|
||||
|| region.isAvailable() && player.hasPermission("areashop.teleportavailable")
|
||||
|| region.getFriendsFeature().getFriends().contains(player.getUniqueId()) && player.hasPermission(
|
||||
"areashop.teleportfriend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (target.hasPermission("areashop.teleportall") || target.hasPermission("areashop.teleport")) {
|
||||
return "help-teleport";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("tp", "teleport")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_REGION, GeneralRegionParser.generalRegionParser(this.fileManager))
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("teleport", "tp");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player player = context.sender().sender();
|
||||
if (!player.hasPermission("areashop.teleport") && !player.hasPermission("areashop.teleportall") && !player.hasPermission(
|
||||
"areashop.teleportavailable") && !player.hasPermission("areashop.teleportavailablesign") && !player.hasPermission(
|
||||
"areashop.teleportsign") && !player.hasPermission("areashop.teleportsignall") && !player.hasPermission(
|
||||
"areashop.teleportfriend") && !player.hasPermission("teleportfriendsign")) {
|
||||
this.messageBridge.message(player, "teleport-noPermission");
|
||||
return;
|
||||
}
|
||||
GeneralRegion region = context.get(KEY_REGION);
|
||||
boolean toSign = context.flags().contains(KEY_TO_SIGN);
|
||||
region.getTeleportFeature().teleportPlayer(player, toSign);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.features.homeaccess.HomeAccessFeature;
|
||||
import me.wiefferink.areashop.features.homeaccess.HomeAccessType;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.component.CommandComponent;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.description.Description;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.EnumParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Singleton
|
||||
public final class ToggleHomeCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<HomeAccessType> KEY_ACCESS_TYPE = CloudKey.of("accessType", HomeAccessType.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public ToggleHomeCommand(@Nonnull MessageBridge messageBridge, @Nonnull IFileManager fileManager) {
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.regionFlag = CommandFlag.<CommandSource<?>>builder("region")
|
||||
.withComponent(
|
||||
CommandComponent.<CommandSource<?>, GeneralRegion>builder()
|
||||
.name("region")
|
||||
.description(Description.EMPTY)
|
||||
.valueType(GeneralRegion.class)
|
||||
.parser(GeneralRegionParser.generalRegionParser(fileManager))
|
||||
.suggestionProvider(this::suggestRegions)
|
||||
.build()
|
||||
).build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (!target.hasPermission("sethomecontrol.control")) {
|
||||
return null;
|
||||
}
|
||||
return "help-togglehome";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("togglehome")
|
||||
.required(KEY_ACCESS_TYPE, EnumParser.enumParser(HomeAccessType.class))
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("togglehome");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.togglehome")) {
|
||||
throw new AreaShopCommandException("togglehome-noPermission");
|
||||
}
|
||||
final HomeAccessType accessType = context.get(KEY_ACCESS_TYPE);
|
||||
final GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
if (!(sender instanceof Player) && !sender.hasPermission("sethome.control.other")) {
|
||||
return;
|
||||
}
|
||||
if (sender instanceof Player player && !region.isOwner(player)) {
|
||||
throw new AreaShopCommandException("togglehome-noPermission");
|
||||
}
|
||||
region.getOrCreateFeature(HomeAccessFeature.class).homeAccessType(accessType);
|
||||
this.messageBridge.message(sender, "togglehome-success", accessType.name());
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestRegions(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
CommandSender sender = context.sender().sender();
|
||||
Stream<GeneralRegion> regions;
|
||||
if (sender.hasPermission("sethome.control.other")) {
|
||||
regions = this.fileManager.getRegionsRef().stream();
|
||||
} else if (!sender.hasPermission("sethome.control.other") && sender instanceof Player player) {
|
||||
regions = this.fileManager.getRegionsRef().stream()
|
||||
.filter(region -> region.isOwner(player.getUniqueId()));
|
||||
} else {
|
||||
regions = Stream.empty();
|
||||
}
|
||||
List<Suggestion> suggestions = regions.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.GeneralRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.OfflinePlayerParser;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class TransferCommand extends AreashopCommandBean {
|
||||
|
||||
private static final CloudKey<String> KEY_PLAYER = CloudKey.of("player", String.class);
|
||||
private final MessageBridge messageBridge;
|
||||
private final IFileManager fileManager;
|
||||
private final CommandFlag<GeneralRegion> regionFlag;
|
||||
private final OfflinePlayerHelper offlinePlayerHelper;
|
||||
|
||||
@Inject
|
||||
public TransferCommand(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull OfflinePlayerHelper offlinePlayerHelper
|
||||
) {
|
||||
ParserDescriptor<PlayerCommandSource, GeneralRegion> regionParser =
|
||||
ParserDescriptor.of(new GeneralRegionParser<>(fileManager, this::suggestRegions), GeneralRegion.class);
|
||||
this.messageBridge = messageBridge;
|
||||
this.fileManager = fileManager;
|
||||
this.regionFlag = CommandFlag.<PlayerCommandSource>builder("region")
|
||||
.withComponent(regionParser)
|
||||
.build();
|
||||
this.offlinePlayerHelper = offlinePlayerHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(@NotNull CommandSender target) {
|
||||
if (!target.hasPermission("areashop.transfer")) {
|
||||
return null;
|
||||
}
|
||||
return "help-transfer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("transfer")
|
||||
.senderType(PlayerCommandSource.class)
|
||||
.required(KEY_PLAYER, OfflinePlayerParser.parser())
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("transfer");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<PlayerCommandSource> context) {
|
||||
Player sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.transfer")) {
|
||||
throw new AreaShopCommandException("transfer-noPermission");
|
||||
}
|
||||
GeneralRegion region = RegionParseUtil.getOrParseRegion(context, sender, this.regionFlag);
|
||||
if (!region.isTransferEnabled()) {
|
||||
throw new AreaShopCommandException("transfer-disabled");
|
||||
}
|
||||
this.offlinePlayerHelper.lookupOfflinePlayerAsync(context.get(KEY_PLAYER))
|
||||
.whenComplete((offlinePlayer, exception) -> {
|
||||
if (exception != null) {
|
||||
sender.sendMessage("failed to lookup offline player!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!offlinePlayer.hasPlayedBefore() &&!offlinePlayer.isOnline()) {
|
||||
this.messageBridge.message(sender, "cmd-invalidPlayer", offlinePlayer.getName());
|
||||
return;
|
||||
}
|
||||
performTransfer(sender, offlinePlayer, region);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void performTransfer(
|
||||
@Nonnull Player sender,
|
||||
@Nonnull OfflinePlayer targetPlayer,
|
||||
@Nonnull GeneralRegion region
|
||||
) {
|
||||
String targetPlayerName = targetPlayer.getName();
|
||||
if (Objects.equals(sender, targetPlayer)) {
|
||||
throw new AreaShopCommandException("transfer-transferSelf");
|
||||
}
|
||||
if (!targetPlayer.hasPlayedBefore() && !targetPlayer.isOnline()) {
|
||||
// Unknown player
|
||||
throw new AreaShopCommandException("transfer-noPlayer", targetPlayerName);
|
||||
}
|
||||
if (region.isLandlord(sender.getUniqueId())) {
|
||||
// Transfer ownership if same as landlord
|
||||
region.getFriendsFeature().deleteFriend(region.getOwner(), null);
|
||||
region.setOwner(targetPlayer.getUniqueId());
|
||||
region.setLandlord(targetPlayer.getUniqueId(), targetPlayerName);
|
||||
this.messageBridge.message(sender, "transfer-transferred-owner", targetPlayerName, region);
|
||||
this.messageBridge.messagePersistent(targetPlayer, "transfer-transferred-owner", targetPlayerName, region);
|
||||
region.update();
|
||||
region.saveRequired();
|
||||
return;
|
||||
}
|
||||
if (!region.isOwner(sender.getUniqueId())) {
|
||||
// Cannot transfer tenant if we aren't the current tenant
|
||||
throw new AreaShopCommandException("transfer-notCurrentTenant");
|
||||
}
|
||||
region.getFriendsFeature().deleteFriend(region.getOwner(), null);
|
||||
// Swap the owner/occupant (renter or buyer)
|
||||
region.setOwner(targetPlayer.getUniqueId());
|
||||
|
||||
this.messageBridge.message(sender, "transfer-transferred-tenant", targetPlayerName, region);
|
||||
this.messageBridge.messagePersistent(targetPlayer, "transfer-transferred-tenant", targetPlayerName, region);
|
||||
region.update();
|
||||
region.saveRequired();
|
||||
}
|
||||
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestRegions(
|
||||
@Nonnull CommandContext<PlayerCommandSource> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
UUID uuid = context.sender().sender().getUniqueId();
|
||||
List<Suggestion> suggestions = this.fileManager.getRegions()
|
||||
.stream()
|
||||
.filter(region -> region.isOwner(uuid) || region.isLandlord(uuid))
|
||||
.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package me.wiefferink.areashop.commands;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import me.wiefferink.areashop.commands.util.AreaShopCommandException;
|
||||
import me.wiefferink.areashop.commands.util.AreashopCommandBean;
|
||||
import me.wiefferink.areashop.commands.util.RegionParseUtil;
|
||||
import me.wiefferink.areashop.commands.util.RentRegionParser;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandProperties;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class UnrentCommand extends AreashopCommandBean {
|
||||
private final IFileManager fileManager;
|
||||
private final CommandFlag<RentRegion> regionFlag;
|
||||
|
||||
@Inject
|
||||
public UnrentCommand(@Nonnull IFileManager fileManager) {
|
||||
ParserDescriptor<CommandSource<?>, RentRegion> regionParser =
|
||||
ParserDescriptor.of(new RentRegionParser<>(fileManager, this::suggestRegions), RentRegion.class);
|
||||
this.fileManager = fileManager;
|
||||
this.regionFlag = CommandFlag.<CommandSource<?>>builder("region")
|
||||
.withComponent(regionParser)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a person can unrent the region.
|
||||
*
|
||||
* @param person The person to check
|
||||
* @param region The region to check for
|
||||
* @return true if the person can unrent it, otherwise false
|
||||
*/
|
||||
public static boolean canUse(CommandSender person, GeneralRegion region) {
|
||||
if (person.hasPermission("areashop.unrent")) {
|
||||
return true;
|
||||
}
|
||||
if (person instanceof Player player) {
|
||||
return region.isOwner(player) && person.hasPermission("areashop.unrentown");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpKey(CommandSender target) {
|
||||
if (target.hasPermission("areashop.unrent") || target.hasPermission("areashop.unrentown")) {
|
||||
return "help-unrent";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command.Builder<? extends CommandSource<?>> configureCommand(Command.@NotNull Builder<CommandSource<?>> builder) {
|
||||
return builder.literal("unrent")
|
||||
.flag(this.regionFlag)
|
||||
.handler(this::handleCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CommandProperties properties() {
|
||||
return CommandProperties.of("unrent");
|
||||
}
|
||||
|
||||
private void handleCommand(@Nonnull CommandContext<CommandSource<?>> context) {
|
||||
CommandSender sender = context.sender().sender();
|
||||
if (!sender.hasPermission("areashop.unrent") && !sender.hasPermission("areashop.unrentown")) {
|
||||
throw new AreaShopCommandException("unrent-noPermission");
|
||||
}
|
||||
RentRegion rent = RegionParseUtil.getOrParseRentRegion(context, sender, this.regionFlag);
|
||||
if (!rent.isRented()) {
|
||||
throw new AreaShopCommandException("unrent-notRented", rent);
|
||||
}
|
||||
rent.unRent(true, sender);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CompletableFuture<Iterable<Suggestion>> suggestRegions(
|
||||
@Nonnull CommandContext<CommandSource<?>> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getRentsRef().stream()
|
||||
.filter(RentRegion::isRented)
|
||||
.map(GeneralRegion::getName)
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class AcceptedValuesParser<C> implements ArgumentParser<C, String>, SuggestionProvider<C> {
|
||||
|
||||
private final Supplier< Collection<String>> valuesProvider;
|
||||
private final boolean caseSensitive;
|
||||
|
||||
private final String failureMessageKey;
|
||||
|
||||
private AcceptedValuesParser(
|
||||
@Nonnull Supplier< Collection<String>> valuesProvider,
|
||||
@Nonnull String failureMessageKey,
|
||||
boolean caseSensitive
|
||||
|
||||
) {
|
||||
this.valuesProvider = valuesProvider;
|
||||
this.failureMessageKey = failureMessageKey;
|
||||
this.caseSensitive = caseSensitive;
|
||||
}
|
||||
|
||||
public static <C> AcceptedValuesParser<C> ofConstant(
|
||||
@Nonnull Collection<String> acceptedValues,
|
||||
@Nonnull String failureMessageKey,
|
||||
boolean caseSensitive
|
||||
) {
|
||||
Collection<String> copy = List.copyOf(acceptedValues);
|
||||
return new AcceptedValuesParser<>(() -> copy, failureMessageKey, caseSensitive);
|
||||
}
|
||||
|
||||
public static <C> AcceptedValuesParser<C> of(
|
||||
@Nonnull Supplier< Collection<String>> supplier,
|
||||
@Nonnull String failureMessageKey,
|
||||
boolean caseSensitive
|
||||
) {
|
||||
return new AcceptedValuesParser<>(supplier, failureMessageKey, caseSensitive);
|
||||
}
|
||||
|
||||
public static <C> AcceptedValuesParser<C> ofCached(
|
||||
@Nonnull Supplier< Collection<String>> supplier,
|
||||
@Nonnull String failureMessageKey,
|
||||
boolean caseSensitive
|
||||
) {
|
||||
return ofConstant(supplier.get(), failureMessageKey, caseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<String> parse(@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput) {
|
||||
String toTest;
|
||||
if (this.caseSensitive) {
|
||||
toTest = commandInput.peekString().toLowerCase(Locale.ENGLISH);
|
||||
} else {
|
||||
toTest = commandInput.peekString();
|
||||
}
|
||||
Collection<String> acceptedValues = this.valuesProvider.get();
|
||||
if (acceptedValues.contains(toTest)) {
|
||||
return ArgumentParseResult.success(toTest);
|
||||
}
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException(this.failureMessageKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull CompletableFuture<Iterable<Suggestion>> suggestionsFuture(
|
||||
@Nonnull CommandContext<C> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
Iterable<Suggestion> suggestions = this.valuesProvider.get().stream()
|
||||
.filter(s -> s.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AreaShopCommandException extends RuntimeException {
|
||||
|
||||
private static final Object[] EMPTY = new Object[0];
|
||||
|
||||
private final String messageKey;
|
||||
private final Object[] replacements;
|
||||
|
||||
public AreaShopCommandException(@Nonnull String messageKey, @Nullable Object... replacements) {
|
||||
this.messageKey = messageKey;
|
||||
this.replacements = replacements == null ? EMPTY : replacements;
|
||||
}
|
||||
|
||||
public String messageKey() {
|
||||
return this.messageKey;
|
||||
}
|
||||
|
||||
public Object[] replacements() {
|
||||
return this.replacements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return this.messageKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bean.CommandBean;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.processors.confirmation.ConfirmationManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An extension of {@link CommandBean} which does extra pre-processing of the commands.
|
||||
* Adapted from <a href="https://github.com/Incendo/kitchensink">KitchenSink</a>
|
||||
*/
|
||||
public abstract class AreashopCommandBean extends CommandBean<CommandSource<?>> implements HelpProvider {
|
||||
|
||||
private boolean requireConfirmation;
|
||||
|
||||
protected void withConfirmation() {
|
||||
this.requireConfirmation = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final @Nonnull Command.Builder<? extends CommandSource<?>> configure(
|
||||
final @Nonnull Command.Builder<CommandSource<?>> builder
|
||||
) {
|
||||
return this.configureCommand(builder)
|
||||
.meta(CloudKey.of("bukkit_description", String.class), this.stringDescription())
|
||||
.meta(ConfirmationManager.META_CONFIRMATION_REQUIRED, this.requireConfirmation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a simple string description of this command.
|
||||
*
|
||||
* <p>This is primarily used in the platform-native help menus.</p>
|
||||
*
|
||||
* @return command description
|
||||
*/
|
||||
public abstract String stringDescription();
|
||||
|
||||
/**
|
||||
* Configures the command and returns the updated builder.
|
||||
*
|
||||
* @param builder builder to configure
|
||||
* @return the updated builder
|
||||
*/
|
||||
protected abstract @Nonnull Command.Builder<? extends CommandSource<?>> configureCommand(
|
||||
@Nonnull Command.Builder<CommandSource<?>> builder
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Singleton;
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.AddCommand;
|
||||
import me.wiefferink.areashop.commands.AddFriendCommand;
|
||||
import me.wiefferink.areashop.commands.AddSignCommand;
|
||||
import me.wiefferink.areashop.commands.BuyCommand;
|
||||
import me.wiefferink.areashop.commands.DelCommand;
|
||||
import me.wiefferink.areashop.commands.DelFriendCommand;
|
||||
import me.wiefferink.areashop.commands.DelSignCommand;
|
||||
import me.wiefferink.areashop.commands.FindCommand;
|
||||
import me.wiefferink.areashop.commands.GroupAddCommand;
|
||||
import me.wiefferink.areashop.commands.GroupDelCommand;
|
||||
import me.wiefferink.areashop.commands.GroupInfoCommand;
|
||||
import me.wiefferink.areashop.commands.GroupListCommand;
|
||||
import me.wiefferink.areashop.commands.HelpCommand;
|
||||
import me.wiefferink.areashop.commands.InfoBaseCommand;
|
||||
import me.wiefferink.areashop.commands.InfoCommand;
|
||||
import me.wiefferink.areashop.commands.InfoPlayerCommand;
|
||||
import me.wiefferink.areashop.commands.InfoRegionCommand;
|
||||
import me.wiefferink.areashop.commands.LinkSignsCommand;
|
||||
import me.wiefferink.areashop.commands.MeCommand;
|
||||
import me.wiefferink.areashop.commands.MessageCommand;
|
||||
import me.wiefferink.areashop.commands.QuickBuyCommand;
|
||||
import me.wiefferink.areashop.commands.QuickDeleteCommand;
|
||||
import me.wiefferink.areashop.commands.QuickRentCommand;
|
||||
import me.wiefferink.areashop.commands.ReloadCommand;
|
||||
import me.wiefferink.areashop.commands.RentCommand;
|
||||
import me.wiefferink.areashop.commands.ResellCommand;
|
||||
import me.wiefferink.areashop.commands.SchematicEventCommand;
|
||||
import me.wiefferink.areashop.commands.SellCommand;
|
||||
import me.wiefferink.areashop.commands.SetDurationCommand;
|
||||
import me.wiefferink.areashop.commands.SetLandlordCommand;
|
||||
import me.wiefferink.areashop.commands.SetOwnerCommand;
|
||||
import me.wiefferink.areashop.commands.SetPriceCommand;
|
||||
import me.wiefferink.areashop.commands.SetRestoreCommand;
|
||||
import me.wiefferink.areashop.commands.SetTeleportCommand;
|
||||
import me.wiefferink.areashop.commands.SetTransferCommand;
|
||||
import me.wiefferink.areashop.commands.StackCommand;
|
||||
import me.wiefferink.areashop.commands.StopResellCommand;
|
||||
import me.wiefferink.areashop.commands.TeleportCommand;
|
||||
import me.wiefferink.areashop.commands.ToggleHomeCommand;
|
||||
import me.wiefferink.areashop.commands.TransferCommand;
|
||||
import me.wiefferink.areashop.commands.UnrentCommand;
|
||||
import me.wiefferink.areashop.commands.SetMaxExtends;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSourceMapper;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.incendo.cloud.exception.ArgumentParseException;
|
||||
import org.incendo.cloud.exception.CommandExecutionException;
|
||||
import org.incendo.cloud.exception.InvalidCommandSenderException;
|
||||
import org.incendo.cloud.exception.handling.ExceptionController;
|
||||
import org.incendo.cloud.exception.handling.ExceptionHandler;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.paper.PaperCommandManager;
|
||||
import org.incendo.cloud.processors.cache.GuavaCache;
|
||||
import org.incendo.cloud.processors.confirmation.ConfirmationConfiguration;
|
||||
import org.incendo.cloud.processors.confirmation.ConfirmationManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class AreashopCommands {
|
||||
|
||||
private static final List<Class<? extends AreashopCommandBean>> COMMAND_CLASSES = List.of(
|
||||
AddCommand.class,
|
||||
AddFriendCommand.class,
|
||||
AddSignCommand.class,
|
||||
BuyCommand.class,
|
||||
DelCommand.class,
|
||||
DelFriendCommand.class,
|
||||
DelSignCommand.class,
|
||||
FindCommand.class,
|
||||
GroupAddCommand.class,
|
||||
GroupDelCommand.class,
|
||||
GroupInfoCommand.class,
|
||||
GroupListCommand.class,
|
||||
HelpCommand.class,
|
||||
InfoCommand.class,
|
||||
InfoBaseCommand.class,
|
||||
InfoPlayerCommand.class,
|
||||
InfoRegionCommand.class,
|
||||
LinkSignsCommand.class,
|
||||
MeCommand.class,
|
||||
MessageCommand.class,
|
||||
QuickBuyCommand.class,
|
||||
QuickDeleteCommand.class,
|
||||
QuickRentCommand.class,
|
||||
ReloadCommand.class,
|
||||
RentCommand.class,
|
||||
ResellCommand.class,
|
||||
SchematicEventCommand.class,
|
||||
SellCommand.class,
|
||||
SetDurationCommand.class,
|
||||
SetLandlordCommand.class,
|
||||
SetOwnerCommand.class,
|
||||
SetPriceCommand.class,
|
||||
SetRestoreCommand.class,
|
||||
SetTeleportCommand.class,
|
||||
SetTransferCommand.class,
|
||||
StackCommand.class,
|
||||
StopResellCommand.class,
|
||||
TeleportCommand.class,
|
||||
ToggleHomeCommand.class,
|
||||
TransferCommand.class,
|
||||
UnrentCommand.class,
|
||||
SetMaxExtends.class
|
||||
);
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
private final Injector injector;
|
||||
private final PaperCommandManager<CommandSource<?>> commandManager;
|
||||
|
||||
private final List<AreashopCommandBean> commands = new ArrayList<>();
|
||||
private HelpRenderer helpRenderer;
|
||||
|
||||
@Inject
|
||||
AreashopCommands(@Nonnull Injector injector, @Nonnull Plugin plugin, @Nonnull MessageBridge messageBridge) {
|
||||
this.injector = injector;
|
||||
this.commandManager = PaperCommandManager.builder(new CommandSourceMapper())
|
||||
.executionCoordinator(ExecutionCoordinator.simpleCoordinator())
|
||||
.buildOnEnable(plugin);
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
public void registerCommands() {
|
||||
this.commands.clear();
|
||||
initCommandManager();
|
||||
var builder = this.commandManager.commandBuilder("areashop", "as");
|
||||
for (Class<? extends AreashopCommandBean> commandClass : COMMAND_CLASSES) {
|
||||
AreashopCommandBean commandBean = injector.getInstance(commandClass);
|
||||
this.commands.add(commandBean);
|
||||
var configuredBuilder = commandBean.configureCommand(builder);
|
||||
this.commandManager.command(configuredBuilder);
|
||||
}
|
||||
// Show help by default
|
||||
this.commandManager.command(builder.handler(context -> showHelp(context.sender().sender())));
|
||||
this.helpRenderer = new HelpRenderer(this.messageBridge, this.commands);
|
||||
}
|
||||
|
||||
private void initCommandManager() {
|
||||
ExceptionController<CommandSource<?>> exceptionController = this.commandManager.exceptionController();
|
||||
// We need to unwrap ArgumentParseException because they wrap the custom exception messages
|
||||
exceptionController.registerHandler(InvalidCommandSenderException.class,
|
||||
new InvalidCommandSenderHandler(this.messageBridge));
|
||||
exceptionController.registerHandler(AreaShopCommandException.class,
|
||||
new ArgumentParseExceptionHandler<>(this.messageBridge));
|
||||
exceptionController.registerHandler(ArgumentParseException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
exceptionController.registerHandler(CommandExecutionException.class,
|
||||
ExceptionHandler.unwrappingHandler(AreaShopCommandException.class));
|
||||
var confirmationConfiguration = ConfirmationConfiguration.<CommandSource<?>>builder()
|
||||
.cache(GuavaCache.of(CacheBuilder.newBuilder().build()))
|
||||
.noPendingCommandNotifier(x -> {
|
||||
})
|
||||
.confirmationRequiredNotifier((x, y) -> {
|
||||
})
|
||||
.build();
|
||||
var confirmationManager = ConfirmationManager.confirmationManager(confirmationConfiguration);
|
||||
commandManager.registerCommandPostProcessor(confirmationManager.createPostprocessor());
|
||||
}
|
||||
|
||||
public void showHelp(@Nonnull CommandSender sender) {
|
||||
if (this.helpRenderer == null) {
|
||||
throw new IllegalStateException("Command handler not yet initialized!");
|
||||
}
|
||||
this.helpRenderer.showHelp(sender);
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import org.incendo.cloud.exception.handling.ExceptionContext;
|
||||
import org.incendo.cloud.exception.handling.ExceptionHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ArgumentParseExceptionHandler<C extends CommandSource<?>> implements ExceptionHandler<C, AreaShopCommandException> {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
public ArgumentParseExceptionHandler(@Nonnull MessageBridge messageBridge) {
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
public static void handleException(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull CommandSource<?> sender,
|
||||
@Nonnull AreaShopCommandException exception
|
||||
) {
|
||||
String key = exception.messageKey();
|
||||
Object[] replacements = exception.replacements();
|
||||
if (replacements.length == 0) {
|
||||
messageBridge.message(sender.sender(), key);
|
||||
return;
|
||||
}
|
||||
// Pass the values as a var-args and not as a string[]
|
||||
messageBridge.message(sender.sender(), key, replacements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@Nonnull ExceptionContext<C, AreaShopCommandException> context) {
|
||||
handleException(this.messageBridge, context.context().sender(), context.exception());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BuyRegionParser<C> implements ArgumentParser<C, BuyRegion> {
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final SuggestionProvider<C> suggestionProvider;
|
||||
|
||||
public BuyRegionParser(@Nonnull IFileManager fileManager, @Nonnull SuggestionProvider<C> suggestionProvider) {
|
||||
this.fileManager = fileManager;
|
||||
this.suggestionProvider = suggestionProvider;
|
||||
}
|
||||
|
||||
public BuyRegionParser(@Nonnull IFileManager fileManager) {
|
||||
this(fileManager, defaultSuggestionProvider(fileManager));
|
||||
}
|
||||
|
||||
private static <C> SuggestionProvider<C> defaultSuggestionProvider(@Nonnull IFileManager fileManager) {
|
||||
return SuggestionProvider.blockingStrings((ctx, input) -> {
|
||||
String text = input.peekString();
|
||||
return fileManager.getBuyNames()
|
||||
.stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.toList();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<BuyRegion> parse(@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput) {
|
||||
String input = commandInput.peekString();
|
||||
BuyRegion region = this.fileManager.getBuy(input);
|
||||
if (region != null) {
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(region);
|
||||
}
|
||||
AreaShopCommandException exception = new AreaShopCommandException("buy-noBuyable", input);
|
||||
return ArgumentParseResult.failure(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull SuggestionProvider<C> suggestionProvider() {
|
||||
return this.suggestionProvider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.tools.DurationInput;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DurationInputParser<C> implements ArgumentParser<C, DurationInput>, SuggestionProvider<C> {
|
||||
|
||||
public static <C> ParserDescriptor<C, DurationInput> durationInputParser() {
|
||||
return ParserDescriptor.of(new DurationInputParser<>(), DurationInput.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<@NonNull DurationInput> parse(@NonNull CommandContext<@NonNull C> commandContext,
|
||||
@NonNull CommandInput commandInput) {
|
||||
String input = commandInput.peekString();
|
||||
int index = 0;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
if (Character.isAlphabetic(input.charAt(i))) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == commandInput.length() - 1) {
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException("setduration-wrongAmount", input));
|
||||
}
|
||||
String duration = input.substring(0, index);
|
||||
String durationUnit = input.substring(index);
|
||||
int durationInt;
|
||||
try {
|
||||
durationInt = Integer.parseInt(duration);
|
||||
} catch (NumberFormatException ex) {
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException("setduration-wrongAmount", duration));
|
||||
}
|
||||
Optional<TimeUnit> timeUnit = DurationInput.getTimeUnit(durationUnit.toLowerCase(Locale.ENGLISH));
|
||||
if (timeUnit.isEmpty()) {
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException("setduration-wrongFormat", durationUnit));
|
||||
}
|
||||
DurationInput durationInput = new DurationInput(durationInt, timeUnit.get());
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(durationInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<@NonNull Iterable<@NonNull Suggestion>> suggestionsFuture(
|
||||
@NonNull CommandContext<C> context,
|
||||
@NonNull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
int firstText = 0;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
if (Character.isAlphabetic(c)) {
|
||||
firstText = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (firstText == 0) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
String timeUnit = text.substring(firstText);
|
||||
List<String> suffixes = DurationInput.SUFFIXES;
|
||||
List<Suggestion> suggestions = suffixes.stream()
|
||||
.filter(suffix -> suffix.startsWith(timeUnit))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GeneralRegionParser<C> implements ArgumentParser<C, GeneralRegion> {
|
||||
|
||||
protected final IFileManager fileManager;
|
||||
private final SuggestionProvider<C> suggestionProvider;
|
||||
|
||||
public GeneralRegionParser(@Nonnull IFileManager fileManager, @Nonnull SuggestionProvider<C> suggestionProvider) {
|
||||
this.fileManager = fileManager;
|
||||
this.suggestionProvider = suggestionProvider;
|
||||
}
|
||||
|
||||
public GeneralRegionParser(@Nonnull IFileManager fileManager) {
|
||||
this(fileManager, defaultProvider(fileManager));
|
||||
}
|
||||
|
||||
public static <C> ParserDescriptor<C, GeneralRegion> generalRegionParser(@Nonnull IFileManager fileManager) {
|
||||
return ParserDescriptor.of(new GeneralRegionParser<>(fileManager), GeneralRegion.class);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static <C> SuggestionProvider<C> defaultProvider(@Nonnull IFileManager fileManager) {
|
||||
return SuggestionProvider.blockingStrings((ctx, input) -> fileManager.getRegionNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<GeneralRegion> parse(@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput) {
|
||||
String input = commandInput.peekString();
|
||||
GeneralRegion region = this.fileManager.getRegion(input);
|
||||
if (region != null) {
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(region);
|
||||
}
|
||||
AreaShopCommandException exception = new AreaShopCommandException("cmd-notRegistered", input);
|
||||
return ArgumentParseResult.failure(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull SuggestionProvider<C> suggestionProvider() {
|
||||
return this.suggestionProvider;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.interactivemessenger.source.LanguageManager;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.component.CommandComponent;
|
||||
import org.incendo.cloud.exception.CommandParseException;
|
||||
import org.incendo.cloud.exception.handling.ExceptionContext;
|
||||
import org.incendo.cloud.exception.handling.ExceptionHandler;
|
||||
|
||||
public class HelpForwardingHandler<C> implements ExceptionHandler<C, CommandParseException> {
|
||||
|
||||
private final LanguageManager languageManager;
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
public HelpForwardingHandler(@NonNull MessageBridge messageBridge, @NonNull LanguageManager languageManager) {
|
||||
this.languageManager = languageManager;
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NonNull ExceptionContext<C, CommandParseException> context) throws Throwable {
|
||||
CommandParseException exception = context.exception();
|
||||
// walk back to the first literal
|
||||
CommandComponent<?> literal = null;
|
||||
for (CommandComponent<?> component : exception.currentChain()) {
|
||||
if (component.type() == CommandComponent.ComponentType.LITERAL) {
|
||||
literal = component;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we can't find the label, rethrow the exception
|
||||
if (literal == null) {
|
||||
throw exception;
|
||||
}
|
||||
String name = literal.name();
|
||||
String helpKey = name + "-help";
|
||||
if (languageManager.getMessage(helpKey).isEmpty()) {
|
||||
// We don't have a help message, rethrow the exception
|
||||
throw exception;
|
||||
}
|
||||
this.messageBridge.message(context.context().sender(), helpKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface HelpProvider {
|
||||
|
||||
@Nullable String getHelpKey(@Nonnull CommandSender target);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HelpRenderer {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
private final List<HelpProvider> providers;
|
||||
|
||||
public HelpRenderer(@Nonnull MessageBridge messageBridge, @Nonnull List<? extends HelpProvider> providers) {
|
||||
this.providers = List.copyOf(providers);
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
public void showHelp(@Nonnull CommandSender target) {
|
||||
if (!target.hasPermission("areashop.help")) {
|
||||
this.messageBridge.message(target, "help-noPermission");
|
||||
return;
|
||||
}
|
||||
// Add all messages to a list
|
||||
List<String> messages = new ArrayList<>();
|
||||
this.messageBridge.message(target, "help-header");
|
||||
this.messageBridge.message(target, "help-alias");
|
||||
for (HelpProvider provider : providers) {
|
||||
String help = provider.getHelpKey(target);
|
||||
if (help != null && !help.isEmpty()) {
|
||||
messages.add(help);
|
||||
}
|
||||
}
|
||||
// Send the messages to the target
|
||||
for (String message : messages) {
|
||||
this.messageBridge.messageNoPrefix(target, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.CommandSource;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.PlayerCommandSource;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.exception.InvalidCommandSenderException;
|
||||
import org.incendo.cloud.exception.handling.ExceptionContext;
|
||||
import org.incendo.cloud.exception.handling.ExceptionHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class InvalidCommandSenderHandler implements ExceptionHandler<CommandSource<?>, InvalidCommandSenderException> {
|
||||
|
||||
private final MessageBridge messageBridge;
|
||||
|
||||
public InvalidCommandSenderHandler(@Nonnull MessageBridge messageBridge) {
|
||||
this.messageBridge = messageBridge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NonNull ExceptionContext<CommandSource<?>, InvalidCommandSenderException> context) throws Throwable {
|
||||
InvalidCommandSenderException exception = context.exception();
|
||||
if (exception.requiredSenderTypes().contains(PlayerCommandSource.class)) {
|
||||
this.messageBridge.message(exception.commandSender(), "cmd-onlyByPlayer");
|
||||
return;
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.suggestion.BlockingSuggestionProvider;
|
||||
|
||||
public class OfflinePlayerParser<C> implements ArgumentParser<C, String>, BlockingSuggestionProvider.Strings<C> {
|
||||
|
||||
|
||||
public static <C> ParserDescriptor<C, String> parser() {
|
||||
return ParserDescriptor.of(new OfflinePlayerParser<>(), String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<@NonNull String> parse(@NonNull CommandContext<@NonNull C> commandContext,
|
||||
@NonNull CommandInput commandInput) {
|
||||
final String input = commandInput.readString();
|
||||
if (input.length() > 16) {
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException("cmd-invalidPlayer", input));
|
||||
}
|
||||
return ArgumentParseResult.success(input);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Iterable<@NonNull String> stringSuggestions(@NonNull CommandContext<C> commandContext,
|
||||
@NonNull CommandInput input) {
|
||||
return Bukkit.getServer().getOnlinePlayers().stream()
|
||||
.map(Player::getName)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ParserWrapper<C, T> implements ArgumentParser<C, T> {
|
||||
|
||||
private final SuggestionProvider<C> suggestionProvider;
|
||||
private final ParserDescriptor<C, T> parser;
|
||||
|
||||
public static <C, T> ParserDescriptor<C, T> wrap(@Nonnull ParserDescriptor<C, T> parser, @Nonnull SuggestionProvider<C> suggestionProvider) {
|
||||
ArgumentParser<C, T> wrapped = new ParserWrapper<>(parser, suggestionProvider);
|
||||
return ParserDescriptor.of(wrapped, parser.valueType());
|
||||
}
|
||||
|
||||
public ParserWrapper(@Nonnull ParserDescriptor<C, T> parser, @Nonnull SuggestionProvider<C> suggestionProvider) {
|
||||
this.parser = parser;
|
||||
this.suggestionProvider = suggestionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArgumentParseResult<@NonNull T> parse(@NonNull CommandContext<@NonNull C> commandContext,
|
||||
@NonNull CommandInput commandInput) {
|
||||
return this.parser.parser().parse(commandContext, commandInput);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SuggestionProvider<C> suggestionProvider() {
|
||||
return this.suggestionProvider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class RegionCreationUtil {
|
||||
|
||||
|
||||
private final Plugin plugin;
|
||||
private final IFileManager fileManager;
|
||||
private final Server server;
|
||||
private final WorldGuardInterface worldGuardInterface;
|
||||
|
||||
@Inject
|
||||
public RegionCreationUtil(
|
||||
@Nonnull WorldGuardInterface worldGuardInterface,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull Server server,
|
||||
@Nonnull Plugin plugin
|
||||
) {
|
||||
this.worldGuardInterface = worldGuardInterface;
|
||||
this.fileManager = fileManager;
|
||||
this.plugin = plugin;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public CompletableFuture<ProtectedRegion> createRegion(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull Player sender,
|
||||
@Nonnull CloudKey<String> regionKey
|
||||
) {
|
||||
World world = sender.getWorld();
|
||||
String regionName = context.get(regionKey);
|
||||
if (this.fileManager.getRegion(regionName) != null) {
|
||||
return CompletableFuture.failedFuture(new AreaShopCommandException("add-failed", regionName));
|
||||
}
|
||||
this.server.dispatchCommand(sender, String.format("rg define %s", regionName));
|
||||
CompletableFuture<ProtectedRegion> future = new CompletableFuture<>();
|
||||
this.server.getScheduler().runTaskLater(this.plugin, () -> {
|
||||
ProtectedRegion region = this.worldGuardInterface.getRegionManager(world).getRegion(regionName);
|
||||
if (region == null) {
|
||||
future.completeExceptionally(new AreaShopCommandException("quickadd-failedCreateWGRegion"));
|
||||
return;
|
||||
}
|
||||
future.complete(region);
|
||||
}, 10);
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RegionGroup;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class RegionGroupParser<C> implements ArgumentParser<C, RegionGroup>, SuggestionProvider<C> {
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final String failureMessageKey;
|
||||
|
||||
public RegionGroupParser(@Nonnull IFileManager fileManager, @Nonnull String failureMessageKey) {
|
||||
this.fileManager = fileManager;
|
||||
this.failureMessageKey = failureMessageKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<RegionGroup> parse(
|
||||
@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput
|
||||
) {
|
||||
String input = commandInput.peekString();
|
||||
RegionGroup regionGroup = this.fileManager.getGroup(input);
|
||||
if (regionGroup != null) {
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(regionGroup);
|
||||
}
|
||||
return ArgumentParseResult.failure(new AreaShopCommandException(this.failureMessageKey, input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull CompletableFuture<Iterable<Suggestion>> suggestionsFuture(
|
||||
@Nonnull CommandContext<C> context,
|
||||
@Nonnull CommandInput input
|
||||
) {
|
||||
String text = input.peekString();
|
||||
List<Suggestion> suggestions = this.fileManager.getGroupNames().stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.map(Suggestion::suggestion)
|
||||
.toList();
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.MessageBridge;
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class RegionInfoUtil {
|
||||
|
||||
public static void showRegionInfo(
|
||||
@Nonnull MessageBridge messageBridge,
|
||||
@Nonnull IFileManager fileManager,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull OfflinePlayer owner
|
||||
) {
|
||||
// Get the regions owned by the player
|
||||
Set<RentRegion> rentRegions = new HashSet<>();
|
||||
for(RentRegion region : fileManager.getRentsRef()) {
|
||||
if(region.isOwner(owner)) {
|
||||
rentRegions.add(region);
|
||||
}
|
||||
}
|
||||
Set<BuyRegion> buyRegions = new HashSet<>();
|
||||
for(BuyRegion region : fileManager.getBuysRef()) {
|
||||
if(region.isOwner(owner)) {
|
||||
buyRegions.add(region);
|
||||
}
|
||||
}
|
||||
// Get the regions the player is added as friend
|
||||
Set<GeneralRegion> friendRegions = new HashSet<>();
|
||||
for(GeneralRegion region : fileManager.getRegionsRef()) {
|
||||
if(region.getFriendsFeature().getFriends().contains(owner.getUniqueId())) {
|
||||
friendRegions.add(region);
|
||||
}
|
||||
}
|
||||
|
||||
// Send messages
|
||||
boolean foundSome = !rentRegions.isEmpty() || !buyRegions.isEmpty() || !friendRegions.isEmpty();
|
||||
if(!foundSome) {
|
||||
messageBridge.message(sender, "me-nothing", owner.getName());
|
||||
return;
|
||||
}
|
||||
messageBridge.message(sender, "me-header", owner.getName());
|
||||
if(!rentRegions.isEmpty()) {
|
||||
for(RentRegion region : rentRegions) {
|
||||
messageBridge.messageNoPrefix(sender, "me-rentLine", region);
|
||||
}
|
||||
}
|
||||
if(!buyRegions.isEmpty()) {
|
||||
for(BuyRegion region : buyRegions) {
|
||||
messageBridge.messageNoPrefix(sender, "me-buyLine", region);
|
||||
}
|
||||
}
|
||||
if(!friendRegions.isEmpty()) {
|
||||
for(GeneralRegion region : friendRegions) {
|
||||
messageBridge.messageNoPrefix(sender, "me-friendLine", region);
|
||||
}
|
||||
}
|
||||
messageBridge.messageNoPrefix(sender, "me-clickHint");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import me.wiefferink.areashop.tools.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.key.CloudKey;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public final class RegionParseUtil {
|
||||
|
||||
private RegionParseUtil() {
|
||||
throw new IllegalStateException("Cannot instantiate static utility class");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CommandFlag<GeneralRegion> createDefault(@Nonnull IFileManager fileManager) {
|
||||
return CommandFlag.builder("region")
|
||||
.withComponent(GeneralRegionParser.generalRegionParser(fileManager))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Collection<GeneralRegion> getOrParseRegionsInSel(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull CommandFlag<GeneralRegion> regionFlag
|
||||
) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
throw new AreaShopCommandException("cmd-weOnlyByPlayer");
|
||||
}
|
||||
GeneralRegion declaredRegion = context.flags().get(regionFlag);
|
||||
if (declaredRegion != null) {
|
||||
return List.of(declaredRegion);
|
||||
}
|
||||
Location location = player.getLocation();
|
||||
List<GeneralRegion> regions = Utils.getImportantRegions(location);
|
||||
if (!regions.isEmpty()) {
|
||||
return regions;
|
||||
|
||||
}
|
||||
throw new AreaShopCommandException("cmd-noRegionsAtLocation");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GeneralRegion getOrParseRegion(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull CommandFlag<GeneralRegion> flag
|
||||
) throws AreaShopCommandException {
|
||||
GeneralRegion region = context.flags().get(flag);
|
||||
if (region != null) {
|
||||
return region;
|
||||
}
|
||||
if (!(sender instanceof Entity entity)) {
|
||||
throw new AreaShopCommandException("cmd-automaticRegionOnlyByPlayer");
|
||||
}
|
||||
Location location = entity.getLocation();
|
||||
List<GeneralRegion> regions = Utils.getImportantRegions(location);
|
||||
String errorMessageKey;
|
||||
if (regions.isEmpty()) {
|
||||
errorMessageKey = "cmd-noRegionsAtLocation";
|
||||
} else if (regions.size() > 1) {
|
||||
errorMessageKey = "cmd-moreRegionsAtLocation";
|
||||
} else {
|
||||
return regions.getFirst();
|
||||
}
|
||||
throw new AreaShopCommandException(errorMessageKey);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GeneralRegion getOrParseRegion(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull CloudKey<GeneralRegion> key
|
||||
) throws AreaShopCommandException {
|
||||
GeneralRegion region = context.getOrDefault(key, null);
|
||||
if (region != null) {
|
||||
return region;
|
||||
}
|
||||
if (!(sender instanceof Entity entity)) {
|
||||
throw new AreaShopCommandException("cmd-automaticRegionOnlyByPlayer");
|
||||
}
|
||||
Location location = entity.getLocation();
|
||||
List<GeneralRegion> regions = Utils.getImportantRegions(location);
|
||||
String errorMessageKey;
|
||||
if (regions.isEmpty()) {
|
||||
errorMessageKey = "cmd-noRegionsAtLocation";
|
||||
} else if (regions.size() > 1) {
|
||||
errorMessageKey = "cmd-moreRegionsAtLocation";
|
||||
} else {
|
||||
return regions.getFirst();
|
||||
}
|
||||
throw new AreaShopCommandException(errorMessageKey);
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public static CommandFlag<BuyRegion> createDefaultBuy(@Nonnull IFileManager fileManager) {
|
||||
return CommandFlag.builder("region")
|
||||
.withComponent(ParserDescriptor.of(new BuyRegionParser<>(fileManager), BuyRegion.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CommandFlag<RentRegion> createDefaultRent(@Nonnull IFileManager fileManager) {
|
||||
return CommandFlag.builder("region")
|
||||
.withComponent(ParserDescriptor.of(new RentRegionParser<>(fileManager), RentRegion.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static BuyRegion getOrParseBuyRegion(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull CommandFlag<BuyRegion> flag) {
|
||||
BuyRegion buyRegion = context.flags().get(flag);
|
||||
if (buyRegion != null) {
|
||||
return buyRegion;
|
||||
}
|
||||
if (!(sender instanceof Player player)) {
|
||||
throw new AreaShopCommandException("cmd-automaticRegionOnlyByPlayer");
|
||||
}
|
||||
List<BuyRegion> regions = Utils.getImportantBuyRegions(player.getLocation());
|
||||
if (regions.isEmpty()) {
|
||||
throw new AreaShopCommandException("cmd-noRegionsAtLocation");
|
||||
} else if (regions.size() != 1) {
|
||||
throw new AreaShopCommandException("cmd-moreRegionsAtLocation");
|
||||
}
|
||||
return regions.getFirst();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static RentRegion getOrParseRentRegion(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandSender sender,
|
||||
@Nonnull CommandFlag<RentRegion> flag) {
|
||||
RentRegion rentRegion = context.flags().get(flag);
|
||||
if (rentRegion != null) {
|
||||
return rentRegion;
|
||||
}
|
||||
if (!(sender instanceof Player player)) {
|
||||
throw new AreaShopCommandException("cmd-automaticRegionOnlyByPlayer");
|
||||
}
|
||||
List<RentRegion> regions = Utils.getImportantRentRegions(player.getLocation());
|
||||
if (regions.isEmpty()) {
|
||||
throw new AreaShopCommandException("cmd-noRegionsAtLocation");
|
||||
} else if (regions.size() != 1) {
|
||||
throw new AreaShopCommandException("cmd-moreRegionsAtLocation");
|
||||
}
|
||||
return regions.getFirst();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.managers.IFileManager;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RentRegionParser<C> implements ArgumentParser<C, RentRegion> {
|
||||
|
||||
private final IFileManager fileManager;
|
||||
private final SuggestionProvider<C> suggestionProvider;
|
||||
|
||||
public RentRegionParser(@Nonnull IFileManager fileManager, @Nonnull SuggestionProvider<C> suggestionProvider) {
|
||||
this.fileManager = fileManager;
|
||||
this.suggestionProvider = suggestionProvider;
|
||||
}
|
||||
|
||||
public RentRegionParser(@Nonnull IFileManager fileManager) {
|
||||
this(fileManager, defaultSuggestionProvider(fileManager));
|
||||
}
|
||||
|
||||
private static <C> SuggestionProvider<C> defaultSuggestionProvider(@Nonnull IFileManager fileManager) {
|
||||
return SuggestionProvider.blockingStrings((ctx, input) -> {
|
||||
String text = input.peekString();
|
||||
return fileManager.getRentNames()
|
||||
.stream()
|
||||
.filter(name -> name.startsWith(text))
|
||||
.toList();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<RentRegion> parse(@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput) {
|
||||
String input = commandInput.peekString();
|
||||
RentRegion region = this.fileManager.getRent(input);
|
||||
if (region != null) {
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(region);
|
||||
}
|
||||
AreaShopCommandException exception = new AreaShopCommandException("rent-notRentable", input);
|
||||
return ArgumentParseResult.failure(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull SuggestionProvider<C> suggestionProvider() {
|
||||
return this.suggestionProvider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class SignProfileUtil {
|
||||
|
||||
public static final CommandFlag<String> DEFAULT_FLAG = CommandFlag.builder("profile")
|
||||
.withComponent(StringParser.stringParser(StringParser.StringMode.SINGLE))
|
||||
.build();
|
||||
|
||||
private SignProfileUtil() {
|
||||
throw new IllegalArgumentException("Static utility class cannot be instantiated");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CommandFlag<String> createDefault(@Nonnull Plugin plugin) {
|
||||
Supplier<Collection<String>> valueSupplier = () -> {
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection("signProfiles");
|
||||
if (section == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return section.getKeys(false);
|
||||
};
|
||||
return CommandFlag.builder("profile")
|
||||
.withComponent(
|
||||
ParserDescriptor.of(
|
||||
AcceptedValuesParser.of(valueSupplier, "addsign-wrongProfile", false),
|
||||
String.class)
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getOrParseProfile(@Nonnull CommandContext<?> context,
|
||||
@Nonnull Plugin plugin) {
|
||||
return getOrParseProfile(context, DEFAULT_FLAG, plugin);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getOrParseProfile(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull CommandFlag<String> flag,
|
||||
@Nonnull Plugin plugin
|
||||
) throws AreaShopCommandException {
|
||||
String profile = context.flags().get(flag);
|
||||
if (profile == null) {
|
||||
return null;
|
||||
}
|
||||
Set<String> profiles = plugin.getConfig().getConfigurationSection("signProfiles").getKeys(false);
|
||||
if (profiles.contains(profile.toLowerCase(Locale.ENGLISH))) {
|
||||
return profile.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
throw new AreaShopCommandException("addsign-wrongProfile");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.incendo.cloud.bukkit.parser.WorldParser;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class WorldFlagUtil {
|
||||
|
||||
public static final CommandFlag<World> DEFAULT_WORLD_FLAG = CommandFlag.builder("world")
|
||||
.withComponent(WorldParser.worldParser())
|
||||
.build();
|
||||
|
||||
private WorldFlagUtil() {
|
||||
throw new IllegalStateException("Cannot instantiate static util class");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static World parseOrDetectWorld(@Nonnull CommandContext<?> context, @Nonnull Entity sender) {
|
||||
return parseOrDetectWorld(context, sender, DEFAULT_WORLD_FLAG);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static World parseOrDetectWorld(
|
||||
@Nonnull CommandContext<?> context,
|
||||
@Nonnull Entity sender,
|
||||
@Nonnull CommandFlag<World> flag
|
||||
) {
|
||||
World world = context.flags().get(flag);
|
||||
if (world != null) {
|
||||
return world;
|
||||
}
|
||||
return sender.getWorld();
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import me.wiefferink.areashop.commands.util.commandsource.EntityCommandSource;
|
||||
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||
import org.incendo.cloud.parser.ArgumentParser;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collections;
|
||||
|
||||
public class WorldGuardRegionParser<C extends EntityCommandSource> implements ArgumentParser<C, ProtectedRegion> {
|
||||
private final WorldGuardInterface worldGuardInterface;
|
||||
private final CommandFlag<World> worldFlag;
|
||||
|
||||
public WorldGuardRegionParser(
|
||||
@Nonnull CommandFlag<World> worldFlag,
|
||||
@Nonnull WorldGuardInterface worldGuardInterface
|
||||
) {
|
||||
this.worldFlag = worldFlag;
|
||||
this.worldGuardInterface = worldGuardInterface;
|
||||
}
|
||||
|
||||
public static <C extends EntityCommandSource> ParserDescriptor<C, ProtectedRegion> worldGuardRegionParser(
|
||||
@Nonnull CommandFlag<World> worldFlag,
|
||||
@Nonnull WorldGuardInterface worldGuardInterface
|
||||
) {
|
||||
return ParserDescriptor.of(new WorldGuardRegionParser<>(worldFlag, worldGuardInterface), ProtectedRegion.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull ArgumentParseResult<ProtectedRegion> parse(@Nonnull CommandContext<C> commandContext,
|
||||
@Nonnull CommandInput commandInput) {
|
||||
Entity sender = commandContext.sender().sender();
|
||||
World world = WorldFlagUtil.parseOrDetectWorld(commandContext, sender, worldFlag);
|
||||
String regionName = commandInput.peekString();
|
||||
RegionManager regionManager = this.worldGuardInterface.getRegionManager(world);
|
||||
if (regionManager == null) {
|
||||
return ArgumentParseResult.failure(new IllegalArgumentException("No region manager for world: " + world.getName()));
|
||||
}
|
||||
ProtectedRegion protectedRegion = regionManager.getRegion(regionName);
|
||||
if (protectedRegion != null) {
|
||||
commandInput.readString();
|
||||
return ArgumentParseResult.success(protectedRegion);
|
||||
}
|
||||
AreaShopCommandException exception = new AreaShopCommandException("cmd-noRegion", regionName);
|
||||
return ArgumentParseResult.failure(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nonnull SuggestionProvider<C> suggestionProvider() {
|
||||
return SuggestionProvider.blockingStrings((commandContext, input) -> {
|
||||
Entity sender = commandContext.sender().sender();
|
||||
if (!(sender instanceof Player player)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.worldGuardInterface.getRegionManager(player.getWorld()).getRegions()
|
||||
.values()
|
||||
.stream()
|
||||
.map(ProtectedRegion::getId)
|
||||
.toList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package me.wiefferink.areashop.commands.util;
|
||||
|
||||
import me.wiefferink.areashop.interfaces.WorldEditInterface;
|
||||
import me.wiefferink.areashop.interfaces.WorldEditSelection;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public record WorldSelection(@Nonnull World world, @Nonnull WorldEditSelection selection) {
|
||||
|
||||
public static WorldSelection fromPlayer(@Nonnull Player player,
|
||||
@Nonnull WorldEditInterface worldEditInterface) throws ParserException {
|
||||
WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
|
||||
if (selection == null) {
|
||||
throw new AreaShopCommandException("cmd-noSelection");
|
||||
}
|
||||
World world = selection.getWorld();
|
||||
return new WorldSelection(world, selection);
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface CommandSource<C extends CommandSender> {
|
||||
|
||||
@Nonnull
|
||||
CommandSourceStack sourceStack();
|
||||
|
||||
@Nonnull
|
||||
C sender();
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.SenderMapper;
|
||||
|
||||
public class CommandSourceMapper implements SenderMapper<CommandSourceStack, CommandSource<?>> {
|
||||
|
||||
@Override
|
||||
public @NonNull CommandSource<?> map(@NonNull CommandSourceStack base) {
|
||||
CommandSender sender = base.getSender();
|
||||
if (sender instanceof Player) {
|
||||
return new PlayerCommandSource(base);
|
||||
} else if (sender instanceof Entity) {
|
||||
return new EntityCommandSource(base);
|
||||
}
|
||||
return new GenericCommandSource(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CommandSourceStack reverse(@NonNull CommandSource<?> mapped) {
|
||||
return mapped.sourceStack();
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public record CommandSourceWrapper(@Nonnull CommandSourceStack commandSourceStack) {
|
||||
|
||||
@Nonnull
|
||||
public CommandSender sender() {
|
||||
return commandSourceStack().getSender();
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public sealed class EntityCommandSource extends GenericCommandSource permits PlayerCommandSource {
|
||||
|
||||
public EntityCommandSource(@Nonnull CommandSourceStack sourceStack) {
|
||||
super(sourceStack);
|
||||
if (!(sourceStack.getSender() instanceof Entity)) {
|
||||
throw new IllegalArgumentException("Source stack sender is not an entity!");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Entity sender() {
|
||||
return (Entity) super.sender();
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GenericCommandSource implements CommandSource<CommandSender> {
|
||||
|
||||
private final CommandSourceStack sourceStack;
|
||||
|
||||
private final CommandSender sender;
|
||||
|
||||
public GenericCommandSource(@Nonnull CommandSourceStack sourceStack) {
|
||||
this.sourceStack = sourceStack;
|
||||
this.sender = sourceStack.getSender();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final CommandSourceStack sourceStack() {
|
||||
return this.sourceStack;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommandSender sender() {
|
||||
return this.sender;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package me.wiefferink.areashop.commands.util.commandsource;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class PlayerCommandSource extends EntityCommandSource {
|
||||
|
||||
public PlayerCommandSource(@Nonnull CommandSourceStack sourceStack) {
|
||||
super(sourceStack);
|
||||
if (!(sourceStack.getSender() instanceof Player)) {
|
||||
throw new IllegalArgumentException("Source stack sender is not a player!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player sender() {
|
||||
return (Player) super.sender();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package me.wiefferink.areashop.events;
|
||||
|
||||
public class CancellableRegionEvent<T> extends RegionEvent<T> {
|
||||
|
||||
private boolean cancelled;
|
||||
private String reason;
|
||||
|
||||
public CancellableRegionEvent(T region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the event from happening.
|
||||
* @param reason The reason of cancelling, used for display to the user, should end with a dot
|
||||
*/
|
||||
public void cancel(String reason) {
|
||||
this.cancelled = true;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the event continue, possible overwriting a cancel() call from another plugin.
|
||||
*/
|
||||
public void allow() {
|
||||
this.cancelled = false;
|
||||
this.reason = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event has been cancelled.
|
||||
* @return true if the event has been cancelled, otherwise false
|
||||
*/
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reason why this event is cancelled.
|
||||
* @return null if there is no reason or the event is not cancelled, otherwise a string
|
||||
*/
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package me.wiefferink.areashop.events;
|
||||
|
||||
public class NotifyRegionEvent<T> extends RegionEvent<T> {
|
||||
public NotifyRegionEvent(T region) {
|
||||
super(region);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# Events
|
||||
|
||||
This package contains event classes that allow other plugins to listen to events about AreaShop regions.
|
||||
|
||||
* `RegionEvent` class represents a generic event.
|
||||
* `CancellableRegionEvent` represents an event that has a region and can be cancelled.
|
||||
* `NotifyRegionEvent` represents events that are to inform only, and cannot be cancelled anymore (an `CancellableRegionEvent` would be sent first).
|
||||
@@ -0,0 +1,31 @@
|
||||
package me.wiefferink.areashop.events;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class RegionEvent<T> extends Event {
|
||||
protected T region;
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
public RegionEvent(T region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
// Required by Bukkit/Spigot
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the region of this event.
|
||||
* @return The region the event is about
|
||||
*/
|
||||
public T getRegion() {
|
||||
return region;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region has been added to AreaShop.
|
||||
*/
|
||||
public class AddingRegionEvent extends CancellableRegionEvent<GeneralRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that has been added
|
||||
*/
|
||||
public AddingRegionEvent(GeneralRegion region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to buy a region.
|
||||
*/
|
||||
public class BuyingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
|
||||
private final OfflinePlayer player;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that is about to get bought
|
||||
* @param player The player that tries to buy the region
|
||||
*/
|
||||
public BuyingRegionEvent(BuyRegion region, OfflinePlayer player) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player that is trying to buy the region.
|
||||
* @return The player that is trying to buy the region
|
||||
*/
|
||||
public OfflinePlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region has been added to AreaShop.
|
||||
*/
|
||||
public class DeletingRegionEvent extends CancellableRegionEvent<GeneralRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that has been added
|
||||
*/
|
||||
public DeletingRegionEvent(GeneralRegion region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to rent a region.
|
||||
*/
|
||||
public class RentingRegionEvent extends CancellableRegionEvent<RentRegion> {
|
||||
|
||||
private final OfflinePlayer player;
|
||||
private final boolean extending;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that is about to be rented
|
||||
* @param player The player that tries to rent the region
|
||||
* @param extending true if the player is extending the rental of the region, otherwise false
|
||||
*/
|
||||
public RentingRegionEvent(RentRegion region, OfflinePlayer player, boolean extending) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
this.extending = extending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player that is trying to rent the region.
|
||||
* @return The player that is trying to rent the region
|
||||
*/
|
||||
public OfflinePlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player is extending the region or renting it for the first time.
|
||||
* @return true if the player tries to extend the region, false if he tries to rent it the first time
|
||||
*/
|
||||
public boolean isExtending() {
|
||||
return extending;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
/**
|
||||
* Broadcasted when a player tries to resell a region.
|
||||
*/
|
||||
public class ResellingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
|
||||
private final OfflinePlayer player;
|
||||
|
||||
/**
|
||||
* Contructor.
|
||||
* @param region The region that the player is trying to resell
|
||||
* @param player The player that is trying to buy this region from the current owner
|
||||
*/
|
||||
public ResellingRegionEvent(BuyRegion region, OfflinePlayer player) {
|
||||
super(region);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player that is trying to buy the region.
|
||||
* @return The player that is trying to buy the region
|
||||
*/
|
||||
public OfflinePlayer getBuyer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region is about to get sold.
|
||||
*/
|
||||
public class SellingRegionEvent extends CancellableRegionEvent<BuyRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that is about to get sold
|
||||
*/
|
||||
public SellingRegionEvent(BuyRegion region) {
|
||||
super(region);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.wiefferink.areashop.events.ask;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.RentRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region is about to be unrented.
|
||||
*/
|
||||
public class UnrentingRegionEvent extends CancellableRegionEvent<RentRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that is about to be unrented
|
||||
*/
|
||||
public UnrentingRegionEvent(RentRegion region) {
|
||||
super(region);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package me.wiefferink.areashop.events.askandnotify;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
/**
|
||||
* Broadcasted when a friend is being added to a region.
|
||||
*/
|
||||
public class AddedFriendEvent extends CancellableRegionEvent<GeneralRegion> {
|
||||
|
||||
private final OfflinePlayer friend;
|
||||
private final CommandSender by;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region the friend is getting added to
|
||||
* @param friend The friend that is about to be added
|
||||
* @param by The CommandSender that is adding the friend, or null if none
|
||||
*/
|
||||
public AddedFriendEvent(GeneralRegion region, OfflinePlayer friend, CommandSender by) {
|
||||
super(region);
|
||||
this.friend = friend;
|
||||
this.by = by;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OfflinePlayer that is getting added as friend.
|
||||
* @return The friend that is getting added
|
||||
*/
|
||||
public OfflinePlayer getFriend() {
|
||||
return friend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CommandSender that is adding the friend.
|
||||
* @return null if none, a CommandSender if done by someone (likely Player or ConsoleCommandSender)
|
||||
*/
|
||||
public CommandSender getBy() {
|
||||
return by;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package me.wiefferink.areashop.events.askandnotify;
|
||||
|
||||
import me.wiefferink.areashop.events.CancellableRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
/**
|
||||
* Broadcasted when a friend is being added to a region.
|
||||
*/
|
||||
public class DeletedFriendEvent extends CancellableRegionEvent<GeneralRegion> {
|
||||
|
||||
private final OfflinePlayer friend;
|
||||
private final CommandSender by;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region the friend is getting added to
|
||||
* @param friend The friend that is about to be added
|
||||
* @param by The CommandSender that is adding the friend, or null if none
|
||||
*/
|
||||
public DeletedFriendEvent(GeneralRegion region, OfflinePlayer friend, CommandSender by) {
|
||||
super(region);
|
||||
this.friend = friend;
|
||||
this.by = by;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OfflinePlayer that is getting added as friend.
|
||||
* @return The friend that is getting added
|
||||
*/
|
||||
public OfflinePlayer getFriend() {
|
||||
return friend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CommandSender that is adding the friend.
|
||||
* @return null if none, a CommandSender if done by someone (likely Player or ConsoleCommandSender)
|
||||
*/
|
||||
public CommandSender getBy() {
|
||||
return by;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.wiefferink.areashop.events.notify;
|
||||
|
||||
import me.wiefferink.areashop.events.NotifyRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region has been added to AreaShop.
|
||||
*/
|
||||
public class AddedRegionEvent extends NotifyRegionEvent<GeneralRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that has been added
|
||||
*/
|
||||
public AddedRegionEvent(GeneralRegion region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.wiefferink.areashop.events.notify;
|
||||
|
||||
import me.wiefferink.areashop.events.NotifyRegionEvent;
|
||||
import me.wiefferink.areashop.regions.BuyRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region has been bought.
|
||||
*/
|
||||
public class BoughtRegionEvent extends NotifyRegionEvent<BuyRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that has been bought
|
||||
*/
|
||||
public BoughtRegionEvent(BuyRegion region) {
|
||||
super(region);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package me.wiefferink.areashop.events.notify;
|
||||
|
||||
import me.wiefferink.areashop.events.NotifyRegionEvent;
|
||||
import me.wiefferink.areashop.regions.GeneralRegion;
|
||||
|
||||
/**
|
||||
* Broadcasted when a region has been removed from AreaShop.
|
||||
*/
|
||||
public class DeletedRegionEvent extends NotifyRegionEvent<GeneralRegion> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param region The region that has been removed
|
||||
*/
|
||||
public DeletedRegionEvent(GeneralRegion region) {
|
||||
super(region);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 278 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user