mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-10-31 15:59:48 +01:00
Compare commits
615 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
41a2484c9d | ||
|
68f2a0f59f | ||
|
3288d22334 | ||
|
c5b1a9037f | ||
|
2cb0651f95 | ||
|
68d53798e9 | ||
|
cc7917b14f | ||
|
2ba295024f | ||
|
8160e08d4f | ||
|
d758c92621 | ||
|
03888f811d | ||
|
9a24ee9537 | ||
|
fdd8b7f894 | ||
|
618a86b464 | ||
|
c994dbdd3d | ||
|
6a638a550f | ||
|
68ede87bb9 | ||
|
57b8a517f0 | ||
|
84b0fa37a2 | ||
|
3d696e10d5 | ||
|
801af3d592 | ||
|
13756cf023 | ||
|
f9c34e5df6 | ||
|
6766c0f906 | ||
|
4c396a136c | ||
|
e0a3f48aed | ||
|
ca9c81e47b | ||
|
58690f203b | ||
|
4cc354eed5 | ||
|
32a9f71b8e | ||
|
bac59d7385 | ||
|
29c50574c3 | ||
|
97aff7a564 | ||
|
0da7130165 | ||
|
9cb8d1cb5e | ||
|
1085332537 | ||
|
b949727912 | ||
|
3992102355 | ||
|
81fb17d90e | ||
|
1782dd666f | ||
|
a7f9f21e65 | ||
|
aa19319d58 | ||
|
6d8ac151b4 | ||
|
80e1063015 | ||
|
83b7c66c4f | ||
|
f1219ecc02 | ||
|
4a972a86ae | ||
|
2784f197cb | ||
|
fd1ab22cee | ||
|
69de5ea564 | ||
|
541d9667fe | ||
|
234fa63a4d | ||
|
a5fee6b37c | ||
|
b5ff3544e7 | ||
|
a40e9eceba | ||
|
a15b437249 | ||
|
37ba89a00f | ||
|
d2410a5f85 | ||
|
e90755d73d | ||
|
4876064a46 | ||
|
5a4cbcce25 | ||
|
625bfa631b | ||
|
060e700fce | ||
|
0965e07d93 | ||
|
f5abdd4c78 | ||
|
2b6c7f85a6 | ||
|
ab8f3a7d70 | ||
|
8240484d4f | ||
|
8ba3f034f7 | ||
|
6896a4579c | ||
|
a9b8613cdc | ||
|
a716feb9a6 | ||
|
80219f38cb | ||
|
dbf4bb75b1 | ||
|
86c9a8f47b | ||
|
e5469b7750 | ||
|
7050973b11 | ||
|
c503ae6134 | ||
|
b4615697fc | ||
|
11259415cc | ||
|
e87cd7e4d2 | ||
|
97d42e4151 | ||
|
d654776d87 | ||
|
3fbfd27e64 | ||
|
e110750a91 | ||
|
caae0af50e | ||
|
2a56414b40 | ||
|
82a77d70ac | ||
|
05524ae69c | ||
|
debcd2c331 | ||
|
28457aba52 | ||
|
e476f33743 | ||
|
bd028aa5f2 | ||
|
86eb9f5edd | ||
|
c2737f00e1 | ||
|
5521c8258d | ||
|
834b60012a | ||
|
7962e3ebc7 | ||
|
8ee366de51 | ||
|
36fde3cfee | ||
|
8d75bc697b | ||
|
8e3f368602 | ||
|
3d3965fe17 | ||
|
b73f63a644 | ||
|
c4339878f5 | ||
|
c73403322c | ||
|
908230047f | ||
|
5424cb9339 | ||
|
6cbbdad34e | ||
|
fdbb2480b4 | ||
|
9305bf7163 | ||
|
04745330c7 | ||
|
09c9e9348b | ||
|
d82b3488a2 | ||
|
103a611b8e | ||
|
3ee840f467 | ||
|
5df1965778 | ||
|
1b22725194 | ||
|
d3123a75bb | ||
|
137622fcae | ||
|
67dd30e709 | ||
|
3c29f88d23 | ||
|
bb80a15399 | ||
|
50dba5cb82 | ||
|
ed700a1915 | ||
|
27ba0fe26e | ||
|
21efeb813b | ||
|
d2a6398b4d | ||
|
3194195009 | ||
|
ac9aa91532 | ||
|
220fc72a21 | ||
|
c9c57e113f | ||
|
7ed9ceaf22 | ||
|
2f055b2a8e | ||
|
afe07a8c23 | ||
|
0766f2967d | ||
|
505de3b5f9 | ||
|
5e3c55f3d6 | ||
|
fc589334df | ||
|
fc22fd23da | ||
|
ef86bdbdc5 | ||
|
d704aa9c67 | ||
|
cccc9ee98d | ||
|
1155ffd08e | ||
|
f4d3e791d6 | ||
|
037e66f6f6 | ||
|
86945bdfbe | ||
|
fcff388810 | ||
|
ad10205c99 | ||
|
05eef0f8ef | ||
|
11540c047f | ||
|
4bfd405c4e | ||
|
a7c9ae6e36 | ||
|
93d50db77f | ||
|
9fccb89261 | ||
|
30ffc5f919 | ||
|
c1582a81cd | ||
|
c6ed2a8ccd | ||
|
d9ef8dfd10 | ||
|
f515ae2e84 | ||
|
72515170d4 | ||
|
18cd62dd6c | ||
|
570fe7448e | ||
|
b4ecb1dadd | ||
|
1c5a52de4c | ||
|
16592c595b | ||
|
3d00191b90 | ||
|
b2d5e0b84e | ||
|
2d9bbb9cc1 | ||
|
2733e31535 | ||
|
34060740c7 | ||
|
a77b380fb0 | ||
|
945728ccac | ||
|
84be104a07 | ||
|
2b1f18eafe | ||
|
950aff3502 | ||
|
251abae6cb | ||
|
a8f01f746e | ||
|
cb2d0e7efd | ||
|
f4604b4c27 | ||
|
755452cd3c | ||
|
8e97dcff7e | ||
|
6bb148ec76 | ||
|
5e0d80e514 | ||
|
e7be920376 | ||
|
ff1438f3a3 | ||
|
a969bbf317 | ||
|
0ffa213fd2 | ||
|
566956fc54 | ||
|
4cd2c8a284 | ||
|
59fd8d94b5 | ||
|
58937d6353 | ||
|
534fd675b3 | ||
|
24fa4fe8d3 | ||
|
2f9e3c42fd | ||
|
09c5cbb449 | ||
|
894b063694 | ||
|
d23f15f16f | ||
|
96564275a8 | ||
|
86e5a02516 | ||
|
156c3da3bb | ||
|
0938df8824 | ||
|
f68af5529f | ||
|
d831722821 | ||
|
961a35bace | ||
|
affb0c263a | ||
|
250c7950f9 | ||
|
01dcd6ecc6 | ||
|
475f6372e2 | ||
|
8e68349004 | ||
|
fc9b00233b | ||
|
1fd4a9043f | ||
|
ee3b0bfcc2 | ||
|
35704b3fd3 | ||
|
60fa60372d | ||
|
8b0a5a3d0b | ||
|
ca15740a8c | ||
|
5e5707f2a2 | ||
|
ef58838c41 | ||
|
885d2449d9 | ||
|
888b485f82 | ||
|
e2d9c2ce34 | ||
|
8aba736383 | ||
|
50276cb8e5 | ||
|
d701b7e43c | ||
|
2fc3396a8f | ||
|
99717f5b60 | ||
|
290158e6ef | ||
|
7126e837ed | ||
|
45e5621d4c | ||
|
f536a13c59 | ||
|
f4780659e3 | ||
|
aad50eab38 | ||
|
24d81da907 | ||
|
d288528a17 | ||
|
83698c267f | ||
|
52a280dc0b | ||
|
4a0d44c035 | ||
|
b8e1f33800 | ||
|
d8891796cd | ||
|
61e7c22bbc | ||
|
b1fe76c45d | ||
|
5afd454fb3 | ||
|
a55c51412d | ||
|
01a8055379 | ||
|
744665a16e | ||
|
3e4ff33d30 | ||
|
09ede87971 | ||
|
b1418c144f | ||
|
15335eb992 | ||
|
e33823d0c0 | ||
|
63cc0a01d9 | ||
|
6949432cb6 | ||
|
8649afdc4b | ||
|
69a22e917e | ||
|
ffb955b22b | ||
|
3de0ff236e | ||
|
c86eb6a19c | ||
|
e7055c6cba | ||
|
5834dcbb59 | ||
|
2c75939bc3 | ||
|
e570401912 | ||
|
f6f4da1c89 | ||
|
6106b661e9 | ||
|
e1536fcae0 | ||
|
1c19703f44 | ||
|
24b7d26fbe | ||
|
ec60991aeb | ||
|
33000f9371 | ||
|
83eaa50b49 | ||
|
1215a43766 | ||
|
81f765df36 | ||
|
0e6a25d74b | ||
|
2b19d43c85 | ||
|
1bce4ec1b9 | ||
|
ea8562f351 | ||
|
d8f2c12fe5 | ||
|
b734d579a1 | ||
|
44454f5854 | ||
|
da590ce319 | ||
|
6599e3de80 | ||
|
3c6e3d1286 | ||
|
d77c94c30c | ||
|
d240e9c8d8 | ||
|
49d05054d2 | ||
|
75412a4674 | ||
|
40e96b9169 | ||
|
db2b97d2fc | ||
|
5ad2ba1cd9 | ||
|
6127cdced1 | ||
|
91998b4e24 | ||
|
06ca7a311a | ||
|
e4e92b9634 | ||
|
0c4a4ba862 | ||
|
3907cba08f | ||
|
4064c9a241 | ||
|
b45c842c2f | ||
|
e2a4233f69 | ||
|
977c82015b | ||
|
6db04f872b | ||
|
6fccf80477 | ||
|
eef3dcbc46 | ||
|
253e5d7101 | ||
|
1c4be17690 | ||
|
dc42f51168 | ||
|
1fb6a8a27c | ||
|
4170616e47 | ||
|
7f532b1257 | ||
|
c39bd75837 | ||
|
4810c4c4ad | ||
|
cb7c63a520 | ||
|
dcc3992762 | ||
|
57164dd846 | ||
|
69017860a0 | ||
|
24c68a0d95 | ||
|
994019836a | ||
|
bbafa6d340 | ||
|
19d81c70c6 | ||
|
7d52325196 | ||
|
2d08365afc | ||
|
a3a4a70921 | ||
|
bb9ed87175 | ||
|
0e833de22a | ||
|
95d89c56bc | ||
|
4ddb204fcf | ||
|
562b515bfe | ||
|
0a9da71c65 | ||
|
631a15563d | ||
|
f93c9ba556 | ||
|
f568ccd2d6 | ||
|
f11a56cc6b | ||
|
ad009156e5 | ||
|
78f84de3cb | ||
|
070c1102db | ||
|
a1d19fae74 | ||
|
59124cfa8a | ||
|
887f09c41b | ||
|
e8acd05dbe | ||
|
3784d5d28d | ||
|
95b7ed137f | ||
|
87b147ace4 | ||
|
1846ed8088 | ||
|
af843aeb35 | ||
|
b43197d54f | ||
|
38551a138a | ||
|
83479ac8a4 | ||
|
5e4634400a | ||
|
f81354fa3e | ||
|
24025fd9ae | ||
|
87054687f0 | ||
|
01f51f4d29 | ||
|
59c18e26f5 | ||
|
b63aef5589 | ||
|
2d0d9ac1c2 | ||
|
8217b375d5 | ||
|
43db8d346c | ||
|
9acb79fc60 | ||
|
6316ff4a93 | ||
|
471e8d681b | ||
|
196e90bf4e | ||
|
c100fe0047 | ||
|
b2550882ba | ||
|
6bf12d5e20 | ||
|
c9b7074e79 | ||
|
b25c65b7b2 | ||
|
787424b999 | ||
|
13bd1bb8f3 | ||
|
5d3821094c | ||
|
90a53e9fd8 | ||
|
ffcda52912 | ||
|
b672755ef9 | ||
|
7c3056b0e8 | ||
|
2d44c5dbca | ||
|
ce4d8a377e | ||
|
cc7b1eba4c | ||
|
4bfbe41956 | ||
|
76a36e685e | ||
|
f1001b1d05 | ||
|
98d336faf0 | ||
|
edd7bcfbd2 | ||
|
be9b429308 | ||
|
26e5d750a0 | ||
|
ca2976cc4b | ||
|
54a7b8b0f2 | ||
|
0e0c502e1d | ||
|
68da898e79 | ||
|
c62d4f603f | ||
|
29a6a51f30 | ||
|
fc658ca073 | ||
|
caade1a71c | ||
|
31fb10629a | ||
|
38d845d2e9 | ||
|
bfb487342a | ||
|
3be034bfa9 | ||
|
e8e1d6184e | ||
|
0352cfdd38 | ||
|
cc5c8aa9b6 | ||
|
86d8d147d1 | ||
|
96499f3ad6 | ||
|
b260cf1f4f | ||
|
f6e26aa5bd | ||
|
1ef55a2b1e | ||
|
b2f5a441e5 | ||
|
8dce036d70 | ||
|
55e94b4c9f | ||
|
5a193cda1c | ||
|
1ab2ff278d | ||
|
1942f5f1df | ||
|
79b95af8bd | ||
|
af861f2a34 | ||
|
6964f8c61a | ||
|
12bf37d2c2 | ||
|
22f398fe53 | ||
|
f256c3af8d | ||
|
54ebf2dfd2 | ||
|
26e6310fba | ||
|
f80cf238f0 | ||
|
187ae1c61a | ||
|
ea6b5dd257 | ||
|
9fe5212c3c | ||
|
625b70de30 | ||
|
4547232ac9 | ||
|
90751224d7 | ||
|
59c84990e5 | ||
|
13c339ef4f | ||
|
5de7302469 | ||
|
1cf7ccbb99 | ||
|
defb1c7a6e | ||
|
0ecbd9150b | ||
|
2818ac8f33 | ||
|
70e4ae15b7 | ||
|
d95727fbdf | ||
|
26dc5c5949 | ||
|
a35353a802 | ||
|
63d092db93 | ||
|
19d7e2fe0a | ||
|
c63de278fe | ||
|
24148f30ba | ||
|
4481881b9e | ||
|
285205fe3f | ||
|
5503ce0d90 | ||
|
6d09a5a359 | ||
|
4200fe4abb | ||
|
4a6bf31dff | ||
|
d903e57ad6 | ||
|
fd99da68d9 | ||
|
7f50073ad1 | ||
|
c4fa6cf26e | ||
|
39882cb7bc | ||
|
4e0e3d2005 | ||
|
c195baf66d | ||
|
b3808334ad | ||
|
9e8df5ce80 | ||
|
2c49e6d2f4 | ||
|
5ccaadb2ae | ||
|
8d0dbcdc36 | ||
|
e4836b9cef | ||
|
af3b0bba2d | ||
|
ea5529f077 | ||
|
489a1e332d | ||
|
c8b2e1d801 | ||
|
a2f1054bbe | ||
|
9f8a6bcded | ||
|
dc51bd87b1 | ||
|
2b65543935 | ||
|
7fbd041be9 | ||
|
6d2f79881b | ||
|
e6ccce4a27 | ||
|
8b78affc9b | ||
|
5c3ebc800c | ||
|
2bc82dd3cf | ||
|
a4bef159be | ||
|
503107a90c | ||
|
b276c0715c | ||
|
8d3be9c0ff | ||
|
ba31dd78b4 | ||
|
a7b791f4be | ||
|
bcf569c019 | ||
|
b2bdce4d25 | ||
|
a6f47e5c54 | ||
|
33a694cfd1 | ||
|
6a5ea171be | ||
|
d6978ce0f6 | ||
|
e23207df2f | ||
|
0f6d5af1f8 | ||
|
da2daae990 | ||
|
aed78038ef | ||
|
1228da131f | ||
|
08d73f232b | ||
|
06ccb8a5e0 | ||
|
768988e803 | ||
|
fd91ab596b | ||
|
397f9e4700 | ||
|
1b2748f920 | ||
|
78092aa3e9 | ||
|
475e67c447 | ||
|
2ad7796582 | ||
|
3e1dc81592 | ||
|
fec43adc35 | ||
|
7a21aba3a8 | ||
|
62a3a8d6fa | ||
|
1a0a314ece | ||
|
2512a892fd | ||
|
850939f3a8 | ||
|
8ce78c8fe0 | ||
|
2dfd136591 | ||
|
357a8fdc5f | ||
|
a0b349ec27 | ||
|
585f720f6f | ||
|
a6bb78c80f | ||
|
c5baa1d0eb | ||
|
988ace8329 | ||
|
170c31fcec | ||
|
211d636bfb | ||
|
4ef974fbde | ||
|
9a464ab795 | ||
|
39a6fc5006 | ||
|
325c9c2351 | ||
|
30d29c6ff9 | ||
|
2c8db2a797 | ||
|
df45fca562 | ||
|
df6fb7d716 | ||
|
54139b60f0 | ||
|
74a2e9d3c8 | ||
|
5953df9dbb | ||
|
363b23a049 | ||
|
9334858675 | ||
|
7d25aff28f | ||
|
f47e87af82 | ||
|
6d3349a0f9 | ||
|
9bd0104a3d | ||
|
7b8e18afff | ||
|
f23ebec34e | ||
|
9c6cc78c32 | ||
|
c28ecb1c74 | ||
|
cbed9ac831 | ||
|
e846d26fab | ||
|
4c0cb9f17c | ||
|
0038c3f2b7 | ||
|
66d27e7070 | ||
|
4b0c5ec894 | ||
|
1a416d9a23 | ||
|
74e053ef8a | ||
|
2ed2492ce3 | ||
|
2b4e1dd5eb | ||
|
89a9b13d81 | ||
|
b50063685f | ||
|
01313def01 | ||
|
2805e5889b | ||
|
a7ffb79f1d | ||
|
0856d48470 | ||
|
4d295068cf | ||
|
bcb4ed28b8 | ||
|
d6d86d39d2 | ||
|
c6a8f7c095 | ||
|
372f3f14c6 | ||
|
393a0131f9 | ||
|
c0beba7467 | ||
|
5c2166fc93 | ||
|
a90a00b09b | ||
|
09c60f24cf | ||
|
b512975b13 | ||
|
e9067cfb28 | ||
|
5a52978803 | ||
|
b64015e3b6 | ||
|
c000da6e6f | ||
|
2672ee5d1b | ||
|
d25d1713f8 | ||
|
6932ce3759 | ||
|
38ddeff369 | ||
|
e4a3891590 | ||
|
7bb1907897 | ||
|
5f6b91bc64 | ||
|
fdc03df298 | ||
|
eb76d00f80 | ||
|
a7b1028496 | ||
|
9ffc838f2d | ||
|
d0d01dbc2b | ||
|
8f954090e7 | ||
|
84adfaa622 | ||
|
f05d4dc57f | ||
|
e991f09921 | ||
|
f52150ec1d | ||
|
ce5830e2ad | ||
|
577e476796 | ||
|
8d0fcf0169 | ||
|
0ee9ff4f10 | ||
|
84e6523b9d | ||
|
5c5077a6b5 | ||
|
9ee5bcbcf2 | ||
|
c235abbfa6 | ||
|
b4737f104c | ||
|
ba19b08f4c | ||
|
073f3a49d5 | ||
|
1a293a6936 | ||
|
85a7375004 | ||
|
25e601b26c | ||
|
907268c2f4 | ||
|
6894695024 | ||
|
233e5ceb65 | ||
|
5d67dbe5e3 | ||
|
2cb561b943 | ||
|
ca604f893c | ||
|
3285ef1ad2 | ||
|
70f044265a | ||
|
2940d2e492 | ||
|
c31458f8e6 | ||
|
2b40ae47d7 | ||
|
2c283ae3a9 | ||
|
f02b4d5011 | ||
|
6925a788f3 | ||
|
1b81e74f4c | ||
|
999ca242d7 | ||
|
7d0eb3586d | ||
|
a713b7be07 |
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@ -10,22 +10,22 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
java-version: '21'
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
- run: mvn --batch-mode clean org.jacoco:jacoco-maven-plugin:prepare-agent install
|
||||
- run: mkdir staging && cp target/*.jar staging
|
||||
- name: Save artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Package
|
||||
path: staging
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
[![Discord](https://img.shields.io/discord/272499714048524288.svg?logo=discord)](https://discord.bentobox.world)
|
||||
[![Build Status](https://ci.codemc.org/buildStatus/icon?job=BentoBoxWorld/BentoBox)](https://ci.codemc.org/job/BentoBoxWorld/job/BentoBox/)
|
||||
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=BentoBoxWorld_BentoBox&metric=ncloc)](https://sonarcloud.io/dashboard?id=BentoBoxWorld_BentoBox)
|
||||
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=BentoBoxWorld_BentoBox&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=BentoBoxWorld_BentoBox)
|
||||
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=BentoBoxWorld_BentoBox&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=BentoBoxWorld_BentoBox)
|
||||
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=BentoBoxWorld_BentoBox&metric=security_rating)](https://sonarcloud.io/dashboard?id=BentoBoxWorld_BentoBox)
|
||||
@ -112,9 +111,10 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'world.bentobox:bentobox:PUT-VERSION-HERE'
|
||||
compileOnly 'world.bentobox:bentobox:PUT-VERSION-HERE-SNAPSHOT'
|
||||
}
|
||||
```
|
||||
**Note:** Due to a Gradle issue with versions for Maven, you need to use -SNAPSHOT at the end.
|
||||
|
||||
### History
|
||||
|
||||
|
204
pom.xml
204
pom.xml
@ -67,16 +67,16 @@
|
||||
<!-- Non-minecraft related dependencies -->
|
||||
<powermock.version>2.0.9</powermock.version>
|
||||
<!-- Database related dependencies -->
|
||||
<mongodb.version>3.12.8</mongodb.version>
|
||||
<mongodb.version>3.12.12</mongodb.version>
|
||||
<mariadb.version>3.0.5</mariadb.version>
|
||||
<mysql.version>8.0.27</mysql.version>
|
||||
<postgresql.version>42.2.18</postgresql.version>
|
||||
<hikaricp.version>5.0.1</hikaricp.version>
|
||||
<!-- More visible way to change dependency versions -->
|
||||
<spigot.version>1.19.3-R0.1-SNAPSHOT</spigot.version>
|
||||
<spigot.version>1.21.3-R0.1-SNAPSHOT</spigot.version>
|
||||
<!-- Might differ from the last Spigot release for short periods
|
||||
of time -->
|
||||
<paper.version>1.19-R0.1-SNAPSHOT</paper.version>
|
||||
<paper.version>1.21.1-R0.1-SNAPSHOT</paper.version>
|
||||
<bstats.version>3.0.0</bstats.version>
|
||||
<vault.version>1.7.1</vault.version>
|
||||
<placeholderapi.version>2.10.9</placeholderapi.version>
|
||||
@ -88,9 +88,10 @@
|
||||
<!-- Do not change unless you want different name for local builds. -->
|
||||
<build.number>-LOCAL</build.number>
|
||||
<!-- This allows to change between versions. -->
|
||||
<build.version>1.22.0</build.version>
|
||||
<build.version>2.7.0</build.version>
|
||||
<sonar.organization>bentobox-world</sonar.organization>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
<server.jars>${project.basedir}/lib</server.jars>
|
||||
</properties>
|
||||
|
||||
<!-- Profiles will allow to automatically change build version. -->
|
||||
@ -126,6 +127,7 @@
|
||||
<value>origin/master</value>
|
||||
</property>
|
||||
</activation>
|
||||
<!--suppress CheckTagEmptyBody -->
|
||||
<properties>
|
||||
<!-- Override only if necessary -->
|
||||
<revision>${build.version}</revision>
|
||||
@ -143,6 +145,10 @@
|
||||
</pluginRepositories>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
|
||||
@ -151,14 +157,6 @@
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>placeholderapi-repo</id>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dynmap-repo</id>
|
||||
<url>https://repo.mikeprimm.com/</url>
|
||||
@ -187,44 +185,28 @@
|
||||
<id>MG-Dev Jenkins CI Maven Repository</id>
|
||||
<url>https://ci.mg-dev.eu/plugin/repository/everything</url>
|
||||
</repository>
|
||||
<!-- For MythicMobs -->
|
||||
<repository>
|
||||
<id>nexus</id>
|
||||
<name>Lumine Releases</name>
|
||||
<url>https://mvn.lumine.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<!-- For Multipaper -->
|
||||
<repository>
|
||||
<id>clojars</id>
|
||||
<url>https://repo.clojars.org/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spigot API -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>${spigot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Paper API -->
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>${paper.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- AuthLib. Used for Head Getter. -->
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>authlib</artifactId>
|
||||
<version>3.16.29</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Metrics -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>${bstats.version}</version>
|
||||
</dependency>
|
||||
<!-- Mockito (Unit testing) -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.11.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Mockito (Unit testing) This goes at the top to ensure the dependencies are accurate. -->
|
||||
<!-- This is required for PowerMockito to work and must be placed before it -->
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.30.2-GA</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
@ -236,6 +218,69 @@
|
||||
<version>${powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.11.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- For test that need a time to test -->
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>4.2.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Spigot API -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>${spigot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc.....</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc....</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.20.6-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc.</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.20.3-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc..</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.20.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc...</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.20.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Paper API -->
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>${paper.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Metrics -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>${bstats.version}</version>
|
||||
</dependency>
|
||||
<!-- Database -->
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
@ -278,6 +323,12 @@
|
||||
<version>${myworlds.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.lumine</groupId>
|
||||
<artifactId>Mythic-Dist</artifactId>
|
||||
<version>5.3.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Shaded APIs -->
|
||||
<dependency>
|
||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||
@ -312,13 +363,34 @@
|
||||
<version>3.2.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Spigot NMS. Used for chunk deletion and pasting. -->
|
||||
<!-- Spigot NMS. Used for chunk deletion and pasting.-->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>${spigot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Slimefun -->
|
||||
<dependency>
|
||||
<groupId>com.github.Slimefun</groupId>
|
||||
<artifactId>Slimefun4</artifactId>
|
||||
<version>RC-37</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- ItemsAdder -->
|
||||
<dependency>
|
||||
<groupId>com.github.LoneDev6</groupId>
|
||||
<artifactId>api-itemsadder</artifactId>
|
||||
<version>3.6.3-beta-14</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Multipaper -->
|
||||
<dependency>
|
||||
<groupId>com.github.puregero</groupId>
|
||||
<artifactId>multilib</artifactId>
|
||||
<version>1.1.13</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -368,6 +440,7 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M5</version>
|
||||
<!--suppress MavenModelInspection -->
|
||||
<configuration>
|
||||
<argLine>
|
||||
${argLine}
|
||||
@ -375,29 +448,23 @@
|
||||
--add-opens java.base/java.math=ALL-UNNAMED
|
||||
--add-opens java.base/java.io=ALL-UNNAMED
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.util.stream=ALL-UNNAMED
|
||||
--add-opens java.base/java.util.stream=ALL-UNNAMED
|
||||
--add-opens java.base/java.text=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.util.regex=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.nio.channels.spi=ALL-UNNAMED
|
||||
--add-opens java.base/java.util.regex=ALL-UNNAMED
|
||||
--add-opens java.base/java.nio.channels.spi=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.ch=ALL-UNNAMED
|
||||
--add-opens java.base/java.net=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.util.concurrent=ALL-UNNAMED
|
||||
--add-opens java.base/java.util.concurrent=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.fs=ALL-UNNAMED
|
||||
--add-opens java.base/sun.nio.cs=ALL-UNNAMED
|
||||
--add-opens java.base/java.nio.file=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.nio.charset=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens
|
||||
java.logging/java.util.logging=ALL-UNNAMED
|
||||
--add-opens java.base/java.nio.charset=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
|
||||
--add-opens java.logging/java.util.logging=ALL-UNNAMED
|
||||
--add-opens java.base/java.lang.ref=ALL-UNNAMED
|
||||
--add-opens java.base/java.util.jar=ALL-UNNAMED
|
||||
--add-opens java.base/java.util.zip=ALL-UNNAMED
|
||||
--add-opens=java.base/java.security=ALL-UNNAMED
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@ -446,9 +513,10 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.4.0</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
@ -460,9 +528,13 @@
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>io.papermc.lib</pattern>
|
||||
<shadedPattern>world.bentobox.bentobox.paperlib</shadedPattern> <!-- Replace this -->
|
||||
<shadedPattern>world.bentobox.bentobox.paperlib</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<relocation>
|
||||
<pattern>com.github.puregero.multilib</pattern>
|
||||
<shadedPattern>world.bentobox.bentobox.multilib</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.apache.maven.shared:*</exclude>
|
||||
@ -504,13 +576,15 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.7</version>
|
||||
<version>0.8.10</version>
|
||||
<configuration>
|
||||
<append>true</append>
|
||||
<excludes>
|
||||
<!-- This is required to prevent Jacoco from adding
|
||||
synthetic fields to a JavaBean class (causes errors in testing) -->
|
||||
<exclude>**/*Names*</exclude>
|
||||
<!-- Prevents the Material is too large to mock error -->
|
||||
<exclude>org/bukkit/Material*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
@ -11,10 +11,8 @@ import org.bstats.charts.AdvancedPie;
|
||||
import org.bstats.charts.SimpleBarChart;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
|
||||
/**
|
||||
* @author Poslovitch
|
||||
@ -59,7 +57,6 @@ public class BStats {
|
||||
registerGameModeAddonsChart();
|
||||
registerHooksChart();
|
||||
registerPlayersPerServerChart();
|
||||
registerFlagsDisplayModeChart();
|
||||
|
||||
// Single Line charts
|
||||
registerIslandsCountChart();
|
||||
@ -171,27 +168,6 @@ public class BStats {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the "flags display mode" of all the online players.
|
||||
* @since 1.6.0
|
||||
*/
|
||||
private void registerFlagsDisplayModeChart() {
|
||||
metrics.addCustomChart(new AdvancedPie("flagsDisplayMode", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
Flag.Mode mode = plugin.getPlayers().getFlagsDisplayMode(player.getUniqueId());
|
||||
if (values.containsKey(mode.name())) {
|
||||
values.put(mode.name(), values.get(mode.name()) + 1);
|
||||
} else {
|
||||
values.put(mode.name(), 1);
|
||||
}
|
||||
});
|
||||
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled addons (except GameModeAddons) of this server as bar chart.
|
||||
* @since 1.17.1
|
||||
|
@ -5,6 +5,9 @@ import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
@ -19,8 +22,12 @@ import world.bentobox.bentobox.api.user.Notifier;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.commands.BentoBoxCommand;
|
||||
import world.bentobox.bentobox.database.DatabaseSetup;
|
||||
import world.bentobox.bentobox.hooks.ItemsAdderHook;
|
||||
import world.bentobox.bentobox.hooks.MultipaperHook;
|
||||
import world.bentobox.bentobox.hooks.MultiverseCoreHook;
|
||||
import world.bentobox.bentobox.hooks.MyWorldsHook;
|
||||
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||
import world.bentobox.bentobox.hooks.SlimefunHook;
|
||||
import world.bentobox.bentobox.hooks.VaultHook;
|
||||
import world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook;
|
||||
import world.bentobox.bentobox.listeners.BannedCommands;
|
||||
@ -28,6 +35,8 @@ import world.bentobox.bentobox.listeners.BlockEndDragon;
|
||||
import world.bentobox.bentobox.listeners.DeathListener;
|
||||
import world.bentobox.bentobox.listeners.JoinLeaveListener;
|
||||
import world.bentobox.bentobox.listeners.PanelListenerManager;
|
||||
import world.bentobox.bentobox.listeners.PrimaryIslandListener;
|
||||
import world.bentobox.bentobox.listeners.SeedWorldMakerListener;
|
||||
import world.bentobox.bentobox.listeners.StandardSpawnProtectionListener;
|
||||
import world.bentobox.bentobox.listeners.teleports.EntityTeleportListener;
|
||||
import world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener;
|
||||
@ -36,7 +45,6 @@ import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.managers.CommandsManager;
|
||||
import world.bentobox.bentobox.managers.FlagsManager;
|
||||
import world.bentobox.bentobox.managers.HooksManager;
|
||||
import world.bentobox.bentobox.managers.IslandChunkDeletionManager;
|
||||
import world.bentobox.bentobox.managers.IslandDeletionManager;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
@ -52,7 +60,7 @@ import world.bentobox.bentobox.versions.ServerCompatibility;
|
||||
* Main BentoBox class
|
||||
* @author tastybento, Poslovitch
|
||||
*/
|
||||
public class BentoBox extends JavaPlugin {
|
||||
public class BentoBox extends JavaPlugin implements Listener {
|
||||
|
||||
private static BentoBox instance;
|
||||
|
||||
@ -66,12 +74,10 @@ public class BentoBox extends JavaPlugin {
|
||||
private AddonsManager addonsManager;
|
||||
private FlagsManager flagsManager;
|
||||
private IslandWorldManager islandWorldManager;
|
||||
private RanksManager ranksManager;
|
||||
private BlueprintsManager blueprintsManager;
|
||||
private HooksManager hooksManager;
|
||||
private PlaceholdersManager placeholdersManager;
|
||||
private IslandDeletionManager islandDeletionManager;
|
||||
private IslandChunkDeletionManager islandChunkDeletionManager;
|
||||
private WebManager webManager;
|
||||
|
||||
// Settings
|
||||
@ -96,6 +102,8 @@ public class BentoBox extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
setInstance(this);
|
||||
|
||||
if (!ServerCompatibility.getInstance().checkCompatibility().isCanLaunch()) {
|
||||
// The server's most likely incompatible.
|
||||
// Show a warning
|
||||
@ -117,7 +125,6 @@ public class BentoBox extends JavaPlugin {
|
||||
|
||||
// Save the default config from config.yml
|
||||
saveDefaultConfig();
|
||||
setInstance(this);
|
||||
// Load Flags
|
||||
flagsManager = new FlagsManager(this);
|
||||
|
||||
@ -135,7 +142,6 @@ public class BentoBox extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
islandsManager = new IslandsManager(this);
|
||||
ranksManager = new RanksManager();
|
||||
|
||||
// Start head getter
|
||||
headGetter = new HeadGetter(this);
|
||||
@ -179,8 +185,14 @@ public class BentoBox extends JavaPlugin {
|
||||
|
||||
private void completeSetup(long loadTime) {
|
||||
final long enableStart = System.currentTimeMillis();
|
||||
|
||||
hooksManager.registerHook(new MultipaperHook());
|
||||
|
||||
hooksManager.registerHook(new VaultHook());
|
||||
|
||||
// MythicMobs
|
||||
hooksManager.registerHook(new MythicMobsHook());
|
||||
|
||||
hooksManager.registerHook(new PlaceholderAPIHook());
|
||||
// Setup the Placeholders manager
|
||||
placeholdersManager = new PlaceholdersManager(this);
|
||||
@ -195,6 +207,7 @@ public class BentoBox extends JavaPlugin {
|
||||
registerListeners();
|
||||
|
||||
// Load islands from database - need to wait until all the worlds are loaded
|
||||
log("Loading islands from database...");
|
||||
try {
|
||||
islandsManager.load();
|
||||
} catch (Exception e) {
|
||||
@ -202,20 +215,6 @@ public class BentoBox extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save islands & players data every X minutes
|
||||
Bukkit.getScheduler().runTaskTimer(instance, () -> {
|
||||
if (!playersManager.isSaveTaskRunning()) {
|
||||
playersManager.saveAll(true);
|
||||
} else {
|
||||
getLogger().warning("Tried to start a player data save task while the previous auto save was still running!");
|
||||
}
|
||||
if (!islandsManager.isSaveTaskRunning()) {
|
||||
islandsManager.saveAll(true);
|
||||
} else {
|
||||
getLogger().warning("Tried to start a island data save task while the previous auto save was still running!");
|
||||
}
|
||||
}, getSettings().getDatabaseBackupPeriod() * 20 * 60L, getSettings().getDatabaseBackupPeriod() * 20 * 60L);
|
||||
|
||||
// Make sure all flag listeners are registered.
|
||||
flagsManager.registerListeners();
|
||||
|
||||
@ -227,7 +226,13 @@ public class BentoBox extends JavaPlugin {
|
||||
// Make sure all worlds are already registered to Multiverse.
|
||||
hooksManager.registerHook(new MultiverseCoreHook());
|
||||
hooksManager.registerHook(new MyWorldsHook());
|
||||
islandWorldManager.registerWorldsToMultiverse();
|
||||
islandWorldManager.registerWorldsToMultiverse(true);
|
||||
|
||||
// Register Slimefun
|
||||
hooksManager.registerHook(new SlimefunHook());
|
||||
|
||||
// Register ItemsAdder
|
||||
hooksManager.registerHook(new ItemsAdderHook(this));
|
||||
|
||||
// TODO: re-enable after implementation
|
||||
//hooksManager.registerHook(new DynmapHook());
|
||||
@ -250,6 +255,8 @@ public class BentoBox extends JavaPlugin {
|
||||
// Tell all addons that everything is loaded
|
||||
isLoaded = true;
|
||||
this.addonsManager.allLoaded();
|
||||
// Run ready commands
|
||||
settings.getReadyCommands().forEach(cmd -> Bukkit.getServer().dispatchCommand(getServer().getConsoleSender(), cmd));
|
||||
// Fire plugin ready event - this should go last after everything else
|
||||
Bukkit.getPluginManager().callEvent(new BentoBoxReadyEvent());
|
||||
instance.log("All blueprints loaded.");
|
||||
@ -300,10 +307,15 @@ public class BentoBox extends JavaPlugin {
|
||||
manager.registerEvents(new BannedCommands(this), this);
|
||||
// Death counter
|
||||
manager.registerEvents(new DeathListener(this), this);
|
||||
// MV unregister
|
||||
manager.registerEvents(this, this);
|
||||
// Island Delete Manager
|
||||
islandChunkDeletionManager = new IslandChunkDeletionManager(this);
|
||||
islandDeletionManager = new IslandDeletionManager(this);
|
||||
manager.registerEvents(islandDeletionManager, this);
|
||||
// Primary Island Listener
|
||||
manager.registerEvents(new PrimaryIslandListener(this), this);
|
||||
// Seed world chunk generator
|
||||
manager.registerEvents(new SeedWorldMakerListener(this), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -311,6 +323,8 @@ public class BentoBox extends JavaPlugin {
|
||||
// Stop all async database tasks
|
||||
shutdown = true;
|
||||
|
||||
HeadGetter.shutdown();
|
||||
|
||||
if (addonsManager != null) {
|
||||
addonsManager.disableAddons();
|
||||
}
|
||||
@ -321,6 +335,19 @@ public class BentoBox extends JavaPlugin {
|
||||
if (islandsManager != null) {
|
||||
islandsManager.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerStop(ServerCommandEvent e) {
|
||||
/* This is no longer needed as with https://github.com/Multiverse/Multiverse-Core/releases/tag/4.3.12 (or maybe earlier) the issue
|
||||
* is fixed where the generator was not remembered across reboots.
|
||||
*/
|
||||
/*
|
||||
if (islandWorldManager != null && (e.getCommand().equalsIgnoreCase("stop") || e.getCommand().equalsIgnoreCase("restart"))) {
|
||||
// Unregister any MV worlds if () {
|
||||
//islandWorldManager.registerWorldsToMultiverse(false);
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,9 +426,11 @@ public class BentoBox extends JavaPlugin {
|
||||
|
||||
/**
|
||||
* @return the ranksManager
|
||||
* @deprecated Just use {@code RanksManager.getInstance()}
|
||||
*/
|
||||
@Deprecated(since = "2.0.0", forRemoval = true)
|
||||
public RanksManager getRanksManager() {
|
||||
return ranksManager;
|
||||
return RanksManager.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,6 +464,7 @@ public class BentoBox extends JavaPlugin {
|
||||
getPluginLoader().disablePlugin(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -531,13 +561,6 @@ public class BentoBox extends JavaPlugin {
|
||||
return islandDeletionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the islandChunkDeletionManager
|
||||
*/
|
||||
public IslandChunkDeletionManager getIslandChunkDeletionManager() {
|
||||
return islandChunkDeletionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an optional of the Bstats instance
|
||||
* @since 1.1
|
||||
|
@ -1,50 +1,35 @@
|
||||
package world.bentobox.bentobox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import world.bentobox.bentobox.api.configuration.ConfigComment;
|
||||
import world.bentobox.bentobox.api.configuration.ConfigEntry;
|
||||
import world.bentobox.bentobox.api.configuration.ConfigObject;
|
||||
import world.bentobox.bentobox.api.configuration.StoreAt;
|
||||
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
|
||||
|
||||
|
||||
/**
|
||||
* All the plugin settings are here
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
@StoreAt(filename="config.yml") // Explicitly call out what name this should have.
|
||||
@StoreAt(filename = "config.yml") // Explicitly call out what name this should have.
|
||||
@ConfigComment("BentoBox v[version] configuration file.")
|
||||
@ConfigComment("")
|
||||
@ConfigComment("This configuration file contains settings that mainly apply to or manage the following elements:")
|
||||
@ConfigComment(" * Data storage")
|
||||
@ConfigComment(" * Gamemodes (commands, ...)")
|
||||
@ConfigComment(" * Internet connectivity (web-based content-enriched features, ...)")
|
||||
@ConfigComment("")
|
||||
@ConfigComment("Note that this configuration file is dynamic:")
|
||||
@ConfigComment(" * It gets updated with the newest settings and comments after BentoBox loaded its settings from it.")
|
||||
@ConfigComment(" * Upon updating BentoBox, new settings will be automatically added into this configuration file.")
|
||||
@ConfigComment(" * Said settings are distinguishable by a dedicated comment, which looks like this:")
|
||||
@ConfigComment(" Added since X.Y.Z.")
|
||||
@ConfigComment(" * They are provided with default values that should not cause issues on live production servers.")
|
||||
@ConfigComment(" * You can however edit this file while the server is online.")
|
||||
@ConfigComment(" You will therefore need to run the following command in order to take the changes into account: /bentobox reload.")
|
||||
@ConfigComment("")
|
||||
@ConfigComment("Here are a few pieces of advice before you get started:")
|
||||
@ConfigComment(" * You should check out our Wiki, which may provide you useful tips or insights about BentoBox's features.")
|
||||
@ConfigComment(" Link: https://github.com/BentoBoxWorld/BentoBox/wiki")
|
||||
@ConfigComment(" * You should edit this configuration file while the server is offline.")
|
||||
@ConfigComment(" * Moreover, whenever you update BentoBox, you should do so on a test server first.")
|
||||
@ConfigComment(" This will allow you to configure the new settings beforehand instead of applying them inadvertently on a live production server.")
|
||||
public class Settings implements ConfigObject {
|
||||
|
||||
/* GENERAL */
|
||||
/* GENERAL */
|
||||
@ConfigComment("Default language for new players.")
|
||||
@ConfigComment("This is the filename in the locale folder without .yml.")
|
||||
@ConfigComment("If this does not exist, the default en-US will be used.")
|
||||
@ -56,10 +41,17 @@ public class Settings implements ConfigObject {
|
||||
@ConfigEntry(path = "general.use-economy")
|
||||
private boolean useEconomy = true;
|
||||
|
||||
/* COMMANDS */
|
||||
@ConfigComment("Console commands to run when BentoBox has loaded all worlds and addons.")
|
||||
@ConfigComment("Commands are run as the console.")
|
||||
@ConfigComment("e.g. set aliases for worlds in Multiverse here, or anything you need to")
|
||||
@ConfigComment("run after the plugin is fully loaded.")
|
||||
@ConfigEntry(path = "general.ready-commands", since = "1.24.2")
|
||||
private List<String> readyCommands = new ArrayList<>();
|
||||
|
||||
// Database
|
||||
@ConfigComment("JSON, MYSQL, MARIADB, MONGODB, SQLITE, POSTGRESQL and YAML(deprecated).")
|
||||
@ConfigComment("JSON, MYSQL, MARIADB, MONGODB, SQLITE, and POSTGRESQL.")
|
||||
@ConfigComment("Transition database options are:")
|
||||
@ConfigComment(" YAML2JSON, YAML2MARIADB, YAML2MYSQL, YAML2MONGODB, YAML2SQLITE")
|
||||
@ConfigComment(" JSON2MARIADB, JSON2MYSQL, JSON2MONGODB, JSON2SQLITE, JSON2POSTGRESQL")
|
||||
@ConfigComment(" MYSQL2JSON, MARIADB2JSON, MONGODB2JSON, SQLITE2JSON, POSTGRESQL2JSON")
|
||||
@ConfigComment("If you need others, please make a feature request.")
|
||||
@ -70,7 +62,7 @@ public class Settings implements ConfigObject {
|
||||
@ConfigComment(" SQLite versions 3.28 or later")
|
||||
@ConfigComment(" PostgreSQL versions 9.4 or later")
|
||||
@ConfigComment("Transition options enable migration from one database type to another. Use /bbox migrate.")
|
||||
@ConfigComment("YAML and JSON are file-based databases.")
|
||||
@ConfigComment("JSON is a file-based database.")
|
||||
@ConfigComment("MYSQL might not work with all implementations: if available, use a dedicated database type (e.g. MARIADB).")
|
||||
@ConfigComment("BentoBox uses HikariCP for connecting with SQL databases.")
|
||||
@ConfigComment("If you use MONGODB, you must also run the BSBMongo plugin (not addon).")
|
||||
@ -149,7 +141,6 @@ public class Settings implements ConfigObject {
|
||||
private Set<String> fakePlayers = new HashSet<>();
|
||||
|
||||
/* PANELS */
|
||||
|
||||
@ConfigComment("Toggle whether panels should be closed or not when the player clicks anywhere outside of the inventory view.")
|
||||
@ConfigEntry(path = "panel.close-on-click-outside")
|
||||
private boolean closePanelOnClickOutside = true;
|
||||
@ -197,6 +188,25 @@ public class Settings implements ConfigObject {
|
||||
/*
|
||||
* Island
|
||||
*/
|
||||
@ConfigComment("Override island distance mismatch checking. BentoBox normally refuses to run if")
|
||||
@ConfigComment("the island distance in the gamemode config is different to the one stored in the database")
|
||||
@ConfigComment("for safety. This overrides that check. You should never need this, and if you do not understand it")
|
||||
@ConfigComment("keep it as false")
|
||||
@ConfigEntry(path = "island.override-safety-check")
|
||||
private boolean overrideSafetyCheck = false;
|
||||
|
||||
// Number of islands
|
||||
@ConfigComment("The default number of concurrent islands a player may have.")
|
||||
@ConfigComment("This may be overridden by individual game mode config settings.")
|
||||
@ConfigEntry(path = "island.concurrent-islands")
|
||||
private int islandNumber = 1;
|
||||
|
||||
@ConfigComment("Hide used blueprints.")
|
||||
@ConfigComment("Blueprints can have a maximum use when players have concurrent islands.")
|
||||
@ConfigComment("If this is true, then ones that are used up will not be shown in the island create menu.")
|
||||
@ConfigEntry(path = "island.hide-used-blueprints", since = "2.3.0")
|
||||
private boolean hideUsedBlueprints = false;
|
||||
|
||||
// Cooldowns
|
||||
@ConfigComment("How long a player must wait until they can rejoin a team island after being kicked in minutes.")
|
||||
@ConfigComment("This slows the effectiveness of players repeating challenges")
|
||||
@ -287,25 +297,6 @@ public class Settings implements ConfigObject {
|
||||
@ConfigEntry(path = "island.delete-speed", since = "1.7.0")
|
||||
private int deleteSpeed = 1;
|
||||
|
||||
// Automated ownership transfer
|
||||
@ConfigComment("Toggles the automated ownership transfer.")
|
||||
@ConfigComment("It automatically transfers the ownership of an island to one of its members in case the current owner is inactive.")
|
||||
@ConfigComment("More precisely, it transfers the ownership of the island to the player who's active, whose rank is the highest")
|
||||
@ConfigComment("and who's been part of the island the longest time.")
|
||||
@ConfigComment("Setting this to 'false' will disable the feature.")
|
||||
@ConfigEntry(path = "island.automated-ownership-transfer.enable", hidden = true)
|
||||
private boolean enableAutoOwnershipTransfer = false;
|
||||
|
||||
@ConfigComment("Time in days since the island owner's last disconnection before they are considered inactive.")
|
||||
@ConfigEntry(path = "island.automated-ownership-transfer.inactivity-threshold", hidden = true)
|
||||
private int autoOwnershipTransferInactivityThreshold = 30;
|
||||
|
||||
@ConfigComment("Ranks are being considered when transferring the island ownership to one of its member.")
|
||||
@ConfigComment("Ignoring ranks will result in the island ownership being transferred to the player who's active and")
|
||||
@ConfigComment("who's been member of the island the longest time.")
|
||||
@ConfigEntry(path = "island.automated-ownership-transfer.ignore-ranks", hidden = true)
|
||||
private boolean autoOwnershipTransferIgnoreRanks = false;
|
||||
|
||||
// Island deletion related settings
|
||||
@ConfigComment("Toggles whether islands, when players are resetting them, should be kept in the world or deleted.")
|
||||
@ConfigComment("* If set to 'true', whenever a player resets his island, his previous island will become unowned and won't be deleted from the world.")
|
||||
@ -402,6 +393,7 @@ public class Settings implements ConfigObject {
|
||||
|
||||
/**
|
||||
* This method returns the useSSL value.
|
||||
*
|
||||
* @return the value of useSSL.
|
||||
* @since 1.12.0
|
||||
*/
|
||||
@ -411,6 +403,7 @@ public class Settings implements ConfigObject {
|
||||
|
||||
/**
|
||||
* This method sets the useSSL value.
|
||||
*
|
||||
* @param useSSL the useSSL new value.
|
||||
* @since 1.12.0
|
||||
*/
|
||||
@ -630,30 +623,6 @@ public class Settings implements ConfigObject {
|
||||
this.deleteSpeed = deleteSpeed;
|
||||
}
|
||||
|
||||
public boolean isEnableAutoOwnershipTransfer() {
|
||||
return enableAutoOwnershipTransfer;
|
||||
}
|
||||
|
||||
public void setEnableAutoOwnershipTransfer(boolean enableAutoOwnershipTransfer) {
|
||||
this.enableAutoOwnershipTransfer = enableAutoOwnershipTransfer;
|
||||
}
|
||||
|
||||
public int getAutoOwnershipTransferInactivityThreshold() {
|
||||
return autoOwnershipTransferInactivityThreshold;
|
||||
}
|
||||
|
||||
public void setAutoOwnershipTransferInactivityThreshold(int autoOwnershipTransferInactivityThreshold) {
|
||||
this.autoOwnershipTransferInactivityThreshold = autoOwnershipTransferInactivityThreshold;
|
||||
}
|
||||
|
||||
public boolean isAutoOwnershipTransferIgnoreRanks() {
|
||||
return autoOwnershipTransferIgnoreRanks;
|
||||
}
|
||||
|
||||
public void setAutoOwnershipTransferIgnoreRanks(boolean autoOwnershipTransferIgnoreRanks) {
|
||||
this.autoOwnershipTransferIgnoreRanks = autoOwnershipTransferIgnoreRanks;
|
||||
}
|
||||
|
||||
public boolean isLogCleanSuperFlatChunks() {
|
||||
return logCleanSuperFlatChunks;
|
||||
}
|
||||
@ -725,7 +694,8 @@ public class Settings implements ConfigObject {
|
||||
* @return the clearRadius
|
||||
*/
|
||||
public int getClearRadius() {
|
||||
if (clearRadius < 0) clearRadius = 0;
|
||||
if (clearRadius < 0)
|
||||
clearRadius = 0;
|
||||
return clearRadius;
|
||||
}
|
||||
|
||||
@ -733,7 +703,8 @@ public class Settings implements ConfigObject {
|
||||
* @param clearRadius the clearRadius to set. Cannot be negative.
|
||||
*/
|
||||
public void setClearRadius(int clearRadius) {
|
||||
if (clearRadius < 0) clearRadius = 0;
|
||||
if (clearRadius < 0)
|
||||
clearRadius = 0;
|
||||
this.clearRadius = clearRadius;
|
||||
}
|
||||
|
||||
@ -757,7 +728,8 @@ public class Settings implements ConfigObject {
|
||||
* @return the databasePrefix
|
||||
*/
|
||||
public String getDatabasePrefix() {
|
||||
if (databasePrefix == null) databasePrefix = "";
|
||||
if (databasePrefix == null)
|
||||
databasePrefix = "";
|
||||
return databasePrefix.isEmpty() ? "" : databasePrefix.replaceAll("[^a-zA-Z0-9]", "_");
|
||||
}
|
||||
|
||||
@ -770,7 +742,9 @@ public class Settings implements ConfigObject {
|
||||
|
||||
/**
|
||||
* Returns whether islands, when reset, should be kept or deleted.
|
||||
* @return {@code true} if islands, when reset, should be kept; {@code false} otherwise.
|
||||
*
|
||||
* @return {@code true} if islands, when reset, should be kept; {@code false}
|
||||
* otherwise.
|
||||
* @since 1.13.0
|
||||
*/
|
||||
public boolean isKeepPreviousIslandOnReset() {
|
||||
@ -779,7 +753,9 @@ public class Settings implements ConfigObject {
|
||||
|
||||
/**
|
||||
* Sets whether islands, when reset, should be kept or deleted.
|
||||
* @param keepPreviousIslandOnReset {@code true} if islands, when reset, should be kept; {@code false} otherwise.
|
||||
*
|
||||
* @param keepPreviousIslandOnReset {@code true} if islands, when reset, should
|
||||
* be kept; {@code false} otherwise.
|
||||
* @since 1.13.0
|
||||
*/
|
||||
public void setKeepPreviousIslandOnReset(boolean keepPreviousIslandOnReset) {
|
||||
@ -787,10 +763,13 @@ public class Settings implements ConfigObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a MongoDB client connection URI to override default connection options.
|
||||
* Returns a MongoDB client connection URI to override default connection
|
||||
* options.
|
||||
*
|
||||
* @return mongodb client connection.
|
||||
* @see <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Documentation</a>
|
||||
* @see <a href=
|
||||
* "https://docs.mongodb.com/manual/reference/connection-string/">MongoDB
|
||||
* Documentation</a>
|
||||
* @since 1.14.0
|
||||
*/
|
||||
public String getMongodbConnectionUri() {
|
||||
@ -799,6 +778,7 @@ public class Settings implements ConfigObject {
|
||||
|
||||
/**
|
||||
* Set the MongoDB client connection URI.
|
||||
*
|
||||
* @param mongodbConnectionUri connection URI.
|
||||
* @since 1.14.0
|
||||
*/
|
||||
@ -807,8 +787,11 @@ public class Settings implements ConfigObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Material of the item to preferably use when one needs to fill gaps in Panels.
|
||||
* @return the Material of the item to preferably use when one needs to fill gaps in Panels.
|
||||
* Returns the Material of the item to preferably use when one needs to fill
|
||||
* gaps in Panels.
|
||||
*
|
||||
* @return the Material of the item to preferably use when one needs to fill
|
||||
* gaps in Panels.
|
||||
* @since 1.14.0
|
||||
*/
|
||||
public Material getPanelFillerMaterial() {
|
||||
@ -816,106 +799,96 @@ public class Settings implements ConfigObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Material of the item to preferably use when one needs to fill gaps in Panels.
|
||||
* @param panelFillerMaterial the Material of the item to preferably use when one needs to fill gaps in Panels.
|
||||
* Sets the Material of the item to preferably use when one needs to fill gaps
|
||||
* in Panels.
|
||||
*
|
||||
* @param panelFillerMaterial the Material of the item to preferably use when
|
||||
* one needs to fill gaps in Panels.
|
||||
* @since 1.14.0
|
||||
*/
|
||||
public void setPanelFillerMaterial(Material panelFillerMaterial) {
|
||||
this.panelFillerMaterial = panelFillerMaterial;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method Settings#getPlayerHeadCacheTime returns the playerHeadCacheTime of this object.
|
||||
* Method Settings#getPlayerHeadCacheTime returns the playerHeadCacheTime of
|
||||
* this object.
|
||||
*
|
||||
* @return the playerHeadCacheTime (type long) of this object.
|
||||
* @since 1.14.1
|
||||
*/
|
||||
public long getPlayerHeadCacheTime()
|
||||
{
|
||||
public long getPlayerHeadCacheTime() {
|
||||
return playerHeadCacheTime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method Settings#setPlayerHeadCacheTime sets new value for the playerHeadCacheTime of this object.
|
||||
* Method Settings#setPlayerHeadCacheTime sets new value for the
|
||||
* playerHeadCacheTime of this object.
|
||||
*
|
||||
* @param playerHeadCacheTime new value for this object.
|
||||
* @since 1.14.1
|
||||
*/
|
||||
public void setPlayerHeadCacheTime(long playerHeadCacheTime)
|
||||
{
|
||||
public void setPlayerHeadCacheTime(long playerHeadCacheTime) {
|
||||
this.playerHeadCacheTime = playerHeadCacheTime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is use cache server boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public boolean isUseCacheServer()
|
||||
{
|
||||
public boolean isUseCacheServer() {
|
||||
return useCacheServer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets use cache server.
|
||||
*
|
||||
* @param useCacheServer the use cache server
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public void setUseCacheServer(boolean useCacheServer)
|
||||
{
|
||||
public void setUseCacheServer(boolean useCacheServer) {
|
||||
this.useCacheServer = useCacheServer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets heads per call.
|
||||
*
|
||||
* @return the heads per call
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public int getHeadsPerCall()
|
||||
{
|
||||
public int getHeadsPerCall() {
|
||||
return headsPerCall;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets heads per call.
|
||||
*
|
||||
* @param headsPerCall the heads per call
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public void setHeadsPerCall(int headsPerCall)
|
||||
{
|
||||
public void setHeadsPerCall(int headsPerCall) {
|
||||
this.headsPerCall = headsPerCall;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets ticks between calls.
|
||||
*
|
||||
* @return the ticks between calls
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public long getTicksBetweenCalls()
|
||||
{
|
||||
public long getTicksBetweenCalls() {
|
||||
return ticksBetweenCalls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets ticks between calls.
|
||||
*
|
||||
* @param ticksBetweenCalls the ticks between calls
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public void setTicksBetweenCalls(long ticksBetweenCalls)
|
||||
{
|
||||
public void setTicksBetweenCalls(long ticksBetweenCalls) {
|
||||
this.ticksBetweenCalls = ticksBetweenCalls;
|
||||
}
|
||||
|
||||
@ -933,7 +906,6 @@ public class Settings implements ConfigObject {
|
||||
this.minPortalSearchRadius = minPortalSearchRadius;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets safe spot search vertical range.
|
||||
*
|
||||
@ -943,7 +915,6 @@ public class Settings implements ConfigObject {
|
||||
return safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets safe spot search vertical range.
|
||||
*
|
||||
@ -953,7 +924,6 @@ public class Settings implements ConfigObject {
|
||||
this.safeSpotSearchVerticalRange = safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is slow deletion boolean.
|
||||
*
|
||||
@ -963,7 +933,6 @@ public class Settings implements ConfigObject {
|
||||
return slowDeletion;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets slow deletion.
|
||||
*
|
||||
@ -973,69 +942,116 @@ public class Settings implements ConfigObject {
|
||||
this.slowDeletion = slowDeletion;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets maximum pool size.
|
||||
*
|
||||
* @return the maximum pool size
|
||||
*/
|
||||
public int getMaximumPoolSize()
|
||||
{
|
||||
public int getMaximumPoolSize() {
|
||||
return maximumPoolSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets safe spot search range.
|
||||
*
|
||||
* @return the safe spot search range
|
||||
*/
|
||||
public int getSafeSpotSearchRange()
|
||||
{
|
||||
public int getSafeSpotSearchRange() {
|
||||
return safeSpotSearchRange;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets maximum pool size.
|
||||
*
|
||||
* @param maximumPoolSize the maximum pool size
|
||||
*/
|
||||
public void setMaximumPoolSize(int maximumPoolSize)
|
||||
{
|
||||
public void setMaximumPoolSize(int maximumPoolSize) {
|
||||
this.maximumPoolSize = maximumPoolSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets custom pool properties.
|
||||
*
|
||||
* @return the custom pool properties
|
||||
*/
|
||||
public Map<String, String> getCustomPoolProperties()
|
||||
{
|
||||
public Map<String, String> getCustomPoolProperties() {
|
||||
return customPoolProperties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets custom pool properties.
|
||||
*
|
||||
* @param customPoolProperties the custom pool properties
|
||||
*/
|
||||
public void setCustomPoolProperties(Map<String, String> customPoolProperties)
|
||||
{
|
||||
public void setCustomPoolProperties(Map<String, String> customPoolProperties) {
|
||||
this.customPoolProperties = customPoolProperties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets safe spot search range.
|
||||
*
|
||||
* @param safeSpotSearchRange the safe spot search range
|
||||
*/
|
||||
public void setSafeSpotSearchRange(int safeSpotSearchRange)
|
||||
{
|
||||
public void setSafeSpotSearchRange(int safeSpotSearchRange) {
|
||||
this.safeSpotSearchRange = safeSpotSearchRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an immutable list of readyCommands
|
||||
*/
|
||||
public List<String> getReadyCommands() {
|
||||
return ImmutableList.copyOf(Objects.requireNonNullElse(readyCommands, Collections.emptyList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param readyCommands the readyCommands to set
|
||||
*/
|
||||
public void setReadyCommands(List<String> readyCommands) {
|
||||
this.readyCommands = readyCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the islandNumber
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public int getIslandNumber() {
|
||||
return islandNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param islandNumber the islandNumber to set
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void setIslandNumber(int islandNumber) {
|
||||
this.islandNumber = islandNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the hideUsedBlueprints
|
||||
*/
|
||||
public boolean isHideUsedBlueprints() {
|
||||
return hideUsedBlueprints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideUsedBlueprints the hideUsedBlueprints to set
|
||||
*/
|
||||
public void setHideUsedBlueprints(boolean hideUsedBlueprints) {
|
||||
this.hideUsedBlueprints = hideUsedBlueprints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the overrideSafetyCheck
|
||||
*/
|
||||
public boolean isOverrideSafetyCheck() {
|
||||
return overrideSafetyCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param overrideSafetyCheck the overrideSafetyCheck to set
|
||||
*/
|
||||
public void setOverrideSafetyCheck(boolean overrideSafetyCheck) {
|
||||
this.overrideSafetyCheck = overrideSafetyCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import java.util.Optional;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
@ -20,11 +21,14 @@ import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import com.github.puregero.multilib.MultiLib;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.managers.PlayersManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Add-on class for BentoBox. Extend this to create an add-on. The operation
|
||||
@ -44,6 +48,10 @@ public abstract class Addon {
|
||||
|
||||
protected Addon() {
|
||||
state = State.DISABLED;
|
||||
if (!Util.inTest()) {
|
||||
// If the config is updated, update the config.
|
||||
MultiLib.onString(getPlugin(), "bentobox-config-update", v -> this.reloadConfig());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,7 +281,9 @@ public abstract class Addon {
|
||||
"The embedded resource '" + jarResource + "' cannot be found in " + jar.getName());
|
||||
}
|
||||
// There are two options, use the path of the resource or not
|
||||
File outFile = new File(destinationFolder, jarResource);
|
||||
File outFile = new File(destinationFolder,
|
||||
jarResource.replaceAll("/", Matcher.quoteReplacement(File.separator)));
|
||||
|
||||
if (noPath) {
|
||||
outFile = new File(destinationFolder, outFile.getName());
|
||||
}
|
||||
|
@ -125,7 +125,11 @@ public class AddonClassLoader extends URLClassLoader {
|
||||
if (softDepend != null) {
|
||||
builder.softDependencies(Arrays.asList(softDepend.split("\\s*,\\s*")));
|
||||
}
|
||||
builder.icon(Objects.requireNonNull(Material.getMaterial(data.getString("icon", "PAPER").toUpperCase(Locale.ENGLISH))));
|
||||
Material icon = Material.getMaterial(data.getString("icon", "PAPER").toUpperCase(Locale.ENGLISH));
|
||||
if (icon == null) {
|
||||
throw new InvalidAddonDescriptionException("'icon' tag refers to an unknown Material: " + data.getString("icon"));
|
||||
}
|
||||
builder.icon(Objects.requireNonNull(icon));
|
||||
|
||||
String apiVersion = data.getString("api-version");
|
||||
if (apiVersion != null) {
|
||||
|
@ -8,6 +8,8 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.github.puregero.multilib.MultiLib;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
@ -117,7 +119,7 @@ public abstract class GameModeAddon extends Addon {
|
||||
/**
|
||||
* Defines the world generator for this game mode
|
||||
* @param worldName - name of world that this applies to
|
||||
* @param id - id if any
|
||||
* @param id - id if any. "delete" is used when this request is for island deletion purposes
|
||||
* @return Chunk generator or null if one does not exist, e.g. the use own generator setting is true
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@ -129,6 +131,18 @@ public abstract class GameModeAddon extends Addon {
|
||||
* in-game and need to be saved.
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract void saveWorldSettings();
|
||||
public void saveWorldSettings() {
|
||||
// Inform other servers
|
||||
MultiLib.notify("bentobox-config-update", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the game mode uses the latest {@link ChunkGenerator} API or
|
||||
* deprecated {@link ChunkGenerator#generateChunkData(World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)} approach.
|
||||
* @return true if this game mode is a void world and should just be deleted as such
|
||||
*/
|
||||
public boolean isUsesNewChunkGeneration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import com.google.common.io.Files;
|
||||
*/
|
||||
public abstract class Pladdon extends JavaPlugin {
|
||||
|
||||
private static final String ADDONS_FOLDER = "BentoBox/addons";
|
||||
private static final String ADDONS_FOLDER = "BentoBox" + File.separator + "addons";
|
||||
|
||||
/**
|
||||
* This must return a new instance of the addon. It is called when the Pladdon is loaded.
|
||||
@ -28,12 +28,20 @@ public abstract class Pladdon extends JavaPlugin {
|
||||
String parentFolder = getFile().getParent();
|
||||
if (parentFolder == null || !parentFolder.endsWith(ADDONS_FOLDER)) {
|
||||
// Jar is in the wrong place. Let's move it
|
||||
moveJar();
|
||||
//moveJar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Addon addon = getAddon();
|
||||
if (addon != null) {
|
||||
addon.onDisable();
|
||||
}
|
||||
}
|
||||
|
||||
protected void moveJar() {
|
||||
getLogger().severe(getFile().getName() + " must be in the BentoBox/addons folder! Trying to move it there...");
|
||||
getLogger().severe(getFile().getName() + " must be in the " + ADDONS_FOLDER + " folder! Trying to move it there...");
|
||||
File addons = new File(getFile().getParent(), ADDONS_FOLDER);
|
||||
if (addons.exists() || addons.mkdirs()) {
|
||||
File to = new File(addons, getFile().getName());
|
||||
@ -44,7 +52,7 @@ public abstract class Pladdon extends JavaPlugin {
|
||||
|
||||
} catch (IOException ex) {
|
||||
getLogger().severe("Failed to move it. " + ex.getMessage());
|
||||
getLogger().severe("Move " + getFile().getName() + " manually into the BentoBox/addons folder. Then restart server.");
|
||||
getLogger().severe("Move " + getFile().getName() + " manually into the " + ADDONS_FOLDER + " folder. Then restart server.");
|
||||
}
|
||||
} else {
|
||||
getLogger().warning(getFile().getName() + " already is in the addons folder. Delete the one in the plugins folder.");
|
||||
|
@ -2,12 +2,11 @@ package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class AddonRequestException extends AddonException
|
||||
{
|
||||
@Serial
|
||||
public class AddonRequestException extends AddonException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5698456013070166174L;
|
||||
|
||||
public AddonRequestException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
public AddonRequestException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
* <p>
|
||||
* Addons can expose data that they want to expose. To access it, call this class with the appropriate addon name,
|
||||
* the label for the data that is requested and if required, a map of key-value pairs that will be given to the addon.
|
||||
*
|
||||
* <p>
|
||||
* <b>Note</b> Since BentoBox 1.17.0, Addons can be declared as Pladdons and be loaded by the Bukkit classloader. This
|
||||
* enables Plugins to access Addon methods directly so this API is not required.
|
||||
* </p>
|
||||
|
@ -26,6 +26,7 @@ import world.bentobox.bentobox.api.addons.Addon;
|
||||
import world.bentobox.bentobox.api.events.command.CommandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.managers.PlayersManager;
|
||||
@ -34,6 +35,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* BentoBox composite command. Provides an abstract implementation of a command.
|
||||
*
|
||||
* @author tastybento
|
||||
* @author Poslovitch
|
||||
*/
|
||||
@ -48,6 +50,13 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
*/
|
||||
private boolean onlyPlayer = false;
|
||||
|
||||
/**
|
||||
* True if the command is only for the console
|
||||
*
|
||||
* @since 1.24.0
|
||||
*/
|
||||
private boolean onlyConsole = false;
|
||||
|
||||
/**
|
||||
* True if command is a configurable rank
|
||||
*/
|
||||
@ -55,22 +64,26 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Make default command rank as owner rank.
|
||||
*
|
||||
* @since 1.20.0
|
||||
*/
|
||||
private int defaultCommandRank = RanksManager.OWNER_RANK;
|
||||
|
||||
/**
|
||||
* True if command is hidden from help and tab complete
|
||||
*
|
||||
* @since 1.13.0
|
||||
*/
|
||||
private boolean hidden = false;
|
||||
|
||||
/**
|
||||
* The parameters string for this command. It is the commands followed by a locale reference.
|
||||
* The parameters string for this command. It is the commands followed by a
|
||||
* locale reference.
|
||||
*/
|
||||
private String parameters = "";
|
||||
/**
|
||||
* The parent command to this one. If this is a top-level command it will be empty.
|
||||
* The parent command to this one. If this is a top-level command it will be
|
||||
* empty.
|
||||
*/
|
||||
protected final CompositeCommand parent;
|
||||
/**
|
||||
@ -102,8 +115,9 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
private final String permissionPrefix;
|
||||
|
||||
/**
|
||||
* The world that this command operates in. This is an overworld and will cover any associated nether or end
|
||||
* If the world value does not exist, then the command is general across worlds
|
||||
* The world that this command operates in. This is an overworld and will cover
|
||||
* any associated nether or end If the world value does not exist, then the
|
||||
* command is general across worlds
|
||||
*/
|
||||
private World world;
|
||||
|
||||
@ -124,8 +138,9 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Top level command
|
||||
* @param addon - addon creating the command
|
||||
* @param label - string for this command
|
||||
*
|
||||
* @param addon - addon creating the command
|
||||
* @param label - string for this command
|
||||
* @param aliases - aliases
|
||||
*/
|
||||
protected CompositeCommand(Addon addon, String label, String... aliases) {
|
||||
@ -157,17 +172,19 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* This is the top-level command constructor for commands that have no parent.
|
||||
* @param label - string for this command
|
||||
*
|
||||
* @param label - string for this command
|
||||
* @param aliases - aliases for this command
|
||||
*/
|
||||
protected CompositeCommand(String label, String... aliases) {
|
||||
this((Addon)null, label, aliases);
|
||||
this((Addon) null, label, aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-command constructor
|
||||
* @param parent - the parent composite command
|
||||
* @param label - string label for this subcommand
|
||||
*
|
||||
* @param parent - the parent composite command
|
||||
* @param label - string label for this subcommand
|
||||
* @param aliases - aliases for this subcommand
|
||||
*/
|
||||
protected CompositeCommand(CompositeCommand parent, String label, String... aliases) {
|
||||
@ -175,12 +192,14 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Command to register a command from an addon under a parent command (that could be from another addon)
|
||||
* @param addon - this command's addon
|
||||
* @param parent - parent command
|
||||
* Command to register a command from an addon under a parent command (that
|
||||
* could be from another addon)
|
||||
*
|
||||
* @param addon - this command's addon
|
||||
* @param parent - parent command
|
||||
* @param aliases - aliases for this command
|
||||
*/
|
||||
protected CompositeCommand(Addon addon, CompositeCommand parent, String label, String... aliases ) {
|
||||
protected CompositeCommand(Addon addon, CompositeCommand parent, String label, String... aliases) {
|
||||
super(label, "", "", Arrays.asList(aliases));
|
||||
this.topLabel = parent.getTopLabel();
|
||||
this.plugin = BentoBox.getInstance();
|
||||
@ -213,7 +232,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
setDescription(COMMANDS + reference + ".description");
|
||||
setParametersHelp(COMMANDS + reference + ".parameters");
|
||||
setup();
|
||||
// If this command does not define its own help class, then use the default help command
|
||||
// If this command does not define its own help class, then use the default help
|
||||
// command
|
||||
if (getSubCommand("help").isEmpty() && !label.equals("help")) {
|
||||
new DefaultHelpCommand(this);
|
||||
}
|
||||
@ -228,68 +248,62 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
// Get the User instance for this sender
|
||||
User user = User.getInstance(sender);
|
||||
// Fire an event to see if this command should be cancelled
|
||||
CommandEvent event = CommandEvent.builder()
|
||||
.setCommand(this)
|
||||
.setLabel(label)
|
||||
.setSender(sender)
|
||||
.setArgs(args)
|
||||
CommandEvent event = CommandEvent.builder().setCommand(this).setLabel(label).setSender(sender).setArgs(args)
|
||||
.build();
|
||||
if (event.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
// Get command
|
||||
CompositeCommand cmd = getCommandFromArgs(args);
|
||||
String cmdLabel = (cmd.subCommandLevel > 0) ? args[cmd.subCommandLevel-1] : label;
|
||||
String cmdLabel = (cmd.subCommandLevel > 0) ? args[cmd.subCommandLevel - 1] : label;
|
||||
List<String> cmdArgs = Arrays.asList(args).subList(cmd.subCommandLevel, args.length);
|
||||
// Call
|
||||
return cmd.call(user, cmdLabel, cmdArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls this composite command.
|
||||
* Does not traverse the tree of subcommands in args.
|
||||
* Event is not fired and it cannot be cancelled.
|
||||
* @param user - user calling this command
|
||||
* Calls this composite command. Does not traverse the tree of subcommands in
|
||||
* args. Event is not fired and it cannot be cancelled.
|
||||
*
|
||||
* @param user - user calling this command
|
||||
* @param cmdLabel - label used
|
||||
* @param cmdArgs - list of args
|
||||
* @param cmdArgs - list of args
|
||||
* @return {@code true} if successful, {@code false} if not.
|
||||
* @since 1.5.3
|
||||
*/
|
||||
public boolean call(User user, String cmdLabel, List<String> cmdArgs) {
|
||||
// Check for console and permissions
|
||||
if (onlyPlayer && !user.isPlayer()) {
|
||||
if (isOnlyPlayer() && !user.isPlayer()) {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.runPermissionCheck(user))
|
||||
{
|
||||
// Error message is displayed by permission check.
|
||||
if (isOnlyConsole() && user.isPlayer()) {
|
||||
user.sendMessage("general.errors.use-in-console");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.runPermissionCheck(user)) {
|
||||
// Error message is displayed by permission check.
|
||||
return false;
|
||||
}
|
||||
// Set the user's addon context
|
||||
user.setAddon(addon);
|
||||
// Execute and trim args
|
||||
return canExecute(user, cmdLabel, cmdArgs) && execute(user, cmdLabel, cmdArgs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method checks and returns if user has access to the called command.
|
||||
* It also recursively checks if user has access to the all parent commands.
|
||||
* This method checks and returns if user has access to the called command. It
|
||||
* also recursively checks if user has access to the all parent commands.
|
||||
*
|
||||
* @param user User who permission must be checked.
|
||||
* @return {@code true} is user can execute given command, {@code false} otherwise.
|
||||
* @return {@code true} is user can execute given command, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean runPermissionCheck(User user)
|
||||
{
|
||||
private boolean runPermissionCheck(User user) {
|
||||
// Check perms, but only if this isn't the console
|
||||
if (user.isPlayer() &&
|
||||
!user.isOp() &&
|
||||
this.getPermission() != null &&
|
||||
!this.getPermission().isEmpty() &&
|
||||
!user.hasPermission(this.getPermission()))
|
||||
{
|
||||
if (user.isPlayer() && !user.isOp() && this.getPermission() != null && !this.getPermission().isEmpty()
|
||||
&& !user.hasPermission(this.getPermission())) {
|
||||
user.sendMessage("general.errors.no-permission", TextVariables.PERMISSION, this.getPermission());
|
||||
return false;
|
||||
}
|
||||
@ -298,9 +312,9 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
return this.getParent() == null || this.getParent().runPermissionCheck(user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current composite command based on the arguments
|
||||
*
|
||||
* @param args - arguments
|
||||
* @return the current composite command based on the arguments
|
||||
*/
|
||||
@ -329,14 +343,16 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Convenience method to get the island manager
|
||||
*
|
||||
* @return IslandsManager
|
||||
*/
|
||||
protected IslandsManager getIslands() {
|
||||
public IslandsManager getIslands() {
|
||||
return plugin.getIslands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get the island manager
|
||||
*
|
||||
* @return IslandsManager
|
||||
*/
|
||||
protected IslandsManager getIslandsManager() {
|
||||
@ -344,8 +360,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this command's sub-level. Top level is 0.
|
||||
* Every time a command registers with a parent, their level will be set.
|
||||
* @return this command's sub-level. Top level is 0. Every time a command
|
||||
* registers with a parent, their level will be set.
|
||||
*/
|
||||
protected int getLevel() {
|
||||
return subCommandLevel;
|
||||
@ -359,13 +375,19 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to obtain team members
|
||||
* Convenience method to obtain team members of the active island for user. Note
|
||||
* that the user may have more than one island in this world.
|
||||
*
|
||||
* @param world - world to check
|
||||
* @param user - the User
|
||||
* @return set of UUIDs of all team members
|
||||
* @param user - the User
|
||||
* @return set of UUIDs of all team members, or empty set if there is no island
|
||||
*/
|
||||
protected Set<UUID> getMembers(World world, User user) {
|
||||
return plugin.getIslands().getMembers(world, user.getUniqueId());
|
||||
Island island = plugin.getIslands().getIsland(world, user);
|
||||
if (island == null) {
|
||||
return Set.of();
|
||||
}
|
||||
return island.getMemberSet();
|
||||
}
|
||||
|
||||
public String getParameters() {
|
||||
@ -386,6 +408,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Convenience method to get the player manager
|
||||
*
|
||||
* @return PlayersManager
|
||||
*/
|
||||
protected PlayersManager getPlayers() {
|
||||
@ -399,11 +422,13 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Get the island worlds manager
|
||||
*
|
||||
* @return island worlds manager
|
||||
*/
|
||||
public IslandWorldManager getIWM() {
|
||||
return plugin.getIWM();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Settings object
|
||||
*/
|
||||
@ -413,6 +438,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Returns the CompositeCommand object referring to this command label
|
||||
*
|
||||
* @param label - command label or alias
|
||||
* @return CompositeCommand or null if none found
|
||||
*/
|
||||
@ -436,9 +462,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of sub commands for this command.
|
||||
* As it needs more calculations to handle the Help subcommand, it is preferable to use {@link #getSubCommands()} when no such distinction is needed.
|
||||
* @param ignoreHelp Whether the Help subcommand should not be returned in the map or not.
|
||||
* Returns a map of sub commands for this command. As it needs more calculations
|
||||
* to handle the Help subcommand, it is preferable to use
|
||||
* {@link #getSubCommands()} when no such distinction is needed.
|
||||
*
|
||||
* @param ignoreHelp Whether the Help subcommand should not be returned in the
|
||||
* map or not.
|
||||
* @return Map of sub commands for this command
|
||||
* @see #hasSubCommands(boolean)
|
||||
*/
|
||||
@ -451,17 +480,6 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
return getSubCommands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to obtain the user's island owner
|
||||
* @param world world to check
|
||||
* @param user the User
|
||||
* @return UUID of player's island owner or null if user has no island
|
||||
*/
|
||||
@Nullable
|
||||
protected UUID getOwner(@NonNull World world, @NonNull User user) {
|
||||
return plugin.getIslands().getOwner(world, user.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String getUsage() {
|
||||
return "/" + usage;
|
||||
@ -469,6 +487,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if this command has a specific sub command.
|
||||
*
|
||||
* @param subCommand - sub command
|
||||
* @return true if this command has this sub command
|
||||
*/
|
||||
@ -478,6 +497,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if this command has any sub commands.
|
||||
*
|
||||
* @return true if this command has subcommands
|
||||
*/
|
||||
protected boolean hasSubCommands() {
|
||||
@ -485,9 +505,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this command has any sub commands.
|
||||
* As it needs more calculations to handle the Help subcommand, it is preferable to use {@link #hasSubCommands()} when no such distinction is needed.
|
||||
* @param ignoreHelp Whether the Help subcommand should not be taken into account or not.
|
||||
* Check if this command has any sub commands. As it needs more calculations to
|
||||
* handle the Help subcommand, it is preferable to use {@link #hasSubCommands()}
|
||||
* when no such distinction is needed.
|
||||
*
|
||||
* @param ignoreHelp Whether the Help subcommand should not be taken into
|
||||
* account or not.
|
||||
* @return true if this command has subcommands
|
||||
* @see #getSubCommands(boolean)
|
||||
*/
|
||||
@ -497,8 +520,10 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Convenience method to check if a user has a team.
|
||||
* Consider checking the island itself {@link Island#inTeam(UUID)}
|
||||
*
|
||||
* @param world - the world to check
|
||||
* @param user - the User
|
||||
* @param user - the User
|
||||
* @return true if player is in a team
|
||||
*/
|
||||
protected boolean inTeam(World world, User user) {
|
||||
@ -507,6 +532,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if this command is only for players.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isOnlyPlayer() {
|
||||
@ -514,11 +540,23 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this command should only be run by players.
|
||||
* If this is set to {@code true}, this command will only be runnable by objects implementing {@link Player}.
|
||||
* <br/><br/>
|
||||
* The default value provided when instantiating this CompositeCommand is {@code false}.
|
||||
* Therefore, this method should only be used in case you want to explicitly edit the value.
|
||||
* Check if this command is only for consoles.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isOnlyConsole() {
|
||||
return onlyConsole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this command should only be run by players. If this is set to
|
||||
* {@code true}, this command will only be runnable by objects implementing
|
||||
* {@link Player}. <br/>
|
||||
* <br/>
|
||||
* The default value provided when instantiating this CompositeCommand is
|
||||
* {@code false}. Therefore, this method should only be used in case you want to
|
||||
* explicitly edit the value.
|
||||
*
|
||||
* @param onlyPlayer {@code true} if this command should only be run by players.
|
||||
*/
|
||||
public void setOnlyPlayer(boolean onlyPlayer) {
|
||||
@ -526,28 +564,48 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locale reference to this command's description.
|
||||
* It is used to display the help of this command.
|
||||
* Sets whether this command should only be run in the console. This is for
|
||||
* commands that dump a lot of data or are for debugging. The default value
|
||||
* provided when instantiating this CompositeCommand is {@code false}.
|
||||
* Therefore, this method should only be used in case you want to explicitly
|
||||
* edit the value.
|
||||
*
|
||||
* <br/><br/>
|
||||
* @param onlyConsole {@code true} if this command should only be run in the
|
||||
* console.
|
||||
* @since 1.24.0
|
||||
*/
|
||||
public void setOnlyConsole(boolean onlyConsole) {
|
||||
this.onlyConsole = onlyConsole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locale reference to this command's description. It is used to display
|
||||
* the help of this command.
|
||||
*
|
||||
* <br/>
|
||||
* <br/>
|
||||
*
|
||||
* A default value is provided when instantiating this CompositeCommand:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code "commands." + getLabel() + ".description"} if this is a top-level command;</li>
|
||||
* <li>{@code "commands." + getParent.getLabel() + getLabel() + ".description"} if this is a sub-command.
|
||||
* <br/>
|
||||
* Note that it can have up to 20 parent commands' labels being inserted before this sub-command's label.
|
||||
* Here are a few examples :
|
||||
* <ul>
|
||||
* <li>/bentobox info : {@code "commands.bentobox.info.description"};</li>
|
||||
* <li>/bsbadmin range set : {@code "commands.bsbadmin.range.set.description"};</li>
|
||||
* <li>/mycommand sub1 sub2 sub3 [...] sub22 : {@code "commands.sub3.[...].sub20.sub21.sub22.description"}.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>{@code "commands." + getLabel() + ".description"} if this is a top-level
|
||||
* command;</li>
|
||||
* <li>{@code "commands." + getParent.getLabel() + getLabel() + ".description"}
|
||||
* if this is a sub-command. <br/>
|
||||
* Note that it can have up to 20 parent commands' labels being inserted before
|
||||
* this sub-command's label. Here are a few examples :
|
||||
* <ul>
|
||||
* <li>/bentobox info : {@code "commands.bentobox.info.description"};</li>
|
||||
* <li>/bsbadmin range set :
|
||||
* {@code "commands.bsbadmin.range.set.description"};</li>
|
||||
* <li>/mycommand sub1 sub2 sub3 [...] sub22 :
|
||||
* {@code "commands.sub3.[...].sub20.sub21.sub22.description"}.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* This method should therefore only be used in case you want to provide a different value than the default one.
|
||||
* This method should therefore only be used in case you want to provide a
|
||||
* different value than the default one.
|
||||
*
|
||||
* @param description The locale command's description reference to set.
|
||||
* @return The instance of this {@link Command}.
|
||||
@ -559,28 +617,33 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locale reference to this command's parameters.
|
||||
* It is used to display the help of this command.
|
||||
* Sets locale reference to this command's parameters. It is used to display the
|
||||
* help of this command.
|
||||
*
|
||||
* <br/><br/>
|
||||
* <br/>
|
||||
* <br/>
|
||||
*
|
||||
* A default value is provided when instantiating this CompositeCommand:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code "commands." + getLabel() + ".parameters"} if this is a top-level command;</li>
|
||||
* <li>{@code "commands." + getParent.getLabel() + getLabel() + ".parameters"} if this is a sub-command.
|
||||
* <br/>
|
||||
* Note that it can have up to 20 parent commands' labels being inserted before this sub-command's label.
|
||||
* Here are a few examples :
|
||||
* <ul>
|
||||
* <li>/bentobox info : {@code "commands.bentobox.info.parameters"};</li>
|
||||
* <li>/bsbadmin range set : {@code "commands.bsbadmin.range.set.parameters"};</li>
|
||||
* <li>/mycommand sub1 sub2 sub3 [...] sub22 : {@code "commands.sub3.[...].sub20.sub21.sub22.parameters"}.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>{@code "commands." + getLabel() + ".parameters"} if this is a top-level
|
||||
* command;</li>
|
||||
* <li>{@code "commands." + getParent.getLabel() + getLabel() + ".parameters"}
|
||||
* if this is a sub-command. <br/>
|
||||
* Note that it can have up to 20 parent commands' labels being inserted before
|
||||
* this sub-command's label. Here are a few examples :
|
||||
* <ul>
|
||||
* <li>/bentobox info : {@code "commands.bentobox.info.parameters"};</li>
|
||||
* <li>/bsbadmin range set :
|
||||
* {@code "commands.bsbadmin.range.set.parameters"};</li>
|
||||
* <li>/mycommand sub1 sub2 sub3 [...] sub22 :
|
||||
* {@code "commands.sub3.[...].sub20.sub21.sub22.parameters"}.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* This method should therefore only be used in case you want to provide a different value than the default one.
|
||||
* This method should therefore only be used in case you want to provide a
|
||||
* different value than the default one.
|
||||
*
|
||||
* @param parametersHelp The locale command's paramaters reference to set.
|
||||
*/
|
||||
@ -588,12 +651,15 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
this.parameters = parametersHelp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.bukkit.command.Command#setPermission(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setPermission(String permission) {
|
||||
this.permission = ((permissionPrefix != null && !permissionPrefix.isEmpty()) ? permissionPrefix : "") + permission;
|
||||
this.permission = ((permissionPrefix != null && !permissionPrefix.isEmpty()) ? permissionPrefix : "")
|
||||
+ permission;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -622,24 +688,31 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<String> tabComplete(final @NonNull CommandSender sender, final @NonNull String alias, final String[] args) {
|
||||
List<String> options = new ArrayList<>();
|
||||
public List<String> tabComplete(final @NonNull CommandSender sender, final @NonNull String alias,
|
||||
final String[] args) {
|
||||
// Get command object based on args entered so far
|
||||
CompositeCommand command = getCommandFromArgs(args);
|
||||
// Check for console and permissions
|
||||
if (command.isOnlyPlayer() && !(sender instanceof Player)) {
|
||||
return options;
|
||||
if ((command.isOnlyPlayer() && !(sender instanceof Player))
|
||||
|| (command.isOnlyConsole() && sender instanceof Player)) {
|
||||
return List.of();
|
||||
}
|
||||
if (command.getPermission() != null && !command.getPermission().isEmpty() && !sender.hasPermission(command.getPermission()) && !sender.isOp()) {
|
||||
return options;
|
||||
if (command.getPermission() != null && !command.getPermission().isEmpty()
|
||||
&& !sender.hasPermission(command.getPermission()) && !sender.isOp()) {
|
||||
return List.of();
|
||||
}
|
||||
// Add any tab completion from the subcommand
|
||||
options.addAll(command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args))).orElseGet(ArrayList::new));
|
||||
List<String> options = new ArrayList<>(
|
||||
command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args)))
|
||||
.orElseGet(ArrayList::new));
|
||||
if (command.hasSubCommands()) {
|
||||
options.addAll(getSubCommandLabels(sender, command));
|
||||
}
|
||||
|
||||
/* /!\ The following check is likely a poor quality patch-up job. If any better solution can be applied, don't hesitate to do so. */
|
||||
/*
|
||||
* /!\ The following check is likely a poor quality patch-up job. If any better
|
||||
* solution can be applied, don't hesitate to do so.
|
||||
*/
|
||||
// See https://github.com/BentoBoxWorld/BentoBox/issues/416
|
||||
|
||||
// "help" shouldn't appear twice, so remove it if it is already in the args.
|
||||
@ -654,27 +727,40 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all the labels of the subcommands for the provided CompositeCommand excluding any hidden commands
|
||||
* @param sender the CommandSender
|
||||
* Returns a list containing all the labels of the subcommands for the provided
|
||||
* CompositeCommand excluding any hidden commands
|
||||
*
|
||||
* @param sender the CommandSender
|
||||
* @param command the CompositeCommand to get the subcommands from
|
||||
* @return a list of subcommands labels or an empty list.
|
||||
*/
|
||||
@NonNull
|
||||
private List<String> getSubCommandLabels(@NonNull CommandSender sender, @NonNull CompositeCommand command) {
|
||||
return command.getSubCommands().values().stream()
|
||||
.filter(cmd -> !cmd.isHidden())
|
||||
.filter(cmd -> !cmd.isOnlyPlayer() || sender.isOp() || (sender instanceof Player && cmd.getPermission() != null && (cmd.getPermission().isEmpty() || sender.hasPermission(cmd.getPermission()))) )
|
||||
.map(CompositeCommand::getLabel).toList();
|
||||
List<String> result = new ArrayList<>();
|
||||
for (CompositeCommand cc : command.getSubCommands().values()) {
|
||||
// Player or not
|
||||
if (sender instanceof Player) {
|
||||
if (!cc.isHidden() && !cc.isOnlyConsole()
|
||||
&& (cc.getPermission().isEmpty() || sender.hasPermission(cc.getPermission()))) {
|
||||
result.add(cc.getLabel());
|
||||
}
|
||||
} else if (!cc.isOnlyPlayer()) {
|
||||
result.add(cc.getLabel());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show help
|
||||
*
|
||||
* @param command - command that this help is for
|
||||
* @param user - the User
|
||||
* @param user - the User
|
||||
* @return result of help command or false if no help defined
|
||||
*/
|
||||
protected boolean showHelp(CompositeCommand command, User user) {
|
||||
return command.getSubCommand("help").map(helpCommand -> helpCommand.execute(user, helpCommand.getLabel(), new ArrayList<>())).orElse(false);
|
||||
public boolean showHelp(CompositeCommand command, User user) {
|
||||
return command.getSubCommand("help")
|
||||
.map(helpCommand -> helpCommand.execute(user, helpCommand.getLabel(), new ArrayList<>())).orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -685,7 +771,9 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
}
|
||||
|
||||
/**
|
||||
* If the permission prefix has been set, will return the prefix plus a trailing dot.
|
||||
* If the permission prefix has been set, will return the prefix plus a trailing
|
||||
* dot.
|
||||
*
|
||||
* @return the permissionPrefix
|
||||
*/
|
||||
@Nullable
|
||||
@ -695,6 +783,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* The the world that this command applies to.
|
||||
*
|
||||
* @return the world
|
||||
*/
|
||||
public World getWorld() {
|
||||
@ -711,6 +800,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Get the parental addon
|
||||
*
|
||||
* @return the addon
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -727,28 +817,33 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Set a cool down - can be set by other commands on this one
|
||||
* @param uniqueId - the unique ID that is having the cooldown
|
||||
* @param targetUUID - the target (if any)
|
||||
*
|
||||
* @param uniqueId - the unique ID that is having the cooldown
|
||||
* @param targetUUID - the target (if any)
|
||||
* @param timeInSeconds - time in seconds to cool down
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public void setCooldown(String uniqueId, String targetUUID, int timeInSeconds) {
|
||||
cooldowns.computeIfAbsent(uniqueId, k -> new HashMap<>()).put(targetUUID, System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
cooldowns.computeIfAbsent(uniqueId, k -> new HashMap<>()).put(targetUUID,
|
||||
System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cool down - can be set by other commands on this one
|
||||
* @param uniqueId - the UUID that is having the cooldown
|
||||
* @param targetUUID - the target UUID (if any)
|
||||
*
|
||||
* @param uniqueId - the UUID that is having the cooldown
|
||||
* @param targetUUID - the target UUID (if any)
|
||||
* @param timeInSeconds - time in seconds to cool down
|
||||
*/
|
||||
public void setCooldown(UUID uniqueId, UUID targetUUID, int timeInSeconds) {
|
||||
cooldowns.computeIfAbsent(uniqueId.toString(), k -> new HashMap<>()).put(targetUUID == null ? null : targetUUID.toString(), System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
cooldowns.computeIfAbsent(uniqueId.toString(), k -> new HashMap<>()).put(
|
||||
targetUUID == null ? null : targetUUID.toString(), System.currentTimeMillis() + timeInSeconds * 1000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cool down for a user - can be set by other commands on this one
|
||||
* @param uniqueId - the UUID that is having the cooldown
|
||||
*
|
||||
* @param uniqueId - the UUID that is having the cooldown
|
||||
* @param timeInSeconds - time in seconds to cool down
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@ -758,7 +853,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if cool down is in progress for user
|
||||
* @param user - the caller of the command
|
||||
*
|
||||
* @param user - the caller of the command
|
||||
* @param targetUUID - the target (if any)
|
||||
* @return true if cool down in place, false if not
|
||||
*/
|
||||
@ -768,6 +864,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if cool down is in progress for user
|
||||
*
|
||||
* @param user - the user to check
|
||||
* @return true if cool down in place, false if not
|
||||
* @since 1.5.0
|
||||
@ -778,14 +875,16 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Check if cool down is in progress
|
||||
* @param user - the caller of the command
|
||||
* @param uniqueId - the id that needs to be checked
|
||||
*
|
||||
* @param user - the caller of the command
|
||||
* @param uniqueId - the id that needs to be checked
|
||||
* @param targetUUID - the target (if any)
|
||||
* @return true if cool down in place, false if not
|
||||
* @since 1.5.0
|
||||
*/
|
||||
protected boolean checkCooldown(User user, String uniqueId, String targetUUID) {
|
||||
if (!cooldowns.containsKey(uniqueId) || user.isOp() || user.hasPermission(getPermissionPrefix() + "mod.bypasscooldowns")) {
|
||||
if (!cooldowns.containsKey(uniqueId) || user.isOp()
|
||||
|| user.hasPermission(getPermissionPrefix() + "mod.bypasscooldowns")) {
|
||||
return false;
|
||||
}
|
||||
cooldowns.putIfAbsent(uniqueId, new HashMap<>());
|
||||
@ -794,7 +893,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
cooldowns.get(uniqueId).remove(targetUUID);
|
||||
return false;
|
||||
}
|
||||
int timeToGo = (int) ((cooldowns.get(uniqueId).getOrDefault(targetUUID, 0L) - System.currentTimeMillis()) / 1000);
|
||||
int timeToGo = (int) ((cooldowns.get(uniqueId).getOrDefault(targetUUID, 0L) - System.currentTimeMillis())
|
||||
/ 1000);
|
||||
user.sendMessage("general.errors.you-must-wait", TextVariables.NUMBER, String.valueOf(timeToGo));
|
||||
return true;
|
||||
}
|
||||
@ -835,6 +935,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Checks if a command is hidden
|
||||
*
|
||||
* @return the hidden
|
||||
* @since 1.13.0
|
||||
*/
|
||||
@ -844,6 +945,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
||||
|
||||
/**
|
||||
* Sets a command and all its help and tab complete as hidden
|
||||
*
|
||||
* @param hidden whether command is hidden or not
|
||||
* @since 1.13.0
|
||||
*/
|
||||
|
@ -11,7 +11,8 @@ import world.bentobox.bentobox.api.user.User;
|
||||
|
||||
/**
|
||||
* BentoBox Confirmable Command
|
||||
* Adds ability to confirm a command before execution
|
||||
* Adds ability to confirm a command before execution.
|
||||
* See {@link #askConfirmation(User, Runnable)}, {@link #askConfirmation(User, String, Runnable)}
|
||||
* @author tastybento
|
||||
* @author Poslovitch
|
||||
*/
|
||||
@ -88,7 +89,8 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells user to confirm command by retyping it.
|
||||
* Tells user to confirm command by retyping it. Uses the default message to retype it.<p>
|
||||
* If you need a custom message, use {@link #askConfirmation(User, String, Runnable)}
|
||||
* @param user User to ask confirmation to.
|
||||
* @param confirmed Runnable to be executed if successfully confirmed.
|
||||
*/
|
||||
|
@ -1,11 +1,13 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
@ -18,6 +20,9 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminDeleteCommand extends ConfirmableCommand {
|
||||
|
||||
private @Nullable UUID targetUUID;
|
||||
private Island island;
|
||||
|
||||
public AdminDeleteCommand(CompositeCommand parent) {
|
||||
super(parent, "delete");
|
||||
}
|
||||
@ -31,68 +36,98 @@ public class AdminDeleteCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
if (args.isEmpty()) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
// Convert name to a UUID
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
UUID owner = getIslands().getOwner(getWorld(), targetUUID);
|
||||
if (owner == null) {
|
||||
// Check island exists
|
||||
if (!getIslands().hasIsland(getWorld(), targetUUID) && !getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() == 1) {
|
||||
// Check if player is owner of any islands
|
||||
if (getIslands().getIslands(getWorld(), targetUUID).stream().filter(Island::hasTeam)
|
||||
.anyMatch(is -> targetUUID.equals(is.getOwner()))) {
|
||||
user.sendMessage("commands.admin.delete.cannot-delete-owner");
|
||||
return false;
|
||||
}
|
||||
// This is a delete everything request
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the island
|
||||
User target = User.getInstance(targetUUID);
|
||||
// They named the island to go to
|
||||
Map<String, IslandInfo> names = getNameIslandMap(target);
|
||||
final String name = String.join(" ", args.subList(1, args.size()));
|
||||
if (!names.containsKey(name)) {
|
||||
// Failed home name check
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
names.keySet()
|
||||
.forEach(n -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, n));
|
||||
return false;
|
||||
} else {
|
||||
IslandInfo info = names.get(name);
|
||||
island = info.island;
|
||||
}
|
||||
|
||||
// Team members should be kicked before deleting otherwise the whole team will become weird
|
||||
if (getIslands().inTeam(getWorld(), targetUUID) && owner.equals(targetUUID)) {
|
||||
if (island.hasTeam() && targetUUID.equals(island.getOwner())) {
|
||||
user.sendMessage("commands.admin.delete.cannot-delete-owner");
|
||||
return false;
|
||||
}
|
||||
if (names.size() == 1) {
|
||||
// This is the only island they have so, no need to specify it
|
||||
island = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get target
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
// Confirm
|
||||
askConfirmation(user, () -> deletePlayer(user, targetUUID));
|
||||
if (island == null) {
|
||||
// Delete the player entirely
|
||||
askConfirmation(user, () -> deletePlayer(user));
|
||||
} else {
|
||||
// Just delete the player's island
|
||||
askConfirmation(user, () -> deleteIsland(user, island));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deletePlayer(User user, UUID targetUUID) {
|
||||
private void deleteIsland(User user, Island oldIsland) {
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder().involvedPlayer(user.getUniqueId()).reason(Reason.PRECLEAR).island(oldIsland)
|
||||
.oldIsland(oldIsland).location(oldIsland.getCenter()).build();
|
||||
user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ,
|
||||
Util.xyz(oldIsland.getCenter().toVector()));
|
||||
getIslands().deleteIsland(oldIsland, true, targetUUID);
|
||||
|
||||
}
|
||||
|
||||
private void deletePlayer(User user) {
|
||||
// Delete player and island
|
||||
// Get the target's island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), targetUUID);
|
||||
Vector vector = null;
|
||||
if (oldIsland != null) {
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(Reason.PRECLEAR)
|
||||
.island(oldIsland)
|
||||
.oldIsland(oldIsland)
|
||||
.location(oldIsland.getCenter())
|
||||
.build();
|
||||
// Check if player is online and on the island
|
||||
User target = User.getInstance(targetUUID);
|
||||
// Remove them from this island (it still exists and will be deleted later)
|
||||
getIslands().removePlayer(getWorld(), targetUUID);
|
||||
if (target.isPlayer() && target.isOnline()) {
|
||||
cleanUp(target);
|
||||
}
|
||||
vector = oldIsland.getCenter().toVector();
|
||||
getIslands().deleteIsland(oldIsland, true, targetUUID);
|
||||
for (Island oldIsland : getIslands().getIslands(getWorld(), targetUUID)) {
|
||||
deleteIsland(user, oldIsland);
|
||||
}
|
||||
if (vector == null) {
|
||||
user.sendMessage("general.success");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ, Util.xyz(vector));
|
||||
// Check if player is online and on the island
|
||||
User target = User.getInstance(targetUUID);
|
||||
// Remove target from any and all islands in the world
|
||||
getIslands().removePlayer(getWorld(), targetUUID);
|
||||
if (target.isPlayer() && target.isOnline()) {
|
||||
cleanUp(target);
|
||||
}
|
||||
user.sendMessage("general.success");
|
||||
}
|
||||
|
||||
private void cleanUp(User target) {
|
||||
@ -118,6 +153,10 @@ public class AdminDeleteCommand extends ConfirmableCommand {
|
||||
|
||||
// Reset the XP
|
||||
if (getIWM().isOnLeaveResetXP(getWorld())) {
|
||||
// Player collected XP (displayed)
|
||||
target.getPlayer().setLevel(0);
|
||||
target.getPlayer().setExp(0);
|
||||
// Player total XP (not displayed)
|
||||
target.getPlayer().setTotalExperience(0);
|
||||
}
|
||||
|
||||
@ -125,6 +164,31 @@ public class AdminDeleteCommand extends ConfirmableCommand {
|
||||
Util.runCommands(target, target.getName(), getIWM().getOnLeaveCommands(getWorld()), "leave");
|
||||
}
|
||||
|
||||
private record IslandInfo(Island island, boolean islandName) {
|
||||
}
|
||||
|
||||
private Map<String, IslandInfo> getNameIslandMap(User target) {
|
||||
Map<String, IslandInfo> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), target.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), new IslandInfo(island, true));
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = target.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
|
||||
target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, new IslandInfo(island, true));
|
||||
}
|
||||
// Add homes. Homes do not need an island specified
|
||||
island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
@ -132,7 +196,16 @@ public class AdminDeleteCommand extends ConfirmableCommand {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
}
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
if (args.size() == 2) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
|
||||
}
|
||||
if (args.size() == 3) {
|
||||
UUID target = Util.getUUID(args.get(1));
|
||||
return target == null ? Optional.empty()
|
||||
: Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(User.getInstance(target)).keySet()),
|
||||
lastArg));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
|
||||
public class AdminEmptyTrashCommand extends ConfirmableCommand {
|
||||
|
||||
/**
|
||||
* Clear trash for player, or all unowned islands in trash
|
||||
* @param parent - admin command
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public AdminEmptyTrashCommand(CompositeCommand parent) {
|
||||
super(parent, "emptytrash");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("admin.trash");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.emptytrash.parameters");
|
||||
setDescription("commands.admin.emptytrash.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() > 1) {
|
||||
// Show help
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
UUID targetUUID = args.isEmpty() ? null : getPlayers().getUUID(args.get(0));
|
||||
if (!args.isEmpty() && targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Remove trash for this player
|
||||
final List<Island> islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
|
||||
if (islands.isEmpty()) {
|
||||
if (args.isEmpty()) {
|
||||
user.sendMessage("commands.admin.trash.no-unowned-in-trash");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.trash.no-islands-in-trash");
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
this.askConfirmation(user, () -> {
|
||||
getIslands().deleteQuarantinedIslandByUser(getWorld(), targetUUID);
|
||||
user.sendMessage("commands.admin.emptytrash.success");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Tells the rank of the player
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@ -82,10 +83,10 @@ public class AdminGetrankCommand extends CompositeCommand {
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get rank
|
||||
RanksManager rm = getPlugin().getRanksManager();
|
||||
User target = User.getInstance(targetUUID);
|
||||
int currentRank = island.getRank(target);
|
||||
user.sendMessage("commands.admin.getrank.rank-is", TextVariables.RANK, user.getTranslation(rm.getRank(currentRank)),
|
||||
user.sendMessage("commands.admin.getrank.rank-is", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(currentRank)),
|
||||
TextVariables.NAME, getPlayers().getName(island.getOwner()));
|
||||
return true;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class AdminInfoCommand extends CompositeCommand {
|
||||
}
|
||||
// If there are no args, then the player wants info on the island at this location
|
||||
if (args.isEmpty()) {
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user), () ->
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user, getAddon()), () ->
|
||||
user.sendMessage("commands.admin.info.no-island"));
|
||||
return true;
|
||||
}
|
||||
@ -48,10 +48,7 @@ public class AdminInfoCommand extends CompositeCommand {
|
||||
// Show info for this player
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (island != null) {
|
||||
new IslandInfo(island).showAdminInfo(user);
|
||||
if (!getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID).isEmpty()) {
|
||||
user.sendMessage("commands.admin.info.islands-in-trash");
|
||||
}
|
||||
new IslandInfo(island).showAdminInfo(user, getAddon());
|
||||
return true;
|
||||
} else {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
|
@ -0,0 +1,174 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Sets the maximum number of homes allowed on this island.
|
||||
*
|
||||
* Commands:
|
||||
* <ul>
|
||||
* <li><b>/bsb maxhomes <player> <number></b> - Sets the maximum number of homes for each island where the player is the owner. This could apply to multiple islands.</li>
|
||||
* <li><b>/bsb maxhomes <player> <number> [island name]</b> - Sets the maximum number of homes for a specific named island where the player is the owner.</li>
|
||||
* <li><b>/bsb maxhomes <number></b> - Sets the maximum number of homes for the island you are standing on (in-game only).</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author tastybento
|
||||
* @since 2.6.0
|
||||
*/
|
||||
|
||||
public class AdminMaxHomesCommand extends ConfirmableCommand {
|
||||
|
||||
Integer maxHomes;
|
||||
Map<String, Island> islands = new HashMap<>();
|
||||
|
||||
public AdminMaxHomesCommand(CompositeCommand parent) {
|
||||
super(parent, "setmaxhomes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.maxhomes");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.maxhomes.parameters");
|
||||
setDescription("commands.admin.maxhomes.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
islands.clear();
|
||||
if (args.isEmpty()) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Check arguments
|
||||
if (args.size() == 1) {
|
||||
// Player must be in game
|
||||
if (!user.isPlayer()) {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
}
|
||||
// Check world
|
||||
if (user.getWorld() != getWorld()) {
|
||||
user.sendMessage("general.errors.wrong-world");
|
||||
return false;
|
||||
}
|
||||
// Arg must be an integer to return true, otherwise false
|
||||
maxHomes = Ints.tryParse(args.get(0));
|
||||
if (maxHomes == null || maxHomes < 1) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Get the island the user is standing on
|
||||
boolean onIsland = getIslands().getIslandAt(user.getLocation()).map(is -> {
|
||||
islands.put("", is);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
if (!onIsland) {
|
||||
user.sendMessage("general.errors.not-on-island");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// More than one argument
|
||||
// First arg must be a valid player name
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Second arg must be the max homes number
|
||||
maxHomes = Ints.tryParse(args.get(1));
|
||||
if (maxHomes == null) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
// Get islands
|
||||
islands = this.getNameIslandMap(User.getInstance(targetUUID));
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
if (args.size() > 2) {
|
||||
// A specific island is mentioned. Parse which one it is and remove the others
|
||||
final String name = String.join(" ", args.subList(2, args.size())); // Join all the args from here with spaces
|
||||
|
||||
islands.keySet().removeIf(n -> !name.equalsIgnoreCase(n));
|
||||
|
||||
if (islands.isEmpty()) {
|
||||
// Failed name check - there are either
|
||||
user.sendMessage("commands.admin.maxhomes.errors.unknown-island", TextVariables.NAME, name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (islands.isEmpty() || maxHomes < 1) {
|
||||
// Sanity check
|
||||
return false;
|
||||
}
|
||||
islands.forEach((name, island) -> {
|
||||
island.setMaxHomes(maxHomes);
|
||||
user.sendMessage("commands.admin.maxhomes.max-homes-set", TextVariables.NAME, name, TextVariables.NUMBER,
|
||||
String.valueOf(maxHomes));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
if (args.size() == 2) {
|
||||
// Suggest player names
|
||||
return Optional.of(Util.getOnlinePlayerList(user));
|
||||
}
|
||||
if (args.size() > 3) {
|
||||
// Work out who is in arg 2
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(1));
|
||||
if (targetUUID != null) {
|
||||
User target = User.getInstance(targetUUID);
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(target).keySet()), lastArg));
|
||||
}
|
||||
}
|
||||
return Optional.of(List.of("1"));
|
||||
|
||||
}
|
||||
|
||||
Map<String, Island> getNameIslandMap(User user) {
|
||||
Map<String, Island> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), island);
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, island);
|
||||
}
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -2,11 +2,13 @@ package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
@ -19,6 +21,10 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminRegisterCommand extends ConfirmableCommand {
|
||||
|
||||
private Island island;
|
||||
private Location closestIsland;
|
||||
private @Nullable UUID targetUUID;
|
||||
|
||||
public AdminRegisterCommand(CompositeCommand parent) {
|
||||
super(parent, "register");
|
||||
}
|
||||
@ -32,104 +38,108 @@ public class AdminRegisterCommand extends ConfirmableCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Check world
|
||||
if (!getWorld().equals(user.getWorld())) {
|
||||
user.sendMessage("general.errors.wrong-world");
|
||||
return false;
|
||||
}
|
||||
// Get target
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
if (getIslands().hasIsland(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.player-has-island");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
user.sendMessage("commands.admin.register.cannot-register-team-player");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if this spot is still being deleted
|
||||
Location closestIsland = Util.getClosestIsland(user.getLocation());
|
||||
closestIsland = Util.getClosestIsland(user.getLocation());
|
||||
if (getPlugin().getIslandDeletionManager().inDeletion(closestIsland)) {
|
||||
user.sendMessage("commands.admin.register.in-deletion");
|
||||
return false;
|
||||
}
|
||||
// Check if island is owned
|
||||
Optional<Island> island = getIslands().getIslandAt(user.getLocation());
|
||||
if (island.filter(Island::isOwned)
|
||||
.filter(i -> !i.getOwner().equals(targetUUID))
|
||||
.isPresent()) {
|
||||
Optional<Island> opIsland = getIslands().getIslandAt(user.getLocation());
|
||||
if (opIsland.isEmpty()) {
|
||||
// Reserve spot
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.register.no-island-here"),
|
||||
() -> reserve(user, args.get(0)));
|
||||
return false;
|
||||
}
|
||||
island = opIsland.get();
|
||||
if (targetUUID.equals(island.getOwner())) {
|
||||
user.sendMessage("commands.admin.register.already-owned");
|
||||
return false;
|
||||
}
|
||||
// Check if island is spawn
|
||||
if (island.map(Island::isSpawn).orElse(false)) {
|
||||
askConfirmation(user, user.getTranslation("commands.admin.register.island-is-spawn"), () -> register(user, args.get(0), targetUUID, island, closestIsland));
|
||||
if (island.isSpawn()) {
|
||||
askConfirmation(user, user.getTranslation("commands.admin.register.island-is-spawn"),
|
||||
() -> register(user, args.get(0)));
|
||||
return false;
|
||||
}
|
||||
return register(user, args.get(0),targetUUID, island, closestIsland);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean register(User user, String targetName, UUID targetUUID, Optional<Island> island, Location closestIsland) {
|
||||
// Register island if it exists
|
||||
if (!island.map(i -> {
|
||||
// Island exists
|
||||
getIslands().setOwner(user, targetUUID, i);
|
||||
if (i.isSpawn()) {
|
||||
getIslands().clearSpawn(i.getWorld());
|
||||
}
|
||||
user.sendMessage("commands.admin.register.registered-island", TextVariables.XYZ, Util.xyz(i.getCenter().toVector()),
|
||||
TextVariables.NAME, targetName);
|
||||
user.sendMessage("general.success");
|
||||
// Build and call event
|
||||
IslandEvent.builder()
|
||||
.island(i)
|
||||
.location(i.getCenter())
|
||||
.reason(IslandEvent.Reason.REGISTERED)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.build();
|
||||
IslandEvent.builder()
|
||||
.island(i)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.VISITOR_RANK, RanksManager.OWNER_RANK)
|
||||
.build();
|
||||
return true;
|
||||
}).orElse(false)) {
|
||||
// Island does not exist - this is a reservation
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.register.no-island-here"), () -> {
|
||||
// Make island here
|
||||
Island i = getIslands().createIsland(closestIsland, targetUUID);
|
||||
if (i == null) {
|
||||
user.sendMessage("commands.admin.register.cannot-make-island");
|
||||
return;
|
||||
}
|
||||
getIslands().setOwner(user, targetUUID, i);
|
||||
i.setReserved(true);
|
||||
i.getCenter().getBlock().setType(Material.BEDROCK);
|
||||
user.sendMessage("commands.admin.register.reserved-island", TextVariables.XYZ, Util.xyz(i.getCenter().toVector()),
|
||||
TextVariables.NAME, targetName);
|
||||
// Build and fire event
|
||||
IslandEvent.builder()
|
||||
.island(i)
|
||||
.location(i.getCenter())
|
||||
.reason(IslandEvent.Reason.RESERVED)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.build();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
register(user, args.get(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve a spot for a target
|
||||
* @param user user doing the reserving
|
||||
* @param targetName target name
|
||||
*/
|
||||
void reserve(User user, String targetName) {
|
||||
Objects.requireNonNull(closestIsland);
|
||||
Objects.requireNonNull(targetUUID);
|
||||
// Island does not exist - this is a reservation
|
||||
// Make island here
|
||||
Island i = getIslands().createIsland(closestIsland, targetUUID);
|
||||
if (i == null) {
|
||||
user.sendMessage("commands.admin.register.cannot-make-island");
|
||||
return;
|
||||
}
|
||||
getIslands().setOwner(user, targetUUID, i, RanksManager.VISITOR_RANK);
|
||||
i.setReserved(true);
|
||||
i.getCenter().getBlock().setType(Material.BEDROCK);
|
||||
user.sendMessage("commands.admin.register.reserved-island", TextVariables.XYZ,
|
||||
Util.xyz(i.getCenter().toVector()), TextVariables.NAME, targetName);
|
||||
// Build and fire event
|
||||
IslandEvent.builder().island(i).location(i.getCenter()).reason(IslandEvent.Reason.RESERVED)
|
||||
.involvedPlayer(targetUUID).admin(true).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the island to a target
|
||||
* @param user user doing the registering
|
||||
* @param targetName name of target
|
||||
*/
|
||||
void register(User user, String targetName) {
|
||||
Objects.requireNonNull(closestIsland);
|
||||
Objects.requireNonNull(targetUUID);
|
||||
Objects.requireNonNull(island);
|
||||
// Island exists
|
||||
getIslands().setOwner(user, targetUUID, island, RanksManager.VISITOR_RANK);
|
||||
if (island.isSpawn()) {
|
||||
getIslands().clearSpawn(island.getWorld());
|
||||
}
|
||||
user.sendMessage("commands.admin.register.registered-island", TextVariables.XYZ,
|
||||
Util.xyz(island.getCenter().toVector()), TextVariables.NAME, targetName);
|
||||
user.sendMessage("general.success");
|
||||
// Build and call event
|
||||
IslandEvent.builder().island(island).location(island.getCenter()).reason(IslandEvent.Reason.REGISTERED)
|
||||
.involvedPlayer(targetUUID).admin(true).build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.VISITOR_RANK, RanksManager.OWNER_RANK)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
|
@ -0,0 +1,158 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* This command resets players island name.
|
||||
* @author BONNe
|
||||
*/
|
||||
public class AdminResetHomeCommand extends CompositeCommand
|
||||
{
|
||||
Map<String, Island> islands = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* @param command Parent command.
|
||||
*/
|
||||
public AdminResetHomeCommand(CompositeCommand command)
|
||||
{
|
||||
super(command, "resethome");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.setPermission("mod.resethome");
|
||||
this.setDescription("commands.admin.resethome.description");
|
||||
this.setParametersHelp("commands.admin.resethome.parameters");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param user the {@link User} who is executing this command.
|
||||
* @param label the label which has been used to execute this command.
|
||||
* It can be {@link CompositeCommand#getLabel()} or an alias.
|
||||
* @param args the command arguments.
|
||||
* @return {@code true} if name can be reset, {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
islands.clear();
|
||||
if (args.isEmpty()) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// First arg must be a valid player name
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Get islands
|
||||
islands = this.getNameIslandMap(User.getInstance(targetUUID));
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Second optional arg must be the name of the island
|
||||
if (args.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A specific island is mentioned. Parse which one it is and remove the others
|
||||
final String name = String.join(" ", args.subList(1, args.size())); // Join all the args from here with spaces
|
||||
|
||||
islands.keySet().removeIf(n -> !name.equalsIgnoreCase(n));
|
||||
|
||||
if (islands.isEmpty()) {
|
||||
// Failed name check - there are either
|
||||
user.sendMessage("commands.admin.maxhomes.errors.unknown-island", TextVariables.NAME, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param user the {@link User} who is executing this command.
|
||||
* @param label the label which has been used to execute this command.
|
||||
* It can be {@link CompositeCommand#getLabel()} or an alias.
|
||||
* @param args the command arguments.
|
||||
* @return {@code true}
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
if (islands.isEmpty()) {
|
||||
// Sanity check
|
||||
return false;
|
||||
}
|
||||
islands.forEach((name, island) -> {
|
||||
island.getHomes().keySet().removeIf(String::isEmpty); // Remove the default home
|
||||
user.sendMessage("commands.admin.resethome.cleared", TextVariables.NAME, name);
|
||||
});
|
||||
|
||||
user.sendMessage("general.success");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (args.size() == 2) {
|
||||
// Suggest player names
|
||||
return Optional.of(Util.getOnlinePlayerList(user));
|
||||
}
|
||||
if (args.size() > 2) {
|
||||
// Work out who is in arg 2
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
if (targetUUID != null) {
|
||||
User target = User.getInstance(targetUUID);
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(target).keySet()), lastArg));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
Map<String, Island> getNameIslandMap(User user) {
|
||||
Map<String, Island> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), island);
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, island);
|
||||
}
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -12,84 +11,70 @@ import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
|
||||
|
||||
/**
|
||||
* This command sets spawn point for island at admin location for island on which admin is located.
|
||||
* This command is only for player entity.
|
||||
* @author BONNe
|
||||
* @since 1.13.0
|
||||
*/
|
||||
public class AdminSetSpawnPointCommand extends ConfirmableCommand
|
||||
{
|
||||
public class AdminSetSpawnPointCommand extends ConfirmableCommand {
|
||||
/**
|
||||
* Sub-command constructor
|
||||
*
|
||||
* @param parent - the parent composite command
|
||||
*/
|
||||
public AdminSetSpawnPointCommand(CompositeCommand parent)
|
||||
{
|
||||
public AdminSetSpawnPointCommand(CompositeCommand parent) {
|
||||
super(parent, "setspawnpoint");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
public void setup() {
|
||||
this.setPermission("admin.setspawnpoint");
|
||||
this.setOnlyPlayer(true);
|
||||
this.setDescription("commands.admin.setspawnpoint.description");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method finds an island in user location and asks confirmation if spawn point
|
||||
* must be changed to that location.
|
||||
* This method finds an island in user location and asks confirmation if spawn point
|
||||
* must be changed to that location.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
Optional<Island> optionalIsland = this.getIslands().getIslandAt(user.getLocation());
|
||||
|
||||
if (optionalIsland.isPresent() &&
|
||||
(optionalIsland.get().hasNetherIsland() ||
|
||||
!World.Environment.NETHER.equals(user.getLocation().getWorld().getEnvironment())) &&
|
||||
(optionalIsland.get().hasEndIsland() ||
|
||||
!World.Environment.THE_END.equals(user.getLocation().getWorld().getEnvironment())))
|
||||
{
|
||||
if (optionalIsland.isPresent()
|
||||
&& (optionalIsland.get().hasNetherIsland()
|
||||
|| !World.Environment.NETHER.equals(user.getLocation().getWorld().getEnvironment()))
|
||||
&& (optionalIsland.get().hasEndIsland()
|
||||
|| !World.Environment.THE_END.equals(user.getLocation().getWorld().getEnvironment()))) {
|
||||
// Everything's fine, we can set the location as spawn point for island :)
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.setspawnpoint.confirmation"),
|
||||
() -> this.setSpawnPoint(user, optionalIsland.get()));
|
||||
() -> this.setSpawnPoint(user, optionalIsland.get()));
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
user.sendMessage("commands.admin.setspawnpoint.no-island-here");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method changes spawn point for island at given user location.
|
||||
* @param user User who initiate spawn point change.
|
||||
* @param island Island which is targeted by user.
|
||||
*/
|
||||
private void setSpawnPoint(User user, Island island)
|
||||
{
|
||||
private void setSpawnPoint(User user, Island island) {
|
||||
island.setSpawnPoint(Objects.requireNonNull(user.getLocation().getWorld()).getEnvironment(),
|
||||
user.getLocation());
|
||||
user.getLocation());
|
||||
user.sendMessage("commands.admin.setspawnpoint.success");
|
||||
|
||||
if (!island.isSpawn())
|
||||
{
|
||||
island.getPlayersOnIsland().forEach(player ->
|
||||
User.getInstance(player).sendMessage("commands.admin.setspawnpoint.island-spawnpoint-changed",
|
||||
"[user]", user.getName()));
|
||||
if (!island.isSpawn()) {
|
||||
island.getPlayersOnIsland().forEach(player -> User.getInstance(player)
|
||||
.sendMessage("commands.admin.setspawnpoint.island-spawnpoint-changed", "[user]", user.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ public class AdminSetrankCommand extends CompositeCommand {
|
||||
private int rankValue;
|
||||
private @Nullable UUID targetUUID;
|
||||
private @Nullable UUID ownerUUID;
|
||||
private RanksManager rm;
|
||||
|
||||
public AdminSetrankCommand(CompositeCommand adminCommand) {
|
||||
super(adminCommand, "setrank");
|
||||
@ -36,7 +35,6 @@ public class AdminSetrankCommand extends CompositeCommand {
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.setrank.parameters");
|
||||
setDescription("commands.admin.setrank.description");
|
||||
rm = getPlugin().getRanksManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,7 +51,7 @@ public class AdminSetrankCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Get rank
|
||||
rankValue = rm.getRanks().entrySet().stream()
|
||||
rankValue = RanksManager.getInstance().getRanks().entrySet().stream()
|
||||
.filter(r -> user.getTranslation(r.getKey()).equalsIgnoreCase(args.get(1))).findFirst()
|
||||
.map(Map.Entry::getValue).orElse(-999);
|
||||
if (rankValue < RanksManager.BANNED_RANK) {
|
||||
@ -121,8 +119,8 @@ public class AdminSetrankCommand extends CompositeCommand {
|
||||
ownerName = target.getName();
|
||||
}
|
||||
user.sendMessage("commands.admin.setrank.rank-set",
|
||||
"[from]", user.getTranslation(rm.getRank(currentRank)),
|
||||
"[to]", user.getTranslation(rm.getRank(rankValue)),
|
||||
"[from]", user.getTranslation(RanksManager.getInstance().getRank(currentRank)), "[to]",
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rankValue)),
|
||||
TextVariables.NAME, ownerName);
|
||||
return true;
|
||||
}
|
||||
@ -136,7 +134,7 @@ public class AdminSetrankCommand extends CompositeCommand {
|
||||
|
||||
// Return the ranks
|
||||
if (args.size() == 3) {
|
||||
return Optional.of(getPlugin().getRanksManager().getRanks()
|
||||
return Optional.of(RanksManager.getInstance().getRanks()
|
||||
.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() > RanksManager.VISITOR_RANK)
|
||||
.map(entry -> user.getTranslation(entry.getKey())).toList());
|
||||
|
@ -65,8 +65,8 @@ public class AdminSetspawnCommand extends ConfirmableCommand {
|
||||
.build();
|
||||
}
|
||||
// If island is owned, then unregister the owner and any members
|
||||
new ImmutableSet.Builder<UUID>().addAll(i.getMembers().keySet()).build().forEach(m ->
|
||||
getIslands().removePlayer(getWorld(), m));
|
||||
new ImmutableSet.Builder<UUID>().addAll(i.getMembers().keySet()).build()
|
||||
.forEach(m -> getIslands().removePlayer(i, m));
|
||||
}
|
||||
getIslands().setSpawn(i);
|
||||
i.setSpawnPoint(World.Environment.NORMAL, user.getLocation());
|
||||
|
@ -16,7 +16,6 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.api.flags.Flag.Mode;
|
||||
import world.bentobox.bentobox.api.flags.Flag.Type;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.panels.builders.TabbedPanelBuilder;
|
||||
@ -107,51 +106,66 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
|
||||
/**
|
||||
* Check that this command is correct to set a setting
|
||||
*
|
||||
* @param user - user
|
||||
* @param args - args
|
||||
* @return true if the syntax is correct
|
||||
*/
|
||||
private boolean checkSyntax(User user, List<String> args) {
|
||||
// Update the flag lists
|
||||
this.makeLists();
|
||||
if (args.size() == 2) {
|
||||
// Should be a world setting
|
||||
// If world settings, then active/disabled, otherwise player flags
|
||||
if (worldSettingFlagNames.contains(args.get(0).toUpperCase(Locale.ENGLISH))) {
|
||||
if (checkActiveDisabled(user, args.get(1))) {
|
||||
flag = getPlugin().getFlagsManager().getFlag(args.get(0).toUpperCase(Locale.ENGLISH));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
} else if (args.size() > 2) {
|
||||
// Get island
|
||||
if (!getIsland(user, args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!settingFlagNames.contains(args.get(1).toUpperCase(Locale.ENGLISH))
|
||||
&& !protectionFlagNames.contains(args.get(1).toUpperCase(Locale.ENGLISH))) {
|
||||
user.sendMessage("commands.admin.settings.unknown-flag", TextVariables.NAME, args.get(2));
|
||||
return false;
|
||||
}
|
||||
// Set flag
|
||||
flag = getPlugin().getFlagsManager().getFlag(args.get(1).toUpperCase(Locale.ENGLISH));
|
||||
// Check settings
|
||||
if (flag.isPresent()) {
|
||||
if (flag.get().getType().equals(Type.SETTING)) {
|
||||
return checkActiveDisabled(user, args.get(2));
|
||||
} else {
|
||||
// Protection flag
|
||||
return checkRank(user, String.join(" ", args.subList(2, args.size())));
|
||||
}
|
||||
int argSize = args.size();
|
||||
|
||||
if (argSize == 2) {
|
||||
return checkWorldSetting(user, args);
|
||||
} else if (argSize > 2) {
|
||||
return checkIslandSetting(user, args);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkWorldSetting(User user, List<String> args) {
|
||||
String arg0 = args.get(0).toUpperCase(Locale.ENGLISH);
|
||||
|
||||
if (worldSettingFlagNames.contains(arg0)) {
|
||||
if (checkActiveDisabled(user, args.get(1))) {
|
||||
flag = getPlugin().getFlagsManager().getFlag(args.get(0).toUpperCase(Locale.ENGLISH));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkIslandSetting(User user, List<String> args) {
|
||||
// Get island
|
||||
if (!getIsland(user, args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String arg1 = args.get(1).toUpperCase(Locale.ENGLISH);
|
||||
|
||||
if (!settingFlagNames.contains(arg1) && !protectionFlagNames.contains(arg1)) {
|
||||
user.sendMessage("commands.admin.settings.unknown-flag", TextVariables.NAME, args.get(2));
|
||||
return false;
|
||||
}
|
||||
// Set flag
|
||||
flag = getPlugin().getFlagsManager().getFlag(arg1);
|
||||
// Check settings
|
||||
if (flag.isPresent()) {
|
||||
if (flag.get().getType().equals(Type.SETTING)) {
|
||||
return checkActiveDisabled(user, args.get(2));
|
||||
} else {
|
||||
// Protection flag
|
||||
return checkRank(user, String.join(" ", args.subList(2, args.size())));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the rank given.
|
||||
@ -160,7 +174,7 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
* @return true if rank is valid
|
||||
*/
|
||||
private boolean checkRank(User user, String string) {
|
||||
for (Entry<String, Integer> en : getPlugin().getRanksManager().getRanks().entrySet()) {
|
||||
for (Entry<String, Integer> en : RanksManager.getInstance().getRanks().entrySet()) {
|
||||
if (en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK
|
||||
&& string.equalsIgnoreCase(ChatColor.stripColor(user.getTranslation(en.getKey())))) {
|
||||
// We have a winner
|
||||
@ -191,11 +205,9 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
switch (f.getType()) {
|
||||
case PROTECTION -> {
|
||||
island.setFlag(f, rank);
|
||||
getIslands().save(island);
|
||||
}
|
||||
case SETTING -> {
|
||||
island.setSettingsFlag(f, activeState);
|
||||
getIslands().save(island);
|
||||
}
|
||||
case WORLD_SETTING -> f.setSetting(getWorld(), activeState);
|
||||
default -> {
|
||||
@ -211,12 +223,11 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
}
|
||||
getPlayers().setFlagsDisplayMode(user.getUniqueId(), Mode.EXPERT);
|
||||
if (args.isEmpty()) {
|
||||
new TabbedPanelBuilder()
|
||||
.user(user)
|
||||
.world(getWorld())
|
||||
.tab(1, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING))
|
||||
.tab(1, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING, Flag.Mode.EXPERT))
|
||||
.tab(2, new WorldDefaultSettingsTab(getWorld(), user))
|
||||
.startingSlot(1)
|
||||
.size(54)
|
||||
@ -227,8 +238,8 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
new TabbedPanelBuilder()
|
||||
.user(user)
|
||||
.world(island.getWorld())
|
||||
.tab(1, new SettingsTab(user, island, Flag.Type.PROTECTION))
|
||||
.tab(2, new SettingsTab(user, island, Flag.Type.SETTING))
|
||||
.island(island).tab(1, new SettingsTab(getWorld(), user, Flag.Type.PROTECTION, Flag.Mode.EXPERT))
|
||||
.tab(2, new SettingsTab(getWorld(), user, Flag.Type.SETTING, Flag.Mode.EXPERT))
|
||||
.startingSlot(1)
|
||||
.size(54)
|
||||
.build().openPanel();
|
||||
@ -262,8 +273,7 @@ public class AdminSettingsCommand extends CompositeCommand {
|
||||
} else if (args.size() == 4) {
|
||||
// Get flag in previous argument
|
||||
options = getPlugin().getFlagsManager().getFlag(args.get(2).toUpperCase(Locale.ENGLISH)).map(f -> switch (f.getType()) {
|
||||
case PROTECTION -> getPlugin().getRanksManager()
|
||||
.getRanks().entrySet().stream()
|
||||
case PROTECTION -> RanksManager.getInstance().getRanks().entrySet().stream()
|
||||
.filter(en -> en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK)
|
||||
.map(Entry::getKey)
|
||||
.map(user::getTranslation).toList();
|
||||
|
@ -1,87 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminSwitchtoCommand extends ConfirmableCommand {
|
||||
|
||||
private UUID targetUUID;
|
||||
private @NonNull List<Island> islands;
|
||||
|
||||
/**
|
||||
* Switch player's island to the numbered one in trash
|
||||
* @param parent - admin command
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public AdminSwitchtoCommand(CompositeCommand parent) {
|
||||
super(parent, "switchto");
|
||||
islands = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("admin.switchto");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.switchto.parameters");
|
||||
setDescription("commands.admin.switchto.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
// Show help
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Check island number
|
||||
islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("commands.admin.trash.no-islands-in-trash");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (NumberUtils.isDigits(args.get(1))) {
|
||||
try {
|
||||
int n = Integer.parseInt(args.get(1));
|
||||
if (n < 1 || n > islands.size()) {
|
||||
user.sendMessage("commands.admin.switchto.out-of-range", TextVariables.NUMBER, String.valueOf(islands.size()), TextVariables.LABEL, getTopLabel());
|
||||
return false;
|
||||
}
|
||||
this.askConfirmation(user, () -> {
|
||||
if (getIslands().switchIsland(getWorld(), targetUUID, islands.get(n -1))) {
|
||||
user.sendMessage("commands.admin.switchto.success");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.switchto.cannot-switch");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -17,11 +20,17 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
import world.bentobox.bentobox.util.teleport.SafeSpotTeleport;
|
||||
|
||||
/**
|
||||
* Enables admins to teleport to a player's island, nether or end islands,
|
||||
*
|
||||
* For example /acid tp tastybento [island name] would teleport to tastybento's [named] island
|
||||
*
|
||||
*/
|
||||
public class AdminTeleportCommand extends CompositeCommand {
|
||||
|
||||
private static final String NOT_SAFE = "general.errors.no-safe-location-found";
|
||||
private @Nullable UUID targetUUID;
|
||||
private @Nullable User userToTeleport;
|
||||
private Location warpSpot;
|
||||
|
||||
/**
|
||||
* @param parent - parent command
|
||||
@ -37,16 +46,17 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
setPermission("admin.tp");
|
||||
setParametersHelp("commands.admin.tp.parameters");
|
||||
setDescription("commands.admin.tp.description");
|
||||
this.setOnlyPlayer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1 && args.size() != 2) {
|
||||
if (args.isEmpty()) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Check for console or not
|
||||
if (!user.isPlayer() && args.size() != 2) {
|
||||
if (!user.isPlayer()) {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
}
|
||||
@ -62,25 +72,6 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
// We are trying to teleport another player
|
||||
UUID playerToTeleportUUID = Util.getUUID(args.get(1));
|
||||
if (playerToTeleportUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(1));
|
||||
return false;
|
||||
} else {
|
||||
userToTeleport = User.getInstance(playerToTeleportUUID);
|
||||
if (!userToTeleport.isOnline()) {
|
||||
user.sendMessage("general.errors.offline-player");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
World world = getWorld();
|
||||
if (getLabel().equals("tpnether")) {
|
||||
world = getPlugin().getIWM().getNetherWorld(getWorld());
|
||||
@ -91,19 +82,46 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
Location warpSpot = getSpot(world);
|
||||
// Get default location if there are no arguments
|
||||
warpSpot = getSpot(world);
|
||||
if (warpSpot == null) {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
if (args.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// They named the island to go to
|
||||
Map<String, IslandInfo> names = getNameIslandMap(User.getInstance(targetUUID));
|
||||
final String name = String.join(" ", args.subList(1, args.size()));
|
||||
if (!names.containsKey(name)) {
|
||||
// Failed home name check
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
names.keySet()
|
||||
.forEach(n -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, n));
|
||||
return false;
|
||||
} else if (names.size() > 1) {
|
||||
IslandInfo info = names.get(name);
|
||||
Island island = info.island;
|
||||
warpSpot = island.getSpawnPoint(world.getEnvironment()) != null
|
||||
? island.getSpawnPoint(world.getEnvironment())
|
||||
: island.getProtectionCenter().toVector().toLocation(world);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
Objects.requireNonNull(warpSpot);
|
||||
// Otherwise, ask the admin to go to a safe spot
|
||||
String failureMessage = user.getTranslation("commands.admin.tp.manual", "[location]", warpSpot.getBlockX() + " " + warpSpot.getBlockY() + " "
|
||||
+ warpSpot.getBlockZ());
|
||||
// Set the player
|
||||
Player player = args.size() == 2 ? userToTeleport.getPlayer() : user.getPlayer();
|
||||
Player player = args.size() == 2 ? user.getPlayer() : user.getPlayer();
|
||||
if (args.size() == 2) {
|
||||
failureMessage = userToTeleport.getTranslation(NOT_SAFE);
|
||||
failureMessage = user.getTranslation(NOT_SAFE);
|
||||
}
|
||||
|
||||
// Teleport
|
||||
@ -118,12 +136,35 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
|
||||
private Location getSpot(World world) {
|
||||
Island island = getIslands().getIsland(world, targetUUID);
|
||||
if (island != null && island.getSpawnPoint(world.getEnvironment()) != null) {
|
||||
// Return the defined spawn point
|
||||
return island.getSpawnPoint(world.getEnvironment());
|
||||
if (island == null) {
|
||||
return null;
|
||||
}
|
||||
// Return the default island protection center
|
||||
return island.getProtectionCenter().toVector().toLocation(world);
|
||||
return island.getSpawnPoint(world.getEnvironment()) != null ? island.getSpawnPoint(world.getEnvironment()) : island.getProtectionCenter().toVector().toLocation(world);
|
||||
}
|
||||
|
||||
private record IslandInfo(Island island, boolean islandName) {
|
||||
}
|
||||
|
||||
private Map<String, IslandInfo> getNameIslandMap(User target) {
|
||||
Map<String, IslandInfo> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), target.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), new IslandInfo(island, true));
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = target.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
|
||||
target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, new IslandInfo(island, true));
|
||||
}
|
||||
// Add homes. Homes do not need an island specified
|
||||
island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,8 +174,17 @@ public class AdminTeleportCommand extends CompositeCommand {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
}
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
if (args.size() == 2) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
UUID target = Util.getUUID(args.get(1));
|
||||
return target == null ? Optional.empty()
|
||||
: Optional
|
||||
.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(User.getInstance(target)).keySet()), lastArg));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,200 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
import world.bentobox.bentobox.util.teleport.SafeSpotTeleport;
|
||||
|
||||
/**
|
||||
* Enables admins to teleport a player to another player's island, nether or end islands,
|
||||
*
|
||||
* For example /acid tp lspvicky tastybento [island name] would teleport lspvicky to tastybento's [named] island
|
||||
*
|
||||
*/
|
||||
public class AdminTeleportUserCommand extends CompositeCommand {
|
||||
|
||||
private static final String NOT_SAFE = "general.errors.no-safe-location-found";
|
||||
private Location warpSpot;
|
||||
private @Nullable UUID targetUUID;
|
||||
private @NonNull User toBeTeleported;
|
||||
|
||||
/**
|
||||
* @param parent - parent command
|
||||
* @param tpCommand - should be "tpuser", "tpusernether" or "tpuserend"
|
||||
*/
|
||||
public AdminTeleportUserCommand(CompositeCommand parent, String tpCommand) {
|
||||
super(parent, tpCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
// Permission
|
||||
setPermission("admin.tpuser");
|
||||
setParametersHelp("commands.admin.tpuser.parameters");
|
||||
setDescription("commands.admin.tpuser.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.isEmpty() || args.size() == 1) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Convert first name to a UUID
|
||||
UUID teleportee = Util.getUUID(args.get(0));
|
||||
if (teleportee == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Check online
|
||||
toBeTeleported = User.getInstance(teleportee);
|
||||
if (!toBeTeleported.isOnline()) {
|
||||
user.sendMessage("general.errors.offline-player");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert second name to a UUID
|
||||
targetUUID = Util.getUUID(args.get(1));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check island exists
|
||||
if (!getIslands().hasIsland(getWorld(), targetUUID) && !getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
World world = getWorld();
|
||||
if (getLabel().equals("tpusernether")) {
|
||||
world = getPlugin().getIWM().getNetherWorld(getWorld());
|
||||
} else if (getLabel().equals("tpuserend")) {
|
||||
world = getPlugin().getIWM().getEndWorld(getWorld());
|
||||
}
|
||||
if (world == null) {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
// Get default location if there are no arguments
|
||||
warpSpot = getSpot(world);
|
||||
if (warpSpot == null) {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
if (args.size() == 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// They named the island to go to
|
||||
Map<String, IslandInfo> names = getNameIslandMap(User.getInstance(targetUUID));
|
||||
final String name = String.join(" ", args.subList(2, args.size()));
|
||||
if (!names.containsKey(name)) {
|
||||
// Failed home name check
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
names.keySet()
|
||||
.forEach(n -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, n));
|
||||
return false;
|
||||
} else if (names.size() > 1) {
|
||||
IslandInfo info = names.get(name);
|
||||
Island island = info.island;
|
||||
warpSpot = island.getSpawnPoint(world.getEnvironment()) != null
|
||||
? island.getSpawnPoint(world.getEnvironment())
|
||||
: island.getProtectionCenter().toVector().toLocation(world);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
Objects.requireNonNull(warpSpot);
|
||||
// Otherwise, ask the admin to go to a safe spot
|
||||
String failureMessage = user.getTranslation("commands.admin.tp.manual", "[location]", warpSpot.getBlockX() + " " + warpSpot.getBlockY() + " "
|
||||
+ warpSpot.getBlockZ());
|
||||
// Set the player
|
||||
Player player = toBeTeleported.getPlayer();
|
||||
if (args.size() == 2) {
|
||||
failureMessage = user.getTranslation(NOT_SAFE);
|
||||
}
|
||||
|
||||
// Teleport
|
||||
new SafeSpotTeleport.Builder(getPlugin())
|
||||
.entity(player)
|
||||
.location(warpSpot)
|
||||
.failureMessage(failureMessage)
|
||||
.thenRun(() -> user.sendMessage("general.success"))
|
||||
.build();
|
||||
return true;
|
||||
}
|
||||
|
||||
private Location getSpot(World world) {
|
||||
Island island = getIslands().getIsland(world, targetUUID);
|
||||
if (island == null) {
|
||||
return null;
|
||||
}
|
||||
return island.getSpawnPoint(world.getEnvironment()) != null ? island.getSpawnPoint(world.getEnvironment()) : island.getProtectionCenter().toVector().toLocation(world);
|
||||
}
|
||||
|
||||
private record IslandInfo(Island island, boolean islandName) {
|
||||
}
|
||||
|
||||
private Map<String, IslandInfo> getNameIslandMap(User target) {
|
||||
Map<String, IslandInfo> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), target.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), new IslandInfo(island, true));
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = target.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
|
||||
target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, new IslandInfo(island, true));
|
||||
}
|
||||
// Add homes. Homes do not need an island specified
|
||||
island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
}
|
||||
if (args.size() == 2 || args.size() == 3) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
UUID target = Util.getUUID(args.get(2));
|
||||
return target == null ? Optional.empty()
|
||||
: Optional
|
||||
.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(User.getInstance(target)).keySet()), lastArg));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.IslandInfo;
|
||||
|
||||
public class AdminTrashCommand extends CompositeCommand {
|
||||
|
||||
/**
|
||||
* A command for viewing islands in the database trash
|
||||
* @param parent - admin command
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public AdminTrashCommand(CompositeCommand parent) {
|
||||
super(parent, "trash");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("admin.trash");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.trash.parameters");
|
||||
setDescription("commands.admin.trash.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() > 1) {
|
||||
// Show help
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
UUID targetUUID = args.isEmpty() ? null : getPlayers().getUUID(args.get(0));
|
||||
if (!args.isEmpty() && targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Show trash can info for this player
|
||||
List<Island> islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
|
||||
if (islands.isEmpty()) {
|
||||
if (args.isEmpty()) {
|
||||
user.sendMessage("commands.admin.trash.no-unowned-in-trash");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.trash.no-islands-in-trash");
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (targetUUID == null) {
|
||||
showTrash(user, islands);
|
||||
} else {
|
||||
getIslands().getQuarantineCache().values().forEach(v -> showTrash(user, v));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void showTrash(User user, List<Island> islands) {
|
||||
user.sendMessage("commands.admin.trash.title");
|
||||
for (int i = 0; i < islands.size(); i++) {
|
||||
user.sendMessage("commands.admin.trash.count", TextVariables.NUMBER, String.valueOf(i+1));
|
||||
new IslandInfo(islands.get(i)).showInfo(user);
|
||||
}
|
||||
user.sendMessage("commands.admin.trash.use-switch", TextVariables.LABEL, getTopLabel());
|
||||
user.sendMessage("commands.admin.trash.use-emptytrash", TextVariables.LABEL, getTopLabel());
|
||||
|
||||
}
|
||||
}
|
@ -2,13 +2,19 @@ package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.logs.LogEntry;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
@ -16,6 +22,9 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminUnregisterCommand extends ConfirmableCommand {
|
||||
|
||||
private Island targetIsland;
|
||||
private @Nullable UUID targetUUID;
|
||||
|
||||
public AdminUnregisterCommand(CompositeCommand parent) {
|
||||
super(parent, "unregister");
|
||||
}
|
||||
@ -30,12 +39,12 @@ public class AdminUnregisterCommand extends ConfirmableCommand {
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
if (args.isEmpty()) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
@ -44,43 +53,76 @@ public class AdminUnregisterCommand extends ConfirmableCommand {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
// Check if the player has more than one island
|
||||
Map<String, Island> islands = getIslandsXYZ(targetUUID);
|
||||
if (islands.size() == 0) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
} else if (args.size() == 1) {
|
||||
if (islands.size() == 1) {
|
||||
targetIsland = islands.values().iterator().next();
|
||||
return true;
|
||||
} else {
|
||||
// They need to specify which island
|
||||
user.sendMessage("commands.admin.unregister.errors.player-has-more-than-one-island");
|
||||
user.sendMessage("commands.admin.unregister.errors.specify-island-location");
|
||||
return false;
|
||||
}
|
||||
} else if (args.size() != 2) {
|
||||
// Check if the name given works
|
||||
user.sendMessage("commands.admin.unregister.errors.specify-island-location");
|
||||
return false;
|
||||
} else if (!islands.containsKey(args.get(1))) {
|
||||
if (args.get(1).equalsIgnoreCase("help")) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
user.sendMessage("commands.admin.unregister.errors.unknown-island-location");
|
||||
return false;
|
||||
}
|
||||
targetIsland = islands.get(args.get(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get target
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
Objects.requireNonNull(targetIsland);
|
||||
Objects.requireNonNull(targetUUID);
|
||||
// Everything's fine, we can set the island as spawn :)
|
||||
askConfirmation(user, () -> unregisterPlayer(user, args.get(0), targetUUID));
|
||||
askConfirmation(user, () -> unregisterIsland(user));
|
||||
return true;
|
||||
}
|
||||
|
||||
void unregisterPlayer(User user, String targetName, UUID targetUUID) {
|
||||
void unregisterIsland(User user) {
|
||||
// Unregister island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (oldIsland == null) return;
|
||||
IslandEvent.builder()
|
||||
.island(oldIsland)
|
||||
.location(oldIsland.getCenter())
|
||||
.island(targetIsland)
|
||||
.location(targetIsland.getCenter())
|
||||
.reason(IslandEvent.Reason.UNREGISTERED)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.build();
|
||||
IslandEvent.builder()
|
||||
.island(oldIsland)
|
||||
.island(targetIsland)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.OWNER_RANK, RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
targetIsland.setOwner(null);
|
||||
// Remove all island members
|
||||
oldIsland.getMemberSet().forEach(m -> getIslands().removePlayer(getWorld(), m));
|
||||
targetIsland.getMemberSet().forEach(m -> getIslands().removePlayer(targetIsland, m));
|
||||
// Remove all island players that reference this island
|
||||
oldIsland.getMembers().clear();
|
||||
getIslands().save(oldIsland);
|
||||
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(oldIsland.getCenter().toVector()),
|
||||
TextVariables.NAME, targetName);
|
||||
targetIsland.getMembers().clear();
|
||||
if (user.isPlayer()) {
|
||||
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
|
||||
.data("admin", user.getUniqueId().toString()).build());
|
||||
} else {
|
||||
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
|
||||
.data("admin", "console").build());
|
||||
}
|
||||
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(targetIsland.getCenter().toVector()),
|
||||
TextVariables.NAME, getPlayers().getName(targetUUID));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,8 +131,22 @@ public class AdminUnregisterCommand extends ConfirmableCommand {
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
} else if (args.size() == 2) {
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else if (args.size() > 2) {
|
||||
// Find out which user
|
||||
UUID uuid = getPlayers().getUUID(args.get(1));
|
||||
if (uuid != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getIslandsXYZ(uuid).keySet()), lastArg));
|
||||
}
|
||||
}
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Map<String, Island> getIslandsXYZ(UUID target) {
|
||||
return getIslands().getOwnedIslands(getWorld(), target).stream()
|
||||
.collect(Collectors.toMap(island -> Util.xyz(island.getCenter().toVector()), island -> island));
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,6 @@ import world.bentobox.bentobox.api.commands.admin.resets.AdminResetsCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamAddCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamDisbandCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamFixCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamKickCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.team.AdminTeamSetownerCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
@ -32,6 +31,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
*/
|
||||
protected DefaultAdminCommand(GameModeAddon addon) {
|
||||
// Register command with alias from config.
|
||||
// The first command listed is the "label" and the others are aliases.
|
||||
super(addon,
|
||||
addon.getWorldSettings().getAdminCommandAliases().split(" ")[0],
|
||||
addon.getWorldSettings().getAdminCommandAliases().split(" "));
|
||||
@ -50,9 +50,14 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
this.setDescription("commands.admin.help.description");
|
||||
|
||||
new AdminVersionCommand(this);
|
||||
|
||||
new AdminTeleportCommand(this, "tp");
|
||||
new AdminTeleportCommand(this, "tpnether");
|
||||
new AdminTeleportCommand(this, "tpend");
|
||||
new AdminTeleportUserCommand(this, "tpuser");
|
||||
new AdminTeleportUserCommand(this, "tpusernether");
|
||||
new AdminTeleportUserCommand(this, "tpuserend");
|
||||
|
||||
new AdminGetrankCommand(this);
|
||||
new AdminSetrankCommand(this);
|
||||
new AdminInfoCommand(this);
|
||||
@ -62,7 +67,6 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
new AdminTeamKickCommand(this);
|
||||
new AdminTeamDisbandCommand(this);
|
||||
new AdminTeamSetownerCommand(this);
|
||||
new AdminTeamFixCommand(this);
|
||||
// Blueprints
|
||||
new AdminBlueprintCommand(this);
|
||||
// Register/unregister islands
|
||||
@ -98,6 +102,10 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
||||
new AdminDeleteHomesCommand(this);
|
||||
// Reset name
|
||||
new AdminResetNameCommand(this);
|
||||
// Max homes
|
||||
new AdminMaxHomesCommand(this);
|
||||
// Reset Home
|
||||
new AdminResetHomeCommand(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@ import org.bukkit.Particle;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.commands.admin.range.AdminRangeDisplayCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
@ -23,7 +24,6 @@ public class AdminBlueprintCommand extends ConfirmableCommand {
|
||||
|
||||
// Map containing selection cuboid display tasks
|
||||
private Map<User, Integer> displayClipboards;
|
||||
private static final Particle PARTICLE = Particle.REDSTONE;
|
||||
private static final Particle.DustOptions PARTICLE_DUST_OPTIONS = new Particle.DustOptions(Color.RED, 1.0F);
|
||||
|
||||
public AdminBlueprintCommand(CompositeCommand parent) {
|
||||
@ -99,31 +99,38 @@ public class AdminBlueprintCommand extends ConfirmableCommand {
|
||||
|
||||
// Drawing x-axes
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, minY + 0.5, minZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, maxY + 0.5, minZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, minY + 0.5, maxZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, maxY + 0.5, maxZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, minY + 0.5,
|
||||
minZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, maxY + 0.5,
|
||||
minZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, minY + 0.5,
|
||||
maxZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, x + 0.5, maxY + 0.5,
|
||||
maxZ + 0.5);
|
||||
}
|
||||
|
||||
// Drawing y-axes
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, y + 0.5, minZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, y + 0.5, minZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, y + 0.5, maxZ + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, y + 0.5, maxZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, y + 0.5,
|
||||
minZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, y + 0.5,
|
||||
minZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, y + 0.5,
|
||||
maxZ + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, y + 0.5,
|
||||
maxZ + 0.5);
|
||||
}
|
||||
|
||||
// Drawing z-axes
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, minY + 0.5, z + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, minY + 0.5, z + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, maxY + 0.5, z + 0.5);
|
||||
user.spawnParticle(PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, maxY + 0.5, z + 0.5);
|
||||
}
|
||||
|
||||
// Drawing origin
|
||||
if (clipboard.getOrigin() != null) {
|
||||
user.spawnParticle(Particle.VILLAGER_HAPPY, null, clipboard.getOrigin().getBlockX() + 0.5, clipboard.getOrigin().getBlockY() + 0.5, clipboard.getOrigin().getBlockZ() + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, minY + 0.5,
|
||||
z + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, minY + 0.5,
|
||||
z + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, minX + 0.5, maxY + 0.5,
|
||||
z + 0.5);
|
||||
user.spawnParticle(AdminRangeDisplayCommand.PARTICLE, PARTICLE_DUST_OPTIONS, maxX + 0.5, maxY + 0.5,
|
||||
z + 0.5);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ public class AdminBlueprintCopyCommand extends CompositeCommand
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.copy");
|
||||
setParametersHelp("commands.admin.blueprint.copy.parameters");
|
||||
setDescription("commands.admin.blueprint.copy.description");
|
||||
}
|
||||
@ -37,7 +37,7 @@ public class AdminBlueprintCopyCommand extends CompositeCommand
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
|
||||
BlueprintClipboard clipboard =
|
||||
parent.getClipboards().computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
parent.getClipboards().computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
|
||||
boolean copyAir = args.stream().anyMatch(key -> key.equalsIgnoreCase("air"));
|
||||
boolean copyBiome = args.stream().anyMatch(key -> key.equalsIgnoreCase("biome"));
|
||||
|
@ -26,7 +26,7 @@ public class AdminBlueprintDeleteCommand extends ConfirmableCommand
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.inheritPermission();
|
||||
setPermission("admin.blueprint.delete");
|
||||
this.setParametersHelp("commands.admin.blueprint.delete.parameters");
|
||||
this.setDescription("commands.admin.blueprint.delete.description");
|
||||
}
|
||||
@ -47,10 +47,10 @@ public class AdminBlueprintDeleteCommand extends ConfirmableCommand
|
||||
if (this.getPlugin().getBlueprintsManager().getBlueprints(this.getAddon()).containsKey(blueprintName))
|
||||
{
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.blueprint.delete.confirmation"),
|
||||
() -> {
|
||||
this.getPlugin().getBlueprintsManager().deleteBlueprint(this.getAddon(), blueprintName);
|
||||
user.sendMessage("commands.admin.blueprint.delete.success", TextVariables.NAME, blueprintName);
|
||||
});
|
||||
() -> {
|
||||
this.getPlugin().getBlueprintsManager().deleteBlueprint(this.getAddon(), blueprintName);
|
||||
user.sendMessage("commands.admin.blueprint.delete.success", TextVariables.NAME, blueprintName);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -22,7 +22,7 @@ public class AdminBlueprintListCommand extends CompositeCommand
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.inheritPermission();
|
||||
setPermission("admin.blueprint.list");
|
||||
this.setDescription("commands.admin.blueprint.list.description");
|
||||
}
|
||||
|
||||
@ -54,8 +54,8 @@ public class AdminBlueprintListCommand extends CompositeCommand
|
||||
FilenameFilter blueprintFilter = (File dir, String name) -> name.endsWith(BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
|
||||
List<String> blueprintList = Arrays.stream(Objects.requireNonNull(blueprints.list(blueprintFilter))).
|
||||
map(name -> name.substring(0, name.length() - BlueprintsManager.BLUEPRINT_SUFFIX.length())).
|
||||
toList();
|
||||
map(name -> name.substring(0, name.length() - BlueprintsManager.BLUEPRINT_SUFFIX.length())).
|
||||
toList();
|
||||
|
||||
if (blueprintList.isEmpty())
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public class AdminBlueprintLoadCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.load");
|
||||
setParametersHelp("commands.admin.blueprint.load.parameters");
|
||||
setDescription("commands.admin.blueprint.load.description");
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ public class AdminBlueprintOriginCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.origin");
|
||||
setParametersHelp("commands.admin.blueprint.origin.parameters");
|
||||
setDescription("commands.admin.blueprint.origin.description");
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public class AdminBlueprintPasteCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.paste");
|
||||
setParametersHelp("commands.admin.blueprint.paste.parameters");
|
||||
setDescription("commands.admin.blueprint.paste.description");
|
||||
}
|
||||
@ -25,7 +25,7 @@ public class AdminBlueprintPasteCommand extends CompositeCommand {
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
BlueprintClipboard clipboard = parent.getClipboards().computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
if (clipboard.isFull()) {
|
||||
new BlueprintPaster(getPlugin(), clipboard, user.getLocation()).paste().thenAccept(b -> {
|
||||
new BlueprintPaster(getPlugin(), clipboard, user.getLocation()).paste(false).thenAccept(b -> {
|
||||
user.sendMessage("general.success");
|
||||
parent.showClipboard(user);
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ public class AdminBlueprintPos1Command extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.pos1");
|
||||
setParametersHelp("commands.admin.blueprint.pos1.parameters");
|
||||
setDescription("commands.admin.blueprint.pos1.description");
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public class AdminBlueprintPos2Command extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.blueprint.pos2");
|
||||
setParametersHelp("commands.admin.blueprint.pos2.parameters");
|
||||
setDescription("commands.admin.blueprint.pos2.description");
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class AdminBlueprintRenameCommand extends ConfirmableCommand
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.inheritPermission();
|
||||
setPermission("admin.blueprint.rename");
|
||||
this.setParametersHelp("commands.admin.blueprint.rename.parameters");
|
||||
this.setDescription("commands.admin.blueprint.rename.description");
|
||||
}
|
||||
@ -83,8 +83,8 @@ public class AdminBlueprintRenameCommand extends ConfirmableCommand
|
||||
{
|
||||
// Ask for confirmation to overwrite
|
||||
this.askConfirmation(user,
|
||||
user.getTranslation("commands.admin.blueprint.file-exists"),
|
||||
() -> this.rename(user, from, to, args.get(1)));
|
||||
user.getTranslation("commands.admin.blueprint.file-exists"),
|
||||
() -> this.rename(user, from, to, args.get(1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -102,11 +102,11 @@ public class AdminBlueprintRenameCommand extends ConfirmableCommand
|
||||
this.getPlugin().getBlueprintsManager().renameBlueprint(this.getAddon(), blueprint, fileName, displayName);
|
||||
|
||||
user.sendMessage("commands.admin.blueprint.rename.success",
|
||||
"[old]",
|
||||
blueprintName,
|
||||
TextVariables.NAME,
|
||||
blueprint.getName(),
|
||||
"[display]",
|
||||
blueprint.getDisplayName());
|
||||
"[old]",
|
||||
blueprintName,
|
||||
TextVariables.NAME,
|
||||
blueprint.getName(),
|
||||
"[display]",
|
||||
blueprint.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class AdminBlueprintSaveCommand extends ConfirmableCommand
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.inheritPermission();
|
||||
setPermission("admin.blueprint.save");
|
||||
this.setParametersHelp("commands.admin.blueprint.save.parameters");
|
||||
this.setDescription("commands.admin.blueprint.save.description");
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ public class NamePrompt extends StringPrompt {
|
||||
@Override
|
||||
public Prompt acceptInput(@NonNull ConversationContext context, String input) {
|
||||
if (island.renameHome(oldName, input)) {
|
||||
plugin.getIslands().save(island);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("general.success"));
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("commands.island.renamehome.already-exists"));
|
||||
|
@ -22,7 +22,7 @@ public class AdminDeathsAddCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.deaths.add");
|
||||
setDescription("commands.admin.deaths.add.description");
|
||||
setParametersHelp("commands.admin.deaths.add.parameters");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class AdminDeathsRemoveCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.deaths.remove");
|
||||
setDescription("commands.admin.deaths.remove.description");
|
||||
setParametersHelp("commands.admin.deaths.remove.parameters");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class AdminDeathsResetCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.deaths.reset");
|
||||
setDescription("commands.admin.deaths.reset.description");
|
||||
setParametersHelp("commands.admin.deaths.reset.parameters");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class AdminDeathsSetCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.deaths.set");
|
||||
setDescription("commands.admin.deaths.set.description");
|
||||
setParametersHelp("commands.admin.deaths.set.parameters");
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.purge;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -21,12 +21,16 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||
|
||||
public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
|
||||
private static final Long YEAR2000 = 946713600L;
|
||||
private static final int TOO_MANY = 1000;
|
||||
private int count;
|
||||
private boolean inPurge;
|
||||
private boolean scanning;
|
||||
private boolean toBeConfirmed;
|
||||
private Iterator<String> it;
|
||||
private User user;
|
||||
private Set<String> islands = new HashSet<>();
|
||||
private Set<Integer> loggedTiers = new HashSet<>(); // Set to store logged percentage tiers
|
||||
|
||||
public AdminPurgeCommand(CompositeCommand parent) {
|
||||
super(parent, "purge");
|
||||
@ -47,6 +51,10 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (scanning) {
|
||||
user.sendMessage("commands.admin.purge.scanning-in-progress");
|
||||
return false;
|
||||
}
|
||||
if (inPurge) {
|
||||
user.sendMessage("commands.admin.purge.purge-in-progress", TextVariables.LABEL, this.getTopLabel());
|
||||
return false;
|
||||
@ -75,14 +83,26 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
user.sendMessage("commands.admin.purge.days-one-or-more");
|
||||
return false;
|
||||
}
|
||||
islands = getOldIslands(days);
|
||||
user.sendMessage("commands.admin.purge.purgable-islands", TextVariables.NUMBER, String.valueOf(islands.size()));
|
||||
if (!islands.isEmpty()) {
|
||||
toBeConfirmed = true;
|
||||
user.sendMessage("commands.admin.purge.confirm", TextVariables.LABEL, this.getTopLabel());
|
||||
return false;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
user.sendMessage("commands.admin.purge.scanning");
|
||||
scanning = true;
|
||||
getOldIslands(days).thenAccept(islandSet -> {
|
||||
user.sendMessage("commands.admin.purge.purgable-islands", TextVariables.NUMBER,
|
||||
String.valueOf(islandSet.size()));
|
||||
if (islandSet.size() > TOO_MANY
|
||||
&& !BentoBox.getInstance().getSettings().isKeepPreviousIslandOnReset()) {
|
||||
user.sendMessage("commands.admin.purge.too-many"); // Give warning
|
||||
}
|
||||
if (!islandSet.isEmpty()) {
|
||||
toBeConfirmed = true;
|
||||
user.sendMessage("commands.admin.purge.confirm", TextVariables.LABEL, this.getTopLabel());
|
||||
islands = islandSet;
|
||||
} else {
|
||||
user.sendMessage("commands.admin.purge.none-found");
|
||||
}
|
||||
scanning = false;
|
||||
});
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
user.sendMessage("commands.admin.purge.number-error");
|
||||
return false;
|
||||
}
|
||||
@ -94,6 +114,7 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
user.sendMessage("commands.admin.purge.see-console-for-status", TextVariables.LABEL, this.getTopLabel());
|
||||
it = islands.iterator();
|
||||
count = 0;
|
||||
loggedTiers.clear(); // % reporting
|
||||
// Delete first island
|
||||
deleteIsland();
|
||||
}
|
||||
@ -103,8 +124,21 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
getIslands().getIslandById(it.next()).ifPresent(i -> {
|
||||
getIslands().deleteIsland(i, true, null);
|
||||
count++;
|
||||
String percentage = String.format("%.1f", (((float) count)/getPurgeableIslandsCount() * 100));
|
||||
getPlugin().log(count + " islands purged out of " + getPurgeableIslandsCount() + " (" + percentage + " %)");
|
||||
float percentage = ((float) count / getPurgeableIslandsCount()) * 100;
|
||||
String percentageStr = String.format("%.1f", percentage);
|
||||
// Round the percentage to check for specific tiers
|
||||
int roundedPercentage = (int) Math.floor(percentage);
|
||||
|
||||
// Determine if this percentage should be logged: 1%, 5%, or any new multiple of 5%
|
||||
if (!BentoBox.getInstance().getSettings().isKeepPreviousIslandOnReset() || (roundedPercentage > 0
|
||||
&& (roundedPercentage == 1 || roundedPercentage == 5 || roundedPercentage % 5 == 0)
|
||||
&& !loggedTiers.contains(roundedPercentage))) {
|
||||
|
||||
// Log the message and add the tier to the logged set
|
||||
getPlugin().log(count + " islands purged out of " + getPurgeableIslandsCount() + " ("
|
||||
+ percentageStr + " %)");
|
||||
loggedTiers.add(roundedPercentage);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
user.sendMessage("commands.admin.purge.completed");
|
||||
@ -116,35 +150,56 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
void onIslandDeleted(IslandDeletedEvent e) {
|
||||
if (inPurge) {
|
||||
deleteIsland();
|
||||
// Run after one tick - you cannot run millions of events in one tick otherwise the server shuts down
|
||||
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> deleteIsland(), 2L); // 10 a second
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> getOldIslands(int days) {
|
||||
getPlugin().getIslands().getIslands().stream()
|
||||
.filter(i -> !i.isSpawn())
|
||||
.filter(i -> !i.getPurgeProtected())
|
||||
.filter(i -> i.getWorld().equals(this.getWorld()))
|
||||
.filter(Island::isOwned)
|
||||
.filter(i -> i.getMembers().size() == 1)
|
||||
.filter(i -> ((double)(System.currentTimeMillis() - Bukkit.getOfflinePlayer(i.getOwner()).getLastPlayed()) / 1000 / 3600 / 24) > days)
|
||||
.forEach(i -> {
|
||||
Date date = new Date(Bukkit.getOfflinePlayer(i.getOwner()).getLastPlayed());
|
||||
BentoBox.getInstance().log("Will purge " +
|
||||
BentoBox.getInstance().getPlayers().getName(i.getOwner()) +
|
||||
" last logged in " + (int)((double)(System.currentTimeMillis() - Bukkit.getOfflinePlayer(i.getOwner()).getLastPlayed()) / 1000 / 3600 / 24) + " days ago. " + date);
|
||||
/**
|
||||
* Gets a set of islands that are older than the parameter in days
|
||||
* @param days days
|
||||
* @return set of islands
|
||||
*/
|
||||
CompletableFuture<Set<String>> getOldIslands(int days) {
|
||||
CompletableFuture<Set<String>> result = new CompletableFuture<>();
|
||||
// Process islands in one pass, logging and adding to the set if applicable
|
||||
getPlugin().getIslands().getIslandsASync().thenAccept(list -> {
|
||||
user.sendMessage("commands.admin.purge.total-islands", TextVariables.NUMBER, String.valueOf(list.size()));
|
||||
Set<String> oldIslands = new HashSet<>();
|
||||
list.stream()
|
||||
.filter(i -> !i.isSpawn()).filter(i -> !i.getPurgeProtected())
|
||||
.filter(i -> i.getWorld() != null) // to handle currently unloaded world islands
|
||||
.filter(i -> i.getWorld().equals(this.getWorld())) // Island needs to be in this world
|
||||
.filter(Island::isOwned) // The island needs to be owned
|
||||
.filter(i -> i.getMemberSet().stream().allMatch(member -> checkLastLoginTimestamp(days, member)))
|
||||
.forEach(i -> oldIslands.add(i.getUniqueId())); // Add the unique island ID to the set
|
||||
|
||||
result.complete(oldIslands);
|
||||
});
|
||||
return getPlugin().getIslands().getIslands().stream()
|
||||
.filter(i -> !i.isSpawn())
|
||||
.filter(i -> !i.getPurgeProtected())
|
||||
.filter(i -> i.getWorld().equals(this.getWorld()))
|
||||
.filter(Island::isOwned)
|
||||
.filter(i -> i.getMembers().size() == 1)
|
||||
.filter(i -> ((double)(System.currentTimeMillis() - Bukkit.getOfflinePlayer(i.getOwner()).getLastPlayed()) / 1000 / 3600 / 24) > days)
|
||||
.map(Island::getUniqueId)
|
||||
.collect(Collectors.toSet());
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean checkLastLoginTimestamp(int days, UUID member) {
|
||||
long daysInMilliseconds = days * 24L * 3600 * 1000; // Calculate days in milliseconds
|
||||
Long lastLoginTimestamp = getPlayers().getLastLoginTimestamp(member);
|
||||
// If no valid last login time is found or it's before the year 2000, try to fetch from Bukkit
|
||||
if (lastLoginTimestamp == null || lastLoginTimestamp < YEAR2000) {
|
||||
lastLoginTimestamp = Bukkit.getOfflinePlayer(member).getLastPlayed();
|
||||
|
||||
// If still invalid, set the current timestamp to mark the user for eventual purging
|
||||
if (lastLoginTimestamp < YEAR2000) {
|
||||
getPlayers().setLoginTimeStamp(member, System.currentTimeMillis());
|
||||
return false; // User will be purged in the future
|
||||
} else {
|
||||
// Otherwise, update the last login timestamp with the valid value from Bukkit
|
||||
getPlayers().setLoginTimeStamp(member, lastLoginTimestamp);
|
||||
}
|
||||
}
|
||||
// Check if the difference between now and the last login is greater than the allowed days
|
||||
return System.currentTimeMillis() - lastLoginTimestamp > daysInMilliseconds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the inPurge
|
||||
*/
|
||||
|
@ -16,7 +16,7 @@ public class AdminPurgeProtectCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.purge.protect");
|
||||
setOnlyPlayer(true);
|
||||
setDescription("commands.admin.purge.protect.description");
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ public class AdminPurgeStatusCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.purge.status");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.purge.status.parameters");
|
||||
setDescription("commands.admin.purge.status.description");
|
||||
|
@ -13,7 +13,7 @@ public class AdminPurgeStopCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.purge.stop");
|
||||
setOnlyPlayer(false);
|
||||
setDescription("commands.admin.purge.stop.description");
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class AdminPurgeUnownedCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.purge.unowned");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.purge.unowned.parameters");
|
||||
setDescription("commands.admin.purge.unowned.description");
|
||||
|
@ -0,0 +1,103 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* @author Poslovitch
|
||||
*/
|
||||
public abstract class AbstractAdminRangeCommand extends CompositeCommand {
|
||||
|
||||
protected @Nullable UUID targetUUID;
|
||||
protected Island targetIsland;
|
||||
|
||||
public AbstractAdminRangeCommand(CompositeCommand parent, String string) {
|
||||
super(parent, string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, @NonNull List<String> args) {
|
||||
if (args.size() <= 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Util.isInteger(args.get(1), true) || Integer.parseInt(args.get(1)) < 0) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
// Check if the player has more than one island
|
||||
Map<String, Island> islands = getIslandsXYZ(targetUUID);
|
||||
if (islands.size() == 0) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
} else if (args.size() == 2) {
|
||||
// If they only have one island, 2 args are fine
|
||||
if (islands.size() == 1) {
|
||||
targetIsland = islands.values().iterator().next();
|
||||
return true;
|
||||
} else {
|
||||
// They need to specify which island
|
||||
user.sendMessage("commands.admin.unregister.errors.player-has-more-than-one-island");
|
||||
user.sendMessage("commands.admin.unregister.errors.specify-island-location");
|
||||
return false;
|
||||
}
|
||||
} else if (args.size() != 3) {
|
||||
// No location
|
||||
user.sendMessage("commands.admin.unregister.errors.specify-island-location");
|
||||
return false;
|
||||
} else if (!islands.containsKey(args.get(2))) {
|
||||
if (args.get(2).equalsIgnoreCase("help")) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
user.sendMessage("commands.admin.unregister.errors.unknown-island-location");
|
||||
return false;
|
||||
}
|
||||
targetIsland = islands.get(args.get(2));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Map<String, Island> getIslandsXYZ(UUID target) {
|
||||
return getIslands().getOwnedIslands(getWorld(), target).stream()
|
||||
.collect(Collectors.toMap(island -> Util.xyz(island.getCenter().toVector()), island -> island));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
} else if (args.size() == 3) {
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else if (args.size() > 4) {
|
||||
// Find out which user
|
||||
UUID uuid = getPlayers().getUUID(args.get(2));
|
||||
if (uuid != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getIslandsXYZ(uuid).keySet()), lastArg));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -1,23 +1,18 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* @since 1.10.0
|
||||
* @author Poslovitch
|
||||
*/
|
||||
public class AdminRangeAddCommand extends CompositeCommand {
|
||||
public class AdminRangeAddCommand extends AbstractAdminRangeCommand {
|
||||
|
||||
public AdminRangeAddCommand(AdminRangeCommand parent) {
|
||||
super(parent, "add");
|
||||
@ -25,60 +20,35 @@ public class AdminRangeAddCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.range.add");
|
||||
setDescription("commands.admin.range.add.description");
|
||||
setParametersHelp("commands.admin.range.add.parameters");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, @NonNull List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
int newRange = targetIsland.getProtectionRange() + Integer.parseInt(args.get(1));
|
||||
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
if (newRange > targetIsland.getRange()) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER,
|
||||
String.valueOf(targetIsland.getRange()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(getIslands().hasIsland(getWorld(), targetUUID) || getIslands().inTeam(getWorld(), targetUUID))) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Util.isInteger(args.get(1), true) || Integer.parseInt(args.get(1)) < 0) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
|
||||
int newRange = island.getProtectionRange() + Integer.parseInt(args.get(1));
|
||||
|
||||
if (newRange > island.getRange()) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER, String.valueOf(island.getRange()));
|
||||
return false;
|
||||
} else if (newRange == island.getProtectionRange()) {
|
||||
} else if (newRange == targetIsland.getProtectionRange()) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.same-as-before", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get old range for event
|
||||
int oldRange = island.getProtectionRange();
|
||||
int oldRange = targetIsland.getProtectionRange();
|
||||
|
||||
// Well, now it can be applied without taking any risks!
|
||||
island.setProtectionRange(newRange);
|
||||
targetIsland.setProtectionRange(newRange);
|
||||
|
||||
// Call Protection Range Change event. Does not support cancelling.
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.location(island.getCenter())
|
||||
.reason(IslandEvent.Reason.RANGE_CHANGE)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.protectionRange(newRange, oldRange)
|
||||
.build();
|
||||
.island(targetIsland).location(targetIsland.getCenter())
|
||||
.reason(IslandEvent.Reason.RANGE_CHANGE).involvedPlayer(targetUUID).admin(true)
|
||||
.protectionRange(newRange, oldRange).build();
|
||||
|
||||
user.sendMessage("commands.admin.range.add.success",
|
||||
TextVariables.NAME, args.get(0), TextVariables.NUMBER, args.get(1),
|
||||
@ -86,4 +56,6 @@ public class AdminRangeAddCommand extends CompositeCommand {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -31,4 +31,5 @@ public class AdminRangeCommand extends CompositeCommand {
|
||||
showHelp(this, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -13,6 +13,7 @@ import org.bukkit.Particle;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* @author Poslovitch
|
||||
@ -23,6 +24,9 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
||||
private static final String DISPLAY = "display";
|
||||
private static final String SHOW = "show";
|
||||
private static final String HIDE = "hide";
|
||||
public static final Particle PARTICLE = Util.findFirstMatchingEnum(Particle.class, "REDSTONE", "DUST");
|
||||
private static final Particle PARTICLE2 = Util.findFirstMatchingEnum(Particle.class, "VILLAGER_HAPPY",
|
||||
"HAPPY_VILLAGER");
|
||||
|
||||
// Map of users to which ranges must be displayed
|
||||
private final Map<User, Integer> displayRanges = new HashMap<>();
|
||||
@ -76,11 +80,11 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
||||
|
||||
// Draw the default protected area if island protected zone is different
|
||||
if (island.getProtectionRange() != getPlugin().getIWM().getIslandProtectionRange(getWorld())) {
|
||||
drawZone(user, Particle.VILLAGER_HAPPY, null, island, getPlugin().getIWM().getIslandProtectionRange(getWorld()));
|
||||
drawZone(user, PARTICLE2, null, island, getPlugin().getIWM().getIslandProtectionRange(getWorld()));
|
||||
}
|
||||
|
||||
// Draw the island area
|
||||
drawZone(user, Particle.REDSTONE, new Particle.DustOptions(Color.GRAY, 1.0F), island, island.getRange());
|
||||
drawZone(user, PARTICLE, new Particle.DustOptions(Color.GRAY, 1.0F), island, island.getRange());
|
||||
});
|
||||
}, 20, 30));
|
||||
}
|
||||
|
@ -1,23 +1,19 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* @since 1.10.0
|
||||
* @author Poslovitch
|
||||
*/
|
||||
public class AdminRangeRemoveCommand extends CompositeCommand {
|
||||
public class AdminRangeRemoveCommand extends AbstractAdminRangeCommand {
|
||||
|
||||
public AdminRangeRemoveCommand(AdminRangeCommand parent) {
|
||||
super(parent, "remove");
|
||||
@ -25,55 +21,38 @@ public class AdminRangeRemoveCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.range.remove");
|
||||
setDescription("commands.admin.range.remove.description");
|
||||
setParametersHelp("commands.admin.range.remove.parameters");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, @NonNull List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(getIslands().hasIsland(getWorld(), targetUUID) || getIslands().inTeam(getWorld(), targetUUID))) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Util.isInteger(args.get(1), true) || Integer.parseInt(args.get(1)) < 0) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
|
||||
int newRange = island.getProtectionRange() - Integer.parseInt(args.get(1));
|
||||
int newRange = targetIsland.getProtectionRange() - Integer.parseInt(args.get(1));
|
||||
|
||||
if (newRange <= 1) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-low", TextVariables.NUMBER, String.valueOf(island.getRange()));
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-low", TextVariables.NUMBER,
|
||||
String.valueOf(targetIsland.getRange()));
|
||||
return false;
|
||||
} else if (newRange == island.getProtectionRange()) {
|
||||
} else if (newRange == targetIsland.getProtectionRange()) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.same-as-before", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get old range for event
|
||||
int oldRange = island.getProtectionRange();
|
||||
int oldRange = targetIsland.getProtectionRange();
|
||||
|
||||
// Well, now it can be applied without taking any risks!
|
||||
island.setProtectionRange(newRange);
|
||||
targetIsland.setProtectionRange(newRange);
|
||||
|
||||
// Call Protection Range Change event. Does not support cancelling.
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.location(island.getCenter())
|
||||
.island(targetIsland).location(targetIsland.getCenter())
|
||||
.reason(IslandEvent.Reason.RANGE_CHANGE)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
|
@ -1,19 +1,14 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminRangeSetCommand extends CompositeCommand {
|
||||
public class AdminRangeSetCommand extends AbstractAdminRangeCommand {
|
||||
|
||||
public AdminRangeSetCommand(CompositeCommand parent) {
|
||||
super(parent, "set");
|
||||
@ -28,23 +23,6 @@ public class AdminRangeSetCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
// Show help
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get target player
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
if (!(getIslands().hasIsland(getWorld(), targetUUID) || getIslands().inTeam(getWorld(), targetUUID))) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get new range
|
||||
if (!Util.isInteger(args.get(1), true) || Integer.parseInt(args.get(1)) < 0) {
|
||||
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
|
||||
@ -52,33 +30,30 @@ public class AdminRangeSetCommand extends CompositeCommand {
|
||||
}
|
||||
int range = Integer.parseInt(args.get(1));
|
||||
|
||||
// Get island
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
|
||||
|
||||
// Do some sanity checks to make sure the new protection range won't cause problems
|
||||
if (range < 1) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-low", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
if (range > island.getRange() * 2) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER, String.valueOf(2 * island.getRange()));
|
||||
if (range > targetIsland.getRange() * 2) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER,
|
||||
String.valueOf(2 * targetIsland.getRange()));
|
||||
return false;
|
||||
}
|
||||
if (range == island.getProtectionRange()) {
|
||||
if (range == targetIsland.getProtectionRange()) {
|
||||
user.sendMessage("commands.admin.range.invalid-value.same-as-before", TextVariables.NUMBER, args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get old range for event
|
||||
int oldRange = island.getProtectionRange();
|
||||
int oldRange = targetIsland.getProtectionRange();
|
||||
|
||||
// Well, now it can be applied without taking any risks!
|
||||
island.setProtectionRange(range);
|
||||
targetIsland.setProtectionRange(range);
|
||||
|
||||
// Call Protection Range Change event. Does not support canceling.
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.location(island.getCenter())
|
||||
.island(targetIsland).location(targetIsland.getCenter())
|
||||
.reason(IslandEvent.Reason.RANGE_CHANGE)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
@ -90,14 +65,4 @@ public class AdminRangeSetCommand extends CompositeCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
}
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class AdminResetsAddCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.resets.add");
|
||||
setDescription("commands.admin.resets.add.description");
|
||||
setParametersHelp("commands.admin.resets.add.parameters");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class AdminResetsRemoveCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.resets.remove");
|
||||
setDescription("commands.admin.resets.remove.description");
|
||||
setParametersHelp("commands.admin.resets.remove.parameters");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class AdminResetsResetCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.resets.remove");
|
||||
setDescription("commands.admin.resets.reset.description");
|
||||
setParametersHelp("commands.admin.resets.reset.parameters");
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class AdminResetsSetCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setPermission("admin.resets.set");
|
||||
setDescription("commands.admin.resets.set.description");
|
||||
setParametersHelp("commands.admin.resets.set.parameters");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class AdminTeamAddCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.team");
|
||||
setPermission("mod.team.add");
|
||||
setParametersHelp("commands.admin.team.add.parameters");
|
||||
setDescription("commands.admin.team.add.description");
|
||||
}
|
||||
@ -44,19 +44,17 @@ public class AdminTeamAddCommand extends CompositeCommand {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(1));
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().hasIsland(getWorld(), ownerUUID)) {
|
||||
Island island = getIslands().getPrimaryIsland(getWorld(), ownerUUID);
|
||||
if (island == null || !getIslands().hasIsland(getWorld(), ownerUUID)) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().inTeam(getWorld(), ownerUUID) && !getIslands().getOwner(getWorld(), ownerUUID).equals(ownerUUID)) {
|
||||
if (getIslands().inTeam(getWorld(), ownerUUID) && !ownerUUID.equals(island.getOwner())) {
|
||||
user.sendMessage("commands.admin.team.add.name-not-owner", TextVariables.NAME, args.get(0));
|
||||
Island island = getIslands().getIsland(getWorld(), ownerUUID);
|
||||
if (island != null) {
|
||||
new IslandInfo(island).showMembers(user);
|
||||
}
|
||||
new IslandInfo(island).showMembers(user);
|
||||
return false;
|
||||
}
|
||||
if (getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands() && island.inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.already-on-team");
|
||||
return false;
|
||||
}
|
||||
@ -67,25 +65,19 @@ public class AdminTeamAddCommand extends CompositeCommand {
|
||||
// Success
|
||||
User target = User.getInstance(targetUUID);
|
||||
User owner = User.getInstance(ownerUUID);
|
||||
owner.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME, getPlugin().getPlayers().getName(targetUUID));
|
||||
owner.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME,
|
||||
getPlugin().getPlayers().getName(targetUUID));
|
||||
target.sendMessage("commands.island.team.invite.accept.you-joined-island", TextVariables.LABEL, getTopLabel());
|
||||
Island teamIsland = getIslands().getIsland(getWorld(), ownerUUID);
|
||||
if (teamIsland != null) {
|
||||
getIslands().setJoinTeam(teamIsland, targetUUID);
|
||||
user.sendMessage("commands.admin.team.add.success", TextVariables.NAME, target.getName(), "[owner]", owner.getName());
|
||||
TeamEvent.builder()
|
||||
.island(teamIsland)
|
||||
.reason(TeamEvent.Reason.JOINED)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.build();
|
||||
IslandEvent.builder()
|
||||
.island(teamIsland)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(teamIsland.getRank(target), RanksManager.MEMBER_RANK)
|
||||
.build();
|
||||
user.sendMessage("commands.admin.team.add.success", TextVariables.NAME, target.getName(), "[owner]",
|
||||
owner.getName());
|
||||
TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(targetUUID)
|
||||
.admin(true).build();
|
||||
IslandEvent.builder().island(teamIsland).involvedPlayer(targetUUID).admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(teamIsland.getRank(target), RanksManager.MEMBER_RANK).build();
|
||||
return true;
|
||||
} else {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
|
@ -32,7 +32,7 @@ public class AdminTeamCommand extends CompositeCommand
|
||||
|
||||
new AdminTeamAddCommand(this);
|
||||
new AdminTeamDisbandCommand(this);
|
||||
new AdminTeamFixCommand(this);
|
||||
|
||||
new AdminTeamKickCommand(this);
|
||||
new AdminTeamSetownerCommand(this);
|
||||
}
|
||||
|
@ -1,7 +1,14 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.team;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
@ -14,66 +21,110 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminTeamDisbandCommand extends CompositeCommand {
|
||||
|
||||
private Island island;
|
||||
private @Nullable UUID targetUUID;
|
||||
|
||||
/**
|
||||
* Disbands a team
|
||||
* @param parent parent command
|
||||
*/
|
||||
public AdminTeamDisbandCommand(CompositeCommand parent) {
|
||||
super(parent, "disband");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.team");
|
||||
setPermission("mod.team.disband");
|
||||
setParametersHelp("commands.admin.team.disband.parameters");
|
||||
setDescription("commands.admin.team.disband.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
if (args.isEmpty() || args.size() > 2) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().hasIsland(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
|
||||
// Find the island the player is an owner of
|
||||
Map<String, Island> islands = getIslandsXYZ(targetUUID);
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.not-in-team");
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().getOwner(getWorld(), targetUUID).equals(targetUUID)) {
|
||||
user.sendMessage("commands.admin.team.disband.use-disband-owner", "[owner]", getPlayers().getName(getIslands().getOwner(getWorld(), targetUUID)));
|
||||
|
||||
if (islands.size() > 1) {
|
||||
if (args.size() != 2 || !islands.containsKey(args.get(1))) {
|
||||
user.sendMessage("commands.admin.team.disband.more-than-one-island", TextVariables.NAME,
|
||||
getPlayers().getName(island.getOwner()));
|
||||
islands.keySet().forEach(coords -> user.sendMessage("commands.admin.team.disband.more-than-one-island",
|
||||
TextVariables.XYZ, coords));
|
||||
return false;
|
||||
}
|
||||
// Get the named island
|
||||
island = islands.get(args.get(1));
|
||||
} else {
|
||||
// Get the only island
|
||||
island = islands.values().iterator().next();
|
||||
}
|
||||
// Check that the target owns the island
|
||||
if (island.getOwner() == null || !island.getOwner().equals(targetUUID)) {
|
||||
user.sendMessage("general.errors.player-is-not-owner", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, Island> getIslandsXYZ(UUID target) {
|
||||
return getIslands().getOwnedIslands(getWorld(), target).stream().filter(is -> is.getMemberSet().size() > 1) // Filter for teams
|
||||
.collect(Collectors.toMap(is -> Util.xyz(is.getCenter().toVector()), is -> is));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
Objects.requireNonNull(island);
|
||||
Objects.requireNonNull(targetUUID);
|
||||
// Disband team
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
getIslands().getMembers(getWorld(), targetUUID).forEach(m -> {
|
||||
island.getMemberSet().forEach(m -> {
|
||||
User mUser = User.getInstance(m);
|
||||
mUser.sendMessage("commands.admin.team.disband.disbanded");
|
||||
// The owner gets to keep the island
|
||||
if (!m.equals(targetUUID)) {
|
||||
getIslands().setLeaveTeam(getWorld(), m);
|
||||
TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.KICK)
|
||||
.involvedPlayer(m)
|
||||
.admin(true)
|
||||
.build();
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(mUser), RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
getIslands().removePlayer(island, m);
|
||||
TeamEvent.builder().island(island).reason(TeamEvent.Reason.KICK).involvedPlayer(m).admin(true).build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(mUser), RanksManager.VISITOR_RANK).build();
|
||||
}
|
||||
});
|
||||
user.sendMessage("commands.admin.team.disband.success", TextVariables.NAME, args.get(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
} else if (args.size() == 3) {
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else if (args.size() > 3) {
|
||||
// Find out which user
|
||||
UUID uuid = getPlayers().getUUID(args.get(1));
|
||||
if (uuid != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getIslandsXYZ(uuid).keySet()), lastArg));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.admin.team;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
|
||||
public class AdminTeamFixCommand extends CompositeCommand {
|
||||
|
||||
|
||||
public AdminTeamFixCommand(CompositeCommand parent) {
|
||||
super(parent, "fix");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.team");
|
||||
setDescription("commands.admin.team.fix.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (!args.isEmpty()) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
getIslands().checkTeams(user, getWorld());
|
||||
return true;
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ public class AdminTeamKickCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.team");
|
||||
setPermission("mod.team.kick");
|
||||
setParametersHelp("commands.admin.team.kick.parameters");
|
||||
setDescription("commands.admin.team.kick.description");
|
||||
}
|
||||
@ -71,7 +71,7 @@ public class AdminTeamKickCommand extends CompositeCommand {
|
||||
User target = User.getInstance(targetUUID);
|
||||
target.sendMessage("commands.admin.team.kick.admin-kicked");
|
||||
|
||||
getIslands().removePlayer(getWorld(), targetUUID);
|
||||
getIslands().removePlayer(island, targetUUID);
|
||||
user.sendMessage("commands.admin.team.kick.success", TextVariables.NAME, target.getName(), "[owner]", getPlayers().getName(island.getOwner()));
|
||||
|
||||
// Fire event so add-ons know
|
||||
|
@ -2,9 +2,16 @@ package world.bentobox.bentobox.api.commands.admin.team;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
@ -15,9 +22,14 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Sets the owner of an island.
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
public class AdminTeamSetownerCommand extends CompositeCommand {
|
||||
public class AdminTeamSetownerCommand extends ConfirmableCommand {
|
||||
|
||||
private @Nullable UUID targetUUID;
|
||||
private Island island;
|
||||
private @Nullable UUID previousOwnerUUID;
|
||||
|
||||
public AdminTeamSetownerCommand(CompositeCommand parent) {
|
||||
super(parent, "setowner");
|
||||
@ -25,73 +37,95 @@ public class AdminTeamSetownerCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.team");
|
||||
setPermission("mod.team.setowner");
|
||||
setParametersHelp("commands.admin.team.setowner.parameters");
|
||||
setDescription("commands.admin.team.setowner.description");
|
||||
this.setOnlyPlayer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get target
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().inTeam(getWorld(), targetUUID)) {
|
||||
user.sendMessage("general.errors.not-in-team");
|
||||
// Check that user is on an island
|
||||
Optional<Island> opIsland = getIslands().getIslandAt(user.getLocation());
|
||||
if (opIsland.isEmpty()) {
|
||||
user.sendMessage("commands.admin.team.setowner.must-be-on-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID previousOwnerUUID = getIslands().getOwner(getWorld(), targetUUID);
|
||||
island = opIsland.get();
|
||||
previousOwnerUUID = island.getOwner();
|
||||
if (targetUUID.equals(previousOwnerUUID)) {
|
||||
user.sendMessage("commands.admin.team.setowner.already-owner", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the User corresponding to the current owner
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
Objects.requireNonNull(island);
|
||||
Objects.requireNonNull(targetUUID);
|
||||
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.team.setowner.confirmation", TextVariables.NAME,
|
||||
args.get(0), TextVariables.XYZ, Util.xyz(island.getCenter().toVector())), () -> changeOwner(user));
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected void changeOwner(User user) {
|
||||
User target = User.getInstance(targetUUID);
|
||||
|
||||
// Fire event so add-ons know
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
|
||||
// Call the setowner event
|
||||
TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.SETOWNER)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.build();
|
||||
TeamEvent.builder().island(island).reason(TeamEvent.Reason.SETOWNER).involvedPlayer(targetUUID).admin(true)
|
||||
.build();
|
||||
|
||||
// Call the rank change event for the new island owner
|
||||
// We need to call it BEFORE the actual change, in order to retain the player's previous rank.
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(target), RanksManager.OWNER_RANK)
|
||||
.build();
|
||||
// We need to call it BEFORE the actual change, in order to retain the player's
|
||||
// previous rank.
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(island.getRank(target), RanksManager.OWNER_RANK)
|
||||
.build();
|
||||
|
||||
// Make new owner
|
||||
getIslands().setOwner(getWorld(), user, targetUUID);
|
||||
user.sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, args.get(0));
|
||||
getIslands().setOwner(user, targetUUID, island, RanksManager.MEMBER_RANK);
|
||||
user.sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, target.getName());
|
||||
|
||||
// Report if this made player have more islands than expected
|
||||
// Get how many islands this player has
|
||||
int num = this.getIslands().getNumberOfConcurrentIslands(targetUUID, getWorld());
|
||||
int max = target.getPermissionValue(
|
||||
this.getIWM().getAddon(getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.number",
|
||||
this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands());
|
||||
if (num > max) {
|
||||
// You cannot make an island
|
||||
user.sendMessage("commands.admin.team.setowner.extra-islands", TextVariables.NUMBER, String.valueOf(num),
|
||||
"[max]", String.valueOf(max));
|
||||
}
|
||||
|
||||
// Call the rank change event for the old island owner
|
||||
if (previousOwnerUUID != null) {
|
||||
// We need to call it AFTER the actual change.
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(previousOwnerUUID)
|
||||
.admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.OWNER_RANK, island.getRank(previousOwnerUUID))
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(previousOwnerUUID).admin(true)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.OWNER_RANK, island.getRank(previousOwnerUUID)).build();
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
List<String> options = Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ public abstract class DefaultPlayerCommand extends CompositeCommand {
|
||||
*/
|
||||
protected DefaultPlayerCommand(GameModeAddon addon) {
|
||||
// Register command with alias from config.
|
||||
// The first command listed is the "label" and the others are aliases.
|
||||
super(addon,
|
||||
addon.getWorldSettings().getPlayerCommandAliases().split(" ")[0],
|
||||
addon.getWorldSettings().getPlayerCommandAliases().split(" "));
|
||||
|
@ -17,6 +17,7 @@ import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandBanCommand extends CompositeCommand {
|
||||
@ -45,7 +46,8 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
}
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
// Player issuing the command must have an island or be in a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())
|
||||
&& !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -53,7 +55,8 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), user));
|
||||
int rank = island.getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -67,7 +70,7 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
user.sendMessage("commands.island.ban.cannot-ban-yourself");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) {
|
||||
if (getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.ban.cannot-ban-member");
|
||||
return false;
|
||||
}
|
||||
@ -97,25 +100,26 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), issuer.getUniqueId()));
|
||||
|
||||
// Check if player can ban any more players
|
||||
int banLimit = issuer.getPermissionValue(getPermissionPrefix() + "ban.maxlimit", getIWM().getBanLimit(getWorld()));
|
||||
int banLimit = issuer.getPermissionValue(getPermissionPrefix() + "ban.maxlimit",
|
||||
getIWM().getBanLimit(getWorld()));
|
||||
if (banLimit <= -1 || island.getBanned().size() < banLimit) {
|
||||
// Run the event
|
||||
IslandBaseEvent banEvent = IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(target.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.BAN)
|
||||
.build();
|
||||
if (banEvent.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(banEvent.isCancelled()) ) {
|
||||
IslandBaseEvent banEvent = IslandEvent.builder().island(island).involvedPlayer(target.getUniqueId())
|
||||
.admin(false).reason(IslandEvent.Reason.BAN).build();
|
||||
if (banEvent.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(banEvent.isCancelled())) {
|
||||
// Banning was blocked due to an event cancellation. Fail silently.
|
||||
return false;
|
||||
}
|
||||
// Event is not cancelled
|
||||
if (island.ban(issuer.getUniqueId(), target.getUniqueId())) {
|
||||
issuer.sendMessage("commands.island.ban.player-banned", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.ban.owner-banned-you", TextVariables.NAME, issuer.getName());
|
||||
// If the player is online, has an island and on the banned island, move them home immediately
|
||||
if (target.isOnline() && getIslands().hasIsland(getWorld(), target.getUniqueId()) && island.onIsland(target.getLocation())) {
|
||||
issuer.sendMessage("commands.island.ban.player-banned", TextVariables.NAME, target.getName(),
|
||||
TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.ban.owner-banned-you", TextVariables.NAME, issuer.getName(),
|
||||
TextVariables.DISPLAY_NAME, issuer.getDisplayName());
|
||||
// If the player is online, has an island and on the banned island, move them
|
||||
// home immediately
|
||||
if (target.isOnline() && getIslands().hasIsland(getWorld(), target.getUniqueId())
|
||||
&& island.onIsland(target.getLocation())) {
|
||||
getIslands().homeTeleportAsync(getWorld(), target.getPlayer());
|
||||
island.getWorld().playSound(target.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1F, 1F);
|
||||
}
|
||||
@ -130,7 +134,7 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (lastArg.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
@ -139,8 +143,7 @@ public class IslandBanCommand extends CompositeCommand {
|
||||
if (island != null) {
|
||||
List<String> options = Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> !p.getUniqueId().equals(user.getUniqueId()))
|
||||
.filter(p -> !island.isBanned(p.getUniqueId()))
|
||||
.filter(p -> user.getPlayer().canSee(p))
|
||||
.filter(p -> !island.isBanned(p.getUniqueId())).filter(p -> user.getPlayer().canSee(p))
|
||||
.map(Player::getName).toList();
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
|
@ -8,6 +8,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
|
||||
public class IslandBanlistCommand extends CompositeCommand {
|
||||
|
||||
@ -40,7 +41,8 @@ public class IslandBanlistCommand extends CompositeCommand {
|
||||
island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -5,16 +5,16 @@ import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.managers.island.NewIsland;
|
||||
import world.bentobox.bentobox.panels.IslandCreationPanel;
|
||||
import world.bentobox.bentobox.panels.customizable.IslandCreationPanel;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* /island create - Create an island.
|
||||
*
|
||||
@ -24,6 +24,7 @@ public class IslandCreateCommand extends CompositeCommand {
|
||||
|
||||
/**
|
||||
* Command to create an island
|
||||
*
|
||||
* @param islandCommand - parent command
|
||||
*/
|
||||
public IslandCreateCommand(CompositeCommand islandCommand) {
|
||||
@ -42,14 +43,29 @@ public class IslandCreateCommand extends CompositeCommand {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Check if the island is reserved
|
||||
@Nullable
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
// Reserved islands can be made
|
||||
if (island.isReserved()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Check if this player is on a team in this world
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()
|
||||
&& getIslands().inTeam(getWorld(), user.getUniqueId()) && island != null
|
||||
&& !user.getUniqueId().equals(island.getOwner())) {
|
||||
// Team members who are not owners cannot make additional islands
|
||||
user.sendMessage("commands.island.create.you-cannot-make-team");
|
||||
return false;
|
||||
}
|
||||
// Get how many islands this player has
|
||||
int num = this.getIslands().getNumberOfConcurrentIslands(user.getUniqueId(), getWorld());
|
||||
int max = user.getPermissionValue(
|
||||
this.getIWM().getAddon(getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.number",
|
||||
this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands());
|
||||
if (num >= max) {
|
||||
// You cannot make an island
|
||||
user.sendMessage("general.errors.already-have-island");
|
||||
user.sendMessage("commands.island.create.you-cannot-make");
|
||||
return false;
|
||||
}
|
||||
if (getIWM().getMaxIslands(getWorld()) > 0
|
||||
@ -71,38 +87,61 @@ public class IslandCreateCommand extends CompositeCommand {
|
||||
user.sendMessage("commands.island.create.unknown-blueprint");
|
||||
return false;
|
||||
}
|
||||
// Check perm
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, Util.sanitizeInput(args.get(0)))) {
|
||||
return false;
|
||||
}
|
||||
// Check maximum uses
|
||||
if (checkMaxUses(user, name)) {
|
||||
return false;
|
||||
}
|
||||
// Make island
|
||||
return makeIsland(user, name);
|
||||
} else {
|
||||
if (getPlugin().getSettings().getIslandNumber() > 1
|
||||
&& checkMaxUses(user, BlueprintsManager.DEFAULT_BUNDLE_NAME)) {
|
||||
return false;
|
||||
}
|
||||
// Show panel only if there are multiple bundles available
|
||||
if (getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).size() > 1) {
|
||||
// Show panel
|
||||
IslandCreationPanel.openPanel(this, user, label);
|
||||
IslandCreationPanel.openPanel(this, user, label, false);
|
||||
return true;
|
||||
}
|
||||
return makeIsland(user, BlueprintsManager.DEFAULT_BUNDLE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkMaxUses(User user, String name) {
|
||||
if (getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).containsKey(name)) {
|
||||
int maxTimes = getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).get(name).getTimes();
|
||||
// Check how many times this player has used this bundle
|
||||
if (maxTimes > 0 && getBundleUses(user, name) >= maxTimes) {
|
||||
user.sendMessage("commands.island.create.max-uses");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private long getBundleUses(User user, String name) {
|
||||
return getIslands().getIslands(getWorld(), user).stream()
|
||||
.filter(is -> is.getMetaData("bundle").map(mdv -> name.equalsIgnoreCase(mdv.asString())).orElse(false))
|
||||
.count();
|
||||
}
|
||||
|
||||
private boolean makeIsland(User user, String name) {
|
||||
user.sendMessage("commands.island.create.creating-island");
|
||||
try {
|
||||
NewIsland.builder()
|
||||
.player(user)
|
||||
.addon(getAddon())
|
||||
.reason(Reason.CREATE)
|
||||
.name(name)
|
||||
.build();
|
||||
NewIsland.builder().player(user).addon(getAddon()).reason(Reason.CREATE).name(name).build();
|
||||
} catch (IOException e) {
|
||||
getPlugin().logError("Could not create island for player. " + e.getMessage());
|
||||
user.sendMessage(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (getSettings().isResetCooldownOnCreate()) {
|
||||
getParent().getSubCommand("reset").ifPresent(resetCommand -> resetCommand.setCooldown(user.getUniqueId(), getSettings().getResetCooldown()));
|
||||
getParent().getSubCommand("reset").ifPresent(
|
||||
resetCommand -> resetCommand.setCooldown(user.getUniqueId(), getSettings().getResetCooldown()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
@ -22,8 +22,10 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class IslandDeletehomeCommand extends ConfirmableCommand {
|
||||
|
||||
private @Nullable Island island;
|
||||
|
||||
/**
|
||||
* Deletes a home
|
||||
* @param islandCommand parent command
|
||||
*/
|
||||
public IslandDeletehomeCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "deletehome");
|
||||
}
|
||||
@ -44,34 +46,36 @@ public class IslandDeletehomeCommand extends ConfirmableCommand {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
island = getIslands().getIsland(getWorld(), user);
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
// Check island
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check command permission
|
||||
// check command ranks
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank",
|
||||
TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
TextVariables.RANK, user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the name is known
|
||||
if (!getIslands().isHomeLocation(island, String.join(" ", args))) {
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("home-list-syntax", TextVariables.NAME, s));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
this.askConfirmation(user, () -> delete(island, user, String.join(" ", args)));
|
||||
// Check if the name is known
|
||||
Map<String, Island> map = getNameIslandMap(user);
|
||||
String name = String.join(" ", args);
|
||||
if (!map.containsKey(name)) {
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
map.keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
|
||||
return false;
|
||||
}
|
||||
this.askConfirmation(user, () -> delete(map.get(name), user, name));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -84,11 +88,19 @@ public class IslandDeletehomeCommand extends ConfirmableCommand {
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
Island is = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (is != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(is.getHomes().keySet()), lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(user).keySet()), lastArg));
|
||||
|
||||
}
|
||||
|
||||
private Map<String, Island> getNameIslandMap(User user) {
|
||||
Map<String, Island> islandMap = new HashMap<>();
|
||||
for (Island isle : getIslands().getIslands(getWorld(), user.getUniqueId())) {
|
||||
// Add homes.
|
||||
isle.getHomes().keySet().forEach(name -> islandMap.put(name, isle));
|
||||
}
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
@ -59,7 +60,8 @@ public class IslandExpelCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -74,7 +76,7 @@ public class IslandExpelCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Or team member
|
||||
if (getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) {
|
||||
if (island.inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.expel.cannot-expel-member");
|
||||
return false;
|
||||
}
|
||||
@ -90,53 +92,48 @@ public class IslandExpelCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Cannot ban ops
|
||||
if (target.isOp() ||
|
||||
target.hasPermission(this.getPermissionPrefix() + "admin.noexpel") ||
|
||||
target.hasPermission(this.getPermissionPrefix() + "mod.bypassexpel")) {
|
||||
if (target.isOp() || target.hasPermission(this.getPermissionPrefix() + "admin.noexpel")
|
||||
|| target.hasPermission(this.getPermissionPrefix() + "mod.bypassexpel")) {
|
||||
user.sendMessage(CANNOT_EXPEL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Finished error checking - expel player
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
// Fire event
|
||||
IslandBaseEvent expelEvent = IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(target.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.EXPEL)
|
||||
.build();
|
||||
IslandBaseEvent expelEvent = IslandEvent.builder().island(island).involvedPlayer(target.getUniqueId())
|
||||
.admin(false).reason(IslandEvent.Reason.EXPEL).build();
|
||||
if (expelEvent.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(expelEvent.isCancelled())) {
|
||||
user.sendMessage(CANNOT_EXPEL);
|
||||
return false;
|
||||
}
|
||||
|
||||
target.sendMessage("commands.island.expel.player-expelled-you", TextVariables.NAME, user.getName());
|
||||
target.sendMessage("commands.island.expel.player-expelled-you", TextVariables.NAME, user.getName(),
|
||||
TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
island.getWorld().playSound(target.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1F, 1F);
|
||||
if (getIslands().hasIsland(getWorld(), target) || getIslands().inTeam(getWorld(), target.getUniqueId())) {
|
||||
// Success
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName());
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME,
|
||||
target.getDisplayName());
|
||||
// Teleport home
|
||||
getIslands().homeTeleportAsync(getWorld(), target.getPlayer());
|
||||
return true;
|
||||
} else if (getIslands().getSpawn(getWorld()).isPresent()){
|
||||
} else if (getIslands().getSpawn(getWorld()).isPresent()) {
|
||||
// Success
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName());
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME,
|
||||
target.getDisplayName());
|
||||
getIslands().spawnTeleport(getWorld(), target.getPlayer());
|
||||
return true;
|
||||
} else if (getIWM().getAddon(getWorld())
|
||||
.map(gm -> gm.getPlayerCommand()
|
||||
.map(pc -> pc.getSubCommand("create").isPresent())
|
||||
.orElse(false))
|
||||
.orElse(false)
|
||||
&& target.performCommand(this.getTopLabel() + " create")) {
|
||||
.map(gm -> gm.getPlayerCommand().map(pc -> pc.getSubCommand("create").isPresent()).orElse(false))
|
||||
.orElse(false) && target.performCommand(this.getTopLabel() + " create")) {
|
||||
getAddon().logWarning("Expel: " + target.getName() + " had no island, so one was created");
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName());
|
||||
user.sendMessage(SUCCESS, TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME,
|
||||
target.getDisplayName());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -149,15 +146,15 @@ public class IslandExpelCommand extends CompositeCommand {
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
if (island != null) {
|
||||
List<String> options = island.getPlayersOnIsland().stream()
|
||||
.filter(p -> !p.equals(user.getPlayer())) // Not self
|
||||
List<String> options = island.getPlayersOnIsland().stream().filter(p -> !p.equals(user.getPlayer())) // Not
|
||||
// self
|
||||
.filter(p -> user.getPlayer().canSee(p)) // Not invisible
|
||||
.filter(p -> !p.isOp()) // Not op
|
||||
.filter(p -> !p.hasPermission(this.getPermissionPrefix() + "admin.noexpel"))
|
||||
.filter(p -> !p.hasPermission(this.getPermissionPrefix() + "mod.bypassexpel"))
|
||||
.map(Player::getName).toList();
|
||||
.filter(p -> !p.hasPermission(this.getPermissionPrefix() + "mod.bypassexpel")).map(Player::getName)
|
||||
.toList();
|
||||
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -2,7 +2,9 @@ package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
@ -35,50 +37,108 @@ public class IslandGoCommand extends DelayedTeleportCommand {
|
||||
// Check if mid-teleport
|
||||
if (getIslands().isGoingHome(user)) {
|
||||
// Tell them again that it's in progress
|
||||
user.sendMessage("commands.island.go.teleport");
|
||||
user.sendMessage("commands.island.go.in-progress");
|
||||
return false;
|
||||
}
|
||||
// Check if the island is reserved
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
List<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId());
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
if (island.isReserved()) {
|
||||
// Send player to create an island
|
||||
getParent().getSubCommand("create").ifPresent(createCmd -> createCmd.call(user, createCmd.getLabel(), Collections.emptyList()));
|
||||
// Check if the island is reserved
|
||||
if (checkReserved(user, islands)) {
|
||||
return false;
|
||||
}
|
||||
// Prevent command if player is falling and its not allowed
|
||||
if ((getIWM().inWorld(user.getWorld()) && Flags.PREVENT_TELEPORT_WHEN_FALLING.isSetForWorld(user.getWorld()))
|
||||
&& user.getPlayer().getFallDistance() > 0) {
|
||||
// We're sending the "hint" to the player to tell them they cannot teleport while falling.
|
||||
user.sendMessage(Flags.PREVENT_TELEPORT_WHEN_FALLING.getHintReference());
|
||||
return false;
|
||||
}
|
||||
if (!args.isEmpty() && !getIslands().isHomeLocation(island, String.join(" ", args))) {
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer(), String.join(" ", args)));
|
||||
Map<String, IslandInfo> names = getNameIslandMap(user);
|
||||
// Check if the home is known
|
||||
if (!args.isEmpty()) {
|
||||
final String name = String.join(" ", args);
|
||||
if (!names.containsKey(name)) {
|
||||
// Failed home name check
|
||||
user.sendMessage("commands.island.go.unknown-home");
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
names.keySet().forEach(n -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, n));
|
||||
return false;
|
||||
} else {
|
||||
IslandInfo info = names.get(name);
|
||||
getIslands().setPrimaryIsland(user.getUniqueId(), info.island);
|
||||
if (!info.islandName) {
|
||||
this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer(), name)
|
||||
.thenAccept((r) -> {
|
||||
if (r.booleanValue()) {
|
||||
// Success
|
||||
getIslands().setPrimaryIsland(user.getUniqueId(), info.island);
|
||||
} else {
|
||||
user.sendMessage("commands.island.go.failure");
|
||||
getPlugin().logError(user.getName() + " could not teleport to their island - async teleport issue");
|
||||
}
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkReserved(User user, List<Island> islands) {
|
||||
for (Island island : islands) {
|
||||
if (island.isReserved()) {
|
||||
// Send player to create an island
|
||||
getParent().getSubCommand("create").ifPresent(createCmd -> createCmd.call(user, createCmd.getLabel(), Collections.emptyList()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(island.getHomes().keySet()), lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(user).keySet()), lastArg));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Record of islands and the name to type
|
||||
*/
|
||||
private record IslandInfo(Island island, boolean islandName) {
|
||||
}
|
||||
|
||||
private Map<String, IslandInfo> getNameIslandMap(User user) {
|
||||
Map<String, IslandInfo> islandMap = new HashMap<>();
|
||||
int index = 0;
|
||||
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
|
||||
index++;
|
||||
if (island.getName() != null && !island.getName().isBlank()) {
|
||||
// Name has been set
|
||||
islandMap.put(island.getName(), new IslandInfo(island, true));
|
||||
} else {
|
||||
// Name has not been set
|
||||
String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index;
|
||||
islandMap.put(text, new IslandInfo(island, true));
|
||||
}
|
||||
// Add homes. Homes do not need an island specified
|
||||
island.getHomes().keySet().stream().filter(n -> !n.isBlank())
|
||||
.forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,17 +2,11 @@ package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.panels.customizable.IslandHomesPanel;
|
||||
|
||||
public class IslandHomesCommand extends ConfirmableCommand {
|
||||
|
||||
private @Nullable Island island;
|
||||
public class IslandHomesCommand extends CompositeCommand {
|
||||
|
||||
public IslandHomesCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "homes");
|
||||
@ -27,9 +21,8 @@ public class IslandHomesCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
island = getIslands().getIsland(getWorld(), user);
|
||||
// Check island
|
||||
if (island == null || island.getOwner() == null) {
|
||||
if (getIslands().getIslands(getWorld(), user).isEmpty()) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -38,9 +31,7 @@ public class IslandHomesCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
island.getHomes().keySet().stream().filter(s -> !s.isEmpty())
|
||||
.forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
|
||||
IslandHomesPanel.openPanel(this, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import java.util.Optional;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.panels.LanguagePanel;
|
||||
import world.bentobox.bentobox.panels.customizable.LanguagePanel;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
@ -46,7 +46,7 @@ public class IslandLanguageCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LanguagePanel.openPanel(user);
|
||||
LanguagePanel.openPanel(this, user);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -65,7 +65,8 @@ public class IslandRenamehomeCommand extends ConfirmableCommand {
|
||||
// check command permission
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,9 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.managers.island.NewIsland;
|
||||
import world.bentobox.bentobox.managers.island.NewIsland.Builder;
|
||||
import world.bentobox.bentobox.panels.IslandCreationPanel;
|
||||
import world.bentobox.bentobox.panels.customizable.IslandCreationPanel;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
*/
|
||||
@ -33,8 +32,9 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
/**
|
||||
* Creates the island reset command
|
||||
*
|
||||
* @param islandCommand - parent command
|
||||
* @param noPaste - true if resetting should not paste a new island
|
||||
* @param noPaste - true if resetting should not paste a new island
|
||||
*/
|
||||
public IslandResetCommand(CompositeCommand islandCommand, boolean noPaste) {
|
||||
super(islandCommand, "reset", "restart");
|
||||
@ -93,7 +93,8 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
} else {
|
||||
// Show panel after confirmation
|
||||
if (getPlugin().getSettings().isResetConfirmation()) {
|
||||
this.askConfirmation(user, user.getTranslation("commands.island.reset.confirmation"), () -> selectBundle(user, label));
|
||||
this.askConfirmation(user, user.getTranslation("commands.island.reset.confirmation"),
|
||||
() -> selectBundle(user, label));
|
||||
} else {
|
||||
selectBundle(user, label);
|
||||
}
|
||||
@ -103,13 +104,14 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
/**
|
||||
* Either selects the bundle to use or asks the user to choose.
|
||||
*
|
||||
* @since 1.5.1
|
||||
*/
|
||||
private void selectBundle(@NonNull User user, @NonNull String label) {
|
||||
// Show panel only if there are multiple bundles available
|
||||
if (getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).size() > 1) {
|
||||
// Show panel - once the player selected a bundle, this will re-run this command
|
||||
IslandCreationPanel.openPanel(this, user, label);
|
||||
IslandCreationPanel.openPanel(this, user, label, true);
|
||||
} else {
|
||||
resetIsland(user, BlueprintsManager.DEFAULT_BUNDLE_NAME);
|
||||
}
|
||||
@ -117,6 +119,7 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
/**
|
||||
* Reset island
|
||||
*
|
||||
* @param user user
|
||||
* @param name name of Blueprint Bundle
|
||||
* @return true if successful
|
||||
@ -124,19 +127,15 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
private boolean resetIsland(User user, String name) {
|
||||
// Get the player's old island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), user);
|
||||
if (oldIsland != null) {
|
||||
deleteOldIsland(user, oldIsland);
|
||||
}
|
||||
deleteOldIsland(user, oldIsland);
|
||||
|
||||
user.sendMessage("commands.island.create.creating-island");
|
||||
// Create new island and then delete the old one
|
||||
try {
|
||||
Builder builder = NewIsland.builder()
|
||||
.player(user)
|
||||
.reason(Reason.RESET)
|
||||
.addon(getAddon())
|
||||
.oldIsland(oldIsland)
|
||||
.name(name);
|
||||
if (noPaste) builder.noPaste();
|
||||
Builder builder = NewIsland.builder().player(user).reason(Reason.RESET).addon(getAddon())
|
||||
.oldIsland(oldIsland).name(name);
|
||||
if (noPaste)
|
||||
builder.noPaste();
|
||||
builder.build();
|
||||
} catch (IOException e) {
|
||||
getPlugin().logError("Could not create island for player. " + e.getMessage());
|
||||
@ -149,13 +148,8 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
private void deleteOldIsland(User user, Island oldIsland) {
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(Reason.PRECLEAR)
|
||||
.island(oldIsland)
|
||||
.oldIsland(oldIsland)
|
||||
.location(oldIsland.getCenter())
|
||||
.build();
|
||||
IslandEvent.builder().involvedPlayer(user.getUniqueId()).reason(Reason.PRECLEAR).island(oldIsland)
|
||||
.oldIsland(oldIsland).location(oldIsland.getCenter()).build();
|
||||
|
||||
// Reset the island
|
||||
|
||||
@ -168,33 +162,33 @@ public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
/**
|
||||
* Kicks the members (incl. owner) of the island.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
private void kickMembers(Island island) {
|
||||
/*
|
||||
* We cannot assume the island owner can run /[cmd] team kick (it might be disabled, or there could be permission restrictions...)
|
||||
* Therefore, we need to do it manually.
|
||||
* Plus, a more specific team event (TeamDeleteEvent) is called by this method.
|
||||
* We cannot assume the island owner can run /[cmd] team kick (it might be
|
||||
* disabled, or there could be permission restrictions...) Therefore, we need to
|
||||
* do it manually. Plus, a more specific team event (TeamDeleteEvent) is called
|
||||
* by this method.
|
||||
*/
|
||||
island.getMemberSet().forEach(memberUUID -> {
|
||||
|
||||
User member = User.getInstance(memberUUID);
|
||||
// Send a "you're kicked" message if the member is not the island owner (send before removing!)
|
||||
// Send a "you're kicked" message if the member is not the island owner (send
|
||||
// before removing!)
|
||||
if (!memberUUID.equals(island.getOwner())) {
|
||||
member.sendMessage("commands.island.reset.kicked-from-island", TextVariables.GAMEMODE, getAddon().getDescription().getName());
|
||||
member.sendMessage("commands.island.reset.kicked-from-island", TextVariables.GAMEMODE,
|
||||
getAddon().getDescription().getName());
|
||||
}
|
||||
// Remove player
|
||||
getIslands().removePlayer(getWorld(), memberUUID);
|
||||
getIslands().removePlayer(island, memberUUID);
|
||||
|
||||
// Clean player
|
||||
getPlayers().cleanLeavingPlayer(getWorld(), member, false, island);
|
||||
|
||||
// Fire event
|
||||
TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.DELETE)
|
||||
.involvedPlayer(memberUUID)
|
||||
.build();
|
||||
TeamEvent.builder().island(island).reason(TeamEvent.Reason.DELETE).involvedPlayer(memberUUID).build();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
|
||||
|
||||
/**
|
||||
@ -41,7 +42,7 @@ public class IslandResetnameCommand extends CompositeCommand {
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank",
|
||||
TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
TextVariables.RANK, user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -46,16 +46,19 @@ public class IslandSethomeCommand extends ConfirmableCommand {
|
||||
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check number of homes
|
||||
|
||||
int maxHomes = getIslands().getMaxHomes(island);
|
||||
if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes) {
|
||||
user.sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, String.valueOf(maxHomes));
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
|
||||
getIslands().getIslands(getWorld(), user).forEach(is ->
|
||||
is.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -6,9 +6,11 @@ import java.util.Objects;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
|
||||
|
||||
/**
|
||||
@ -50,7 +52,8 @@ public class IslandSetnameCommand extends CompositeCommand {
|
||||
// Check command rank.
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -72,12 +75,6 @@ public class IslandSetnameCommand extends CompositeCommand {
|
||||
name = ChatColor.translateAlternateColorCodes('&', name);
|
||||
}
|
||||
|
||||
// Check if the name doesn't already exist in the gamemode
|
||||
if (getSettings().isNameUniqueness() && getIslands().nameExists(getWorld(), name)) {
|
||||
user.sendMessage("commands.island.setname.name-already-exists");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -93,8 +90,18 @@ public class IslandSetnameCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
// Everything's good!
|
||||
Objects.requireNonNull(getIslands().getIsland(getWorld(), user)).setName(name);
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), user));
|
||||
String previousName = island.getName();
|
||||
island.setName(name);
|
||||
user.sendMessage("commands.island.setname.success", TextVariables.NAME, name);
|
||||
// Fire the IslandNameEvent
|
||||
new IslandEvent.IslandEventBuilder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(IslandEvent.Reason.NAME)
|
||||
.previousName(previousName)
|
||||
.admin(false)
|
||||
.build();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ public class IslandSettingsCommand extends CompositeCommand {
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
new TabbedPanelBuilder()
|
||||
.user(user)
|
||||
.island(island)
|
||||
.world(island.getWorld())
|
||||
.tab(1, new SettingsTab(user, island, Flag.Type.PROTECTION))
|
||||
.tab(2, new SettingsTab(user, island, Flag.Type.SETTING))
|
||||
.tab(1, new SettingsTab(getWorld(), user, Flag.Type.PROTECTION))
|
||||
.tab(2, new SettingsTab(getWorld(), user, Flag.Type.SETTING))
|
||||
.startingSlot(1)
|
||||
.size(54)
|
||||
.hideIfEmpty()
|
||||
.build().openPanel();
|
||||
return true;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
@ -54,7 +55,8 @@ public class IslandUnbanCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -94,8 +96,8 @@ public class IslandUnbanCommand extends CompositeCommand {
|
||||
}
|
||||
// Event is not cancelled
|
||||
if (island.unban(user.getUniqueId(), target.getUniqueId())) {
|
||||
user.sendMessage("commands.island.unban.player-unbanned", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.unban.you-are-unbanned", TextVariables.NAME, user.getName());
|
||||
user.sendMessage("commands.island.unban.player-unbanned", TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.unban.you-are-unbanned", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
// Set cooldown
|
||||
if (getSettings().getBanCooldown() > 0 && getParent() != null) {
|
||||
getParent().getSubCommand("ban").ifPresent(subCommand ->
|
||||
|
@ -1,83 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents an invite
|
||||
* @author tastybento
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public class Invite {
|
||||
|
||||
/**
|
||||
* Type of invitation
|
||||
*
|
||||
*/
|
||||
public enum Type {
|
||||
COOP,
|
||||
TEAM,
|
||||
TRUST
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final UUID inviter;
|
||||
private final UUID invitee;
|
||||
|
||||
/**
|
||||
* @param type - invitation type, e.g., coop, team, trust
|
||||
* @param inviter - UUID of inviter
|
||||
* @param invitee - UUID of invitee
|
||||
*/
|
||||
public Invite(Type type, UUID inviter, UUID invitee) {
|
||||
this.type = type;
|
||||
this.inviter = inviter;
|
||||
this.invitee = invitee;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the inviter
|
||||
*/
|
||||
public UUID getInviter() {
|
||||
return inviter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the invitee
|
||||
*/
|
||||
public UUID getInvitee() {
|
||||
return invitee;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(invitee, inviter, type);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof Invite other)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(invitee, other.invitee) && Objects.equals(inviter, other.inviter) && type == other.type;
|
||||
}
|
||||
}
|
@ -1,15 +1,10 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -17,22 +12,44 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.Database;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandTeamCommand extends CompositeCommand {
|
||||
|
||||
/**
|
||||
* Invited list. Key is the invited party, value is the invite.
|
||||
* @since 1.8.0
|
||||
*/
|
||||
private final Map<UUID, Invite> inviteMap;
|
||||
private IslandTeamKickCommand kickCommand;
|
||||
|
||||
private IslandTeamLeaveCommand leaveCommand;
|
||||
|
||||
private IslandTeamSetownerCommand setOwnerCommand;
|
||||
|
||||
private IslandTeamUncoopCommand uncoopCommand;
|
||||
|
||||
private IslandTeamUntrustCommand unTrustCommand;
|
||||
|
||||
private @Nullable TemplateItem border;
|
||||
|
||||
private @Nullable TemplateItem background;
|
||||
|
||||
private IslandTeamInviteAcceptCommand acceptCommand;
|
||||
|
||||
private IslandTeamInviteRejectCommand rejectCommand;
|
||||
|
||||
private IslandTeamInviteCommand inviteCommand;
|
||||
|
||||
private IslandTeamCoopCommand coopCommand;
|
||||
|
||||
private IslandTeamTrustCommand trustCommand;
|
||||
|
||||
private final Database<TeamInvite> handler;
|
||||
|
||||
public IslandTeamCommand(CompositeCommand parent) {
|
||||
super(parent, "team");
|
||||
inviteMap = new HashMap<>();
|
||||
handler = new Database<>(parent.getAddon(), TeamInvite.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,143 +58,74 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
setOnlyPlayer(true);
|
||||
setDescription("commands.island.team.description");
|
||||
// Register commands
|
||||
new IslandTeamInviteCommand(this);
|
||||
new IslandTeamLeaveCommand(this);
|
||||
new IslandTeamSetownerCommand(this);
|
||||
new IslandTeamKickCommand(this);
|
||||
new IslandTeamInviteAcceptCommand(this);
|
||||
new IslandTeamInviteRejectCommand(this);
|
||||
new IslandTeamCoopCommand(this);
|
||||
new IslandTeamUncoopCommand(this);
|
||||
new IslandTeamTrustCommand(this);
|
||||
new IslandTeamUntrustCommand(this);
|
||||
inviteCommand = new IslandTeamInviteCommand(this);
|
||||
leaveCommand = new IslandTeamLeaveCommand(this);
|
||||
setOwnerCommand = new IslandTeamSetownerCommand(this);
|
||||
kickCommand = new IslandTeamKickCommand(this);
|
||||
acceptCommand = new IslandTeamInviteAcceptCommand(this);
|
||||
rejectCommand = new IslandTeamInviteRejectCommand(this);
|
||||
if (RanksManager.getInstance().rankExists(RanksManager.COOP_RANK_REF)) {
|
||||
coopCommand = new IslandTeamCoopCommand(this);
|
||||
uncoopCommand = new IslandTeamUncoopCommand(this);
|
||||
}
|
||||
if (RanksManager.getInstance().rankExists(RanksManager.TRUSTED_RANK_REF)) {
|
||||
trustCommand = new IslandTeamTrustCommand(this);
|
||||
unTrustCommand = new IslandTeamUntrustCommand(this);
|
||||
}
|
||||
new IslandTeamPromoteCommand(this, "promote");
|
||||
new IslandTeamPromoteCommand(this, "demote");
|
||||
|
||||
// Panels
|
||||
if (!new File(getPlugin().getDataFolder() + File.separator + "panels", "team_panel.yml").exists()) {
|
||||
getPlugin().saveResource("panels/team_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Player issuing the command must have an island
|
||||
UUID ownerUUID = getOwner(getWorld(), user);
|
||||
if (ownerUUID == null) {
|
||||
Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
if (isInvited(user.getUniqueId())) {
|
||||
// Player has an invite, so show the invite
|
||||
new IslandTeamGUI(getPlugin(), this, user, island).build();
|
||||
return true;
|
||||
}
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
// Fire event so add-ons can run commands, etc.
|
||||
if (fireEvent(user)) {
|
||||
if (fireEvent(user, island)) {
|
||||
// Cancelled
|
||||
return false;
|
||||
}
|
||||
Island island = getIslands().getIsland(getWorld(), playerUUID);
|
||||
if (island == null) {
|
||||
return false;
|
||||
}
|
||||
Set<UUID> teamMembers = getMembers(getWorld(), user);
|
||||
if (ownerUUID.equals(playerUUID)) {
|
||||
if (playerUUID.equals(island.getOwner())) {
|
||||
int maxSize = getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK);
|
||||
if (teamMembers.size() < maxSize) {
|
||||
user.sendMessage("commands.island.team.invite.you-can-invite", TextVariables.NUMBER, String.valueOf(maxSize - teamMembers.size()));
|
||||
user.sendMessage("commands.island.team.invite.you-can-invite", TextVariables.NUMBER,
|
||||
String.valueOf(maxSize - teamMembers.size()));
|
||||
} else {
|
||||
user.sendMessage("commands.island.team.invite.errors.island-is-full");
|
||||
}
|
||||
}
|
||||
// Show members of island
|
||||
showMembers(island, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showMembers(Island island, User user) {
|
||||
// Gather online members
|
||||
long count = island
|
||||
.getMemberSet(RanksManager.MEMBER_RANK)
|
||||
.stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName()))
|
||||
.count();
|
||||
|
||||
// List of ranks that we will loop through
|
||||
Integer[] ranks = new Integer[]{RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK, RanksManager.MEMBER_RANK, RanksManager.TRUSTED_RANK, RanksManager.COOP_RANK};
|
||||
|
||||
// Show header:
|
||||
user.sendMessage("commands.island.team.info.header",
|
||||
"[max]", String.valueOf(getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)),
|
||||
"[total]", String.valueOf(island.getMemberSet().size()),
|
||||
"[online]", String.valueOf(count));
|
||||
|
||||
// We now need to get all online "members" of the island - incl. Trusted and coop
|
||||
List<UUID> onlineMembers = island.getMemberSet(RanksManager.COOP_RANK).stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName())).toList();
|
||||
|
||||
for (int rank : ranks) {
|
||||
Set<UUID> players = island.getMemberSet(rank, false);
|
||||
if (!players.isEmpty()) {
|
||||
if (rank == RanksManager.OWNER_RANK) {
|
||||
// Slightly special handling for the owner rank
|
||||
user.sendMessage("commands.island.team.info.rank-layout.owner",
|
||||
TextVariables.RANK, user.getTranslation(RanksManager.OWNER_RANK_REF));
|
||||
} else {
|
||||
user.sendMessage("commands.island.team.info.rank-layout.generic",
|
||||
TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)),
|
||||
TextVariables.NUMBER, String.valueOf(island.getMemberSet(rank, false).size()));
|
||||
}
|
||||
displayOnOffline(user, rank, island, onlineMembers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displayOnOffline(User user, int rank, Island island, List<UUID> onlineMembers) {
|
||||
for (UUID member : island.getMemberSet(rank, false)) {
|
||||
OfflinePlayer offlineMember = Bukkit.getOfflinePlayer(member);
|
||||
if (onlineMembers.contains(member)) {
|
||||
// the player is online
|
||||
user.sendMessage("commands.island.team.info.member-layout.online",
|
||||
TextVariables.NAME, offlineMember.getName());
|
||||
} else {
|
||||
// A bit of handling for the last joined date
|
||||
Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed());
|
||||
Instant now = Instant.now();
|
||||
|
||||
Duration duration = Duration.between(lastJoined, now);
|
||||
String lastSeen;
|
||||
final String reference = "commands.island.team.info.last-seen.layout";
|
||||
if (duration.toMinutes() < 60L) {
|
||||
lastSeen = user.getTranslation(reference,
|
||||
TextVariables.NUMBER, String.valueOf(duration.toMinutes()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.minutes"));
|
||||
} else if (duration.toHours() < 24L) {
|
||||
lastSeen = user.getTranslation(reference,
|
||||
TextVariables.NUMBER, String.valueOf(duration.toHours()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.hours"));
|
||||
} else {
|
||||
lastSeen = user.getTranslation(reference,
|
||||
TextVariables.NUMBER, String.valueOf(duration.toDays()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.days"));
|
||||
}
|
||||
|
||||
if(island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(member)) {
|
||||
user.sendMessage("commands.island.team.info.member-layout.offline",
|
||||
TextVariables.NAME, offlineMember.getName(),
|
||||
"[last_seen]", lastSeen);
|
||||
} else {
|
||||
// This will prevent anyone that is trusted or below to not have a last-seen status
|
||||
user.sendMessage("commands.island.team.info.member-layout.offline-not-last-seen",
|
||||
TextVariables.NAME, offlineMember.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean fireEvent(User user) {
|
||||
IslandBaseEvent e = TeamEvent.builder()
|
||||
.island(getIslands()
|
||||
.getIsland(getWorld(), user.getUniqueId()))
|
||||
.reason(TeamEvent.Reason.INFO)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Show the panel
|
||||
new IslandTeamGUI(getPlugin(), this, user, getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()))
|
||||
.build();
|
||||
return e.getNewEvent().map(IslandBaseEvent::isCancelled)
|
||||
.orElse(e.isCancelled());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean fireEvent(User user, Island island) {
|
||||
IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.INFO)
|
||||
.involvedPlayer(user.getUniqueId()).build();
|
||||
return e.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(e.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,29 +135,42 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
* @param invitee - uuid of invitee
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public void addInvite(Invite.Type type, @NonNull UUID inviter, @NonNull UUID invitee) {
|
||||
inviteMap.put(invitee, new Invite(type, inviter, invitee));
|
||||
public void addInvite(TeamInvite.Type type, @NonNull UUID inviter, @NonNull UUID invitee, @NonNull Island island) {
|
||||
handler.saveObjectAsync(new TeamInvite(type, inviter, invitee, island.getUniqueId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a player has been invited
|
||||
* Check if a player has been invited - validates any invite that may be in the system
|
||||
* @param invitee - UUID of invitee to check
|
||||
* @return true if invited, false if not
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public boolean isInvited(@NonNull UUID invitee) {
|
||||
return inviteMap.containsKey(invitee);
|
||||
boolean valid = false;
|
||||
if (handler.objectExists(invitee.toString())) {
|
||||
@Nullable
|
||||
TeamInvite invite = getInvite(invitee);
|
||||
valid = getIslands().getIslandById(invite.getIslandID()).map(island -> island.isOwned() // Still owned by someone
|
||||
&& !island.isDeleted() // Not deleted
|
||||
&& island.getMemberSet().contains(invite.getInviter()) // the inviter is still a member of the island
|
||||
).orElse(false);
|
||||
if (!valid) {
|
||||
// Remove invite
|
||||
handler.deleteObject(invite);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whoever invited invitee
|
||||
* Get whoever invited invitee.
|
||||
* @param invitee - uuid
|
||||
* @return UUID of inviter, or null if invitee has not been invited
|
||||
* @since 1.8.0
|
||||
*/
|
||||
@Nullable
|
||||
public UUID getInviter(UUID invitee) {
|
||||
return isInvited(invitee) ? inviteMap.get(invitee).getInviter() : null;
|
||||
return isInvited(invitee) ? handler.loadObject(invitee.toString()).getInviter() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,8 +180,8 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
* @since 1.8.0
|
||||
*/
|
||||
@Nullable
|
||||
public Invite getInvite(UUID invitee) {
|
||||
return inviteMap.get(invitee);
|
||||
public TeamInvite getInvite(UUID invitee) {
|
||||
return handler.loadObject(invitee.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,6 +190,68 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public void removeInvite(@NonNull UUID invitee) {
|
||||
inviteMap.remove(invitee);
|
||||
handler.deleteID(invitee.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the coopCommand
|
||||
*/
|
||||
protected IslandTeamCoopCommand getCoopCommand() {
|
||||
return coopCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the trustCommand
|
||||
*/
|
||||
protected IslandTeamTrustCommand getTrustCommand() {
|
||||
return trustCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteCommand getInviteCommand() {
|
||||
return inviteCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteAcceptCommand getAcceptCommand() {
|
||||
return acceptCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteRejectCommand getRejectCommand() {
|
||||
return rejectCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kickCommand
|
||||
*/
|
||||
public IslandTeamKickCommand getKickCommand() {
|
||||
return kickCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the leaveCommand
|
||||
*/
|
||||
public IslandTeamLeaveCommand getLeaveCommand() {
|
||||
return leaveCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the setOwnerCommand
|
||||
*/
|
||||
public IslandTeamSetownerCommand getSetOwnerCommand() {
|
||||
return setOwnerCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the uncoopCommand
|
||||
*/
|
||||
public IslandTeamUncoopCommand getUncoopCommand() {
|
||||
return uncoopCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unTrustCommand
|
||||
*/
|
||||
public IslandTeamUntrustCommand getUnTrustCommand() {
|
||||
return unTrustCommand;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,15 +8,16 @@ import java.util.UUID;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Command to coop another player
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@ -47,7 +48,8 @@ public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Player issuing the command must have an island or be in a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())
|
||||
&& !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -55,7 +57,8 @@ public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -73,11 +76,13 @@ public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
user.sendMessage("commands.island.team.coop.cannot-coop-yourself");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().getMembers(getWorld(), user.getUniqueId(), RanksManager.COOP_RANK).contains(targetUUID)) {
|
||||
if (getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).getMemberSet(RanksManager.COOP_RANK)
|
||||
.contains(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.coop.already-has-rank");
|
||||
return false;
|
||||
}
|
||||
if (itc.isInvited(targetUUID) && itc.getInviter(targetUUID).equals(user.getUniqueId()) && itc.getInvite(targetUUID).getType().equals(Type.COOP)) {
|
||||
if (itc.isInvited(targetUUID) && user.getUniqueId().equals(itc.getInviter(targetUUID))
|
||||
&& itc.getInvite(targetUUID) != null && itc.getInvite(targetUUID).getType().equals(Type.COOP)) {
|
||||
// Prevent spam
|
||||
user.sendMessage("commands.island.team.invite.errors.you-have-already-invited");
|
||||
return false;
|
||||
@ -92,21 +97,27 @@ public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
if (island != null) {
|
||||
if (getPlugin().getSettings().isInviteConfirmation()) {
|
||||
// Put the invited player (key) onto the list with inviter (value)
|
||||
// If someone else has invited a player, then this invite will overwrite the previous invite!
|
||||
itc.addInvite(Invite.Type.COOP, user.getUniqueId(), target.getUniqueId());
|
||||
// If someone else has invited a player, then this invite will overwrite the
|
||||
// previous invite!
|
||||
itc.addInvite(Type.COOP, user.getUniqueId(), target.getUniqueId(), island);
|
||||
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName());
|
||||
// Send message to online player
|
||||
target.sendMessage("commands.island.team.coop.name-has-invited-you", TextVariables.NAME, user.getName());
|
||||
target.sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, getTopLabel());
|
||||
target.sendMessage("commands.island.team.coop.name-has-invited-you", TextVariables.NAME,
|
||||
user.getName());
|
||||
target.sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL,
|
||||
getTopLabel());
|
||||
} else {
|
||||
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() >= getIslands().getMaxMembers(island, RanksManager.COOP_RANK)) {
|
||||
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() >= getIslands().getMaxMembers(island,
|
||||
RanksManager.COOP_RANK)) {
|
||||
user.sendMessage("commands.island.team.coop.is-full");
|
||||
return false;
|
||||
}
|
||||
|
||||
island.setRank(target, RanksManager.COOP_RANK);
|
||||
user.sendMessage("commands.island.team.coop.success", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.team.coop.you-are-a-coop-member", TextVariables.NAME, user.getName());
|
||||
user.sendMessage("commands.island.team.coop.success", TextVariables.NAME, target.getName(),
|
||||
TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.team.coop.you-are-a-coop-member", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@ -118,7 +129,7 @@ public class IslandTeamCoopCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (lastArg.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
|
@ -0,0 +1,568 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecords;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandTeamGUI {
|
||||
|
||||
/**
|
||||
* List of ranks that we will loop through in order
|
||||
*/
|
||||
private static final List<Integer> RANKS = List.of(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK,
|
||||
RanksManager.MEMBER_RANK, RanksManager.TRUSTED_RANK, RanksManager.COOP_RANK);
|
||||
|
||||
private static final String NAME = ".name";
|
||||
|
||||
private static final String TIPS = "commands.island.team.gui.tips.";
|
||||
|
||||
private final User user;
|
||||
|
||||
private final Island island;
|
||||
|
||||
private int rankView = RanksManager.OWNER_RANK;
|
||||
|
||||
private @Nullable TemplateItem border;
|
||||
|
||||
private @Nullable TemplateItem background;
|
||||
|
||||
private final IslandTeamCommand parent;
|
||||
|
||||
private final BentoBox plugin;
|
||||
|
||||
|
||||
/**
|
||||
* Displays the team management GUI
|
||||
* @param plugin BentoBox
|
||||
* @param parent IslandTeamCommand object
|
||||
* @param user user who is opening the GUI
|
||||
* @param island island that the GUI is managing
|
||||
*/
|
||||
public IslandTeamGUI(BentoBox plugin, IslandTeamCommand parent, User user, Island island) {
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
this.user = user;
|
||||
this.island = island;
|
||||
// Panels
|
||||
if (!new File(plugin.getDataFolder() + File.separator + "panels", "team_panel.yml").exists()) {
|
||||
plugin.saveResource("panels/team_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds this GUI.
|
||||
*/
|
||||
public void build() {
|
||||
// Start building panel.
|
||||
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||
panelBuilder.user(user);
|
||||
panelBuilder.world(user.getWorld());
|
||||
|
||||
panelBuilder.template("team_panel", new File(plugin.getDataFolder(), "panels"));
|
||||
|
||||
panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName());
|
||||
|
||||
panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton);
|
||||
panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton);
|
||||
panelBuilder.registerTypeBuilder("INVITED", this::createInvitedButton);
|
||||
panelBuilder.registerTypeBuilder("RANK", this::createRankButton);
|
||||
panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton);
|
||||
border = panelBuilder.getPanelTemplate().border();
|
||||
background = panelBuilder.getPanelTemplate().background();
|
||||
// Register unknown type builder.
|
||||
panelBuilder.build();
|
||||
}
|
||||
|
||||
private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
if (island == null || !user.hasPermission(this.parent.getInviteCommand().getPermission())
|
||||
|| island.getRank(user) < island.getRankCommand(parent.getLabel() + " invite")) {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
builder.icon(Material.PLAYER_HEAD);
|
||||
builder.name(user.getTranslation("commands.island.team.gui.buttons.invite.name"));
|
||||
builder.description(user.getTranslation("commands.island.team.gui.buttons.invite.description"));
|
||||
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
if (template.actions().stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
user.closeInventory();
|
||||
new IslandTeamInviteGUI(parent, false, island).build(user);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
// If there is no island, the do not show this icon
|
||||
if (island == null) {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
builder.name(user.getTranslation("commands.island.team.gui.buttons.rank-filter.name"));
|
||||
builder.icon(Material.AMETHYST_SHARD);
|
||||
// Create description
|
||||
createDescription(builder);
|
||||
createClickHandler(builder, template.actions());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void createClickHandler(PanelItemBuilder builder, @NonNull List<ActionRecords> actions) {
|
||||
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
if (actions.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
rankView = RanksManager.getInstance().getRankDownValue(rankView);
|
||||
if (rankView <= RanksManager.VISITOR_RANK) {
|
||||
rankView = RanksManager.OWNER_RANK;
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
|
||||
} else {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
}
|
||||
}
|
||||
if (clickType.equals(ClickType.RIGHT)) {
|
||||
rankView = RanksManager.getInstance().getRankUpValue(rankView);
|
||||
if (rankView >= RanksManager.OWNER_RANK) {
|
||||
rankView = RanksManager.getInstance().getRankUpValue(RanksManager.VISITOR_RANK);
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
|
||||
} else {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
}
|
||||
}
|
||||
|
||||
// Update panel after click
|
||||
build();
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void createDescription(PanelItemBuilder builder) {
|
||||
RanksManager.getInstance().getRanks().forEach((reference, score) -> {
|
||||
if (rankView == RanksManager.OWNER_RANK && score > RanksManager.VISITOR_RANK
|
||||
&& score <= RanksManager.OWNER_RANK) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.allowed-rank")
|
||||
+ user.getTranslation(reference));
|
||||
} else if (score > RanksManager.VISITOR_RANK && score < rankView) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank")
|
||||
+ user.getTranslation(reference));
|
||||
} else if (score <= RanksManager.OWNER_RANK && score > rankView) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank")
|
||||
+ user.getTranslation(reference));
|
||||
} else if (score == rankView) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.allowed-rank")
|
||||
+ user.getTranslation(reference));
|
||||
}
|
||||
});
|
||||
builder.description(user.getTranslation("commands.island.team.gui.buttons.rank-filter.description"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create invited button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
if (parent.isInvited(user.getUniqueId()) && user.hasPermission(parent.getAcceptCommand().getPermission())) {
|
||||
TeamInvite invite = parent.getInvite(user.getUniqueId());
|
||||
if (invite == null) {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
User inviter = User.getInstance(invite.getInviter());
|
||||
String name = inviter.getName();
|
||||
builder.icon(inviter.getName());
|
||||
builder.name(user.getTranslation("commands.island.team.gui.buttons.invitation"));
|
||||
createInviteDescription(builder, invite.getType(), name, template.actions());
|
||||
createInviteClickHandler(builder, invite, template.actions());
|
||||
} else {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void createInviteClickHandler(PanelItemBuilder builder, TeamInvite invite,
|
||||
@NonNull List<ActionRecords> list) {
|
||||
Type type = invite.getType();
|
||||
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
if (list.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.SHIFT_LEFT)
|
||||
&& user.hasPermission(parent.getAcceptCommand().getPermission())) {
|
||||
plugin.log("Invite accepted: " + user.getName() + " accepted " + type);
|
||||
// Accept
|
||||
switch (type) {
|
||||
case COOP -> parent.getAcceptCommand().acceptCoopInvite(user, invite);
|
||||
case TRUST -> parent.getAcceptCommand().acceptTrustInvite(user, invite);
|
||||
default -> parent.getAcceptCommand().acceptTeamInvite(user, invite);
|
||||
}
|
||||
user.closeInventory();
|
||||
}
|
||||
if (clickType.equals(ClickType.SHIFT_RIGHT)
|
||||
&& user.hasPermission(parent.getRejectCommand().getPermission())) {
|
||||
// Reject
|
||||
plugin.log("Invite rejected: " + user.getName() + " rejected " + type + " invite.");
|
||||
parent.getRejectCommand().execute(user, "", List.of());
|
||||
user.closeInventory();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void createInviteDescription(PanelItemBuilder builder, Type type, String name,
|
||||
@NonNull List<ActionRecords> list) {
|
||||
builder.description(switch (type) {
|
||||
case COOP -> List.of(
|
||||
user.getTranslation("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name));
|
||||
case TRUST -> List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you.trust",
|
||||
TextVariables.NAME, name));
|
||||
default ->
|
||||
List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name),
|
||||
user.getTranslation("commands.island.team.invite.accept.confirmation"));
|
||||
});
|
||||
// Add all the tool tips
|
||||
builder.description(list.stream()
|
||||
.map(ar -> user.getTranslation(TIPS + ar.clickType().name() + NAME) + " "
|
||||
+ user.getTranslation(ar.tooltip()))
|
||||
.toList());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create status button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createStatusButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
// Player issuing the command must have an island
|
||||
Island is = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||
if (is == null) {
|
||||
return getBlankBorder();
|
||||
}
|
||||
|
||||
return builder.icon(user.getName()).name(user.getTranslation("commands.island.team.gui.buttons.status.name"))
|
||||
.description(showMembers()).build();
|
||||
}
|
||||
|
||||
private PanelItem getBlankBorder() {
|
||||
return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER)))
|
||||
.name((Objects.requireNonNullElse(border.title(), ""))).build();
|
||||
}
|
||||
|
||||
private PanelItem getBlankBackground() {
|
||||
return new PanelItemBuilder()
|
||||
.icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER)))
|
||||
.name((Objects.requireNonNullElse(background.title(), ""))).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create member button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
// Player issuing the command must have an island
|
||||
Island is = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||
if (is == null) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
int minimumRank = RanksManager.getInstance().getRankUpValue(RanksManager.VISITOR_RANK); // Get the rank above Visitor.
|
||||
Optional<User> opMember = is.getMemberSet(minimumRank).stream().map(User::getInstance)
|
||||
.filter((User usr) -> rankView == RanksManager.OWNER_RANK || is.getRank(usr) == rankView) // If rankView is owner then show all ranks
|
||||
.sorted(Comparator.comparingInt((User usr) -> is.getRank(usr)).reversed()) // Show owner on left, then descending ranks
|
||||
.skip(slot.slot()) // Get the head for this slot
|
||||
.limit(1L).findFirst(); // Get just one head
|
||||
if (opMember.isEmpty()) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
User member = opMember.get();
|
||||
int rank = is.getRank(member);
|
||||
String rankRef = RanksManager.getInstance().getRank(rank);
|
||||
@NonNull
|
||||
List<ActionRecords> actions = template.actions();
|
||||
// Make button description depending on viewer
|
||||
List<String> desc = new ArrayList<>();
|
||||
int userRank = Objects.requireNonNull(is).getRank(user);
|
||||
// Add the tooltip for kicking
|
||||
if (user.hasPermission(parent.getKickCommand().getPermission())
|
||||
&& userRank >= is.getRankCommand(parent.getLabel() + " kick") && !user.equals(member)) {
|
||||
actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick"))
|
||||
.map(ar -> user.getTranslation(TIPS + ar.clickType().name() + NAME)
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
// Set Owner
|
||||
if (user.hasPermission(parent.getSetOwnerCommand().getPermission()) && !user.equals(member)
|
||||
&& userRank >= RanksManager.OWNER_RANK && rank >= RanksManager.MEMBER_RANK) {
|
||||
// Add the tooltip for setowner
|
||||
actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("setowner"))
|
||||
.map(ar -> user.getTranslation(TIPS + ar.clickType().name() + NAME)
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
// Leave
|
||||
if (user.hasPermission(parent.getLeaveCommand().getPermission()) && user.equals(member)
|
||||
&& userRank < RanksManager.OWNER_RANK) {
|
||||
// Add the tooltip for leave
|
||||
actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("leave"))
|
||||
.map(ar -> user.getTranslation(TIPS + ar.clickType().name() + NAME)
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
if (member.isOnline()) {
|
||||
desc.add(0, user.getTranslation(rankRef));
|
||||
return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()).description(desc)
|
||||
.clickHandler(
|
||||
(panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions))
|
||||
.build();
|
||||
} else {
|
||||
// Offline player
|
||||
desc.add(0, user.getTranslation(rankRef));
|
||||
return new PanelItemBuilder().icon(member.getName())
|
||||
.name(offlinePlayerStatus(Bukkit.getOfflinePlayer(member.getUniqueId()))).description(desc)
|
||||
.clickHandler(
|
||||
(panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Click listener
|
||||
* @param panel panel
|
||||
* @param clickingUser clicking user
|
||||
* @param clickType click type
|
||||
* @param i slot
|
||||
* @param target target user
|
||||
* @param actions actions
|
||||
* @return true if the inventory item should not be removed - always true
|
||||
*/
|
||||
private boolean clickListener(Panel panel, User clickingUser, ClickType clickType, int i, User target,
|
||||
List<ActionRecords> actions) {
|
||||
if (actions.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
int rank = Objects.requireNonNull(island).getRank(clickingUser);
|
||||
for (ItemTemplateRecord.ActionRecords action : actions) {
|
||||
if (clickType.equals(action.clickType())) {
|
||||
switch (action.actionType().toUpperCase(Locale.ENGLISH)) {
|
||||
case "KICK" -> kickPlayer(clickingUser, target, rank);
|
||||
case "SETOWNER" -> setOwner(clickingUser, target);
|
||||
case "LEAVE" -> leave(clickingUser, target);
|
||||
default -> {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void leave(User clickingUser, User target) {
|
||||
if (clickingUser.hasPermission(parent.getLeaveCommand().getPermission()) && target.equals(clickingUser)
|
||||
&& !clickingUser.getUniqueId().equals(island.getOwner())) {
|
||||
plugin.log("Leave: " + clickingUser.getName() + " trying to leave island at " + island.getCenter());
|
||||
clickingUser.closeInventory();
|
||||
if (parent.getLeaveCommand().leave(clickingUser)) {
|
||||
plugin.log("Leave: success");
|
||||
} else {
|
||||
plugin.log("Leave: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setOwner(User clickingUser, User target) {
|
||||
// Make the player the leader of the island
|
||||
if (clickingUser.hasPermission(parent.getSetOwnerCommand().getPermission()) && !target.equals(clickingUser)
|
||||
&& clickingUser.getUniqueId().equals(island.getOwner())
|
||||
&& island.getRank(target) >= RanksManager.MEMBER_RANK) {
|
||||
plugin.log("Set Owner: " + clickingUser.getName() + " trying to make " + target.getName()
|
||||
+ " owner of island at " + island.getCenter());
|
||||
clickingUser.closeInventory();
|
||||
if (parent.getSetOwnerCommand().setOwner(clickingUser, target.getUniqueId())) {
|
||||
plugin.log("Set Owner: success");
|
||||
} else {
|
||||
plugin.log("Set Owner: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void kickPlayer(User clickingUser, User target, int rank) {
|
||||
// Kick the player, or uncoop, or untrust
|
||||
if (clickingUser.hasPermission(parent.getKickCommand().getPermission()) && !target.equals(clickingUser)
|
||||
&& rank >= island.getRankCommand(parent.getLabel() + " kick")) {
|
||||
plugin.log("Kick: " + clickingUser.getName() + " kicked " + target.getName() + " from island at "
|
||||
+ island.getCenter());
|
||||
clickingUser.closeInventory();
|
||||
if (removePlayer(clickingUser, target)) {
|
||||
clickingUser.getPlayer().playSound(clickingUser.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F);
|
||||
plugin.log("Kick: success");
|
||||
} else {
|
||||
plugin.log("Kick: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean removePlayer(User clicker, User member) {
|
||||
// If member then kick, if coop, uncoop, if trusted, then untrust
|
||||
return switch (island.getRank(member)) {
|
||||
case RanksManager.COOP_RANK -> parent.getUncoopCommand().unCoopCmd(user, member.getUniqueId());
|
||||
case RanksManager.TRUSTED_RANK -> parent.getUnTrustCommand().unTrustCmd(user, member.getUniqueId());
|
||||
default -> {
|
||||
if (parent.getKickCommand().canExecute(user, parent.getKickCommand().getLabel(),
|
||||
List.of(member.getName()))) {
|
||||
yield parent.getKickCommand().kick(clicker, member.getUniqueId());
|
||||
} else {
|
||||
yield false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private List<String> showMembers() {
|
||||
List<String> message = new ArrayList<>();
|
||||
// Gather online members
|
||||
long onlineMemberCount = island.getMemberSet(RanksManager.MEMBER_RANK).stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName()))
|
||||
.count();
|
||||
|
||||
// Show header:
|
||||
message.add(user.getTranslation("commands.island.team.info.header", "[max]",
|
||||
String.valueOf(plugin.getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)), "[total]",
|
||||
String.valueOf(island.getMemberSet().size()), "[online]", String.valueOf(onlineMemberCount)));
|
||||
|
||||
// We now need to get all online "members" of the island - incl. Trusted and coop
|
||||
List<UUID> onlineMembers = island.getMemberSet(RanksManager.COOP_RANK).stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName()))
|
||||
.toList();
|
||||
|
||||
for (int rank : RANKS) {
|
||||
Set<UUID> players = island.getMemberSet(rank, false);
|
||||
if (!players.isEmpty()) {
|
||||
if (rank == RanksManager.OWNER_RANK) {
|
||||
// Slightly special handling for the owner rank
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.OWNER_RANK_REF)));
|
||||
} else {
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)), TextVariables.NUMBER,
|
||||
String.valueOf(island.getMemberSet(rank, false).size())));
|
||||
}
|
||||
message.addAll(displayOnOffline(rank, island, onlineMembers));
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private List<String> displayOnOffline(int rank, Island island, List<UUID> onlineMembers) {
|
||||
List<String> message = new ArrayList<>();
|
||||
for (UUID member : island.getMemberSet(rank, false)) {
|
||||
message.add(getMemberStatus(member, onlineMembers.contains(member)));
|
||||
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private String getMemberStatus(UUID member, boolean online) {
|
||||
OfflinePlayer offlineMember = Bukkit.getOfflinePlayer(member);
|
||||
if (online) {
|
||||
return user.getTranslation("commands.island.team.info.member-layout.online", TextVariables.NAME,
|
||||
offlineMember.getName());
|
||||
} else {
|
||||
return offlinePlayerStatus(offlineMember);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates text to describe the status of the player
|
||||
* @param offlineMember member of the team
|
||||
* @return string
|
||||
*/
|
||||
private String offlinePlayerStatus(OfflinePlayer offlineMember) {
|
||||
String lastSeen = lastSeen(offlineMember);
|
||||
if (island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(offlineMember.getUniqueId())) {
|
||||
return user.getTranslation("commands.island.team.info.member-layout.offline", TextVariables.NAME,
|
||||
offlineMember.getName(), "[last_seen]", lastSeen);
|
||||
} else {
|
||||
// This will prevent anyone that is trusted or below to not have a last-seen status
|
||||
return user.getTranslation("commands.island.team.info.member-layout.offline-not-last-seen",
|
||||
TextVariables.NAME, offlineMember.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private String lastSeen(OfflinePlayer offlineMember) {
|
||||
// A bit of handling for the last joined date
|
||||
Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed());
|
||||
Instant now = Instant.now();
|
||||
|
||||
Duration duration = Duration.between(lastJoined, now);
|
||||
String lastSeen;
|
||||
final String reference = "commands.island.team.info.last-seen.layout";
|
||||
if (duration.toMinutes() < 60L) {
|
||||
lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toMinutes()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.minutes"));
|
||||
} else if (duration.toHours() < 24L) {
|
||||
lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toHours()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.hours"));
|
||||
} else {
|
||||
lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toDays()),
|
||||
TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.days"));
|
||||
}
|
||||
return lastSeen;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -5,13 +5,14 @@ import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
|
||||
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
@ -22,8 +23,6 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
|
||||
private static final String INVALID_INVITE = "commands.island.team.invite.errors.invalid-invite";
|
||||
private final IslandTeamCommand itc;
|
||||
private UUID playerUUID;
|
||||
private UUID prospectiveOwnerUUID;
|
||||
|
||||
public IslandTeamInviteAcceptCommand(IslandTeamCommand islandTeamCommand) {
|
||||
super(islandTeamCommand, "accept");
|
||||
@ -39,19 +38,20 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
playerUUID = user.getUniqueId();
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
// Check if player has been invited
|
||||
if (!itc.isInvited(playerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.none-invited-you");
|
||||
return false;
|
||||
}
|
||||
// Get the island owner
|
||||
prospectiveOwnerUUID = itc.getInviter(playerUUID);
|
||||
UUID prospectiveOwnerUUID = itc.getInviter(playerUUID);
|
||||
if (prospectiveOwnerUUID == null) {
|
||||
user.sendMessage(INVALID_INVITE);
|
||||
itc.removeInvite(playerUUID);
|
||||
return false;
|
||||
}
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
TeamInvite invite = itc.getInvite(playerUUID);
|
||||
if (invite.getType().equals(Type.TEAM)) {
|
||||
// Check rank to of inviter
|
||||
Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
|
||||
@ -63,16 +63,15 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
}
|
||||
|
||||
// Check if player is already in a team
|
||||
if (getIslands().inTeam(getWorld(), playerUUID)) {
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()
|
||||
&& getIslands().inTeam(getWorld(), playerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.you-already-are-in-team");
|
||||
itc.removeInvite(playerUUID);
|
||||
return false;
|
||||
}
|
||||
// Fire event so add-ons can run commands, etc.
|
||||
IslandBaseEvent e = TeamEvent.builder()
|
||||
.island(getIslands().getIsland(getWorld(), prospectiveOwnerUUID))
|
||||
.reason(TeamEvent.Reason.JOIN)
|
||||
.involvedPlayer(playerUUID)
|
||||
.build();
|
||||
IslandBaseEvent e = TeamEvent.builder().island(getIslands().getIsland(getWorld(), prospectiveOwnerUUID))
|
||||
.reason(TeamEvent.Reason.JOIN).involvedPlayer(playerUUID).build();
|
||||
return !e.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(e.isCancelled());
|
||||
|
||||
}
|
||||
@ -82,96 +81,104 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get the invite
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
TeamInvite invite = itc.getInvite(user.getUniqueId());
|
||||
switch (invite.getType()) {
|
||||
case COOP -> askConfirmation(user, () -> acceptCoopInvite(user, invite));
|
||||
case TRUST -> askConfirmation(user, () -> acceptTrustInvite(user, invite));
|
||||
default -> askConfirmation(user, user.getTranslation("commands.island.team.invite.accept.confirmation"),
|
||||
() -> acceptTeamInvite(user, invite));
|
||||
default -> {
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()) {
|
||||
askConfirmation(user, user.getTranslation("commands.island.team.invite.accept.confirmation"),
|
||||
() -> acceptTeamInvite(user, invite));
|
||||
} else {
|
||||
acceptTeamInvite(user, invite);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void acceptTrustInvite(User user, Invite invite) {
|
||||
void acceptTrustInvite(User user, TeamInvite invite) {
|
||||
// Remove the invite
|
||||
itc.removeInvite(playerUUID);
|
||||
itc.removeInvite(user.getUniqueId());
|
||||
User inviter = User.getInstance(invite.getInviter());
|
||||
Island island = getIslands().getIsland(getWorld(), inviter);
|
||||
Island island = getIslands().getIslandById(invite.getIslandID()).orElse(null);
|
||||
if (island != null) {
|
||||
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.TRUSTED_RANK)) {
|
||||
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island,
|
||||
RanksManager.TRUSTED_RANK)) {
|
||||
user.sendMessage("commands.island.team.trust.is-full");
|
||||
return;
|
||||
}
|
||||
island.setRank(user, RanksManager.TRUSTED_RANK);
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(user), RanksManager.TRUSTED_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(island.getRank(user), RanksManager.TRUSTED_RANK)
|
||||
.build();
|
||||
if (inviter.isOnline()) {
|
||||
inviter.sendMessage("commands.island.team.trust.success", TextVariables.NAME, user.getName());
|
||||
inviter.sendMessage("commands.island.team.trust.success", TextVariables.NAME, user.getName(),
|
||||
TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
if (inviter.isPlayer()) {
|
||||
user.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, inviter.getName());
|
||||
user.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, inviter.getName(),
|
||||
TextVariables.DISPLAY_NAME, inviter.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void acceptCoopInvite(User user, Invite invite) {
|
||||
void acceptCoopInvite(User user, TeamInvite invite) {
|
||||
// Remove the invite
|
||||
itc.removeInvite(playerUUID);
|
||||
itc.removeInvite(user.getUniqueId());
|
||||
User inviter = User.getInstance(invite.getInviter());
|
||||
Island island = getIslands().getIsland(getWorld(), inviter);
|
||||
Island island = getIslands().getIslandById(invite.getIslandID()).orElse(null);
|
||||
if (island != null) {
|
||||
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.COOP_RANK)) {
|
||||
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island,
|
||||
RanksManager.COOP_RANK)) {
|
||||
user.sendMessage("commands.island.team.coop.is-full");
|
||||
return;
|
||||
}
|
||||
island.setRank(user, RanksManager.COOP_RANK);
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(user), RanksManager.COOP_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(island.getRank(user), RanksManager.COOP_RANK)
|
||||
.build();
|
||||
if (inviter.isOnline()) {
|
||||
inviter.sendMessage("commands.island.team.coop.success", TextVariables.NAME, user.getName());
|
||||
inviter.sendMessage("commands.island.team.coop.success", TextVariables.NAME, user.getName(),
|
||||
TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
if (inviter.isPlayer()) {
|
||||
user.sendMessage("commands.island.team.coop.you-are-a-coop-member", TextVariables.NAME, inviter.getName());
|
||||
user.sendMessage("commands.island.team.coop.you-are-a-coop-member", TextVariables.NAME,
|
||||
inviter.getName(), TextVariables.DISPLAY_NAME, inviter.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void acceptTeamInvite(User user, Invite invite) {
|
||||
void acceptTeamInvite(User user, TeamInvite invite) {
|
||||
// Remove the invite
|
||||
itc.removeInvite(playerUUID);
|
||||
itc.removeInvite(user.getUniqueId());
|
||||
// Get the player's island - may be null if the player has no island
|
||||
Island island = getIslands().getIsland(getWorld(), playerUUID);
|
||||
List<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId());
|
||||
// Get the team's island
|
||||
Island teamIsland = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
|
||||
Island teamIsland = getIslands().getIslandById(invite.getIslandID()).orElse(null);
|
||||
if (teamIsland == null) {
|
||||
user.sendMessage(INVALID_INVITE);
|
||||
return;
|
||||
}
|
||||
if (teamIsland.getMemberSet(RanksManager.MEMBER_RANK, true).size() >= getIslands().getMaxMembers(teamIsland, RanksManager.MEMBER_RANK)) {
|
||||
if (teamIsland.getMemberSet(RanksManager.MEMBER_RANK, true).size() >= getIslands().getMaxMembers(teamIsland,
|
||||
RanksManager.MEMBER_RANK)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.island-is-full");
|
||||
return;
|
||||
}
|
||||
// Remove player as owner of the old island
|
||||
getIslands().removePlayer(getWorld(), playerUUID);
|
||||
// Remove money inventory etc. for leaving
|
||||
cleanPlayer(user);
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()) {
|
||||
// Remove the player's other islands
|
||||
getIslands().removePlayer(getWorld(), user.getUniqueId());
|
||||
// Remove money inventory etc. for leaving
|
||||
cleanPlayer(user);
|
||||
}
|
||||
// Add the player as a team member of the new island
|
||||
getIslands().setJoinTeam(teamIsland, playerUUID);
|
||||
getIslands().setJoinTeam(teamIsland, user.getUniqueId());
|
||||
// Move player to team's island
|
||||
getIslands().setPrimaryIsland(user.getUniqueId(), teamIsland);
|
||||
getIslands().homeTeleportAsync(getWorld(), user.getPlayer()).thenRun(() -> {
|
||||
// Delete the old island
|
||||
if (island != null) {
|
||||
getIslands().deleteIsland(island, true, user.getUniqueId());
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()) {
|
||||
// Delete the old islands
|
||||
islands.forEach(island -> getIslands().deleteIsland(island, true, user.getUniqueId()));
|
||||
}
|
||||
// Put player back into normal mode
|
||||
user.setGameMode(getIWM().getDefaultGameMode(getWorld()));
|
||||
@ -181,29 +188,23 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
Util.runCommands(user, ownerName, getIWM().getOnJoinCommands(getWorld()), "join");
|
||||
|
||||
});
|
||||
// Reset deaths
|
||||
if (getIWM().isTeamJoinDeathReset(getWorld())) {
|
||||
getPlayers().setDeaths(getWorld(), playerUUID, 0);
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()
|
||||
&& getIWM().isTeamJoinDeathReset(getWorld())) {
|
||||
// Reset deaths
|
||||
getPlayers().setDeaths(getWorld(), user.getUniqueId(), 0);
|
||||
}
|
||||
user.sendMessage("commands.island.team.invite.accept.you-joined-island", TextVariables.LABEL, getTopLabel());
|
||||
User inviter = User.getInstance(invite.getInviter());
|
||||
if (inviter.isOnline()) {
|
||||
inviter.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME, user.getName());
|
||||
inviter.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
getIslands().save(teamIsland);
|
||||
// Fire event
|
||||
TeamEvent.builder()
|
||||
.island(getIslands().getIsland(getWorld(), prospectiveOwnerUUID))
|
||||
.reason(TeamEvent.Reason.JOINED)
|
||||
.involvedPlayer(playerUUID)
|
||||
.build();
|
||||
IslandEvent.builder()
|
||||
.island(teamIsland)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(teamIsland.getRank(user), RanksManager.MEMBER_RANK)
|
||||
.build();
|
||||
TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(user.getUniqueId())
|
||||
.build();
|
||||
IslandEvent.builder().island(teamIsland).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(teamIsland.getRank(user), RanksManager.MEMBER_RANK)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void cleanPlayer(User user) {
|
||||
@ -213,7 +214,8 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
if (getIWM().isOnLeaveResetInventory(getWorld()) || getIWM().isOnJoinResetInventory(getWorld())) {
|
||||
user.getPlayer().getInventory().clear();
|
||||
}
|
||||
if (getSettings().isUseEconomy() && (getIWM().isOnLeaveResetMoney(getWorld()) || getIWM().isOnJoinResetMoney(getWorld()))) {
|
||||
if (getSettings().isUseEconomy()
|
||||
&& (getIWM().isOnLeaveResetMoney(getWorld()) || getIWM().isOnJoinResetMoney(getWorld()))) {
|
||||
getPlugin().getVault().ifPresent(vault -> vault.withdraw(user, vault.getBalance(user)));
|
||||
}
|
||||
|
||||
@ -229,6 +231,10 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
|
||||
|
||||
// Reset the XP
|
||||
if (getIWM().isOnJoinResetXP(getWorld())) {
|
||||
// Player collected XP (displayed)
|
||||
user.getPlayer().setLevel(0);
|
||||
user.getPlayer().setExp(0);
|
||||
// Player total XP (not displayed)
|
||||
user.getPlayer().setTotalExperience(0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -9,12 +10,15 @@ import java.util.UUID;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
|
||||
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.managers.PlayersManager;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
@ -22,6 +26,8 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
|
||||
private final IslandTeamCommand itc;
|
||||
private @Nullable User invitedPlayer;
|
||||
private @Nullable TemplateItem border;
|
||||
private @Nullable TemplateItem background;
|
||||
|
||||
public IslandTeamInviteCommand(IslandTeamCommand parent) {
|
||||
super(parent, "invite");
|
||||
@ -34,79 +40,106 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
setOnlyPlayer(true);
|
||||
setDescription("commands.island.team.invite.description");
|
||||
setConfigurableRankCommand();
|
||||
// Panels
|
||||
if (!new File(getPlugin().getDataFolder() + File.separator + "panels", "team_invite_panel.yml").exists()) {
|
||||
getPlugin().saveResource("panels/team_invite_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
IslandsManager islandsManager = getIslands();
|
||||
|
||||
// Player issuing the command must have an island or be in a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (!islandsManager.inTeam(getWorld(), playerUUID) && !islandsManager.hasIsland(getWorld(), playerUUID)) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
Island island = islandsManager.getIsland(getWorld(), user);
|
||||
|
||||
if (args.size() != 1) {
|
||||
// Invite label with no name, i.e., /island invite - tells the player who has invited them so far and why
|
||||
if (itc.isInvited(playerUUID)) {
|
||||
Invite invite = itc.getInvite(playerUUID);
|
||||
String name = getPlayers().getName(playerUUID);
|
||||
switch (invite.getType()) {
|
||||
case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name);
|
||||
case TRUST -> user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name);
|
||||
default -> user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Show help
|
||||
showHelp(this, user);
|
||||
new IslandTeamInviteGUI(itc, true, island).build(user);
|
||||
return false;
|
||||
}
|
||||
// Check rank to use command
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
|
||||
return checkRankAndInvitePlayer(user, island, rank, args.get(0));
|
||||
}
|
||||
|
||||
private boolean checkRankAndInvitePlayer(User user, Island island, int rank, String playerName) {
|
||||
PlayersManager playersManager = getPlayers();
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
|
||||
// Check rank to use command
|
||||
int requiredRank = island.getRankCommand(getUsage());
|
||||
if (rank < requiredRank) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space on team
|
||||
if (island.getMemberSet().size() >= getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)) {
|
||||
int maxMembers = getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK);
|
||||
if (island.getMemberSet().size() >= maxMembers) {
|
||||
user.sendMessage("commands.island.team.invite.errors.island-is-full");
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID invitedPlayerUUID = getPlayers().getUUID(args.get(0));
|
||||
UUID invitedPlayerUUID = playersManager.getUUID(playerName);
|
||||
if (invitedPlayerUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, playerName);
|
||||
return false;
|
||||
}
|
||||
// Only online players can be invited
|
||||
// Write to field as this is used by execute method
|
||||
invitedPlayer = User.getInstance(invitedPlayerUUID);
|
||||
if (!canInvitePlayer(user, invitedPlayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check cooldown
|
||||
if (this.getSettings().getInviteCooldown() > 0 && checkCooldown(user, island.getUniqueId(), invitedPlayerUUID.toString())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Player cannot invite someone already on a team
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()
|
||||
&& getIslands().inTeam(getWorld(), invitedPlayerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.already-on-team");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isInvitedByUser(invitedPlayerUUID, playerUUID) && isInviteTypeTeam(invitedPlayerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.you-have-already-invited");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canInvitePlayer(User user, User invitedPlayer) {
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
if (!invitedPlayer.isOnline() || !user.getPlayer().canSee(invitedPlayer.getPlayer())) {
|
||||
user.sendMessage("general.errors.offline-player");
|
||||
return false;
|
||||
}
|
||||
// Player cannot invite themselves
|
||||
if (playerUUID.equals(invitedPlayerUUID)) {
|
||||
if (playerUUID.equals(invitedPlayer.getUniqueId())) {
|
||||
user.sendMessage("commands.island.team.invite.errors.cannot-invite-self");
|
||||
return false;
|
||||
}
|
||||
// Check cool down
|
||||
if (getSettings().getInviteCooldown() > 0 && checkCooldown(user, getIslands().getIsland(getWorld(), user).getUniqueId(), invitedPlayerUUID.toString())) {
|
||||
return false;
|
||||
}
|
||||
// Player cannot invite someone already on a team
|
||||
if (getIslands().inTeam(getWorld(), invitedPlayerUUID)) {
|
||||
user.sendMessage("commands.island.team.invite.errors.already-on-team");
|
||||
return false;
|
||||
}
|
||||
if (itc.isInvited(invitedPlayerUUID) && itc.getInviter(invitedPlayerUUID).equals(user.getUniqueId()) && itc.getInvite(invitedPlayerUUID).getType().equals(Type.TEAM)) {
|
||||
// Prevent spam
|
||||
user.sendMessage("commands.island.team.invite.errors.you-have-already-invited");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isInvitedByUser(UUID invitedPlayerUUID, UUID inviterUUID) {
|
||||
return itc.isInvited(invitedPlayerUUID) && itc.getInviter(invitedPlayerUUID).equals(inviterUUID);
|
||||
}
|
||||
|
||||
private boolean isInviteTypeTeam(UUID invitedPlayerUUID) {
|
||||
return Objects.requireNonNull(itc.getInvite(invitedPlayerUUID)).getType().equals(Type.TEAM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Rare case when invited player is null. Could be a race condition.
|
||||
@ -117,25 +150,34 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
itc.removeInvite(invitedPlayer.getUniqueId());
|
||||
user.sendMessage("commands.island.team.invite.removing-invite");
|
||||
}
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
invitedPlayer = null;
|
||||
return false;
|
||||
}
|
||||
// Fire event so add-ons can run commands, etc.
|
||||
IslandBaseEvent e = TeamEvent.builder()
|
||||
.island(getIslands().getIsland(getWorld(), user.getUniqueId()))
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.INVITE)
|
||||
.involvedPlayer(invitedPlayer.getUniqueId())
|
||||
.build();
|
||||
if (e.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(e.isCancelled())) {
|
||||
invitedPlayer = null;
|
||||
return false;
|
||||
}
|
||||
// Put the invited player (key) onto the list with inviter (value)
|
||||
// If someone else has invited a player, then this invite will overwrite the previous invite!
|
||||
itc.addInvite(Invite.Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId());
|
||||
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, invitedPlayer.getName());
|
||||
itc.addInvite(Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId(), island);
|
||||
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, invitedPlayer.getName(), TextVariables.DISPLAY_NAME, invitedPlayer.getDisplayName());
|
||||
// Send message to online player
|
||||
invitedPlayer.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, user.getName());
|
||||
invitedPlayer.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
invitedPlayer.sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, getTopLabel());
|
||||
if (getIslands().hasIsland(getWorld(), invitedPlayer.getUniqueId())) {
|
||||
if (getIWM().getWorldSettings(getWorld()).isDisallowTeamMemberIslands()
|
||||
&& getIslands().hasIsland(getWorld(), invitedPlayer.getUniqueId())) {
|
||||
invitedPlayer.sendMessage("commands.island.team.invite.you-will-lose-your-island");
|
||||
}
|
||||
invitedPlayer = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,288 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.conversations.ConversationContext;
|
||||
import org.bukkit.conversations.ConversationFactory;
|
||||
import org.bukkit.conversations.Prompt;
|
||||
import org.bukkit.conversations.StringPrompt;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
|
||||
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecords;
|
||||
import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
|
||||
public class IslandTeamInviteGUI {
|
||||
|
||||
private final IslandTeamInviteCommand itic;
|
||||
private final IslandTeamCommand itc;
|
||||
private @Nullable TemplateItem border;
|
||||
private @Nullable TemplateItem background;
|
||||
private User user;
|
||||
private long page = 0; // This number by 35
|
||||
private final boolean inviteCmd;
|
||||
private static final long PER_PAGE = 35;
|
||||
private String searchName = "";
|
||||
private final BentoBox plugin;
|
||||
private final Island island;
|
||||
|
||||
public IslandTeamInviteGUI(IslandTeamCommand itc, boolean invitedCmd, Island island) {
|
||||
this.island = island;
|
||||
this.plugin = itc.getPlugin();
|
||||
this.inviteCmd = invitedCmd;
|
||||
itic = itc.getInviteCommand();
|
||||
this.itc = itc;
|
||||
// Panels
|
||||
if (!new File(plugin.getDataFolder() + File.separator + "panels", "team_invite_panel.yml")
|
||||
.exists()) {
|
||||
plugin.saveResource("panels/team_invite_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the invite panel
|
||||
* @param user use of the panel
|
||||
*/
|
||||
void build(User user) {
|
||||
this.user = user;
|
||||
// Start building panel.
|
||||
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||
panelBuilder.user(user);
|
||||
panelBuilder.world(user.getWorld());
|
||||
|
||||
panelBuilder.template("team_invite_panel", new File(plugin.getDataFolder(), "panels"));
|
||||
|
||||
panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName());
|
||||
|
||||
panelBuilder.registerTypeBuilder("PROSPECT", this::createProspectButton);
|
||||
panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton);
|
||||
panelBuilder.registerTypeBuilder("NEXT", this::createNextButton);
|
||||
panelBuilder.registerTypeBuilder("SEARCH", this::createSearchButton);
|
||||
panelBuilder.registerTypeBuilder("BACK", this::createBackButton);
|
||||
// Stash the backgrounds for later use
|
||||
border = panelBuilder.getPanelTemplate().border();
|
||||
background = panelBuilder.getPanelTemplate().background();
|
||||
// Register unknown type builder.
|
||||
panelBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
private PanelItem createBackButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
checkTemplate(template);
|
||||
return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon())
|
||||
.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
user.closeInventory();
|
||||
if (!inviteCmd) {
|
||||
new IslandTeamGUI(plugin, itc, user, island).build();
|
||||
}
|
||||
return true;
|
||||
}).build();
|
||||
}
|
||||
|
||||
private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
checkTemplate(template);
|
||||
PanelItemBuilder pib = new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon())
|
||||
.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
user.closeInventory();
|
||||
new ConversationFactory(BentoBox.getInstance()).withLocalEcho(false).withTimeout(90)
|
||||
.withModality(false).withFirstPrompt(new InviteNamePrompt())
|
||||
.buildConversation(user.getPlayer()).begin();
|
||||
return true;
|
||||
});
|
||||
if (!this.searchName.isBlank()) {
|
||||
pib.description(user.getTranslation(Objects
|
||||
.requireNonNullElse(template.description(),
|
||||
"commands.island.team.invite.gui.button.searching"),
|
||||
TextVariables.NAME, searchName));
|
||||
}
|
||||
return pib.build();
|
||||
}
|
||||
|
||||
private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
checkTemplate(template);
|
||||
long count = itc.getWorld().getPlayers().stream().filter(player -> user.getPlayer().canSee(player))
|
||||
.filter(player -> !player.equals(user.getPlayer())).count();
|
||||
if (count > page * PER_PAGE) {
|
||||
// We need to show a next button
|
||||
return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon())
|
||||
.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
page++;
|
||||
build(user);
|
||||
return true;
|
||||
}).build();
|
||||
}
|
||||
return getBlankBorder();
|
||||
}
|
||||
|
||||
private void checkTemplate(ItemTemplateRecord template) {
|
||||
if (template.icon() == null) {
|
||||
plugin.logError("Icon in template is missing or unknown! " + template.toString());
|
||||
}
|
||||
if (template.title() == null) {
|
||||
plugin.logError("Title in template is missing! " + template.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PanelItem createPreviousButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
checkTemplate(template);
|
||||
if (page > 0) {
|
||||
// We need to show a next button
|
||||
return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon())
|
||||
.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
page--;
|
||||
build(user);
|
||||
return true;
|
||||
}).build();
|
||||
}
|
||||
return getBlankBorder();
|
||||
}
|
||||
|
||||
private PanelItem getBlankBorder() {
|
||||
return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER)))
|
||||
.name((Objects.requireNonNullElse(border.title(), ""))).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create member button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createProspectButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
// Player issuing the command must have an island
|
||||
Island is = plugin.getIslands().getPrimaryIsland(itc.getWorld(), user.getUniqueId());
|
||||
if (is == null) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
// Stream of all players that the user can see
|
||||
Stream<Player> visiblePlayers = itc.getWorld().getPlayers().stream().filter(user.getPlayer()::canSee);
|
||||
|
||||
// Filter players based on searchName if it's not blank, and ensure they're not the user
|
||||
Stream<Player> filteredPlayers = visiblePlayers
|
||||
.filter(player -> this.searchName.isBlank()
|
||||
|| player.getName().toLowerCase().contains(searchName.toLowerCase()))
|
||||
.filter(player -> !player.equals(user.getPlayer()));
|
||||
|
||||
// Skipping to the correct pagination slot, then finding the first player
|
||||
Optional<Player> playerOptional = filteredPlayers.skip(slot.slot() + page * PER_PAGE).findFirst();
|
||||
|
||||
// Map the player to a prospect or return a blank background if not found
|
||||
return playerOptional.map(player -> getProspect(player, template)).orElse(this.getBlankBackground());
|
||||
}
|
||||
|
||||
private PanelItem getProspect(Player player, ItemTemplateRecord template) {
|
||||
// Check if the prospect has already been invited
|
||||
if (this.itc.isInvited(player.getUniqueId())
|
||||
&& user.getUniqueId().equals(this.itc.getInvite(player.getUniqueId()).getInviter())) {
|
||||
return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName())
|
||||
.description(user.getTranslation("commands.island.team.invite.gui.button.already-invited")).build();
|
||||
}
|
||||
List<String> desc = template.actions().stream().map(ar -> user
|
||||
.getTranslation("commands.island.team.invite.gui.tips." + ar.clickType().name() + ".name")
|
||||
+ " " + user.getTranslation(ar.tooltip())).toList();
|
||||
return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()).description(desc)
|
||||
.clickHandler(
|
||||
(panel, user, clickType, clickSlot) -> clickHandler(user, clickType, player,
|
||||
template.actions()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean clickHandler(User user, ClickType clickType, Player player, @NonNull List<ActionRecords> list) {
|
||||
if (list.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
// Close inventory after one tick to allow the no pickup click return to occur
|
||||
Bukkit.getScheduler().runTask(plugin, () -> user.closeInventory());
|
||||
if (itic.canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Invite sent to: " + player.getName() + " by " + user.getName() + " to join island in "
|
||||
+ itc.getWorld().getName());
|
||||
itic.execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log("Invite failed: " + player.getName() + " by " + user.getName() + " to join island in "
|
||||
+ itc.getWorld().getName());
|
||||
}
|
||||
} else if (clickType.equals(ClickType.RIGHT)) {
|
||||
// Close inventory after one tick to allow the no pickup click return to occur
|
||||
Bukkit.getScheduler().runTask(plugin, () -> user.closeInventory());
|
||||
if (this.itc.getCoopCommand().canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Coop: " + player.getName() + " cooped " + user.getName() + " to island in "
|
||||
+ itc.getWorld().getName());
|
||||
this.itc.getCoopCommand().execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log(
|
||||
"Coop failed: " + player.getName() + "'s coop to " + user.getName() + " failed for island in "
|
||||
+ itc.getWorld().getName());
|
||||
}
|
||||
} else if (clickType.equals(ClickType.SHIFT_LEFT)) {
|
||||
// Close inventory after one tick to allow the no pickup click return to occur
|
||||
Bukkit.getScheduler().runTask(plugin, () -> user.closeInventory());
|
||||
if (this.itc.getTrustCommand().canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Trust: " + player.getName() + " trusted " + user.getName() + " to island in "
|
||||
+ itc.getWorld().getName());
|
||||
this.itc.getTrustCommand().execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log("Trust failed: " + player.getName() + "'s trust failed for " + user.getName()
|
||||
+ " for island in " + itc.getWorld().getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PanelItem getBlankBackground() {
|
||||
return new PanelItemBuilder()
|
||||
.icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER)))
|
||||
.name((Objects.requireNonNullElse(background.title(), ""))).build();
|
||||
}
|
||||
|
||||
class InviteNamePrompt extends StringPrompt {
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String getPromptText(@NonNull ConversationContext context) {
|
||||
return user.getTranslation("commands.island.team.invite.gui.enter-name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Prompt acceptInput(@NonNull ConversationContext context, String input) {
|
||||
if (itic.canExecute(user, itic.getLabel(), List.of(input))
|
||||
&& itic.execute(user, itic.getLabel(), List.of(input))) {
|
||||
return Prompt.END_OF_CONVERSATION;
|
||||
}
|
||||
// Set the search item to what was entered
|
||||
searchName = input;
|
||||
// Return to the GUI but give a second for the error to show
|
||||
// TODO: return the failed input and display the options in the GUI.
|
||||
Bukkit.getScheduler().runTaskLater(BentoBox.getInstance(), () -> build(user), 20L);
|
||||
return Prompt.END_OF_CONVERSATION;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -42,9 +42,9 @@ public class IslandTeamInviteRejectCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
Optional.ofNullable(itc.getInviter(playerUUID))
|
||||
.map(User::getInstance)
|
||||
.ifPresent(inviter ->
|
||||
inviter.sendMessage("commands.island.team.invite.reject.name-rejected-your-invite", TextVariables.NAME, user.getName())
|
||||
.map(User::getInstance)
|
||||
.ifPresent(inviter ->
|
||||
inviter.sendMessage("commands.island.team.invite.reject.name-rejected-your-invite", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName())
|
||||
);
|
||||
|
||||
// Remove this player from the global invite list
|
||||
|
@ -19,7 +19,6 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
|
||||
public IslandTeamKickCommand(CompositeCommand islandTeamCommand) {
|
||||
@ -36,7 +35,7 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return false;
|
||||
@ -45,7 +44,8 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// If args are not right, show help
|
||||
@ -63,18 +63,24 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
user.sendMessage("commands.island.team.kick.cannot-kick");
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) {
|
||||
if (!getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).inTeam(targetUUID)) {
|
||||
user.sendMessage("general.errors.not-in-team");
|
||||
return false;
|
||||
}
|
||||
|
||||
int targetRank = Objects.requireNonNull(island).getRank(targetUUID);
|
||||
if (rank <= targetRank) {
|
||||
user.sendMessage("commands.island.team.kick.cannot-kick-rank",
|
||||
TextVariables.NAME, getPlayers().getName(targetUUID));
|
||||
user.sendMessage("commands.island.team.kick.cannot-kick-rank", TextVariables.NAME,
|
||||
getPlayers().getName(targetUUID));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get target
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
if (!getSettings().isKickConfirmation()) {
|
||||
kick(user, targetUUID);
|
||||
return true;
|
||||
@ -84,43 +90,41 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private void kick(User user, UUID targetUUID) {
|
||||
User target = User.getInstance(targetUUID);
|
||||
Island oldIsland = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID)); // Should never be null because of checks above
|
||||
// Fire event
|
||||
IslandBaseEvent event = TeamEvent.builder()
|
||||
.island(oldIsland)
|
||||
.reason(TeamEvent.Reason.KICK)
|
||||
.involvedPlayer(targetUUID)
|
||||
.build();
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
protected boolean kick(User user, UUID targetUUID) {
|
||||
if (targetUUID == null) {
|
||||
return false;
|
||||
}
|
||||
target.sendMessage("commands.island.team.kick.player-kicked",
|
||||
TextVariables.GAMEMODE, getAddon().getDescription().getName(),
|
||||
TextVariables.NAME, user.getName());
|
||||
User target = User.getInstance(targetUUID);
|
||||
Island oldIsland = Objects.requireNonNull(getIslands().getIsland(getWorld(), user)); // Should never be
|
||||
// null because of
|
||||
// checks above
|
||||
// Fire event
|
||||
IslandBaseEvent event = TeamEvent.builder().island(oldIsland).reason(TeamEvent.Reason.KICK)
|
||||
.involvedPlayer(targetUUID).build();
|
||||
if (event.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
target.sendMessage("commands.island.team.kick.player-kicked", TextVariables.GAMEMODE,
|
||||
getAddon().getDescription().getName(), TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME,
|
||||
user.getDisplayName());
|
||||
|
||||
getIslands().removePlayer(getWorld(), targetUUID);
|
||||
getIslands().removePlayer(oldIsland, targetUUID);
|
||||
// Clean the target player
|
||||
getPlayers().cleanLeavingPlayer(getWorld(), target, true, oldIsland);
|
||||
|
||||
user.sendMessage("commands.island.team.kick.success", TextVariables.NAME, target.getName());
|
||||
IslandEvent.builder()
|
||||
.island(oldIsland)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(oldIsland.getRank(user), RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
user.sendMessage("commands.island.team.kick.success", TextVariables.NAME, target.getName(),
|
||||
TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
IslandEvent.builder().island(oldIsland).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(oldIsland.getRank(user), RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
|
||||
// Add cooldown for this player and target
|
||||
if (getSettings().getInviteCooldown() > 0 && getParent() != null) {
|
||||
// Get the invite class from the parent
|
||||
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(
|
||||
oldIsland.getUniqueId(),
|
||||
targetUUID.toString(),
|
||||
getSettings().getInviteCooldown() * 60));
|
||||
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(oldIsland.getUniqueId(),
|
||||
targetUUID.toString(), getSettings().getInviteCooldown() * 60));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,11 +132,10 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
List<String> options = island.getMemberSet().stream()
|
||||
.filter(uuid -> island.getRank(uuid) >= RanksManager.MEMBER_RANK)
|
||||
.map(Bukkit::getOfflinePlayer)
|
||||
.filter(uuid -> island.getRank(uuid) >= RanksManager.MEMBER_RANK).map(Bukkit::getOfflinePlayer)
|
||||
.map(OfflinePlayer::getName).toList();
|
||||
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -32,7 +32,7 @@ public class IslandTeamLeaveCommand extends ConfirmableCommand {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (user.getUniqueId().equals(getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).getOwner())) {
|
||||
user.sendMessage("commands.island.team.leave.cannot-leave");
|
||||
return false;
|
||||
}
|
||||
@ -65,29 +65,32 @@ public class IslandTeamLeaveCommand extends ConfirmableCommand {
|
||||
|
||||
}
|
||||
|
||||
private void leave(User user) {
|
||||
protected boolean leave(User user) {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
// Fire event
|
||||
IslandBaseEvent event = TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.LEAVE)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.build();
|
||||
IslandBaseEvent event = TeamEvent.builder().island(island).reason(TeamEvent.Reason.LEAVE)
|
||||
.involvedPlayer(user.getUniqueId()).build();
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
UUID ownerUUID = getIslands().getOwner(getWorld(), user.getUniqueId());
|
||||
UUID ownerUUID = island.getOwner();
|
||||
if (ownerUUID != null) {
|
||||
User.getInstance(ownerUUID).sendMessage("commands.island.team.leave.left-your-island", TextVariables.NAME, user.getName());
|
||||
User.getInstance(ownerUUID).sendMessage("commands.island.team.leave.left-your-island", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
getIslands().setLeaveTeam(getWorld(), user.getUniqueId());
|
||||
getIslands().removePlayer(island, user.getUniqueId());
|
||||
// Clean the player
|
||||
getPlayers().cleanLeavingPlayer(getWorld(), user, false, island);
|
||||
|
||||
// Add cooldown for this player and target
|
||||
if (getSettings().getInviteCooldown() > 0 && getParent() != null) {
|
||||
// Get the invite class from the parent
|
||||
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(island.getUniqueId(), user.getUniqueId().toString(), getSettings().getInviteCooldown() * 60));
|
||||
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(island.getUniqueId(),
|
||||
user.getUniqueId().toString(), getSettings().getInviteCooldown() * 60));
|
||||
}
|
||||
// Remove reset if required
|
||||
if (getIWM().isLeaversLoseReset(getWorld())) {
|
||||
@ -97,12 +100,9 @@ public class IslandTeamLeaveCommand extends ConfirmableCommand {
|
||||
showResets(user);
|
||||
}
|
||||
user.sendMessage("commands.island.team.leave.success");
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(user), RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(island.getRank(user), RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
return true;
|
||||
}
|
||||
}
|
@ -15,8 +15,13 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Handle promotion and demotion
|
||||
*/
|
||||
public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||
|
||||
private User target;
|
||||
|
||||
public IslandTeamPromoteCommand(CompositeCommand islandTeamCommand, String string) {
|
||||
super(islandTeamCommand, string);
|
||||
}
|
||||
@ -35,54 +40,79 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||
this.setConfigurableRankCommand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return true;
|
||||
}
|
||||
// Check rank to use command
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Get target
|
||||
User target = getPlayers().getUser(args.get(0));
|
||||
if (target == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return true;
|
||||
// Check if the user has a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return false;
|
||||
}
|
||||
// Check if the user is not trying to promote/ demote himself
|
||||
if (target == user) {
|
||||
user.sendMessage("commands.island.team.demote.errors.cant-demote-yourself");
|
||||
return true;
|
||||
}
|
||||
if (!inTeam(getWorld(), target) || !Objects.requireNonNull(getOwner(getWorld(), user), "Island has no owner!").equals(getOwner(getWorld(), target))) {
|
||||
user.sendMessage("general.errors.not-in-team");
|
||||
return true;
|
||||
// Check rank to use command
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get target
|
||||
target = getPlayers().getUser(args.get(0));
|
||||
if (target == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Check that target is a member of this island
|
||||
if (!island.inTeam(target.getUniqueId())) {
|
||||
user.sendMessage("commands.island.team.promote.errors.must-be-member");
|
||||
return false;
|
||||
}
|
||||
// Check if the user is not trying to promote/ demote himself
|
||||
if (target.equals(user)) {
|
||||
if (this.getLabel().equals("promote")) {
|
||||
user.sendMessage("commands.island.team.promote.errors.cant-promote-yourself");
|
||||
} else {
|
||||
user.sendMessage("commands.island.team.demote.errors.cant-demote-yourself");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Check that user is not trying to promote above their own rank
|
||||
// Check that user is not trying to demote ranks higher than them
|
||||
if (island.getRank(target) >= island.getRank(user)) {
|
||||
if (this.getLabel().equals("promote")) {
|
||||
user.sendMessage("commands.island.team.promote.errors.cant-promote");
|
||||
} else {
|
||||
user.sendMessage("commands.island.team.demote.errors.cant-demote");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
return change(user, target);
|
||||
}
|
||||
|
||||
private boolean change(User user, User target) {
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int currentRank = island.getRank(target);
|
||||
if (this.getLabel().equals("promote")) {
|
||||
int nextRank = getPlugin().getRanksManager().getRankUpValue(currentRank);
|
||||
int nextRank = RanksManager.getInstance().getRankUpValue(currentRank);
|
||||
// Stop short of owner
|
||||
if (nextRank != RanksManager.OWNER_RANK && nextRank > currentRank) {
|
||||
getIslands().getIsland(getWorld(), user.getUniqueId()).setRank(target, nextRank);
|
||||
String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(nextRank));
|
||||
user.sendMessage("commands.island.team.promote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName);
|
||||
if (nextRank < RanksManager.OWNER_RANK && currentRank >= RanksManager.MEMBER_RANK
|
||||
&& nextRank > currentRank) {
|
||||
island.setRank(target, nextRank);
|
||||
String rankName = user.getTranslation(RanksManager.getInstance().getRank(nextRank));
|
||||
user.sendMessage("commands.island.team.promote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
@ -97,12 +127,12 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||
}
|
||||
} else {
|
||||
// Demote
|
||||
int prevRank = getPlugin().getRanksManager().getRankDownValue(currentRank);
|
||||
int prevRank = RanksManager.getInstance().getRankDownValue(currentRank);
|
||||
// Lowest is Member
|
||||
if (prevRank >= RanksManager.MEMBER_RANK && prevRank < currentRank) {
|
||||
getIslands().getIsland(getWorld(), user.getUniqueId()).setRank(target, prevRank);
|
||||
String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(prevRank));
|
||||
user.sendMessage("commands.island.team.demote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName);
|
||||
island.setRank(target, prevRank);
|
||||
String rankName = user.getTranslation(RanksManager.getInstance().getRank(prevRank));
|
||||
user.sendMessage("commands.island.team.demote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
@ -120,7 +150,7 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
if (island != null) {
|
||||
List<String> options = island.getMemberSet().stream()
|
||||
.map(Bukkit::getOfflinePlayer)
|
||||
|
@ -4,6 +4,9 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
@ -16,6 +19,8 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandTeamSetownerCommand extends CompositeCommand {
|
||||
|
||||
private @Nullable UUID targetUUID;
|
||||
|
||||
public IslandTeamSetownerCommand(CompositeCommand islandTeamCommand) {
|
||||
super(islandTeamCommand, "setowner");
|
||||
}
|
||||
@ -29,73 +34,76 @@ public class IslandTeamSetownerCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
// Can use if in a team
|
||||
boolean inTeam = getIslands().inTeam(getWorld(), playerUUID);
|
||||
if (!inTeam) {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return false;
|
||||
}
|
||||
UUID ownerUUID = getOwner(getWorld(), user);
|
||||
if (ownerUUID == null || !ownerUUID.equals(playerUUID)) {
|
||||
user.sendMessage("general.errors.not-owner");
|
||||
return false;
|
||||
}
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
UUID targetUUID = getPlayers().getUUID(args.get(0));
|
||||
// Can use if in a team
|
||||
Island is = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId());
|
||||
if (is == null || !is.inTeam(user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-team");
|
||||
return false;
|
||||
}
|
||||
UUID ownerUUID = is.getOwner();
|
||||
if (ownerUUID == null || !ownerUUID.equals(user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.not-owner");
|
||||
return false;
|
||||
}
|
||||
targetUUID = getPlayers().getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
if (targetUUID.equals(playerUUID)) {
|
||||
if (targetUUID.equals(user.getUniqueId())) {
|
||||
user.sendMessage("commands.island.team.setowner.errors.cant-transfer-to-yourself");
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().getMembers(getWorld(), playerUUID).contains(targetUUID)) {
|
||||
if (!is.inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.setowner.errors.target-is-not-member");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
return setOwner(user, targetUUID);
|
||||
|
||||
}
|
||||
|
||||
protected boolean setOwner(User user, @NonNull UUID targetUUID2) {
|
||||
// Fire event so add-ons can run commands, etc.
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId());
|
||||
// Fire event so add-ons can run commands, etc.
|
||||
IslandBaseEvent e = TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.SETOWNER)
|
||||
.involvedPlayer(targetUUID)
|
||||
.build();
|
||||
IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.SETOWNER)
|
||||
.involvedPlayer(targetUUID2).build();
|
||||
if (e.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
getIslands().setOwner(getWorld(), user, targetUUID);
|
||||
getIslands().setOwner(getWorld(), user, targetUUID2);
|
||||
// Call the event for the new owner
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(User.getInstance(targetUUID)), RanksManager.OWNER_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID2).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(island.getRank(User.getInstance(targetUUID2)), RanksManager.OWNER_RANK).build();
|
||||
// Call the event for the previous owner
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(playerUUID)
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.OWNER_RANK, island.getRank(user))
|
||||
.build();
|
||||
getIslands().save(island);
|
||||
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK)
|
||||
.build();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
return Optional.of(Util.tabLimit(getIslands().getMembers(getWorld(), user.getUniqueId()).stream().map(getPlayers()::getName).toList(), lastArg));
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
if (getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()) == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(Util.tabLimit(
|
||||
getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).getMemberSet().stream()
|
||||
.filter(uuid -> !user.getUniqueId().equals(uuid)).map(getPlayers()::getName).toList(),
|
||||
lastArg));
|
||||
}
|
||||
|
||||
}
|
@ -8,10 +8,10 @@ import java.util.UUID;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
@ -55,7 +55,8 @@ public class IslandTeamTrustCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -95,10 +96,10 @@ public class IslandTeamTrustCommand extends CompositeCommand {
|
||||
if (getPlugin().getSettings().isInviteConfirmation()) {
|
||||
// Put the invited player (key) onto the list with inviter (value)
|
||||
// If someone else has invited a player, then this invite will overwrite the previous invite!
|
||||
itc.addInvite(Type.TRUST, user.getUniqueId(), target.getUniqueId());
|
||||
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName());
|
||||
itc.addInvite(Type.TRUST, user.getUniqueId(), target.getUniqueId(), island);
|
||||
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
// Send message to online player
|
||||
target.sendMessage("commands.island.team.trust.name-has-invited-you", TextVariables.NAME, user.getName());
|
||||
target.sendMessage("commands.island.team.trust.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
target.sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, getTopLabel());
|
||||
} else {
|
||||
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() >= getIslands().getMaxMembers(island, RanksManager.TRUSTED_RANK)) {
|
||||
@ -107,8 +108,8 @@ public class IslandTeamTrustCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
island.setRank(target, RanksManager.TRUSTED_RANK);
|
||||
user.sendMessage("commands.island.team.trust.success", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, user.getName());
|
||||
user.sendMessage("commands.island.team.trust.success", TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
@ -18,6 +18,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Command to uncoop a player
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@ -44,7 +45,8 @@ public class IslandTeamUncoopCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Player issuing the command must have an island or be in a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())
|
||||
&& !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -52,7 +54,8 @@ public class IslandTeamUncoopCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -65,13 +68,13 @@ public class IslandTeamUncoopCommand extends CompositeCommand {
|
||||
return unCoopCmd(user, targetUUID);
|
||||
}
|
||||
|
||||
private boolean unCoopCmd(User user, UUID targetUUID) {
|
||||
protected boolean unCoopCmd(User user, UUID targetUUID) {
|
||||
// Player cannot uncoop themselves
|
||||
if (user.getUniqueId().equals(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.uncoop.cannot-uncoop-yourself");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) {
|
||||
if (getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.uncoop.cannot-uncoop-member");
|
||||
return false;
|
||||
}
|
||||
@ -83,21 +86,19 @@ public class IslandTeamUncoopCommand extends CompositeCommand {
|
||||
}
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
island.removeMember(targetUUID);
|
||||
user.sendMessage("commands.island.team.uncoop.success", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.team.uncoop.you-are-no-longer-a-coop-member", TextVariables.NAME, user.getName());
|
||||
getIslands().removePlayer(island, targetUUID);
|
||||
user.sendMessage("commands.island.team.uncoop.success", TextVariables.NAME, target.getName(),
|
||||
TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.team.uncoop.you-are-no-longer-a-coop-member", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
// Set cooldown
|
||||
if (getSettings().getCoopCooldown() > 0 && getParent() != null) {
|
||||
getParent().getSubCommand("coop").ifPresent(subCommand ->
|
||||
subCommand.setCooldown(island.getUniqueId(), targetUUID.toString(), getSettings().getCoopCooldown() * 60));
|
||||
getParent().getSubCommand("coop").ifPresent(subCommand -> subCommand.setCooldown(island.getUniqueId(),
|
||||
targetUUID.toString(), getSettings().getCoopCooldown() * 60));
|
||||
}
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.COOP_RANK, RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.COOP_RANK, RanksManager.VISITOR_RANK).build();
|
||||
return true;
|
||||
} else {
|
||||
// Should not happen
|
||||
@ -111,10 +112,9 @@ public class IslandTeamUncoopCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
List<String> options = island.getMembers().entrySet().stream()
|
||||
.filter(e -> e.getValue() == RanksManager.COOP_RANK)
|
||||
.map(e -> Bukkit.getOfflinePlayer(e.getKey()))
|
||||
.filter(e -> e.getValue() == RanksManager.COOP_RANK).map(e -> Bukkit.getOfflinePlayer(e.getKey()))
|
||||
.map(OfflinePlayer::getName).toList();
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -18,6 +18,7 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Command to untrust a player
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@ -44,7 +45,8 @@ public class IslandTeamUntrustCommand extends CompositeCommand {
|
||||
return false;
|
||||
}
|
||||
// Player issuing the command must have an island or be in a team
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())
|
||||
&& !getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
@ -52,7 +54,8 @@ public class IslandTeamUntrustCommand extends CompositeCommand {
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
if (rank < island.getRankCommand(getUsage())) {
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)));
|
||||
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Get target player
|
||||
@ -65,13 +68,13 @@ public class IslandTeamUntrustCommand extends CompositeCommand {
|
||||
return unTrustCmd(user, targetUUID);
|
||||
}
|
||||
|
||||
private boolean unTrustCmd(User user, UUID targetUUID) {
|
||||
protected boolean unTrustCmd(User user, UUID targetUUID) {
|
||||
// Player cannot untrust themselves
|
||||
if (user.getUniqueId().equals(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.untrust.cannot-untrust-yourself");
|
||||
return false;
|
||||
}
|
||||
if (getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) {
|
||||
if (getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()).inTeam(targetUUID)) {
|
||||
user.sendMessage("commands.island.team.untrust.cannot-untrust-member");
|
||||
return false;
|
||||
}
|
||||
@ -83,21 +86,19 @@ public class IslandTeamUntrustCommand extends CompositeCommand {
|
||||
}
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
island.removeMember(targetUUID);
|
||||
user.sendMessage("commands.island.team.untrust.success", TextVariables.NAME, target.getName());
|
||||
target.sendMessage("commands.island.team.untrust.you-are-no-longer-trusted", TextVariables.NAME, user.getName());
|
||||
getIslands().removePlayer(island, targetUUID);
|
||||
user.sendMessage("commands.island.team.untrust.success", TextVariables.NAME, target.getName(),
|
||||
TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||
target.sendMessage("commands.island.team.untrust.you-are-no-longer-trusted", TextVariables.NAME,
|
||||
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
|
||||
// Set cooldown
|
||||
if (getSettings().getTrustCooldown() > 0 && getParent() != null) {
|
||||
getParent().getSubCommand("trust").ifPresent(subCommand ->
|
||||
subCommand.setCooldown(island.getUniqueId(), targetUUID.toString(), getSettings().getTrustCooldown() * 60));
|
||||
getParent().getSubCommand("trust").ifPresent(subCommand -> subCommand.setCooldown(island.getUniqueId(),
|
||||
targetUUID.toString(), getSettings().getTrustCooldown() * 60));
|
||||
}
|
||||
IslandEvent.builder()
|
||||
.island(island)
|
||||
.involvedPlayer(targetUUID)
|
||||
.admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.TRUSTED_RANK, RanksManager.VISITOR_RANK)
|
||||
.build();
|
||||
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(false)
|
||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||
.rankChange(RanksManager.TRUSTED_RANK, RanksManager.VISITOR_RANK).build();
|
||||
return true;
|
||||
} else {
|
||||
// Should not happen
|
||||
@ -112,9 +113,8 @@ public class IslandTeamUntrustCommand extends CompositeCommand {
|
||||
if (island != null) {
|
||||
List<String> options = island.getMembers().entrySet().stream()
|
||||
.filter(e -> e.getValue() == RanksManager.TRUSTED_RANK)
|
||||
.map(e -> Bukkit.getOfflinePlayer(e.getKey()))
|
||||
.map(OfflinePlayer::getName).toList();
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
.map(e -> Bukkit.getOfflinePlayer(e.getKey())).map(OfflinePlayer::getName).toList();
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -13,6 +13,7 @@ import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
|
||||
@ -549,6 +550,7 @@ public interface WorldSettings extends ConfigObject {
|
||||
* Returns all aliases for main admin command.
|
||||
* It is assumed that all aliases are split with whitespace between them.
|
||||
* String cannot be empty.
|
||||
* The first command listed is the "label" in the API, and after that are the aliases
|
||||
* Default value: {@code getFriendlyName() + "admin"} (to retain backward compatibility).
|
||||
* @return String value
|
||||
* @since 1.13.0
|
||||
@ -563,6 +565,7 @@ public interface WorldSettings extends ConfigObject {
|
||||
* Returns all aliases for main player command.
|
||||
* It is assumed that all aliases are split with whitespace between them.
|
||||
* String cannot be empty.
|
||||
* The first command listed is the "label" in the API, and after that are the aliases
|
||||
* Default value: {@code getFriendlyName()} (to retain backward compatibility).
|
||||
* @return String value
|
||||
* @since 1.13.0
|
||||
@ -632,4 +635,22 @@ public interface WorldSettings extends ConfigObject {
|
||||
default boolean isCheckForBlocks() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of concurrent islands a player can have in the world
|
||||
* @return 1 by default
|
||||
* @since 2.0.0
|
||||
*/
|
||||
default int getConcurrentIslands() {
|
||||
return BentoBox.getInstance().getSettings().getIslandNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove islands when players join a team and not allow players to have other islands if they are in a team.
|
||||
* @return true or false
|
||||
* @since 2.3.0
|
||||
*/
|
||||
default boolean isDisallowTeamMemberIslands() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user