Compare commits
864 Commits
Author | SHA1 | Date |
---|---|---|
tastybento | fc9b00233b | |
tastybento | 1fd4a9043f | |
tastybento | ee3b0bfcc2 | |
tastybento | 35704b3fd3 | |
tastybento | 60fa60372d | |
tastybento | 8b0a5a3d0b | |
tastybento | ca15740a8c | |
tastybento | 5e5707f2a2 | |
tastybento | ef58838c41 | |
BONNe | 885d2449d9 | |
tastybento | 888b485f82 | |
tastybento | e2d9c2ce34 | |
tastybento | 8aba736383 | |
tastybento | 50276cb8e5 | |
tastybento | d701b7e43c | |
tastybento | 2fc3396a8f | |
tastybento | 99717f5b60 | |
tastybento | 290158e6ef | |
tastybento | 7126e837ed | |
tastybento | 45e5621d4c | |
tastybento | f536a13c59 | |
tastybento | f4780659e3 | |
tastybento | aad50eab38 | |
tastybento | 24d81da907 | |
tastybento | d288528a17 | |
tastybento | 83698c267f | |
tastybento | 52a280dc0b | |
tastybento | 4a0d44c035 | |
tastybento | b8e1f33800 | |
tastybento | d8891796cd | |
tastybento | 61e7c22bbc | |
tastybento | b1fe76c45d | |
tastybento | 5afd454fb3 | |
tastybento | a55c51412d | |
tastybento | 01a8055379 | |
tastybento | 744665a16e | |
tastybento | 3e4ff33d30 | |
tastybento | 09ede87971 | |
tastybento | b1418c144f | |
tastybento | 15335eb992 | |
tastybento | e33823d0c0 | |
tastybento | 63cc0a01d9 | |
tastybento | 6949432cb6 | |
tastybento | 69a22e917e | |
tastybento | ffb955b22b | |
tastybento | 3de0ff236e | |
tastybento | c86eb6a19c | |
tastybento | e7055c6cba | |
tastybento | 5834dcbb59 | |
tastybento | 2c75939bc3 | |
tastybento | e570401912 | |
tastybento | f6f4da1c89 | |
tastybento | 6106b661e9 | |
tastybento | e1536fcae0 | |
tastybento | 1c19703f44 | |
tastybento | 24b7d26fbe | |
tastybento | ec60991aeb | |
tastybento | 33000f9371 | |
tastybento | 83eaa50b49 | |
tastybento | 1215a43766 | |
tastybento | 81f765df36 | |
tastybento | 0e6a25d74b | |
tastybento | 2b19d43c85 | |
tastybento | 1bce4ec1b9 | |
tastybento | ea8562f351 | |
tastybento | d8f2c12fe5 | |
tastybento | b734d579a1 | |
tastybento | 44454f5854 | |
tastybento | da590ce319 | |
tastybento | 6599e3de80 | |
tastybento | 3c6e3d1286 | |
tastybento | d77c94c30c | |
tastybento | d240e9c8d8 | |
tastybento | 75412a4674 | |
tastybento | 40e96b9169 | |
tastybento | db2b97d2fc | |
tastybento | 5ad2ba1cd9 | |
tastybento | 6127cdced1 | |
tastybento | 91998b4e24 | |
tastybento | 06ca7a311a | |
tastybento | e4e92b9634 | |
tastybento | 0c4a4ba862 | |
tastybento | 3907cba08f | |
tastybento | 4064c9a241 | |
tastybento | b45c842c2f | |
tastybento | e2a4233f69 | |
tastybento | 977c82015b | |
tastybento | 6db04f872b | |
tastybento | 6fccf80477 | |
tastybento | eef3dcbc46 | |
tastybento | 253e5d7101 | |
tastybento | 1c4be17690 | |
tastybento | dc42f51168 | |
tastybento | 1fb6a8a27c | |
tastybento | 4170616e47 | |
tastybento | 7f532b1257 | |
tastybento | c39bd75837 | |
tastybento | 4810c4c4ad | |
tastybento | cb7c63a520 | |
tastybento | dcc3992762 | |
tastybento | 57164dd846 | |
tastybento | 69017860a0 | |
tastybento | 24c68a0d95 | |
tastybento | 994019836a | |
tastybento | bbafa6d340 | |
tastybento | 19d81c70c6 | |
tastybento | 7d52325196 | |
tastybento | 2d08365afc | |
tastybento | a3a4a70921 | |
tastybento | bb9ed87175 | |
tastybento | 0e833de22a | |
tastybento | 95d89c56bc | |
tastybento | 4ddb204fcf | |
tastybento | 562b515bfe | |
tastybento | 0a9da71c65 | |
tastybento | 631a15563d | |
tastybento | f93c9ba556 | |
tastybento | f568ccd2d6 | |
tastybento | f11a56cc6b | |
tastybento | ad009156e5 | |
tastybento | 78f84de3cb | |
tastybento | 070c1102db | |
tastybento | a1d19fae74 | |
tastybento | 59124cfa8a | |
tastybento | 887f09c41b | |
tastybento | e8acd05dbe | |
tastybento | 3784d5d28d | |
tastybento | 95b7ed137f | |
tastybento | 87b147ace4 | |
tastybento | 1846ed8088 | |
tastybento | af843aeb35 | |
tastybento | b43197d54f | |
tastybento | 38551a138a | |
tastybento | 83479ac8a4 | |
tastybento | 5e4634400a | |
tastybento | f81354fa3e | |
tastybento | 24025fd9ae | |
tastybento | 87054687f0 | |
tastybento | 01f51f4d29 | |
tastybento | 59c18e26f5 | |
tastybento | b63aef5589 | |
tastybento | 2d0d9ac1c2 | |
tastybento | 8217b375d5 | |
tastybento | 43db8d346c | |
tastybento | 9acb79fc60 | |
tastybento | 6316ff4a93 | |
tastybento | 471e8d681b | |
tastybento | 196e90bf4e | |
tastybento | c100fe0047 | |
tastybento | b2550882ba | |
BONNe | 6bf12d5e20 | |
tastybento | c9b7074e79 | |
tastybento | b25c65b7b2 | |
tastybento | 787424b999 | |
tastybento | 13bd1bb8f3 | |
tastybento | 5d3821094c | |
tastybento | 90a53e9fd8 | |
tastybento | ffcda52912 | |
tastybento | b672755ef9 | |
tastybento | 7c3056b0e8 | |
tastybento | 2d44c5dbca | |
tastybento | ce4d8a377e | |
tastybento | cc7b1eba4c | |
tastybento | 4bfbe41956 | |
tastybento | 76a36e685e | |
tastybento | f1001b1d05 | |
tastybento | 98d336faf0 | |
tastybento | edd7bcfbd2 | |
tastybento | be9b429308 | |
tastybento | 26e5d750a0 | |
tastybento | ca2976cc4b | |
tastybento | 54a7b8b0f2 | |
tastybento | 0e0c502e1d | |
Rafał Chomczyk | 68da898e79 | |
tastybento | c62d4f603f | |
tastybento | 29a6a51f30 | |
BONNe | fc658ca073 | |
BONNe | caade1a71c | |
BONNe | 31fb10629a | |
BONNe | 38d845d2e9 | |
BONNe | bfb487342a | |
BONNe | 3be034bfa9 | |
tastybento | e8e1d6184e | |
tastybento | 0352cfdd38 | |
tastybento | cc5c8aa9b6 | |
tastybento | 86d8d147d1 | |
BONNe | 96499f3ad6 | |
tastybento | b260cf1f4f | |
tastybento | f6e26aa5bd | |
tastybento | 1ef55a2b1e | |
tastybento | b2f5a441e5 | |
tastybento | 8dce036d70 | |
tastybento | 55e94b4c9f | |
tastybento | 5a193cda1c | |
tastybento | 1ab2ff278d | |
tastybento | 1942f5f1df | |
tastybento | 79b95af8bd | |
tastybento | af861f2a34 | |
tastybento | 6964f8c61a | |
tastybento | 12bf37d2c2 | |
tastybento | 22f398fe53 | |
tastybento | f256c3af8d | |
tastybento | 54ebf2dfd2 | |
tastybento | 26e6310fba | |
BONNe | f80cf238f0 | |
gitlocalize-app[bot] | 187ae1c61a | |
gitlocalize-app[bot] | ea6b5dd257 | |
tastybento | 9fe5212c3c | |
tastybento | 625b70de30 | |
tastybento | 4547232ac9 | |
tastybento | 90751224d7 | |
tastybento | 59c84990e5 | |
Baterka | 13c339ef4f | |
Huynh Tien | 5de7302469 | |
tastybento | 1cf7ccbb99 | |
tastybento | defb1c7a6e | |
tastybento | 0ecbd9150b | |
tastybento | 2818ac8f33 | |
tastybento | 70e4ae15b7 | |
tastybento | d95727fbdf | |
tastybento | 26dc5c5949 | |
BONNe | a35353a802 | |
tastybento | 63d092db93 | |
tastybento | 19d7e2fe0a | |
tastybento | c63de278fe | |
tastybento | 24148f30ba | |
tastybento | 4481881b9e | |
BONNe | 285205fe3f | |
tastybento | 5503ce0d90 | |
tastybento | 6d09a5a359 | |
BONNe | 4200fe4abb | |
tastybento | 4a6bf31dff | |
tastybento | d903e57ad6 | |
tastybento | fd99da68d9 | |
gitlocalize-app[bot] | 7f50073ad1 | |
gitlocalize-app[bot] | c4fa6cf26e | |
gitlocalize-app[bot] | 39882cb7bc | |
gitlocalize-app[bot] | 4e0e3d2005 | |
gitlocalize-app[bot] | c195baf66d | |
gitlocalize-app[bot] | b3808334ad | |
gitlocalize-app[bot] | 9e8df5ce80 | |
gitlocalize-app[bot] | 2c49e6d2f4 | |
tastybento | 5ccaadb2ae | |
tastybento | 8d0dbcdc36 | |
tastybento | e4836b9cef | |
BONNe | af3b0bba2d | |
tastybento | ea5529f077 | |
tastybento | 489a1e332d | |
tastybento | c8b2e1d801 | |
tastybento | a2f1054bbe | |
tastybento | 9f8a6bcded | |
tastybento | dc51bd87b1 | |
tastybento | 2b65543935 | |
tastybento | 7fbd041be9 | |
tastybento | 6d2f79881b | |
tastybento | e6ccce4a27 | |
tastybento | 8b78affc9b | |
tastybento | 5c3ebc800c | |
tastybento | 2bc82dd3cf | |
tastybento | a4bef159be | |
tastybento | 503107a90c | |
tastybento | b276c0715c | |
tastybento | 8d3be9c0ff | |
tastybento | ba31dd78b4 | |
tastybento | a7b791f4be | |
gitlocalize-app[bot] | bcf569c019 | |
tastybento | b2bdce4d25 | |
tastybento | a6f47e5c54 | |
mt-gitlocalize | 33a694cfd1 | |
tastybento | 6a5ea171be | |
tastybento | d6978ce0f6 | |
tastybento | e23207df2f | |
tastybento | 0f6d5af1f8 | |
BONNe | da2daae990 | |
tastybento | aed78038ef | |
tastybento | 1228da131f | |
tastybento | 08d73f232b | |
tastybento | 06ccb8a5e0 | |
tastybento | 768988e803 | |
tastybento | fd91ab596b | |
tastybento | 397f9e4700 | |
tastybento | 1b2748f920 | |
tastybento | 78092aa3e9 | |
tastybento | 475e67c447 | |
tastybento | 2ad7796582 | |
tastybento | 3e1dc81592 | |
tastybento | fec43adc35 | |
tastybento | 7a21aba3a8 | |
tastybento | 62a3a8d6fa | |
tastybento | 1a0a314ece | |
tastybento | 2512a892fd | |
tastybento | 850939f3a8 | |
tastybento | 8ce78c8fe0 | |
tastybento | 2dfd136591 | |
tastybento | 357a8fdc5f | |
tastybento | a0b349ec27 | |
tastybento | 585f720f6f | |
tastybento | a6bb78c80f | |
tastybento | c5baa1d0eb | |
tastybento | 988ace8329 | |
tastybento | 170c31fcec | |
tastybento | 211d636bfb | |
tastybento | 4ef974fbde | |
tastybento | 9a464ab795 | |
tastybento | 39a6fc5006 | |
tastybento | 325c9c2351 | |
tastybento | 30d29c6ff9 | |
tastybento | 2c8db2a797 | |
tastybento | df45fca562 | |
tastybento | df6fb7d716 | |
tastybento | 54139b60f0 | |
tastybento | 74a2e9d3c8 | |
tastybento | 5953df9dbb | |
tastybento | 363b23a049 | |
tastybento | 9334858675 | |
tastybento | 7d25aff28f | |
tastybento | f47e87af82 | |
tastybento | 6d3349a0f9 | |
tastybento | 9bd0104a3d | |
tastybento | 7b8e18afff | |
tastybento | f23ebec34e | |
tastybento | 9c6cc78c32 | |
tastybento | c28ecb1c74 | |
tastybento | cbed9ac831 | |
tastybento | e846d26fab | |
tastybento | 4c0cb9f17c | |
tastybento | 0038c3f2b7 | |
tastybento | 66d27e7070 | |
tastybento | 4b0c5ec894 | |
tastybento | 1a416d9a23 | |
tastybento | 74e053ef8a | |
tastybento | 2ed2492ce3 | |
tastybento | 2b4e1dd5eb | |
tastybento | 89a9b13d81 | |
tastybento | b50063685f | |
tastybento | 01313def01 | |
tastybento | 2805e5889b | |
tastybento | a7ffb79f1d | |
tastybento | 0856d48470 | |
tastybento | 4d295068cf | |
tastybento | bcb4ed28b8 | |
tastybento | d6d86d39d2 | |
tastybento | c6a8f7c095 | |
tastybento | 372f3f14c6 | |
tastybento | 393a0131f9 | |
tastybento | c0beba7467 | |
tastybento | 5c2166fc93 | |
tastybento | a90a00b09b | |
tastybento | 09c60f24cf | |
tastybento | b512975b13 | |
tastybento | e9067cfb28 | |
tastybento | 5a52978803 | |
tastybento | b64015e3b6 | |
Nico Mexis | c000da6e6f | |
tastybento | 2672ee5d1b | |
tastybento | d25d1713f8 | |
tastybento | 6932ce3759 | |
tastybento | 38ddeff369 | |
tastybento | e4a3891590 | |
tastybento | 7bb1907897 | |
tastybento | 5f6b91bc64 | |
tastybento | fdc03df298 | |
tastybento | eb76d00f80 | |
tastybento | a7b1028496 | |
tastybento | 9ffc838f2d | |
Dusty | d0d01dbc2b | |
tastybento | 8f954090e7 | |
zrdzn | 84adfaa622 | |
tastybento | f05d4dc57f | |
steve4744 | e991f09921 | |
tastybento | f52150ec1d | |
tastybento | ce5830e2ad | |
tastybento | 577e476796 | |
tastybento | 8d0fcf0169 | |
tastybento | 0ee9ff4f10 | |
tastybento | 84e6523b9d | |
tastybento | 5c5077a6b5 | |
tastybento | 9ee5bcbcf2 | |
BONNe | c235abbfa6 | |
tastybento | b4737f104c | |
tastybento | ba19b08f4c | |
tastybento | 073f3a49d5 | |
tastybento | 1a293a6936 | |
tastybento | 85a7375004 | |
tastybento | 25e601b26c | |
tastybento | 907268c2f4 | |
tastybento | 6894695024 | |
tastybento | 233e5ceb65 | |
tastybento | 5d67dbe5e3 | |
tastybento | 2cb561b943 | |
tastybento | ca604f893c | |
tastybento | 3285ef1ad2 | |
tastybento | 70f044265a | |
tastybento | 2940d2e492 | |
tastybento | c31458f8e6 | |
tastybento | 2b40ae47d7 | |
tastybento | 2c283ae3a9 | |
tastybento | f02b4d5011 | |
tastybento | 6925a788f3 | |
tastybento | 1b81e74f4c | |
tastybento | 999ca242d7 | |
tastybento | 7d0eb3586d | |
tastybento | a713b7be07 | |
tastybento | fe888a8d0e | |
tastybento | 45f2dca414 | |
tastybento | 8276406f9f | |
tastybento | 5eaf54e905 | |
tastybento | 04545e676f | |
tastybento | 08a1ad8126 | |
tastybento | 79d56a5cef | |
tastybento | f93c49184f | |
tastybento | 0f0b5aacc2 | |
tastybento | e978b29d85 | |
tastybento | 6c1bcdec05 | |
tastybento | a793a33758 | |
tastybento | 1783bb7058 | |
tastybento | a703499817 | |
tastybento | 224be307a0 | |
tastybento | b62a1862a2 | |
JamesMCL44 | 3623537d84 | |
tastybento | 6c8ccd2a57 | |
tastybento | f1eaa0fcde | |
tastybento | 9ccdcceaba | |
tastybento | 35ece03e5b | |
tastybento | 760bc2e086 | |
tastybento | caf994738e | |
tastybento | f00320095d | |
tastybento | 46d20f34ff | |
tastybento | df910e96d3 | |
tastybento | f29e78557a | |
tastybento | 2d8b3074a9 | |
tastybento | ad2541963e | |
tastybento | 2c1a018071 | |
tastybento | c6fc42846a | |
tastybento | 0e253f3ba5 | |
tastybento | a68436fde1 | |
tastybento | 1d28979d5c | |
tastybento | 187132bc1d | |
tastybento | 3331ffac4e | |
tastybento | f9e57898ab | |
tastybento | 0c29d0b5dd | |
tastybento | 7040047fcb | |
BONNe | ea6ca3d26b | |
tastybento | a604d5cf82 | |
tastybento | bbb8207cf0 | |
BONNe | e89970b49b | |
tastybento | 0de2c3a7b6 | |
tastybento | 0f89de6c2a | |
tastybento | 8e40bf9dcf | |
tastybento | 10a73e66b4 | |
tastybento | 3746349e22 | |
tastybento | 0e5db0f41f | |
tastybento | 1262a08a22 | |
tastybento | f545a4576e | |
tastybento | ab434b63fa | |
tastybento | 6b88d31762 | |
tastybento | 93ca9fb0e6 | |
tastybento | 0bffe3806a | |
tastybento | 872940011a | |
tastybento | 056cff4b6f | |
tastybento | 0183380b82 | |
tastybento | d541e7054c | |
tastybento | 36ae34da5d | |
tastybento | a7869832f1 | |
tastybento | 18983e5570 | |
tastybento | ebd9215c56 | |
tastybento | 70262be896 | |
tastybento | bde294e0e6 | |
tastybento | e7f1269443 | |
tastybento | e2b5545f3f | |
tastybento | 69fa951907 | |
tastybento | 7aa1e2da89 | |
tastybento | 2629e940c7 | |
tastybento | 1c4fb76828 | |
BONNe | acb984ee90 | |
BONNe | d9ad9f158b | |
BONNe | 87a6799cd1 | |
tastybento | d50208c0e1 | |
BONNe | a22ce33175 | |
Irmo van den Berge | ac4922534e | |
BONNe | b48a5a73b8 | |
BONNe | 065f4ba4bd | |
BONNe | e47890c16e | |
BONNe | 866dff6244 | |
BONNe | 369001d368 | |
BONNe | 4792ff3f62 | |
BONNe | 1a59ca7785 | |
BONNe | b263c92c13 | |
BONNe | 52bca66149 | |
BONNe | f01e5540c7 | |
BONNe | bf87cca754 | |
BONNe | 682d835961 | |
BONNe | 4458d16274 | |
BONNe | d197ce8bea | |
BONNe | aa7abe02bf | |
BONNe | 97c4cf883f | |
BONNe | eb5147e710 | |
BONNe | 755aeb866e | |
BONNe | 173808b787 | |
BONNe | 35ce1a7d81 | |
Huynh Tien | 12926f9ee7 | |
BONNe | 9088ea4b80 | |
BONNe | 50bc236bbc | |
BONNe | c7b48b3d2a | |
BONNe | 6f791420e7 | |
BONNe | 6c1399c2b4 | |
BONNe | 44201afa1f | |
BONNe | 64b4c43742 | |
BONNe | a59697c14e | |
BONNe | 5a527d4119 | |
BONNe | aed8caeb76 | |
BONNe | 927fcba15a | |
BONNe | 9ec8730359 | |
BONNe | 9643f617b6 | |
BONNe | 3784aa48d7 | |
BONNe | 2f244c0606 | |
BONNe | f969f2721f | |
Galić Mijo | cbd063c9e8 | |
BONNe | db323390cf | |
BONNe | d8fa029ac9 | |
Sliman4 | 3cd5b05130 | |
BONNe | 1991dc7236 | |
BONNe | c54358441d | |
BONNe | e41f5ac24f | |
BONNe | d984955af3 | |
BONNe | 85b52f4bfb | |
BONNe | 6f2a9929c0 | |
BONNe | aad10ad74f | |
BONNe | 345b9e2564 | |
BONNe | 3ab7ac8484 | |
Huynh Tien | 0f815d8175 | |
evlad | 4ab579f2cd | |
Huynh Tien | 6fba4bfbea | |
evlad | d07c1b5a8c | |
Huynh Tien | 3e0368fbab | |
BONNe | 385aed02cd | |
BONNe | c4c51d00e2 | |
tastybento | 928f1eb1eb | |
BONNe | b3e55a7b55 | |
BONNe | 9f163f0572 | |
BONNe | 4341c28aca | |
BONNe | ad0931ffcb | |
Invvk | c02e566266 | |
BONNe | 36751d5573 | |
BONNe | 9f21314818 | |
tastybento | 6796fceee8 | |
tastybento | 51dbca0f99 | |
tastybento | b0f1417166 | |
tastybento | 0b3ef8df6d | |
tastybento | bda56763a8 | |
BONNe | 3ba6620e73 | |
tastybento | 4e8ca6d22c | |
tastybento | fd44e03b7b | |
BONNe | 6d59e79e78 | |
BONNe | 0cf1d43a29 | |
tastybento | e7599ec805 | |
tastybento | 546cf2c9b9 | |
tastybento | 945bfa66ee | |
BONNe | 50b677f4c5 | |
tastybento | 6a009946f5 | |
tastybento | 6c7d77f093 | |
tastybento | 5910aa2685 | |
tastybento | 73a432d75c | |
tastybento | 4e3079b623 | |
BONNe | d492539c51 | |
BONNe | fa68f8f01c | |
tastybento | cef31306ac | |
tastybento | ee94a49e85 | |
tastybento | 78a3c49361 | |
tastybento | 937e8bf614 | |
BONNe | 09ab327551 | |
BONNe | 90ebe103c4 | |
Huynh Tien | 178529adb1 | |
BONNe | 52cc2a8593 | |
BONNe | 3ecdda65b5 | |
BONNe | da98bbcf38 | |
tastybento | 7b94aa0ea2 | |
BONNe | 54869a400a | |
BONNe | 56c9f5c28e | |
tastybento | 2f0869fd6e | |
tastybento | d14ad977ab | |
tastybento | 9062aab34b | |
tastybento | 94b982f644 | |
tastybento | 5573e9f329 | |
tastybento | 823bc5ceed | |
tastybento | f25e54f3c8 | |
tastybento | 5ab89ac63d | |
tastybento | 046c4fff35 | |
tastybento | bea9f0e394 | |
tastybento | 721f0271aa | |
tastybento | b63df41082 | |
tastybento | d06688ad45 | |
tastybento | 00e174258e | |
BONNe | eaf2236f7f | |
gitlocalize-app[bot] | ff4a7c9d61 | |
gitlocalize-app[bot] | 318d399a5b | |
tastybento | 5c94f97e71 | |
tastybento | bfbeb7964b | |
tastybento | 5c8af0c1df | |
tastybento | 728c60d472 | |
gitlocalize-app[bot] | 2d08e28a01 | |
gitlocalize-app[bot] | c1f33ad1d4 | |
gitlocalize-app[bot] | a5f093758c | |
tastybento | 20a6846523 | |
tastybento | 796114eeef | |
BONNe | d1eb175e88 | |
Huynh Tien | 7088a2736f | |
Huynh Tien | dffe8a811e | |
Huynh Tien | ce1d8e5117 | |
Huynh Tien | c9c9ea0389 | |
gitlocalize-app[bot] | b6a739db00 | |
tastybento | 17ac4f688a | |
tastybento | bf62f18de5 | |
tastybento | acba363523 | |
tastybento | 7fbae58bb2 | |
tastybento | 3ece0d049a | |
tastybento | f049fc6941 | |
Huynh Tien | e3b99195ca | |
Huynh Tien | 333c9a8272 | |
BONNe | ed50765b98 | |
Huynh Tien | 168de622ea | |
Huynh Tien | f91ed4705a | |
Huynh Tien | 6f01310f92 | |
tastybento | 2e6ef59040 | |
tastybento | cec58c7a45 | |
tastybento | 60cde5334d | |
tastybento | 6567104f94 | |
tastybento | 524cb46e27 | |
tastybento | 8a6cc39214 | |
BONNe | 3b64973c2b | |
tastybento | 59de6a8efb | |
tastybento | 11a3bf9227 | |
tastybento | 79abf965f3 | |
tastybento | de951b6c4b | |
Fredthedoggy | 2d032523c7 | |
tastybento | 7277432c41 | |
tastybento | 7616f6aa2a | |
tastybento | 6b6ab711e5 | |
tastybento | f3a7ed1303 | |
tastybento | 7b1c19c084 | |
tastybento | 22c62c91b4 | |
tastybento | df2b445002 | |
tastybento | 5e3cffbe11 | |
tastybento | 1953caa7c5 | |
tastybento | 8752e19e5d | |
tastybento | 6aa7869b17 | |
tastybento | 930433b64b | |
tastybento | 731d902d98 | |
tastybento | 1a802a7510 | |
tastybento | 37e7846908 | |
tastybento | 28a2ecfcfa | |
tastybento | 081f74544b | |
tastybento | 2ffa4c9874 | |
tastybento | 907c6b3534 | |
tastybento | 8852b9d660 | |
tastybento | 765f774652 | |
tastybento | db464d5c04 | |
tastybento | f37226b115 | |
tastybento | 536d7ef1c3 | |
tastybento | d3e7b55be5 | |
tastybento | 665724e825 | |
tastybento | fe2e9e1a9e | |
tastybento | b5d9d2e52e | |
tastybento | cfad9879a5 | |
tastybento | 3a43c40634 | |
tastybento | 60c62a5967 | |
tastybento | 3c65194dfb | |
tastybento | a1c3f78293 | |
tastybento | b5fd992fa7 | |
tastybento | bc6ec36f87 | |
tastybento | d780bbd4c0 | |
tastybento | f66eeed4a1 | |
tastybento | 3236c68e5c | |
tastybento | 500f7292c6 | |
tastybento | af3c0a874c | |
tastybento | 0a4fc83218 | |
tastybento | 8b474833e1 | |
tastybento | bc737d4d66 | |
tastybento | 3d2a99c036 | |
BONNe | 16d5775c84 | |
tastybento | 690ea2f99e | |
tastybento | 29fa03976c | |
tastybento | f6f5b63110 | |
tastybento | 110a282deb | |
tastybento | 53f02ae686 | |
tastybento | b247b360bf | |
tastybento | 68890eba00 | |
tastybento | 8eac5070f0 | |
tastybento | 25fe86d812 | |
tastybento | cad7dc1666 | |
tastybento | 8eb45e817c | |
tastybento | 4f22df069b | |
tastybento | 3282b1bd12 | |
tastybento | d92632341d | |
tastybento | 02a14cab6e | |
tastybento | 063fa97cf3 | |
tastybento | bb7f124066 | |
tastybento | 5b838d0668 | |
tastybento | 005007b0db | |
tastybento | 5c063a692d | |
tastybento | c7a1220028 | |
tastybento | 0e744cae81 | |
tastybento | 7271096ace | |
tastybento | 3dd9e973fb | |
tastybento | 2b452cddbd | |
tastybento | a6d70d6e90 | |
tastybento | e71d67d3c9 | |
tastybento | b24c1fdc86 | |
tastybento | 6bff4c8132 | |
BONNe | 9da329356a | |
BONNe | 6bf3264ab5 | |
tastybento | 3650863fa1 | |
BONNe | 23e3554c4d | |
tastybento | 938940199d | |
tastybento | 184c86bafe | |
tastybento | 0844e97530 | |
tastybento | 28cecc2658 | |
tastybento | e77a40f0cb | |
tastybento | 7d7882c309 | |
tastybento | 74ded5a187 | |
tastybento | 7621677c93 | |
tastybento | 23522a297f | |
tastybento | 0f7ca6ac60 | |
tastybento | 547c266975 | |
tastybento | 5bb12d53bd | |
tastybento | 23857501f5 | |
tastybento | 9dc4ebc2d1 | |
tastybento | a9a7673ce8 | |
tastybento | 44f06f2911 | |
BONNe | 2607256c06 | |
tastybento | faf351fd59 | |
BONNe | fa41abc062 | |
tastybento | 0341515fc8 | |
tastybento | ed4cc0eb8b | |
tastybento | 773f0391cf | |
tastybento | 876ba91837 | |
tastybento | 6c75733417 | |
Fredthedoggy | 705693f904 | |
BONNe | c635647f85 | |
tastybento | b906f5561a | |
tastybento | e0d6e4df30 | |
tastybento | 32638e7a87 | |
tastybento | 233c058bfe | |
tastybento | 6b839d9c69 | |
tastybento | 7cadebc792 | |
tastybento | cc974c795f | |
BONNe | 56a1fdb55a | |
tastybento | cf8df9c2a8 | |
tastybento | 27e9c9c54f | |
tastybento | 1bd11bbff6 | |
tastybento | acfc001cd6 | |
tastybento | f89050fe2f | |
tastybento | 1a7b7cdeb7 | |
tastybento | 5d7c199d12 | |
tastybento | b5725e7107 | |
tastybento | 6bac200ac0 | |
tastybento | 3b136f0d68 | |
tastybento | 9b1d61659b | |
gecko10000 | 21fed6ebfe | |
BONNe | 2044c73f05 | |
tastybento | 09d6a9fc6f | |
tastybento | 376ac167e8 | |
tastybento | 9cdebe8f9f | |
tastybento | 03f6b95a68 | |
tastybento | e1c08107c2 | |
tastybento | 3d1481fec5 | |
tastybento | ce4b124279 | |
tastybento | 9e3a57248a | |
tastybento | 0845722150 | |
tastybento | 3450bae8f0 | |
tastybento | 4da61f6849 | |
tastybento | 70a2c20e51 | |
tastybento | ed0084f2c4 | |
tastybento | dfca46abf1 | |
BONNe | 69f7b49469 | |
Justin | 759ba522f4 | |
Justin | 0f7866a00b | |
Justin | f88b8d4d6d | |
Fredthedoggy | 7de6563ece | |
BONNe | 89625a78b8 | |
BONNe | 4139c5f252 | |
BONNe | 3a1ec0a570 | |
tastybento | 19ddd73204 | |
tastybento | 85a9e44c4d | |
tastybento | 17d9271369 | |
tastybento | 1ee83cd782 | |
tastybento | e0e1f2878c | |
tastybento | c89fd03833 | |
tastybento | a0f2f11499 | |
tastybento | c2e832095a | |
tastybento | 2a5d8c14e3 | |
tastybento | cc43dbfabe | |
gecko10000 | 7768cc69cc | |
Korinocho | a91203d439 | |
tastybento | 044a0c5c0d | |
tastybento | c3b25c92b5 | |
tastybento | d647f58e36 | |
tastybento | 6e9513f2ea | |
tastybento | 9fc22aa8e7 | |
tastybento | bedeb7c168 | |
gitlocalize-app[bot] | 7f8297475d | |
tastybento | e472e07c34 | |
tastybento | a1a78de96f | |
gitlocalize-app[bot] | 03417a78f7 | |
Fredthedoggy | ca39e05fc7 | |
tastybento | 64c83f809c | |
tastybento | 36d0a07e35 | |
tastybento | 2bc35c8936 | |
Fredthedoggy | 022d343295 | |
tastybento | 10a51a5874 | |
tastybento | 982dc2fd52 | |
tastybento | 17af44e67a | |
tastybento | 839f05de71 | |
Fredthedoggy | 9ed0620bb0 | |
tastybento | 09bac48b5e | |
tastybento | 352c6dec84 | |
gitlocalize-app[bot] | 3242a497db | |
tastybento | b1ab2ecece | |
tastybento | 33b49a2349 | |
fredthedoggy | 2a1d9fcc61 | |
tastybento | ac8458fd3c | |
tastybento | 2098fd636a | |
tastybento | 3e068e4283 | |
tastybento | fb2c9c0553 | |
tastybento | c85f3b9af2 | |
BONNe | dc829786d3 | |
tastybento | 9220f9652b | |
tastybento | 609322d582 | |
tastybento | 4b9b6774ea | |
tastybento | c6e2a9bd66 | |
Qumoo | 9db7721016 | |
tastybento | ed46695546 | |
tastybento | 3c4b7deb75 | |
Florian CUNY | 8ecfee4359 | |
tastybento | 9e0fdbd210 | |
tastybento | 1bc58facee | |
tastybento | 99e6e11a4a | |
tastybento | 8f767d5e44 | |
tastybento | 87bdee0946 | |
apachezy | b8d9b73103 | |
BONNe | 592b4e3d1f | |
BONNe | 8ce30a7cb5 | |
apachezy | 4582b23522 | |
BONNe | cf5483e49d | |
apachezy | 17d5b7392b | |
tastybento | 69b059f423 | |
tastybento | d70b07c273 | |
tastybento | 6c775329d0 | |
tastybento | 74023914a7 | |
gitlocalize-app[bot] | 487fa6af8e | |
tastybento | 0769af0c65 | |
tastybento | d97d15d47a | |
tastybento | 1feaddf704 | |
tastybento | 45bcf64da5 | |
apachezy | 4544cada3a | |
apachezy | e36dc68ccd | |
apachezy | 0f0d8b9ebc | |
poslovitch | 40d1c318d5 | |
tastybento | 031d789896 | |
tastybento | 9f9dc40773 | |
tastybento | 6849c2a8bd | |
tastybento | 7d6cce6563 | |
Huynh Tien | 5142894127 | |
tastybento | 9c1a239501 |
|
@ -10,30 +10,35 @@ 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 8
|
||||
uses: actions/setup-java@v1
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 8
|
||||
distribution: 'adopt'
|
||||
java-version: '21'
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2
|
||||
- name: Build
|
||||
run: mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install
|
||||
- name: Build and analyze
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=BentoBoxWorld_BentoBox
|
||||
- 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
|
||||
|
|
|
@ -84,4 +84,5 @@ dist/
|
|||
nbdist/
|
||||
nbactions.xml
|
||||
nb-configuration.xml
|
||||
.nb-gradle/
|
||||
.nb-gradle/
|
||||
/BentoBox/
|
||||
|
|
23
.travis.yml
23
.travis.yml
|
@ -1,23 +0,0 @@
|
|||
language: java
|
||||
sudo: false
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "bentobox-world"
|
||||
|
||||
jdk:
|
||||
- openjdk8
|
||||
- openjdk11
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- jdk: openjdk11
|
||||
|
||||
script:
|
||||
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install
|
||||
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh && . ./install-jdk.sh -F 11 -L GPL
|
||||
- mvn sonar:sonar -Dsonar.projectKey=BentoBoxWorld_BentoBox
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
- '$HOME/.sonar/cache'
|
1
ADDON.md
1
ADDON.md
|
@ -1,4 +1,5 @@
|
|||
The following is a list of all addons currently made for BentoBox:
|
||||
* [**Bank**](https://github.com/BentoBoxWorld/Bank/): Provides an island bank to enable island members to share money.
|
||||
* [**Biomes**](https://github.com/BentoBoxWorld/Biomes/): Enables players to change biomes on islands.
|
||||
* [**Border**](https://github.com/BentoBoxWorld/Border/): Adds a world border around islands.
|
||||
* [**Cauldron Witchery**](https://github.com/BentoBoxWorld/CauldronWitchery/): Allows summoning mobs using some magic!
|
||||
|
|
11
README.md
11
README.md
|
@ -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)
|
||||
|
@ -25,6 +24,7 @@ Start now to create the server you've dreamed of!
|
|||
These are some popular Gamemodes:
|
||||
* [**AcidIsland**](https://github.com/BentoBoxWorld/AcidIsland): You are marooned in a sea of acid!
|
||||
* [**AOneBlock**](https://github.com/BentoBoxWorld/AOneBlock): Start to play with only 1 magical block.
|
||||
* [**Boxed**](https://github.com/BentoBoxWorld/Boxed): A game mode where you are boxed into a tiny space that only expands by completing advancements.
|
||||
* [**BSkyBlock**](https://github.com/BentoBoxWorld/BSkyBlock): The successor to the popular ASkyBlock.
|
||||
* [**CaveBlock**](https://github.com/BentoBoxWorld/CaveBlock): Try to live underground!
|
||||
* [**SkyGrid**](https://github.com/BentoBoxWorld/SkyGrid): Survive in world made up of scattered blocks - what an adventure!
|
||||
|
@ -37,7 +37,7 @@ There are also plenty of other official or community-made Addons you can try and
|
|||
## Documentation
|
||||
|
||||
* Start reading: [https://docs.bentobox.world](https://docs.bentobox.world)
|
||||
* For developers: [Javadocs](https://bentoboxworld.github.io/BentoBox/)
|
||||
* For developers: [Javadocs](https://ci.codemc.io/job/BentoBoxWorld/job/BentoBox/ws/target/apidocs/index.html)
|
||||
|
||||
## Downloads
|
||||
|
||||
|
@ -84,6 +84,10 @@ BentoBox uses Maven, and its Maven repository is kindly provided by [CodeMC](htt
|
|||
### Maven
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>codemc-snapshots</id>
|
||||
<url>https://repo.codemc.org/repository/maven-snapshots</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
|
@ -107,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
|
||||
|
||||
|
|
328
pom.xml
328
pom.xml
|
@ -63,27 +63,35 @@
|
|||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<!-- Non-minecraft related dependencies -->
|
||||
<powermock.version>2.0.4</powermock.version>
|
||||
<mongodb.version>3.8.0</mongodb.version>
|
||||
<powermock.version>2.0.9</powermock.version>
|
||||
<!-- Database related dependencies -->
|
||||
<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.16.4-R0.1-SNAPSHOT</spigot.version>
|
||||
<spigot.version>1.20.5-R0.1-SNAPSHOT</spigot.version>
|
||||
<!-- Might differ from the last Spigot release for short periods
|
||||
of time -->
|
||||
<paper.version>1.16.4-R0.1-SNAPSHOT</paper.version>
|
||||
<bstats.version>2.1.0</bstats.version>
|
||||
<vault.version>1.7</vault.version>
|
||||
<paper.version>1.20.6-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>
|
||||
<githubapi.version>d5f5e0bbd8</githubapi.version>
|
||||
<dynmap.version>3.0-SNAPSHOT</dynmap.version>
|
||||
<worldedit.version>7.0.0</worldedit.version>
|
||||
<myworlds.version>1.19.3-v1</myworlds.version>
|
||||
<!-- Revision variable removes warning about dynamic version -->
|
||||
<revision>${build.version}-SNAPSHOT</revision>
|
||||
<!-- 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.16.0</build.version>
|
||||
<build.version>2.4.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. -->
|
||||
|
@ -119,6 +127,7 @@
|
|||
<value>origin/master</value>
|
||||
</property>
|
||||
</activation>
|
||||
<!--suppress CheckTagEmptyBody -->
|
||||
<properties>
|
||||
<!-- Override only if necessary -->
|
||||
<revision>${build.version}</revision>
|
||||
|
@ -126,34 +135,20 @@
|
|||
<build.number></build.number>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>sonar</id>
|
||||
<properties>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
<sonar.organization>bentobox-world</sonar.organization>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<!-- was <version>3.4.1.1168</version> -->
|
||||
<version>3.6.0.1398</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sonar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/snapshots/</url>
|
||||
</pluginRepository>
|
||||
</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>
|
||||
|
@ -162,64 +157,60 @@
|
|||
<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>http://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dynmap-repo</id>
|
||||
<url>https://repo.mikeprimm.com/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>worldedit-repo</id>
|
||||
<url>https://maven.sk89q.com/repo/</url>
|
||||
<id>papermc</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<!-- This is a temporary reference as the Maven Shade plugin
|
||||
that supports Java 16 is not released yet -->
|
||||
<id>maven-snapshots</id>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>minecraft-repo</id>
|
||||
<url>https://libraries.minecraft.net/</url>
|
||||
</repository>
|
||||
<!-- Spigot NMS required for world regeneration :( -->
|
||||
<repository>
|
||||
<id>nms-repo</id>
|
||||
<url>https://repo.codemc.io/repository/nms/</url>
|
||||
</repository>
|
||||
<!-- Used for MyWorlds hook -->
|
||||
<repository>
|
||||
<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>com.destroystokyo.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>${paper.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Spigot NMS. Used for Head Getter and chunk deletion. -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>${spigot.version}</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.1.0</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>
|
||||
|
@ -231,16 +222,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>
|
||||
<!-- 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.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>
|
||||
<artifactId>mongodb-driver</artifactId>
|
||||
<version>${mongodb.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- HikariCP database handler -->
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.1-901-1.jdbc4</version>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>${hikaricp.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Vault: as their maven repo is down, we need to get it from jitpack -->
|
||||
<!-- See https://github.com/MilkBowl/VaultAPI/issues/69 -->
|
||||
|
@ -265,9 +309,15 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sk89q.worldedit</groupId>
|
||||
<artifactId>worldedit-core</artifactId>
|
||||
<version>${worldedit.version}</version>
|
||||
<groupId>com.bergerkiller.bukkit</groupId>
|
||||
<artifactId>MyWorlds</artifactId>
|
||||
<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 -->
|
||||
|
@ -276,6 +326,11 @@
|
|||
<artifactId>GitHubWebAPI4Java</artifactId>
|
||||
<version>${githubapi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.Marcono1234</groupId>
|
||||
<artifactId>gson-record-type-adapter-factory</artifactId>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<!-- Static analysis -->
|
||||
<!-- We are using Eclipse's annotations. If you're using IDEA, update
|
||||
your project settings to take these into account for in real time static
|
||||
|
@ -283,7 +338,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jdt</groupId>
|
||||
<artifactId>org.eclipse.jdt.annotation</artifactId>
|
||||
<version>2.2.200</version>
|
||||
<version>2.2.600</version>
|
||||
</dependency>
|
||||
<!-- PaperLib -->
|
||||
<dependency>
|
||||
|
@ -292,6 +347,41 @@
|
|||
<version>1.0.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- LangUtils -->
|
||||
<dependency>
|
||||
<groupId>com.github.apachezy</groupId>
|
||||
<artifactId>LangUtils</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- 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>
|
||||
|
@ -326,21 +416,48 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<release>${java.version}</release>
|
||||
<!-- <source>${java.version}</source> <target>${java.version}</target> -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<version>3.0.0-M5</version>
|
||||
<!--suppress MavenModelInspection -->
|
||||
<configuration>
|
||||
<argLine>
|
||||
${argLine}
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
--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.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/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/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.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>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -350,19 +467,20 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<source>${java.version}</source>
|
||||
<show>private</show>
|
||||
<quiet>true</quiet>
|
||||
<failOnError>false</failOnError>
|
||||
<additionalJOption>-Xdoclint:none</additionalJOption>
|
||||
<!-- To compile with Java 11, this tag may be required -->
|
||||
<!-- <javadocExecutable>${java.home}/bin/javadoc</javadocExecutable> -->
|
||||
<javadocExecutable>${java.home}/bin/javadoc</javadocExecutable>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<phase>install</phase>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
|
@ -386,9 +504,10 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</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>
|
||||
|
@ -400,11 +519,17 @@
|
|||
</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>
|
||||
<exclude>org.apache.maven:*</exclude>
|
||||
<exclude>com.google.code.gson:*</exclude>
|
||||
<exclude>org.mongodb:*</exclude>
|
||||
<exclude>org.eclipse.jdt:*</exclude>
|
||||
|
@ -442,27 +567,34 @@
|
|||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.4</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>
|
||||
<execution>
|
||||
<id>pre-unit-test</id>
|
||||
<id>prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>post-unit-test</id>
|
||||
<id>report</id>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>XML</format>
|
||||
</formats>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package world.bentobox.bentobox;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
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
|
||||
|
@ -29,6 +31,13 @@ public class BStats {
|
|||
*/
|
||||
private int islandsCreatedCount = 0;
|
||||
|
||||
/**
|
||||
* Contains the amount of connected players since last data send.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private final Set<UUID> connectedPlayerSet = new HashSet<>();
|
||||
|
||||
|
||||
BStats(BentoBox plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
@ -48,11 +57,15 @@ public class BStats {
|
|||
registerGameModeAddonsChart();
|
||||
registerHooksChart();
|
||||
registerPlayersPerServerChart();
|
||||
registerFlagsDisplayModeChart();
|
||||
|
||||
// Single Line charts
|
||||
registerIslandsCountChart();
|
||||
registerIslandsCreatedChart();
|
||||
|
||||
// Bar Charts
|
||||
registerAddonsBarChart();
|
||||
registerGameModeAddonsBarChart();
|
||||
registerHooksBarChart();
|
||||
}
|
||||
|
||||
private void registerDefaultLanguageChart() {
|
||||
|
@ -86,6 +99,15 @@ public class BStats {
|
|||
islandsCreatedCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given UUID to the connected player set.
|
||||
* @param uuid UUID of a player who logins.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
public void addPlayer(UUID uuid) {
|
||||
this.connectedPlayerSet.add(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled addons (except GameModeAddons) of this server.
|
||||
* @since 1.1
|
||||
|
@ -132,7 +154,9 @@ public class BStats {
|
|||
*/
|
||||
private void registerPlayersPerServerChart() {
|
||||
metrics.addCustomChart(new SimplePie("playersPerServer", () -> {
|
||||
int players = Bukkit.getOnlinePlayers().size();
|
||||
int players = this.connectedPlayerSet.size();
|
||||
this.connectedPlayerSet.clear();
|
||||
|
||||
if (players <= 0) return "0";
|
||||
else if (players <= 10) return "1-10";
|
||||
else if (players <= 30) return "11-30";
|
||||
|
@ -145,22 +169,41 @@ public class BStats {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sends the "flags display mode" of all the online players.
|
||||
* @since 1.6.0
|
||||
* Sends the enabled addons (except GameModeAddons) of this server as bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerFlagsDisplayModeChart() {
|
||||
metrics.addCustomChart(new AdvancedPie("flagsDisplayMode", () -> {
|
||||
private void registerAddonsBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("addonsBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getAddonsManager().getEnabledAddons().stream()
|
||||
.filter(addon -> !(addon instanceof GameModeAddon) && addon.getDescription().isMetrics())
|
||||
.forEach(addon -> values.put(addon.getDescription().getName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Sends the enabled GameModeAddons of this server as a bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerGameModeAddonsBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("gameModeAddonsBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gameModeAddon -> gameModeAddon.getDescription().isMetrics())
|
||||
.forEach(gameModeAddon -> values.put(gameModeAddon.getDescription().getName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled Hooks of this server as a bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerHooksBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("hooksBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getHooks().getHooks().forEach(hook -> values.put(hook.getPluginName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package world.bentobox.bentobox;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
|
@ -20,18 +24,24 @@ 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.DynmapHook;
|
||||
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.WorldEditHook;
|
||||
import world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook;
|
||||
import world.bentobox.bentobox.listeners.BannedCommands;
|
||||
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.PortalTeleportationListener;
|
||||
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;
|
||||
import world.bentobox.bentobox.managers.AddonsManager;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.managers.CommandsManager;
|
||||
|
@ -52,7 +62,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,7 +76,6 @@ 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;
|
||||
|
@ -95,6 +104,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
|
||||
|
@ -103,7 +114,7 @@ public class BentoBox extends JavaPlugin {
|
|||
logWarning("BentoBox is tested only on the following Spigot versions:");
|
||||
|
||||
List<String> versions = ServerCompatibility.ServerVersion.getVersions(ServerCompatibility.Compatibility.COMPATIBLE, ServerCompatibility.Compatibility.SUPPORTED)
|
||||
.stream().map(ServerCompatibility.ServerVersion::toString).collect(Collectors.toList());
|
||||
.stream().map(ServerCompatibility.ServerVersion::toString).toList();
|
||||
|
||||
logWarning(String.join(", ", versions));
|
||||
logWarning("**************************************");
|
||||
|
@ -116,7 +127,6 @@ public class BentoBox extends JavaPlugin {
|
|||
|
||||
// Save the default config from config.yml
|
||||
saveDefaultConfig();
|
||||
setInstance(this);
|
||||
// Load Flags
|
||||
flagsManager = new FlagsManager(this);
|
||||
|
||||
|
@ -134,7 +144,6 @@ public class BentoBox extends JavaPlugin {
|
|||
return;
|
||||
}
|
||||
islandsManager = new IslandsManager(this);
|
||||
ranksManager = new RanksManager();
|
||||
|
||||
// Start head getter
|
||||
headGetter = new HeadGetter(this);
|
||||
|
@ -159,7 +168,6 @@ public class BentoBox extends JavaPlugin {
|
|||
|
||||
// Load hooks
|
||||
hooksManager = new HooksManager(this);
|
||||
hooksManager.registerHook(new VaultHook());
|
||||
|
||||
// Load addons. Addons may load worlds, so they must go before islands are loaded.
|
||||
addonsManager = new AddonsManager(this);
|
||||
|
@ -172,12 +180,21 @@ public class BentoBox extends JavaPlugin {
|
|||
completeSetup(loadTime);
|
||||
} catch (Exception e) {
|
||||
fireCriticalError(e.getMessage(), "");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -199,20 +216,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();
|
||||
|
||||
|
@ -223,11 +226,19 @@ public class BentoBox extends JavaPlugin {
|
|||
// Register Multiverse hook - MV loads AFTER BentoBox
|
||||
// Make sure all worlds are already registered to Multiverse.
|
||||
hooksManager.registerHook(new MultiverseCoreHook());
|
||||
islandWorldManager.registerWorldsToMultiverse();
|
||||
hooksManager.registerHook(new MyWorldsHook());
|
||||
islandWorldManager.registerWorldsToMultiverse(true);
|
||||
|
||||
// Register additional hooks
|
||||
hooksManager.registerHook(new DynmapHook());
|
||||
hooksManager.registerHook(new WorldEditHook());
|
||||
// Register Slimefun
|
||||
hooksManager.registerHook(new SlimefunHook());
|
||||
|
||||
// Register ItemsAdder
|
||||
hooksManager.registerHook(new ItemsAdderHook(this));
|
||||
|
||||
// TODO: re-enable after implementation
|
||||
//hooksManager.registerHook(new DynmapHook());
|
||||
// TODO: re-enable after rework
|
||||
//hooksManager.registerHook(new LangUtilsHook());
|
||||
|
||||
webManager = new WebManager(this);
|
||||
|
||||
|
@ -245,6 +256,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.");
|
||||
|
@ -261,7 +274,7 @@ public class BentoBox extends JavaPlugin {
|
|||
}
|
||||
|
||||
private void fireCriticalError(String message, String error) {
|
||||
logError("*****************CRITIAL ERROR!******************");
|
||||
logError("*****************CRITICAL ERROR!******************");
|
||||
logError(message);
|
||||
logError(error + " Disabling BentoBox...");
|
||||
logError("*************************************************");
|
||||
|
@ -285,17 +298,25 @@ public class BentoBox extends JavaPlugin {
|
|||
manager.registerEvents(new PanelListenerManager(), this);
|
||||
// Standard Nether/End spawns protection
|
||||
manager.registerEvents(new StandardSpawnProtectionListener(this), this);
|
||||
// Nether portals
|
||||
manager.registerEvents(new PortalTeleportationListener(this), this);
|
||||
// Player portals
|
||||
manager.registerEvents(new PlayerTeleportListener(this), this);
|
||||
// Entity portals
|
||||
manager.registerEvents(new EntityTeleportListener(this), this);
|
||||
// End dragon blocking
|
||||
manager.registerEvents(new BlockEndDragon(this), this);
|
||||
// Banned visitor commands
|
||||
manager.registerEvents(new BannedCommands(this), this);
|
||||
// Death counter
|
||||
manager.registerEvents(new DeathListener(this), this);
|
||||
// MV unregister
|
||||
manager.registerEvents(this, this);
|
||||
// Island Delete Manager
|
||||
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
|
||||
|
@ -313,6 +334,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);
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,9 +362,10 @@ public class BentoBox extends JavaPlugin {
|
|||
* Returns the player manager
|
||||
* @return the player manager
|
||||
* @see #getPlayers()
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public PlayersManager getPlayersManager() {
|
||||
return playersManager;
|
||||
return getPlayers();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -346,9 +381,10 @@ public class BentoBox extends JavaPlugin {
|
|||
* Returns the island manager
|
||||
* @return the island manager
|
||||
* @see #getIslands()
|
||||
* @since 1.16.0
|
||||
*/
|
||||
public IslandsManager getIslandsManager() {
|
||||
return islandsManager;
|
||||
return getIslands();
|
||||
}
|
||||
|
||||
private static void setInstance(BentoBox plugin) {
|
||||
|
@ -389,9 +425,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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,6 +463,17 @@ public class BentoBox extends JavaPlugin {
|
|||
getPluginLoader().disablePlugin(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
log("Saving default panels...");
|
||||
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "island_creation_panel.yml"))) {
|
||||
log("Saving default island_creation_panel...");
|
||||
this.saveResource("panels/island_creation_panel.yml", false);
|
||||
}
|
||||
|
||||
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "language_panel.yml"))) {
|
||||
log("Saving default language_panel...");
|
||||
this.saveResource("panels/language_panel.yml", false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
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;
|
||||
|
@ -13,34 +21,15 @@ 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.")
|
||||
|
@ -52,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.")
|
||||
|
@ -66,8 +62,9 @@ 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).")
|
||||
@ConfigComment("See https://github.com/tastybento/bsbMongo/releases/.")
|
||||
@ConfigEntry(path = "general.database.type", video = "https://youtu.be/FFzCk5-y7-g")
|
||||
|
@ -107,6 +104,11 @@ public class Settings implements ConfigObject {
|
|||
@ConfigEntry(path = "general.database.max-saved-islands-per-tick")
|
||||
private int maxSavedIslandsPerTick = 20;
|
||||
|
||||
@ConfigComment("Number of active connections to the SQL database at the same time.")
|
||||
@ConfigComment("Default 10.")
|
||||
@ConfigEntry(path = "general.database.max-pool-size", since = "1.21.0")
|
||||
private int maximumPoolSize = 10;
|
||||
|
||||
@ConfigComment("Enable SSL connection to MongoDB, MariaDB, MySQL and PostgreSQL databases.")
|
||||
@ConfigEntry(path = "general.database.use-ssl", since = "1.12.0")
|
||||
private boolean useSSL = false;
|
||||
|
@ -118,6 +120,16 @@ public class Settings implements ConfigObject {
|
|||
@ConfigEntry(path = "general.database.prefix-character", since = "1.13.0")
|
||||
private String databasePrefix = "";
|
||||
|
||||
@ConfigComment("Custom connection datasource properties that will be applied to connection pool.")
|
||||
@ConfigComment("Check available values to your SQL driver implementation.")
|
||||
@ConfigComment("Example: ")
|
||||
@ConfigComment(" custom-properties: ")
|
||||
@ConfigComment(" cachePrepStmts: 'true'")
|
||||
@ConfigComment(" prepStmtCacheSize: '250'")
|
||||
@ConfigComment(" prepStmtCacheSqlLimit: '2048'")
|
||||
@ConfigEntry(path = "general.database.custom-properties", since = "1.21.0")
|
||||
private Map<String, String> customPoolProperties = new HashMap<>();
|
||||
|
||||
@ConfigComment("MongoDB client connection URI to override default connection options.")
|
||||
@ConfigComment("See: https://docs.mongodb.com/manual/reference/connection-string/")
|
||||
@ConfigEntry(path = "general.database.mongodb-connection-uri", since = "1.14.0")
|
||||
|
@ -177,6 +189,18 @@ public class Settings implements ConfigObject {
|
|||
/*
|
||||
* Island
|
||||
*/
|
||||
// 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")
|
||||
|
@ -248,6 +272,11 @@ public class Settings implements ConfigObject {
|
|||
@ConfigEntry(path = "island.clear-radius", since = "1.6.0")
|
||||
private int clearRadius = 5;
|
||||
|
||||
@ConfigComment("Minimum nether portal search radius. If this is too low, duplicate portals may appear.")
|
||||
@ConfigComment("Vanilla default is 128.")
|
||||
@ConfigEntry(path = "island.portal-search-radius", since = "1.16.2")
|
||||
private int minPortalSearchRadius = 64;
|
||||
|
||||
@ConfigComment("Number of blocks to paste per tick when pasting blueprints.")
|
||||
@ConfigComment("Smaller values will help reduce noticeable lag but will make pasting take slightly longer.")
|
||||
@ConfigComment("On the contrary, greater values will make pasting take less time, but this benefit is quickly severely impacted by the")
|
||||
|
@ -262,25 +291,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.")
|
||||
|
@ -293,6 +303,28 @@ public class Settings implements ConfigObject {
|
|||
@ConfigEntry(path = "island.deletion.keep-previous-island-on-reset", since = "1.13.0")
|
||||
private boolean keepPreviousIslandOnReset = false;
|
||||
|
||||
@ConfigComment("Toggles how the islands are deleted.")
|
||||
@ConfigComment("* If set to 'false', all islands will be deleted at once.")
|
||||
@ConfigComment(" This is fast but may cause an impact on the performance")
|
||||
@ConfigComment(" as it'll load all the chunks of the in-deletion islands.")
|
||||
@ConfigComment("* If set to 'true', the islands will be deleted one by one.")
|
||||
@ConfigComment(" This is slower but will not cause any impact on the performance.")
|
||||
@ConfigEntry(path = "island.deletion.slow-deletion", since = "1.19.1")
|
||||
private boolean slowDeletion = false;
|
||||
|
||||
@ConfigComment("By default, If the destination is not safe, the plugin will try to search for a safe spot around the destination,")
|
||||
@ConfigComment("then it will try to expand the y-coordinate up and down from the destination.")
|
||||
@ConfigComment("This setting limits how far the y-coordinate will be expanded.")
|
||||
@ConfigComment("If set to 0 or lower, the plugin will not expand the y-coordinate.")
|
||||
@ConfigEntry(path = "island.safe-spot-search-vertical-range", since = "1.19.1")
|
||||
private int safeSpotSearchVerticalRange = 400;
|
||||
|
||||
@ConfigComment("By default, if the destination is not safe, the plugin will try to search for a safe spot around the destination.")
|
||||
@ConfigComment("This allows to change the distance for searching this spot. Larger value will mean longer position search.")
|
||||
@ConfigComment("This value is also used for valid nether portal linking between dimension.")
|
||||
@ConfigEntry(path = "island.safe-spot-search-range", since = "1.21.0")
|
||||
private int safeSpotSearchRange = 16;
|
||||
|
||||
/* WEB */
|
||||
@ConfigComment("Toggle whether BentoBox can connect to GitHub to get data about updates and addons.")
|
||||
@ConfigComment("Disabling this will result in the deactivation of the update checker and of some other")
|
||||
|
@ -355,6 +387,7 @@ public class Settings implements ConfigObject {
|
|||
|
||||
/**
|
||||
* This method returns the useSSL value.
|
||||
*
|
||||
* @return the value of useSSL.
|
||||
* @since 1.12.0
|
||||
*/
|
||||
|
@ -364,6 +397,7 @@ public class Settings implements ConfigObject {
|
|||
|
||||
/**
|
||||
* This method sets the useSSL value.
|
||||
*
|
||||
* @param useSSL the useSSL new value.
|
||||
* @since 1.12.0
|
||||
*/
|
||||
|
@ -583,30 +617,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;
|
||||
}
|
||||
|
@ -678,7 +688,8 @@ public class Settings implements ConfigObject {
|
|||
* @return the clearRadius
|
||||
*/
|
||||
public int getClearRadius() {
|
||||
if (clearRadius < 0) clearRadius = 0;
|
||||
if (clearRadius < 0)
|
||||
clearRadius = 0;
|
||||
return clearRadius;
|
||||
}
|
||||
|
||||
|
@ -686,7 +697,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;
|
||||
}
|
||||
|
||||
|
@ -710,7 +722,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]", "_");
|
||||
}
|
||||
|
||||
|
@ -723,7 +736,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() {
|
||||
|
@ -732,7 +747,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) {
|
||||
|
@ -740,10 +757,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() {
|
||||
|
@ -752,6 +772,7 @@ public class Settings implements ConfigObject {
|
|||
|
||||
/**
|
||||
* Set the MongoDB client connection URI.
|
||||
*
|
||||
* @param mongodbConnectionUri connection URI.
|
||||
* @since 1.14.0
|
||||
*/
|
||||
|
@ -760,8 +781,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() {
|
||||
|
@ -769,37 +793,38 @@ 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()
|
||||
{
|
||||
return playerHeadCacheTime;
|
||||
}
|
||||
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)
|
||||
{
|
||||
this.playerHeadCacheTime = playerHeadCacheTime;
|
||||
}
|
||||
|
||||
public void setPlayerHeadCacheTime(long playerHeadCacheTime) {
|
||||
this.playerHeadCacheTime = playerHeadCacheTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is use cache server boolean.
|
||||
|
@ -807,68 +832,206 @@ public class Settings implements ConfigObject {
|
|||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the minPortalSearchRadius
|
||||
*/
|
||||
public int getMinPortalSearchRadius() {
|
||||
return minPortalSearchRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param minPortalSearchRadius the minPortalSearchRadius to set
|
||||
*/
|
||||
public void setMinPortalSearchRadius(int minPortalSearchRadius) {
|
||||
this.minPortalSearchRadius = minPortalSearchRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets safe spot search vertical range.
|
||||
*
|
||||
* @return the safe spot search vertical range
|
||||
*/
|
||||
public int getSafeSpotSearchVerticalRange() {
|
||||
return safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets safe spot search vertical range.
|
||||
*
|
||||
* @param safeSpotSearchVerticalRange the safe spot search vertical range
|
||||
*/
|
||||
public void setSafeSpotSearchVerticalRange(int safeSpotSearchVerticalRange) {
|
||||
this.safeSpotSearchVerticalRange = safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is slow deletion boolean.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean isSlowDeletion() {
|
||||
return slowDeletion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets slow deletion.
|
||||
*
|
||||
* @param slowDeletion the slow deletion
|
||||
*/
|
||||
public void setSlowDeletion(boolean slowDeletion) {
|
||||
this.slowDeletion = slowDeletion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets maximum pool size.
|
||||
*
|
||||
* @return the maximum pool size
|
||||
*/
|
||||
public int getMaximumPoolSize() {
|
||||
return maximumPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets safe spot search range.
|
||||
*
|
||||
* @return the safe spot search range
|
||||
*/
|
||||
public int getSafeSpotSearchRange() {
|
||||
return safeSpotSearchRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximum pool size.
|
||||
*
|
||||
* @param maximumPoolSize the maximum pool size
|
||||
*/
|
||||
public void setMaximumPoolSize(int maximumPoolSize) {
|
||||
this.maximumPoolSize = maximumPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets custom pool properties.
|
||||
*
|
||||
* @return the custom pool properties
|
||||
*/
|
||||
public Map<String, String> getCustomPoolProperties() {
|
||||
return customPoolProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom pool properties.
|
||||
*
|
||||
* @param customPoolProperties the custom pool properties
|
||||
*/
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,6 +21,8 @@ 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;
|
||||
|
@ -40,10 +43,12 @@ public abstract class Addon {
|
|||
private FileConfiguration config;
|
||||
private File dataFolder;
|
||||
private File file;
|
||||
private Map<String, AddonRequestHandler> requestHandlers = new HashMap<>();
|
||||
private final Map<String, AddonRequestHandler> requestHandlers = new HashMap<>();
|
||||
|
||||
protected Addon() {
|
||||
state = State.DISABLED;
|
||||
// If the config is updated, update the config.
|
||||
MultiLib.onString(getPlugin(), "bentobox-config-update", v -> this.reloadConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -273,7 +278,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());
|
||||
}
|
||||
|
@ -393,6 +400,16 @@ public abstract class Addon {
|
|||
public IslandsManager getIslands() {
|
||||
return getPlugin().getIslands();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Islands Manager
|
||||
* @return Islands manager
|
||||
* @see #getIslands()
|
||||
* @since 1.17.1
|
||||
*/
|
||||
public IslandsManager getIslandsManager() {
|
||||
return getPlugin().getIslandsManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Addon By Name
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
@ -30,17 +31,30 @@ import world.bentobox.bentobox.managers.AddonsManager;
|
|||
public class AddonClassLoader extends URLClassLoader {
|
||||
|
||||
private final Map<String, Class<?>> classes = new HashMap<>();
|
||||
private Addon addon;
|
||||
private AddonsManager loader;
|
||||
private final Addon addon;
|
||||
private final AddonsManager loader;
|
||||
|
||||
public AddonClassLoader(AddonsManager addonsManager, YamlConfiguration data, File path, ClassLoader parent)
|
||||
/**
|
||||
* For testing only
|
||||
* @param addon addon
|
||||
* @param loader Addons Manager
|
||||
* @param jarFile Jar File
|
||||
* @throws MalformedURLException exception
|
||||
*/
|
||||
protected AddonClassLoader(Addon addon, AddonsManager loader, File jarFile) throws MalformedURLException {
|
||||
super(new URL[]{jarFile.toURI().toURL()});
|
||||
this.addon = addon;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public AddonClassLoader(AddonsManager addonsManager, YamlConfiguration data, File jarFile, ClassLoader parent)
|
||||
throws InvalidAddonInheritException,
|
||||
MalformedURLException,
|
||||
InvalidDescriptionException,
|
||||
InvalidAddonDescriptionException,
|
||||
InstantiationException,
|
||||
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||
super(new URL[]{path.toURI().toURL()}, parent);
|
||||
super(new URL[]{jarFile.toURI().toURL()}, parent);
|
||||
|
||||
loader = addonsManager;
|
||||
|
||||
|
@ -55,7 +69,7 @@ public class AddonClassLoader extends URLClassLoader {
|
|||
throw new InvalidAddonFormatException("Package declaration cannot start with 'world.bentobox.bentobox'");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDescriptionException("Could not load '" + path.getName() + "' in folder '" + path.getParent() + "' - " + e.getMessage());
|
||||
throw new InvalidDescriptionException("Could not load '" + jarFile.getName() + "' in folder '" + jarFile.getParent() + "' - " + e.getMessage());
|
||||
}
|
||||
|
||||
Class<? extends Addon> addonClass;
|
||||
|
@ -78,9 +92,28 @@ public class AddonClassLoader extends URLClassLoader {
|
|||
* @throws InvalidAddonDescriptionException - if there's a bug in the addon.yml
|
||||
*/
|
||||
@NonNull
|
||||
private AddonDescription asDescription(YamlConfiguration data) throws InvalidAddonDescriptionException {
|
||||
AddonDescription.Builder builder = new AddonDescription.Builder(data.getString("main"), data.getString("name"), data.getString("version"))
|
||||
.authors(data.getString("authors"))
|
||||
public static AddonDescription asDescription(YamlConfiguration data) throws InvalidAddonDescriptionException {
|
||||
// Validate addon.yml
|
||||
if (!data.contains("main")) {
|
||||
throw new InvalidAddonDescriptionException("Missing 'main' tag. A main class must be listed in addon.yml");
|
||||
}
|
||||
if (!data.contains("name")) {
|
||||
throw new InvalidAddonDescriptionException("Missing 'name' tag. An addon name must be listed in addon.yml");
|
||||
}
|
||||
if (!data.contains("version")) {
|
||||
throw new InvalidAddonDescriptionException("Missing 'version' tag. A version must be listed in addon.yml");
|
||||
}
|
||||
if (!data.contains("authors")) {
|
||||
throw new InvalidAddonDescriptionException("Missing 'authors' tag. At least one author must be listed in addon.yml");
|
||||
}
|
||||
|
||||
AddonDescription.Builder builder = new AddonDescription.Builder(
|
||||
// Mandatory elements
|
||||
Objects.requireNonNull(data.getString("main")),
|
||||
Objects.requireNonNull(data.getString("name")),
|
||||
Objects.requireNonNull(data.getString("version")))
|
||||
.authors(Objects.requireNonNull(data.getString("authors")))
|
||||
// Optional elements
|
||||
.metrics(data.getBoolean("metrics", true))
|
||||
.repository(data.getString("repository", ""));
|
||||
|
||||
|
@ -92,7 +125,11 @@ public class AddonClassLoader extends URLClassLoader {
|
|||
if (softDepend != null) {
|
||||
builder.softDependencies(Arrays.asList(softDepend.split("\\s*,\\s*")));
|
||||
}
|
||||
builder.icon(Material.getMaterial(data.getString("icon", "PAPER")));
|
||||
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) {
|
||||
|
|
|
@ -158,23 +158,35 @@ public final class AddonDescription {
|
|||
* @return the permissions
|
||||
* @since 1.13.0
|
||||
*/
|
||||
@Nullable
|
||||
public ConfigurationSection getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private @NonNull String main;
|
||||
private @NonNull String name;
|
||||
private @NonNull String version;
|
||||
private @NonNull String description = "";
|
||||
private @NonNull List<String> authors = new ArrayList<>();
|
||||
private @NonNull List<String> dependencies = new ArrayList<>();
|
||||
private @NonNull List<String> softDependencies = new ArrayList<>();
|
||||
@NonNull
|
||||
private final String main;
|
||||
@NonNull
|
||||
private final String name;
|
||||
@NonNull
|
||||
private final String version;
|
||||
@NonNull
|
||||
private String description = "";
|
||||
@NonNull
|
||||
private List<String> authors = new ArrayList<>();
|
||||
@NonNull
|
||||
private List<String> dependencies = new ArrayList<>();
|
||||
@NonNull
|
||||
private List<String> softDependencies = new ArrayList<>();
|
||||
private boolean metrics = true;
|
||||
private @NonNull String repository = "";
|
||||
private @NonNull Material icon = Material.PAPER;
|
||||
private @NonNull String apiVersion = "1";
|
||||
private @Nullable ConfigurationSection permissions;
|
||||
@NonNull
|
||||
private String repository = "";
|
||||
@NonNull
|
||||
private Material icon = Material.PAPER;
|
||||
@NonNull
|
||||
private String apiVersion = "1";
|
||||
@Nullable
|
||||
private ConfigurationSection permissions;
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
|
@ -275,7 +287,7 @@ public final class AddonDescription {
|
|||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AddonDescription [" + (name != null ? "name=" + name + ", " : "")
|
||||
+ (version != null ? "version=" + version : "") + "]";
|
||||
return "AddonDescription [" + "name=" + name + ", "
|
||||
+ "version=" + version + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -52,9 +54,9 @@ public abstract class GameModeAddon extends Addon {
|
|||
public abstract WorldSettings getWorldSettings();
|
||||
|
||||
/**
|
||||
* Checks if a player is in any of the island worlds
|
||||
* @param loc - player to check
|
||||
* @return true if in a world or false if not
|
||||
* Checks if location is governed by this game mode
|
||||
* @param loc - location to check
|
||||
* @return true if location in covered by this addon or false if not
|
||||
*/
|
||||
public boolean inWorld(Location loc) {
|
||||
return Util.sameWorld(loc.getWorld(), islandWorld);
|
||||
|
@ -63,7 +65,7 @@ public abstract class GameModeAddon extends Addon {
|
|||
/**
|
||||
* Checks if world is governed by this game mode
|
||||
* @param world - world to check
|
||||
* @return true if in a world or false if not
|
||||
* @return true if world in covered by this addon or false if not
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public boolean inWorld(World world) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package world.bentobox.bentobox.api.addons;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
/**
|
||||
* Provides a shell for addons to become Plugins so that other Plugins
|
||||
* can tap into their API more easily. Plugin + addon = Pladdon
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
public abstract class Pladdon extends JavaPlugin {
|
||||
|
||||
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.
|
||||
* @return new instance of the addon
|
||||
*/
|
||||
public abstract Addon getAddon();
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
String parentFolder = getFile().getParent();
|
||||
if (parentFolder == null || !parentFolder.endsWith(ADDONS_FOLDER)) {
|
||||
// Jar is in the wrong place. Let's move it
|
||||
//moveJar();
|
||||
}
|
||||
}
|
||||
|
||||
protected void moveJar() {
|
||||
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());
|
||||
if (!to.exists()) {
|
||||
try {
|
||||
Files.move(getFile(), to);
|
||||
getLogger().severe(getFile().getName() + " moved successfully.");
|
||||
|
||||
} catch (IOException ex) {
|
||||
getLogger().severe("Failed to move it. " + ex.getMessage());
|
||||
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.");
|
||||
}
|
||||
} else {
|
||||
getLogger().severe("BentoBox addons folder could not be made! " + addons.getAbsolutePath());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method enables marks pladdons as enabled.
|
||||
* By default, enable status is not set because onEnable and onLoad is not triggered.
|
||||
*/
|
||||
public void setEnabled() {
|
||||
this.setEnabled(true);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public abstract class AddonException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4203162022348693854L;
|
||||
|
||||
protected AddonException(String errorMessage){
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
public class AddonRequestException extends AddonException
|
||||
{
|
||||
private static final long serialVersionUID = -5698456013070166174L;
|
||||
import java.io.Serial;
|
||||
|
||||
public AddonRequestException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
public class AddonRequestException extends AddonException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5698456013070166174L;
|
||||
|
||||
public AddonRequestException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* @since 1.11.0
|
||||
*/
|
||||
|
@ -8,6 +10,7 @@ public class InvalidAddonDescriptionException extends AddonException {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 7741502900847049986L;
|
||||
|
||||
public InvalidAddonDescriptionException(String errorMessage) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -9,6 +10,7 @@ public class InvalidAddonFormatException extends AddonException {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = 7741502900847049986L;
|
||||
|
||||
public InvalidAddonFormatException(String errorMessage) {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package world.bentobox.bentobox.api.addons.exceptions;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
public class InvalidAddonInheritException extends AddonException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5847358994397613244L;
|
||||
|
||||
public InvalidAddonInheritException(String errorMessage) {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* This package covers Addon exceptions
|
||||
* <p>
|
||||
* These exceptions can be thrown when the addon is loaded.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
* @author tastybento
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons.exceptions;
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* This package covers all addon-specific API
|
||||
* <p>
|
||||
* The Addon class and the associated Pladdon are like Bukkit plugins
|
||||
* but contain extra API specific for BentoBox games.
|
||||
* </p>
|
||||
*
|
||||
* @since 1.0
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons;
|
|
@ -20,7 +20,7 @@ public class AddonRequestBuilder
|
|||
{
|
||||
private String addonName;
|
||||
private String requestLabel;
|
||||
private Map<String, Object> metaData = new HashMap<>();
|
||||
private final Map<String, Object> metaData = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Define the addon you wish to request.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* API to enable plugins to request data from addons.
|
||||
* <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>
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
package world.bentobox.bentobox.api.addons.request;
|
|
@ -11,7 +11,6 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
|
@ -27,13 +26,16 @@ 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;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* BSB composite command
|
||||
* BentoBox composite command. Provides an abstract implementation of a command.
|
||||
*
|
||||
* @author tastybento
|
||||
* @author Poslovitch
|
||||
*/
|
||||
|
@ -48,23 +50,40 @@ 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
|
||||
*/
|
||||
private boolean configurableRankCommand = false;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
|
@ -78,12 +97,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
/**
|
||||
* Map of sub commands
|
||||
*/
|
||||
private Map<String, CompositeCommand> subCommands;
|
||||
private final Map<String, CompositeCommand> subCommands;
|
||||
|
||||
/**
|
||||
* Map of aliases for subcommands
|
||||
*/
|
||||
private Map<String, CompositeCommand> subCommandAliases;
|
||||
private final Map<String, CompositeCommand> subCommandAliases;
|
||||
/**
|
||||
* The command chain from the very top, e.g., island team promote
|
||||
*/
|
||||
|
@ -93,33 +112,35 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
* The prefix to be used in this command
|
||||
*/
|
||||
@Nullable
|
||||
private String permissionPrefix;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The addon creating this command, if any
|
||||
*/
|
||||
private Addon addon;
|
||||
private final Addon addon;
|
||||
|
||||
/**
|
||||
* The top level label
|
||||
*/
|
||||
private String topLabel;
|
||||
private final String topLabel;
|
||||
|
||||
/**
|
||||
* Cool down tracker
|
||||
*/
|
||||
private Map<String, Map<String, Long>> cooldowns = new HashMap<>();
|
||||
private final Map<String, Map<String, Long>> cooldowns = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
@ -144,24 +165,26 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
|
||||
// Run setup
|
||||
setup();
|
||||
if (!getSubCommand("help").isPresent() && !label.equals("help")) {
|
||||
if (getSubCommand("help").isEmpty() && !label.equals("help")) {
|
||||
new DefaultHelpCommand(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
@ -169,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();
|
||||
|
@ -182,13 +207,13 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
this.parent = parent;
|
||||
subCommandLevel = parent.getLevel() + 1;
|
||||
// Add this sub-command to the parent
|
||||
parent.getSubCommands().put(label, this);
|
||||
parent.getSubCommands().put(label.toLowerCase(java.util.Locale.ENGLISH), this);
|
||||
setAliases(new ArrayList<>(Arrays.asList(aliases)));
|
||||
subCommands = new LinkedHashMap<>();
|
||||
subCommandAliases = new LinkedHashMap<>();
|
||||
// Add aliases to the parent for this command
|
||||
for (String alias : aliases) {
|
||||
parent.getSubCommandAliases().put(alias, this);
|
||||
parent.getSubCommandAliases().put(alias.toLowerCase(java.util.Locale.ENGLISH), this);
|
||||
}
|
||||
setUsage("");
|
||||
// Inherit permission prefix
|
||||
|
@ -204,11 +229,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
p = p.getParent();
|
||||
index++;
|
||||
}
|
||||
setDescription(COMMANDS + reference.toString() + ".description");
|
||||
setParametersHelp(COMMANDS + reference.toString() + ".parameters");
|
||||
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 (!getSubCommand("help").isPresent() && !label.equals("help")) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -218,46 +244,46 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
* subcommands until it finds the right object and then runs execute on it.
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String label, String[] args) {
|
||||
public boolean execute(@NonNull CommandSender sender, @NonNull String label, String[] args) {
|
||||
// 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;
|
||||
}
|
||||
// Check perms, but only if this isn't the console
|
||||
if (user.isPlayer() && !user.isOp() && getPermission() != null && !getPermission().isEmpty() && !user.hasPermission(getPermission())) {
|
||||
user.sendMessage("general.errors.no-permission", TextVariables.PERMISSION, getPermission());
|
||||
|
||||
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
|
||||
|
@ -266,8 +292,29 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
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.
|
||||
*
|
||||
* @param user User who permission must be checked.
|
||||
* @return {@code true} is user can execute given command, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
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())) {
|
||||
user.sendMessage("general.errors.no-permission", TextVariables.PERMISSION, this.getPermission());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Recursive permission check to find if user has access to the parent command.
|
||||
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
|
||||
*/
|
||||
|
@ -278,7 +325,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
// get the subcommand corresponding to the arg
|
||||
if (subCommand.hasSubCommands()) {
|
||||
Optional<CompositeCommand> sub = subCommand.getSubCommand(arg);
|
||||
if (!sub.isPresent()) {
|
||||
if (sub.isEmpty()) {
|
||||
return subCommand;
|
||||
}
|
||||
// Step down one
|
||||
|
@ -296,6 +343,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
|
||||
/**
|
||||
* Convenience method to get the island manager
|
||||
*
|
||||
* @return IslandsManager
|
||||
*/
|
||||
protected IslandsManager getIslands() {
|
||||
|
@ -303,8 +351,17 @@ 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.
|
||||
* Convenience method to get the island manager
|
||||
*
|
||||
* @return IslandsManager
|
||||
*/
|
||||
protected IslandsManager getIslandsManager() {
|
||||
return plugin.getIslandsManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
@ -318,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() {
|
||||
|
@ -345,6 +408,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
|
||||
/**
|
||||
* Convenience method to get the player manager
|
||||
*
|
||||
* @return PlayersManager
|
||||
*/
|
||||
protected PlayersManager getPlayers() {
|
||||
|
@ -352,17 +416,19 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
}
|
||||
|
||||
@Override
|
||||
public BentoBox getPlugin() {
|
||||
public @NonNull BentoBox getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the island worlds manager
|
||||
*
|
||||
* @return island worlds manager
|
||||
*/
|
||||
public IslandWorldManager getIWM() {
|
||||
return plugin.getIWM();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Settings object
|
||||
*/
|
||||
|
@ -372,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
|
||||
*/
|
||||
|
@ -395,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)
|
||||
*/
|
||||
|
@ -410,24 +480,14 @@ 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 String getUsage() {
|
||||
public @NonNull String getUsage() {
|
||||
return "/" + usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this command has a specific sub command.
|
||||
*
|
||||
* @param subCommand - sub command
|
||||
* @return true if this command has this sub command
|
||||
*/
|
||||
|
@ -437,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() {
|
||||
|
@ -444,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)
|
||||
*/
|
||||
|
@ -456,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) {
|
||||
|
@ -466,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() {
|
||||
|
@ -473,20 +540,23 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience method to check if a user is a player
|
||||
* @param user - the User
|
||||
* @return true if sender is a player
|
||||
* Check if this command is only for consoles.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
protected boolean isPlayer(User user) {
|
||||
return user.getPlayer() != null;
|
||||
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.
|
||||
* 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) {
|
||||
|
@ -494,61 +564,86 @@ 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.
|
||||
*
|
||||
* @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/>
|
||||
* <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}.
|
||||
*/
|
||||
@Override
|
||||
public Command setDescription(String description) {
|
||||
public @NonNull Command setDescription(@NonNull String description) {
|
||||
super.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -556,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -575,7 +673,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
* This creates the full linking chain of commands
|
||||
*/
|
||||
@Override
|
||||
public Command setUsage(String usage) {
|
||||
public @NonNull Command setUsage(@NonNull String usage) {
|
||||
// Go up the chain
|
||||
CompositeCommand parentCommand = getParent();
|
||||
StringBuilder u = new StringBuilder().append(getLabel()).append(" ").append(usage);
|
||||
|
@ -590,24 +688,31 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<String> tabComplete(final CommandSender sender, final 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(() -> new ArrayList<>()));
|
||||
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.
|
||||
|
@ -618,31 +723,44 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
/* ------------ */
|
||||
|
||||
String lastArg = args.length != 0 ? args[args.length - 1] : "";
|
||||
return Util.tabLimit(options, lastArg).stream().sorted().collect(Collectors.toList());
|
||||
return Util.tabLimit(options, lastArg).stream().sorted().toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).collect(Collectors.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);
|
||||
return command.getSubCommand("help")
|
||||
.map(helpCommand -> helpCommand.execute(user, helpCommand.getLabel(), new ArrayList<>())).orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -653,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
|
||||
|
@ -663,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() {
|
||||
|
@ -678,6 +799,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the parental addon
|
||||
*
|
||||
* @return the addon
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -694,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 * 1000);
|
||||
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 * 1000);
|
||||
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
|
||||
*/
|
||||
|
@ -725,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
|
||||
*/
|
||||
|
@ -735,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
|
||||
|
@ -745,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<>());
|
||||
|
@ -761,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;
|
||||
}
|
||||
|
@ -780,8 +913,29 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
|
|||
this.configurableRankCommand = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default command rank.
|
||||
*
|
||||
* @param rank the rank
|
||||
* @since 1.20.0
|
||||
*/
|
||||
public void setDefaultCommandRank(int rank) {
|
||||
this.defaultCommandRank = rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default command rank.
|
||||
*
|
||||
* @return the default command rank
|
||||
* @since 1.20.0
|
||||
*/
|
||||
public int getDefaultCommandRank() {
|
||||
return this.defaultCommandRank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a command is hidden
|
||||
*
|
||||
* @return the hidden
|
||||
* @since 1.13.0
|
||||
*/
|
||||
|
@ -791,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
|
||||
*/
|
||||
|
@ -20,7 +21,7 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
|||
/**
|
||||
* Confirmation tracker
|
||||
*/
|
||||
private static Map<User, Confirmer> toBeConfirmed = new HashMap<>();
|
||||
private static final Map<User, Confirmer> toBeConfirmed = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Top level command
|
||||
|
@ -44,9 +45,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param parent
|
||||
* @param label
|
||||
* @param aliases
|
||||
* @param parent - parent command
|
||||
* @param label - command label
|
||||
* @param aliases - command aliases
|
||||
*/
|
||||
protected ConfirmableCommand(CompositeCommand parent, String label, String... aliases) {
|
||||
super(parent, label, aliases);
|
||||
|
@ -61,9 +62,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
|||
public void askConfirmation(User user, String message, Runnable confirmed) {
|
||||
// Check for pending confirmations
|
||||
if (toBeConfirmed.containsKey(user)) {
|
||||
if (toBeConfirmed.get(user).getTopLabel().equals(getTopLabel()) && toBeConfirmed.get(user).getLabel().equalsIgnoreCase(getLabel())) {
|
||||
toBeConfirmed.get(user).getTask().cancel();
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).getRunnable());
|
||||
if (toBeConfirmed.get(user).topLabel().equals(getTopLabel()) && toBeConfirmed.get(user).label().equalsIgnoreCase(getLabel())) {
|
||||
toBeConfirmed.get(user).task().cancel();
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeConfirmed.get(user).runnable());
|
||||
toBeConfirmed.remove(user);
|
||||
return;
|
||||
} else {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -97,51 +99,9 @@ public abstract class ConfirmableCommand extends CompositeCommand {
|
|||
}
|
||||
|
||||
/**
|
||||
* Holds the data to run once the confirmation is given
|
||||
* @author tastybento
|
||||
* Record to hold the data to run once the confirmation is given
|
||||
*
|
||||
*/
|
||||
private class Confirmer {
|
||||
private final String topLabel;
|
||||
private final String label;
|
||||
private final Runnable runnable;
|
||||
private final BukkitTask task;
|
||||
|
||||
/**
|
||||
* @param label - command label
|
||||
* @param runnable - runnable to run when confirmed
|
||||
* @param task - task ID to cancel when confirmed
|
||||
*/
|
||||
Confirmer(String topLabel, String label, Runnable runnable, BukkitTask task) {
|
||||
this.topLabel = topLabel;
|
||||
this.label = label;
|
||||
this.runnable = runnable;
|
||||
this.task = task;
|
||||
}
|
||||
/**
|
||||
* @return the topLabel
|
||||
*/
|
||||
public String getTopLabel() {
|
||||
return topLabel;
|
||||
}
|
||||
/**
|
||||
* @return the label
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
/**
|
||||
* @return the runnable
|
||||
*/
|
||||
public Runnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
/**
|
||||
* @return the task
|
||||
*/
|
||||
public BukkitTask getTask() {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
private record Confirmer (String topLabel, String label, Runnable runnable, BukkitTask task) { }
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@ import java.util.UUID;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import world.bentobox.bentobox.api.addons.Addon;
|
||||
|
@ -24,21 +26,34 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
|||
/**
|
||||
* User monitor map
|
||||
*/
|
||||
private static Map<UUID, DelayedCommand> toBeMonitored = new HashMap<>();
|
||||
private static final Map<UUID, DelayedCommand> toBeMonitored = new HashMap<>();
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerMove(PlayerMoveEvent e) {
|
||||
UUID uuid = e.getPlayer().getUniqueId();
|
||||
// Only check x,y,z
|
||||
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).getLocation().toVector())) {
|
||||
// Player moved
|
||||
toBeMonitored.get(uuid).getTask().cancel();
|
||||
toBeMonitored.remove(uuid);
|
||||
// Player has another outstanding confirmation request that will now be cancelled
|
||||
User.getInstance(e.getPlayer()).notify("commands.delay.moved-so-command-cancelled");
|
||||
if (toBeMonitored.containsKey(uuid) && !e.getTo().toVector().equals(toBeMonitored.get(uuid).location().toVector())) {
|
||||
moved(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void moved(UUID uuid) {
|
||||
// Player moved
|
||||
toBeMonitored.get(uuid).task().cancel();
|
||||
toBeMonitored.remove(uuid);
|
||||
// Player has another outstanding confirmation request that will now be cancelled
|
||||
User.getInstance(uuid).notify("commands.delay.moved-so-command-cancelled");
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerTeleport(PlayerTeleportEvent e) {
|
||||
UUID uuid = e.getPlayer().getUniqueId();
|
||||
if (toBeMonitored.containsKey(uuid)) {
|
||||
moved(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Top level command
|
||||
* @param addon - addon creating the command
|
||||
|
@ -63,9 +78,9 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
|||
|
||||
/**
|
||||
*
|
||||
* @param parent
|
||||
* @param label
|
||||
* @param aliases
|
||||
* @param parent - parent command
|
||||
* @param label - command label
|
||||
* @param aliases - command aliases
|
||||
*/
|
||||
protected DelayedTeleportCommand(CompositeCommand parent, String label, String... aliases) {
|
||||
super(parent, label, aliases);
|
||||
|
@ -88,7 +103,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
|||
UUID uuid = user.getUniqueId();
|
||||
if (toBeMonitored.containsKey(uuid)) {
|
||||
// A double request - clear out the old one
|
||||
toBeMonitored.get(uuid).getTask().cancel();
|
||||
toBeMonitored.get(uuid).task().cancel();
|
||||
toBeMonitored.remove(uuid);
|
||||
// Player has another outstanding confirmation request that will now be cancelled
|
||||
user.sendMessage("commands.delay.previous-command-cancelled");
|
||||
|
@ -101,7 +116,7 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
|||
user.sendMessage("commands.delay.stand-still", "[seconds]", String.valueOf(getSettings().getDelayTime()));
|
||||
// Set up the run task
|
||||
BukkitTask task = Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).getRunnable());
|
||||
Bukkit.getScheduler().runTask(getPlugin(), toBeMonitored.get(uuid).runnable());
|
||||
toBeMonitored.remove(uuid);
|
||||
}, getPlugin().getSettings().getDelayTime() * 20L);
|
||||
|
||||
|
@ -120,42 +135,8 @@ public abstract class DelayedTeleportCommand extends CompositeCommand implements
|
|||
|
||||
/**
|
||||
* Holds the data to run once the confirmation is given
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
private class DelayedCommand {
|
||||
private final Runnable runnable;
|
||||
private final BukkitTask task;
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* @param runnable - runnable to run when confirmed
|
||||
* @param task - task ID to cancel when confirmed
|
||||
* @param location - location
|
||||
*/
|
||||
DelayedCommand(Runnable runnable, BukkitTask task, Location location) {
|
||||
this.runnable = runnable;
|
||||
this.task = task;
|
||||
this.location = location;
|
||||
}
|
||||
/**
|
||||
* @return the runnable
|
||||
*/
|
||||
public Runnable getRunnable() {
|
||||
return runnable;
|
||||
}
|
||||
/**
|
||||
* @return the task
|
||||
*/
|
||||
public BukkitTask getTask() {
|
||||
return task;
|
||||
}
|
||||
/**
|
||||
* @return the location
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
private record DelayedCommand(Runnable runnable, BukkitTask task, Location location) {}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,97 +36,157 @@ 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;
|
||||
}
|
||||
if (!getIslands().hasIsland(getWorld(), targetUUID)) {
|
||||
// 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) && getIslands().getOwner(getWorld(), targetUUID).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) {
|
||||
// If args are not right, show help
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// 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.isOnline()) {
|
||||
// Execute commands when leaving
|
||||
Util.runCommands(user, getIWM().getOnLeaveCommands(getWorld()), "leave");
|
||||
// Remove money inventory etc.
|
||||
if (getIWM().isOnLeaveResetEnderChest(getWorld())) {
|
||||
target.getPlayer().getEnderChest().clear();
|
||||
}
|
||||
if (getIWM().isOnLeaveResetInventory(getWorld())) {
|
||||
target.getPlayer().getInventory().clear();
|
||||
}
|
||||
if (getSettings().isUseEconomy() && getIWM().isOnLeaveResetMoney(getWorld())) {
|
||||
getPlugin().getVault().ifPresent(vault -> vault.withdraw(target, vault.getBalance(target)));
|
||||
}
|
||||
// Reset the health
|
||||
if (getIWM().isOnLeaveResetHealth(getWorld())) {
|
||||
Util.resetHealth(target.getPlayer());
|
||||
}
|
||||
for (Island oldIsland : getIslands().getIslands(getWorld(), targetUUID)) {
|
||||
deleteIsland(user, oldIsland);
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
|
||||
// Reset the hunger
|
||||
if (getIWM().isOnLeaveResetHunger(getWorld())) {
|
||||
target.getPlayer().setFoodLevel(20);
|
||||
}
|
||||
private void cleanUp(User target) {
|
||||
// Remove money inventory etc.
|
||||
if (getIWM().isOnLeaveResetEnderChest(getWorld())) {
|
||||
target.getPlayer().getEnderChest().clear();
|
||||
}
|
||||
if (getIWM().isOnLeaveResetInventory(getWorld())) {
|
||||
target.getPlayer().getInventory().clear();
|
||||
}
|
||||
if (getSettings().isUseEconomy() && getIWM().isOnLeaveResetMoney(getWorld())) {
|
||||
getPlugin().getVault().ifPresent(vault -> vault.withdraw(target, vault.getBalance(target)));
|
||||
}
|
||||
// Reset the health
|
||||
if (getIWM().isOnLeaveResetHealth(getWorld())) {
|
||||
Util.resetHealth(target.getPlayer());
|
||||
}
|
||||
|
||||
// Reset the XP
|
||||
if (getIWM().isOnLeaveResetXP(getWorld())) {
|
||||
target.getPlayer().setTotalExperience(0);
|
||||
}
|
||||
// Reset the hunger
|
||||
if (getIWM().isOnLeaveResetHunger(getWorld())) {
|
||||
target.getPlayer().setFoodLevel(20);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Execute commands when leaving
|
||||
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));
|
||||
}
|
||||
vector = oldIsland.getCenter().toVector();
|
||||
getIslands().deleteIsland(oldIsland, true, targetUUID);
|
||||
}
|
||||
getPlayers().clearHomeLocations(getWorld(), targetUUID);
|
||||
if (vector == null) {
|
||||
user.sendMessage("general.success");
|
||||
} else {
|
||||
user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ, Util.xyz(vector));
|
||||
// Add homes. Homes do not need an island specified
|
||||
island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
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;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Deletes all named homes from an island
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
public class AdminDeleteHomesCommand extends ConfirmableCommand {
|
||||
|
||||
public AdminDeleteHomesCommand(CompositeCommand parent) {
|
||||
super(parent, "deletehomes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.deletehomes");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.deletehomes.parameters");
|
||||
setDescription("commands.admin.deletehomes.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// 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;
|
||||
}
|
||||
// Get island
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
// Confirm
|
||||
askConfirmation(user, user.getTranslation("commands.admin.deletehomes.warning"), () -> deleteHomes(user, island));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean deleteHomes(User user, Island island) {
|
||||
island.removeHomes();
|
||||
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.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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package world.bentobox.bentobox.api.commands.admin;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -17,6 +16,7 @@ import world.bentobox.bentobox.managers.RanksManager;
|
|||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Tells the rank of the player
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
|
@ -83,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;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class AdminGetrankCommand extends CompositeCommand {
|
|||
return Optional.empty();
|
||||
}
|
||||
String lastArg = args.get(args.size() - 1);
|
||||
List<String> options = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
|
||||
List<String> options = Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,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.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminInfoCommand extends CompositeCommand {
|
||||
|
@ -34,10 +35,8 @@ public class AdminInfoCommand extends CompositeCommand {
|
|||
}
|
||||
// If there are no args, then the player wants info on the island at this location
|
||||
if (args.isEmpty()) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.showInfo(user)).orElse(false)) {
|
||||
user.sendMessage("commands.admin.info.no-island");
|
||||
return false;
|
||||
}
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user, getAddon()), () ->
|
||||
user.sendMessage("commands.admin.info.no-island"));
|
||||
return true;
|
||||
}
|
||||
// Get target player
|
||||
|
@ -49,10 +48,7 @@ public class AdminInfoCommand extends CompositeCommand {
|
|||
// Show info for this player
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (island != null) {
|
||||
island.showInfo(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");
|
||||
|
|
|
@ -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) : "";
|
||||
|
|
|
@ -3,7 +3,6 @@ package world.bentobox.bentobox.api.commands.admin;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
|
@ -20,13 +19,13 @@ import world.bentobox.bentobox.util.Util;
|
|||
*/
|
||||
public class AdminResetFlagsCommand extends ConfirmableCommand {
|
||||
|
||||
private List<String> options;
|
||||
private final List<String> options;
|
||||
|
||||
public AdminResetFlagsCommand(CompositeCommand parent) {
|
||||
super(parent, "resetflags");
|
||||
options = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.filter(f -> f.getType().equals(Type.PROTECTION) || f.getType().equals(Type.SETTING))
|
||||
.map(Flag::getID).collect(Collectors.toList());
|
||||
.map(Flag::getID).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* This command resets players island name.
|
||||
* @author BONNe
|
||||
*/
|
||||
public class AdminResetNameCommand extends CompositeCommand
|
||||
{
|
||||
/**
|
||||
* Default constructor.
|
||||
* @param command Parent command.
|
||||
*/
|
||||
public AdminResetNameCommand(CompositeCommand command)
|
||||
{
|
||||
super(command, "resetname");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.setPermission("mod.resetname");
|
||||
this.setOnlyPlayer(true);
|
||||
this.setDescription("commands.admin.resetname.description");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (args.size() == 1)
|
||||
{
|
||||
UUID playerUUID = Util.getUUID(args.get(0));
|
||||
|
||||
if (playerUUID == null)
|
||||
{
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
this.island = this.getIslandsManager().getIsland(this.getWorld(), playerUUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.island = this.getIslandsManager().getIslandAt(user.getLocation()).orElse(null);
|
||||
}
|
||||
|
||||
if (this.island == null)
|
||||
{
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
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 (this.island == null)
|
||||
{
|
||||
this.showHelp(this, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resets the island name
|
||||
this.island.setName(null);
|
||||
user.sendMessage("commands.admin.resetname.success", TextVariables.NAME, this.getPlayers().getName(this.island.getOwner()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param user the {@link User} who is executing this command.
|
||||
* @param alias alias for command
|
||||
* @param args command arguments
|
||||
* @return Optional of possible values.
|
||||
*/
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
// Return the player names
|
||||
|
||||
if (args.size() == 1)
|
||||
{
|
||||
return Optional.of(Util.getOnlinePlayerList(user));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Island which name must be changed.
|
||||
*/
|
||||
@Nullable
|
||||
private Island island;
|
||||
}
|
|
@ -50,7 +50,7 @@ public class AdminSetProtectionCenterCommand extends ConfirmableCommand
|
|||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() == 3) {
|
||||
// Get location
|
||||
targetLoc = getLocation(user, args);
|
||||
targetLoc = getLocation(args);
|
||||
} else {
|
||||
targetLoc = new Location(getWorld(), user.getLocation().getBlockX(), user.getLocation().getBlockY(), user.getLocation().getBlockZ());
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class AdminSetProtectionCenterCommand extends ConfirmableCommand
|
|||
return false;
|
||||
}
|
||||
Optional<Island> optionalIsland = getIslands().getIslandAt(targetLoc);
|
||||
if (!optionalIsland.isPresent()) {
|
||||
if (optionalIsland.isEmpty()) {
|
||||
user.sendMessage("commands.admin.setspawnpoint.no-island-here");
|
||||
return false;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class AdminSetProtectionCenterCommand extends ConfirmableCommand
|
|||
return true;
|
||||
}
|
||||
|
||||
private Location getLocation(User user, List<String> args) {
|
||||
private Location getLocation(List<String> args) {
|
||||
try {
|
||||
int x = Integer.parseInt(args.get(0));
|
||||
int y = Integer.parseInt(args.get(1));
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ 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.Nullable;
|
||||
|
||||
|
@ -25,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");
|
||||
|
@ -37,7 +35,6 @@ public class AdminSetrankCommand extends CompositeCommand {
|
|||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.setrank.parameters");
|
||||
setDescription("commands.admin.setrank.description");
|
||||
rm = getPlugin().getRanksManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,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) {
|
||||
|
@ -101,6 +98,10 @@ public class AdminSetrankCommand extends CompositeCommand {
|
|||
} else {
|
||||
island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
}
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
int currentRank = island.getRank(target);
|
||||
island.setRank(target, rankValue);
|
||||
IslandEvent.builder()
|
||||
|
@ -118,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;
|
||||
}
|
||||
|
@ -133,10 +134,10 @@ 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())).collect(Collectors.toList()));
|
||||
.map(entry -> user.getTranslation(entry.getKey())).toList());
|
||||
}
|
||||
|
||||
// Return the player names again for the optional island owner argument
|
||||
|
|
|
@ -65,10 +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);
|
||||
getPlayers().clearHomeLocations(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());
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Locale;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
@ -17,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;
|
||||
|
@ -34,33 +32,37 @@ import world.bentobox.bentobox.util.Util;
|
|||
*/
|
||||
public class AdminSettingsCommand extends CompositeCommand {
|
||||
|
||||
private final List<String> PROTECTION_FLAG_NAMES;
|
||||
private static final String SPAWN_ISLAND = "spawn-island";
|
||||
private List<String> protectionFlagNames;
|
||||
private Island island;
|
||||
private final List<String> SETTING_FLAG_NAMES;
|
||||
private List<String> WORLD_SETTING_FLAG_NAMES;
|
||||
private @NonNull Optional<Flag> flag;
|
||||
private List<String> settingFlagNames;
|
||||
private List<String> worldSettingFlagNames;
|
||||
private @NonNull Optional<Flag> flag = Optional.empty();
|
||||
private boolean activeState;
|
||||
private int rank;
|
||||
private final GameModeAddon gameMode;
|
||||
|
||||
public AdminSettingsCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "settings", "flags", "options");
|
||||
// make constants
|
||||
GameModeAddon gameMode = getPlugin().getIWM().getAddon(getWorld()).orElse(null);
|
||||
PROTECTION_FLAG_NAMES = getPlugin().getFlagsManager().getFlags().stream()
|
||||
gameMode = getPlugin().getIWM().getAddon(getWorld()).orElse(null);
|
||||
}
|
||||
|
||||
private void makeLists() {
|
||||
protectionFlagNames = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.filter(f -> f.getType().equals(Type.PROTECTION))
|
||||
.filter(f -> f.getGameModes().isEmpty() || gameMode == null || f.getGameModes().contains(gameMode))
|
||||
.map(Flag::getID)
|
||||
.collect(Collectors.toList());
|
||||
SETTING_FLAG_NAMES = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.toList();
|
||||
settingFlagNames = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.filter(f -> f.getType().equals(Type.SETTING))
|
||||
.filter(f -> f.getGameModes().isEmpty() || gameMode == null || f.getGameModes().contains(gameMode))
|
||||
.map(Flag::getID)
|
||||
.collect(Collectors.toList());
|
||||
WORLD_SETTING_FLAG_NAMES = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.toList();
|
||||
worldSettingFlagNames = getPlugin().getFlagsManager().getFlags().stream()
|
||||
.filter(f -> f.getType().equals(Type.WORLD_SETTING))
|
||||
.filter(f -> f.getGameModes().isEmpty() || gameMode == null || f.getGameModes().contains(gameMode))
|
||||
.map(Flag::getID)
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,12 +80,16 @@ public class AdminSettingsCommand extends CompositeCommand {
|
|||
}
|
||||
if (args.size() > 1) {
|
||||
// Command
|
||||
return checkSyntax(user, args);
|
||||
return checkSyntax(user, args);
|
||||
}
|
||||
return getIsland(user, args);
|
||||
}
|
||||
|
||||
private boolean getIsland(User user, List<String> args) {
|
||||
if (args.get(0).equalsIgnoreCase(SPAWN_ISLAND) && getIslands().getSpawn(getWorld()).isPresent()) {
|
||||
island = getIslands().getSpawn(getWorld()).get();
|
||||
return true;
|
||||
}
|
||||
// Get target player
|
||||
@Nullable UUID targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
|
@ -100,49 +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) {
|
||||
if (args.size() == 2) {
|
||||
// Should be a world setting
|
||||
// If world settings, then active/disabled, otherwise player flags
|
||||
if (WORLD_SETTING_FLAG_NAMES.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;
|
||||
}
|
||||
this.makeLists();
|
||||
|
||||
if (!SETTING_FLAG_NAMES.contains(args.get(1).toUpperCase(Locale.ENGLISH))
|
||||
&& !PROTECTION_FLAG_NAMES.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.
|
||||
|
@ -151,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
|
||||
|
@ -168,7 +191,7 @@ public class AdminSettingsCommand extends CompositeCommand {
|
|||
String disabled = ChatColor.stripColor(user.getTranslation("protection.panel.flag-item.setting-disabled"));
|
||||
if (!string.equalsIgnoreCase(active) && !string.equalsIgnoreCase(disabled)) {
|
||||
user.sendMessage("commands.admin.settings.unknown-setting", TextVariables.NAME, string);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
activeState = string.equalsIgnoreCase(active);
|
||||
return true;
|
||||
|
@ -180,19 +203,16 @@ public class AdminSettingsCommand extends CompositeCommand {
|
|||
// Command line setting
|
||||
flag.ifPresent(f -> {
|
||||
switch (f.getType()) {
|
||||
case PROTECTION:
|
||||
case PROTECTION -> {
|
||||
island.setFlag(f, rank);
|
||||
getIslands().save(island);
|
||||
break;
|
||||
case SETTING:
|
||||
}
|
||||
case SETTING -> {
|
||||
island.setSettingsFlag(f, activeState);
|
||||
getIslands().save(island);
|
||||
break;
|
||||
case WORLD_SETTING:
|
||||
f.setSetting(getWorld(), activeState);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case WORLD_SETTING -> f.setSetting(getWorld(), activeState);
|
||||
default -> {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
user.sendMessage("general.success");
|
||||
|
@ -200,15 +220,14 @@ public class AdminSettingsCommand extends CompositeCommand {
|
|||
}
|
||||
// GUI requires in-game
|
||||
if (!user.isPlayer()) {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
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)
|
||||
|
@ -219,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();
|
||||
|
@ -229,39 +248,37 @@ public class AdminSettingsCommand extends CompositeCommand {
|
|||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
// Update with the latest lists
|
||||
this.makeLists();
|
||||
String active = ChatColor.stripColor(user.getTranslation("protection.panel.flag-item.setting-active"));
|
||||
String disabled = ChatColor.stripColor(user.getTranslation("protection.panel.flag-item.setting-disabled"));
|
||||
List<String> options = new ArrayList<>();
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
if (args.size() == 2) {
|
||||
// Player names or world settings
|
||||
// Player names or world settings
|
||||
options = Util.tabLimit(Util.getOnlinePlayerList(user), lastArg);
|
||||
options.addAll(WORLD_SETTING_FLAG_NAMES);
|
||||
options.addAll(worldSettingFlagNames);
|
||||
if (getIslands().getSpawn(getWorld()).isPresent()) {
|
||||
options.add(SPAWN_ISLAND);
|
||||
}
|
||||
} else if (args.size() == 3) {
|
||||
// If world settings, then active/disabled, otherwise player flags
|
||||
if (WORLD_SETTING_FLAG_NAMES.contains(args.get(1).toUpperCase(Locale.ENGLISH))) {
|
||||
if (worldSettingFlagNames.contains(args.get(1).toUpperCase(Locale.ENGLISH))) {
|
||||
options = Arrays.asList(active, disabled);
|
||||
} else {
|
||||
// Flag IDs
|
||||
options.addAll(PROTECTION_FLAG_NAMES);
|
||||
options.addAll(SETTING_FLAG_NAMES);
|
||||
options.addAll(protectionFlagNames);
|
||||
options.addAll(settingFlagNames);
|
||||
}
|
||||
} 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:
|
||||
return getPlugin().getRanksManager()
|
||||
.getRanks().entrySet().stream()
|
||||
.filter(en -> en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK)
|
||||
.map(Entry::getKey)
|
||||
.map(user::getTranslation).collect(Collectors.toList());
|
||||
case SETTING:
|
||||
return Arrays.asList(active, disabled);
|
||||
default:
|
||||
return Collections.<String>emptyList();
|
||||
|
||||
}
|
||||
options = getPlugin().getFlagsManager().getFlag(args.get(2).toUpperCase(Locale.ENGLISH)).map(f -> switch (f.getType()) {
|
||||
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();
|
||||
case SETTING -> Arrays.asList(active, disabled);
|
||||
default -> Collections.<String>emptyList();
|
||||
}).orElse(Collections.emptyList());
|
||||
}
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
|
|
|
@ -44,15 +44,15 @@ public class AdminSwitchCommand extends ConfirmableCommand {
|
|||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
boolean switchState = user.getMetaData("AdminCommandSwitch").map(MetaDataValue::asBoolean).orElse(false);
|
||||
boolean switchState = user.getMetaData(META_TAG).map(MetaDataValue::asBoolean).orElse(false);
|
||||
if (switchState) {
|
||||
// Turn off
|
||||
user.putMetaData("AdminCommandSwitch", new MetaDataValue(false));
|
||||
user.putMetaData(META_TAG, new MetaDataValue(false));
|
||||
user.sendMessage("commands.admin.switch.adding"); // Adding protection bypass
|
||||
user.sendMessage("general.success");
|
||||
} else {
|
||||
// Turn on
|
||||
user.putMetaData("AdminCommandSwitch", new MetaDataValue(true));
|
||||
user.putMetaData(META_TAG, new MetaDataValue(true));
|
||||
user.sendMessage("commands.admin.switch.removing"); // Removing protection bypass
|
||||
user.sendMessage("general.success");
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
Integer n = Integer.valueOf(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,24 +1,36 @@
|
|||
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.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 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
|
||||
|
@ -38,12 +50,12 @@ public class AdminTeleportCommand extends CompositeCommand {
|
|||
|
||||
@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;
|
||||
}
|
||||
|
@ -59,39 +71,56 @@ 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;
|
||||
}
|
||||
}
|
||||
World world = getWorld();
|
||||
if (getLabel().equals("tpnether")) {
|
||||
world = getPlugin().getIWM().getNetherWorld(getWorld());
|
||||
} else if (getLabel().equals("tpend")) {
|
||||
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() == 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) {
|
||||
Location warpSpot = getIslands().getIslandLocation(getWorld(), targetUUID).toVector().toLocation(getWorld());
|
||||
if (getLabel().equals("tpnether")) {
|
||||
warpSpot = getIslands().getIslandLocation(getWorld(), targetUUID).toVector().toLocation(getPlugin().getIWM().getNetherWorld(getWorld()));
|
||||
} else if (getLabel().equals("tpend")) {
|
||||
warpSpot = getIslands().getIslandLocation(getWorld(), targetUUID).toVector().toLocation(getPlugin().getIWM().getEndWorld(getWorld()));
|
||||
}
|
||||
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());
|
||||
|
||||
Player player = user.getPlayer();
|
||||
// Set the player
|
||||
Player player = args.size() == 2 ? user.getPlayer() : user.getPlayer();
|
||||
if (args.size() == 2) {
|
||||
player = userToTeleport.getPlayer();
|
||||
failureMessage = userToTeleport.getTranslation("general.errors.no-safe-location-found");
|
||||
failureMessage = user.getTranslation(NOT_SAFE);
|
||||
}
|
||||
|
||||
// Teleport
|
||||
|
@ -99,10 +128,44 @@ public class AdminTeleportCommand extends CompositeCommand {
|
|||
.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) : "";
|
||||
|
@ -110,8 +173,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,199 @@
|
|||
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.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
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 to a player's island, nether or end islands, or to teleport another player
|
||||
* to a player's island
|
||||
*
|
||||
* For example /acid tp tastybento boxmanager would teleport BoxManager to tastybento's overwold island
|
||||
*
|
||||
* If the user has multiple islands, then the format is:
|
||||
* [admin_command] [user with island] [island to go to]
|
||||
*/
|
||||
public class AdminTeleportUserCommand extends CompositeCommand {
|
||||
|
||||
private static final String NOT_SAFE = "general.errors.no-safe-location-found";
|
||||
private @Nullable UUID targetUUID;
|
||||
private @Nullable User userToTeleport;
|
||||
|
||||
/**
|
||||
* @param parent - parent command
|
||||
* @param tpCommand - should be "tp", "tpnether" or "tpend"
|
||||
*/
|
||||
public AdminTeleportUserCommand(CompositeCommand parent, String tpCommand) {
|
||||
super(parent, tpCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
// Permission
|
||||
setPermission("admin.tp");
|
||||
setParametersHelp("commands.admin.tp.parameters");
|
||||
setDescription("commands.admin.tp.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.isEmpty() || args.size() > 3) {
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
// Check for console or not
|
||||
if (!user.isPlayer() && args.size() == 1) {
|
||||
user.sendMessage("general.errors.use-in-game");
|
||||
return false;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
// 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() == 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());
|
||||
} else if (getLabel().equals("tpend")) {
|
||||
world = getPlugin().getIWM().getEndWorld(getWorld());
|
||||
}
|
||||
if (world == null) {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
// Get default location if there are no arguments
|
||||
Location warpSpot = getSpot(world);
|
||||
if (warpSpot == null) {
|
||||
user.sendMessage(NOT_SAFE);
|
||||
return false;
|
||||
}
|
||||
// See if there is a quoted island name
|
||||
if (args.size() == 2) {
|
||||
Map<String, IslandInfo> names = getNameIslandMap(user);
|
||||
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);
|
||||
Island island = info.island;
|
||||
warpSpot = island.getSpawnPoint(world.getEnvironment()) != null
|
||||
? island.getSpawnPoint(world.getEnvironment())
|
||||
: island.getProtectionCenter().toVector().toLocation(world);
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (args.size() == 2) {
|
||||
failureMessage = userToTeleport.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 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().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() == 1) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(Util.getOnlinePlayerList(user)), lastArg));
|
||||
}
|
||||
if (args.size() == 2) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(user).keySet()), lastArg));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +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;
|
||||
|
||||
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));
|
||||
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,46 +53,71 @@ 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);
|
||||
getPlayers().clearHomeLocations(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();
|
||||
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
|
||||
.data("admin", user.getUniqueId().toString()).build());
|
||||
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(targetIsland.getCenter().toVector()),
|
||||
TextVariables.NAME, getPlayers().getName(targetUUID));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,8 +126,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));
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@ public class AdminVersionCommand extends CompositeCommand {
|
|||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
user.sendMessage("commands.bentobox.version.addon-syntax", TextVariables.NAME, getAddon().getDescription().getName(),
|
||||
TextVariables.VERSION, getAddon().getDescription().getVersion());
|
||||
TextVariables.VERSION, getAddon().getDescription().getVersion(), "[state]", getAddon().getState().name());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import world.bentobox.bentobox.api.commands.admin.purge.AdminPurgeCommand;
|
|||
import world.bentobox.bentobox.api.commands.admin.range.AdminRangeCommand;
|
||||
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;
|
||||
|
@ -29,8 +29,9 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
|||
*
|
||||
* @param addon - GameMode addon
|
||||
*/
|
||||
public DefaultAdminCommand(GameModeAddon addon) {
|
||||
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(" "));
|
||||
|
@ -42,7 +43,7 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
|||
*/
|
||||
@Override
|
||||
public void setup() {
|
||||
this.setPermission("admin.*");
|
||||
this.setPermission("admin");
|
||||
this.setOnlyPlayer(false);
|
||||
|
||||
this.setParametersHelp("commands.admin.help.parameters");
|
||||
|
@ -56,12 +57,12 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
|||
new AdminSetrankCommand(this);
|
||||
new AdminInfoCommand(this);
|
||||
// Team commands
|
||||
new AdminTeamCommand(this);
|
||||
new AdminTeamAddCommand(this);
|
||||
new AdminTeamKickCommand(this);
|
||||
new AdminTeamDisbandCommand(this);
|
||||
new AdminTeamSetownerCommand(this);
|
||||
new AdminTeamFixCommand(this);
|
||||
// Schems
|
||||
// Blueprints
|
||||
new AdminBlueprintCommand(this);
|
||||
// Register/unregister islands
|
||||
new AdminRegisterCommand(this);
|
||||
|
@ -92,11 +93,15 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
|||
new AdminSettingsCommand(this);
|
||||
// Location
|
||||
new AdminSetProtectionCenterCommand(this);
|
||||
// Delete homes
|
||||
new AdminDeleteHomesCommand(this);
|
||||
// Reset name
|
||||
new AdminResetNameCommand(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines what will be executed when this command is run.
|
||||
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List<String>)
|
||||
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(User, String, List)
|
||||
*/
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
|
|
|
@ -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) {
|
||||
|
@ -62,23 +62,34 @@ public class AdminBlueprintCommand extends ConfirmableCommand {
|
|||
return clipboards;
|
||||
}
|
||||
|
||||
protected void showClipboard(User user) {
|
||||
displayClipboards.putIfAbsent(user, Bukkit.getScheduler().scheduleSyncRepeatingTask(getPlugin(), () -> {
|
||||
if (!user.getPlayer().isOnline()) {
|
||||
hideClipboard(user);
|
||||
}
|
||||
|
||||
if (clipboards.containsKey(user.getUniqueId())) {
|
||||
BlueprintClipboard clipboard = clipboards.get(user.getUniqueId());
|
||||
if (clipboard.getPos1() != null && clipboard.getPos2() != null) {
|
||||
paintAxis(user, clipboard);
|
||||
/**
|
||||
* This method shows clipboard for requested user.
|
||||
* @param user User who need to see clipboard.
|
||||
*/
|
||||
protected void showClipboard(User user)
|
||||
{
|
||||
this.displayClipboards.computeIfAbsent(user,
|
||||
key -> Bukkit.getScheduler().scheduleSyncRepeatingTask(this.getPlugin(), () ->
|
||||
{
|
||||
if (!key.isPlayer() || !key.getPlayer().isOnline())
|
||||
{
|
||||
this.hideClipboard(key);
|
||||
}
|
||||
}
|
||||
|
||||
}, 20, 20));
|
||||
if (this.clipboards.containsKey(key.getUniqueId()))
|
||||
{
|
||||
BlueprintClipboard clipboard = this.clipboards.get(key.getUniqueId());
|
||||
this.paintAxis(key, clipboard);
|
||||
}
|
||||
}, 20, 20));
|
||||
}
|
||||
|
||||
|
||||
private void paintAxis(User user, BlueprintClipboard clipboard) {
|
||||
if (clipboard.getPos1() == null || clipboard.getPos2() == null) {
|
||||
return;
|
||||
}
|
||||
int minX = Math.min(clipboard.getPos1().getBlockX(), clipboard.getPos2().getBlockX());
|
||||
int minY = Math.min(clipboard.getPos1().getBlockY(), clipboard.getPos2().getBlockY());
|
||||
int minZ = Math.min(clipboard.getPos1().getBlockZ(), clipboard.getPos2().getBlockZ());
|
||||
|
@ -88,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,35 +1,54 @@
|
|||
package world.bentobox.bentobox.api.commands.admin.blueprints;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
|
||||
|
||||
public class AdminBlueprintCopyCommand extends CompositeCommand {
|
||||
|
||||
public AdminBlueprintCopyCommand(AdminBlueprintCommand parent) {
|
||||
public class AdminBlueprintCopyCommand extends CompositeCommand
|
||||
{
|
||||
public AdminBlueprintCopyCommand(AdminBlueprintCommand parent)
|
||||
{
|
||||
super(parent, "copy");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
public void setup()
|
||||
{
|
||||
setPermission("admin.blueprint.copy");
|
||||
setParametersHelp("commands.admin.blueprint.copy.parameters");
|
||||
setDescription("commands.admin.blueprint.copy.description");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() > 1) {
|
||||
showHelp(this, user);
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
if (args.size() > 2)
|
||||
{
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
|
||||
BlueprintClipboard clipboard = parent.getClipboards().computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
boolean copyAir = (args.size() == 1 && args.get(0).equalsIgnoreCase("air"));
|
||||
return clipboard.copy(user, copyAir);
|
||||
BlueprintClipboard clipboard =
|
||||
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"));
|
||||
|
||||
return clipboard.copy(user, copyAir, copyBiome);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args)
|
||||
{
|
||||
return Optional.of(List.of("air", "biome"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,55 +2,68 @@ package world.bentobox.bentobox.api.commands.admin.blueprints;
|
|||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
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.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* Command that deletes a Blueprint.
|
||||
* @author Poslovitch
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class AdminBlueprintDeleteCommand extends ConfirmableCommand {
|
||||
|
||||
public AdminBlueprintDeleteCommand(AdminBlueprintCommand parent) {
|
||||
public class AdminBlueprintDeleteCommand extends ConfirmableCommand
|
||||
{
|
||||
public AdminBlueprintDeleteCommand(AdminBlueprintCommand parent)
|
||||
{
|
||||
super(parent, "delete", "remove");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setParametersHelp("commands.admin.blueprint.delete.parameters");
|
||||
setDescription("commands.admin.blueprint.delete.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
public void setup()
|
||||
{
|
||||
setPermission("admin.blueprint.delete");
|
||||
this.setParametersHelp("commands.admin.blueprint.delete.parameters");
|
||||
this.setDescription("commands.admin.blueprint.delete.description");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
String blueprintName = args.get(0).toLowerCase(Locale.ENGLISH);
|
||||
String blueprintName = Util.sanitizeInput(args.get(0));
|
||||
|
||||
// Check if blueprint exist
|
||||
if (getPlugin().getBlueprintsManager().getBlueprints(getAddon()).containsKey(blueprintName)) {
|
||||
askConfirmation(user, user.getTranslation("commands.admin.blueprint.delete.confirmation"), () -> {
|
||||
getPlugin().getBlueprintsManager().deleteBlueprint(getAddon(), blueprintName);
|
||||
user.sendMessage("commands.admin.blueprint.delete.success", TextVariables.NAME, blueprintName);
|
||||
});
|
||||
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);
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
user.sendMessage("commands.admin.blueprint.delete.no-blueprint", TextVariables.NAME, blueprintName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
return Optional.of(new LinkedList<>(getPlugin().getBlueprintsManager().getBlueprints(getAddon()).keySet()));
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args)
|
||||
{
|
||||
return Optional.of(new LinkedList<>(this.getPlugin().getBlueprintsManager().getBlueprints(this.getAddon()).keySet()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,51 +5,66 @@ import java.io.FilenameFilter;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
|
||||
public class AdminBlueprintListCommand extends CompositeCommand {
|
||||
public class AdminBlueprintListCommand extends CompositeCommand
|
||||
{
|
||||
|
||||
public AdminBlueprintListCommand(AdminBlueprintCommand parent) {
|
||||
public AdminBlueprintListCommand(AdminBlueprintCommand parent)
|
||||
{
|
||||
super(parent, "list");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setDescription("commands.admin.blueprint.list.description");
|
||||
public void setup()
|
||||
{
|
||||
setPermission("admin.blueprint.list");
|
||||
this.setDescription("commands.admin.blueprint.list.description");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (!args.isEmpty()) {
|
||||
showHelp(this, user);
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
if (!args.isEmpty())
|
||||
{
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
File blueprints = new File(getAddon().getDataFolder(), BlueprintsManager.FOLDER_NAME);
|
||||
if (!blueprints.exists()) {
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
File blueprints = new File(this.getAddon().getDataFolder(), BlueprintsManager.FOLDER_NAME);
|
||||
|
||||
if (!blueprints.exists())
|
||||
{
|
||||
user.sendMessage("commands.admin.blueprint.list.no-blueprints");
|
||||
return false;
|
||||
}
|
||||
FilenameFilter blueprintFilter = (File dir, String name) -> name.toLowerCase(java.util.Locale.ENGLISH).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())).collect(Collectors.toList());
|
||||
if (blueprintList.isEmpty()) {
|
||||
|
||||
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();
|
||||
|
||||
if (blueprintList.isEmpty())
|
||||
{
|
||||
user.sendMessage("commands.admin.blueprint.list.no-blueprints");
|
||||
return false;
|
||||
}
|
||||
|
||||
user.sendMessage("commands.admin.blueprint.list.available-blueprints");
|
||||
blueprintList.forEach(user::sendRawMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class AdminBlueprintLoadCommand extends CompositeCommand {
|
|||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
|
||||
BlueprintClipboardManager bp = new BlueprintClipboardManager(getPlugin(), parent.getBlueprintsFolder());
|
||||
if (bp.load(user, args.get(0))) {
|
||||
if (bp.load(user, Util.sanitizeInput(args.get(0)))) {
|
||||
parent.getClipboards().put(user.getUniqueId(), bp.getClipboard());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package world.bentobox.bentobox.api.commands.admin.blueprints;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
@ -18,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");
|
||||
}
|
||||
|
@ -34,7 +35,7 @@ public class AdminBlueprintOriginCommand extends CompositeCommand {
|
|||
}
|
||||
|
||||
// Get the block player is looking at
|
||||
Block b = user.getPlayer().getLineOfSight(null, 20).stream().filter(x -> !x.getType().equals(Material.AIR)).findFirst().orElse(null);
|
||||
Block b = Objects.requireNonNull(user.getPlayer()).getLineOfSight(null, 20).stream().filter(x -> !x.getType().equals(Material.AIR)).findFirst().orElse(null);
|
||||
if (b != null) {
|
||||
clipboard.setOrigin(b.getLocation().toVector());
|
||||
user.getPlayer().sendBlockChange(b.getLocation(), Material.REDSTONE_BLOCK.createBlockData());
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class AdminBlueprintPos1Command extends CompositeCommand {
|
|||
return false;
|
||||
}
|
||||
clipboard.setPos1(user.getLocation());
|
||||
user.sendMessage("commands.admin.blueprint.set-pos1", "[vector]", Util.xyz(clipboard.getPos1().toVector()));
|
||||
user.sendMessage("commands.admin.blueprint.set-pos1", "[vector]", Util.xyz(user.getLocation().toVector()));
|
||||
parent.getClipboards().put(user.getUniqueId(), clipboard);
|
||||
parent.showClipboard(user);
|
||||
return true;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class AdminBlueprintPos2Command extends CompositeCommand {
|
|||
return false;
|
||||
}
|
||||
clipboard.setPos2(user.getLocation());
|
||||
user.sendMessage("commands.admin.blueprint.set-pos2", "[vector]", Util.xyz((clipboard.getPos2()).toVector()));
|
||||
user.sendMessage("commands.admin.blueprint.set-pos2", "[vector]", Util.xyz(user.getLocation().toVector()));
|
||||
parent.getClipboards().put(user.getUniqueId(), clipboard);
|
||||
parent.showClipboard(user);
|
||||
return true;
|
||||
|
|
|
@ -2,72 +2,111 @@ package world.bentobox.bentobox.api.commands.admin.blueprints;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
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.blueprints.Blueprint;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* Renames an existing blueprint.
|
||||
* @author Poslovitch
|
||||
* @since 1.10.0
|
||||
*/
|
||||
public class AdminBlueprintRenameCommand extends ConfirmableCommand {
|
||||
|
||||
public AdminBlueprintRenameCommand(AdminBlueprintCommand parent) {
|
||||
public class AdminBlueprintRenameCommand extends ConfirmableCommand
|
||||
{
|
||||
public AdminBlueprintRenameCommand(AdminBlueprintCommand parent)
|
||||
{
|
||||
super(parent, "rename");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setParametersHelp("commands.admin.blueprint.rename.parameters");
|
||||
setDescription("commands.admin.blueprint.rename.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
showHelp(this, user);
|
||||
public void setup()
|
||||
{
|
||||
setPermission("admin.blueprint.rename");
|
||||
this.setParametersHelp("commands.admin.blueprint.rename.parameters");
|
||||
this.setDescription("commands.admin.blueprint.rename.description");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
if (args.size() != 2)
|
||||
{
|
||||
// Blueprint must have a name.
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
String from = Util.sanitizeInput(args.get(0));
|
||||
String to = Util.sanitizeInput(args.get(1));
|
||||
|
||||
// Check if the names are the same
|
||||
String from = args.get(0).toLowerCase(Locale.ENGLISH);
|
||||
String to = args.get(1).toLowerCase(Locale.ENGLISH);
|
||||
|
||||
if (from.equals(to)) {
|
||||
// Check if name is changed.
|
||||
if (from.equals(to))
|
||||
{
|
||||
user.sendMessage("commands.admin.blueprint.rename.pick-different-name");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the 'from' file exists
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) this.getParent();
|
||||
File fromFile = new File(parent.getBlueprintsFolder(), from + BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
if (!fromFile.exists()) {
|
||||
|
||||
if (!fromFile.exists())
|
||||
{
|
||||
user.sendMessage("commands.admin.blueprint.no-such-file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the 'to' file exists
|
||||
|
||||
File toFile = new File(parent.getBlueprintsFolder(), to + BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
if (toFile.exists()) {
|
||||
// Ask for confirmation to overwrite
|
||||
askConfirmation(user, user.getTranslation("commands.admin.blueprint.file-exists"), () -> rename(user, from, to));
|
||||
} else {
|
||||
askConfirmation(user, () -> rename(user, from, to));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void rename(User user, String blueprintName, String newName) {
|
||||
Blueprint blueprint = getPlugin().getBlueprintsManager().getBlueprints(getAddon()).get(blueprintName);
|
||||
getPlugin().getBlueprintsManager().renameBlueprint(getAddon(), blueprint, newName);
|
||||
user.sendMessage("commands.admin.blueprint.rename.success", "[old]", blueprintName, TextVariables.NAME, blueprint.getName());
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
|
||||
// Check if the names are the same
|
||||
String from = Util.sanitizeInput(args.get(0));
|
||||
String to = Util.sanitizeInput(args.get(1));
|
||||
|
||||
// Check if the 'to' file exists
|
||||
File toFile = new File(parent.getBlueprintsFolder(), to + BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
|
||||
if (toFile.exists())
|
||||
{
|
||||
// Ask for confirmation to overwrite
|
||||
this.askConfirmation(user,
|
||||
user.getTranslation("commands.admin.blueprint.file-exists"),
|
||||
() -> this.rename(user, from, to, args.get(1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.askConfirmation(user, () -> this.rename(user, from, to, args.get(1)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void rename(User user, String blueprintName, String fileName, String displayName)
|
||||
{
|
||||
Blueprint blueprint = this.getPlugin().getBlueprintsManager().getBlueprints(this.getAddon()).get(blueprintName);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,62 +2,115 @@ package world.bentobox.bentobox.api.commands.admin.blueprints;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
|
||||
import world.bentobox.bentobox.managers.BlueprintClipboardManager;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminBlueprintSaveCommand extends ConfirmableCommand {
|
||||
|
||||
public AdminBlueprintSaveCommand(AdminBlueprintCommand parent) {
|
||||
/**
|
||||
* This method allows to save blueprint from the clipboard.
|
||||
*/
|
||||
public class AdminBlueprintSaveCommand extends ConfirmableCommand
|
||||
{
|
||||
public AdminBlueprintSaveCommand(AdminBlueprintCommand parent)
|
||||
{
|
||||
super(parent, "save");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
inheritPermission();
|
||||
setParametersHelp("commands.admin.blueprint.save.parameters");
|
||||
setDescription("commands.admin.blueprint.save.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
public void setup()
|
||||
{
|
||||
setPermission("admin.blueprint.save");
|
||||
this.setParametersHelp("commands.admin.blueprint.save.parameters");
|
||||
this.setDescription("commands.admin.blueprint.save.description");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
// Blueprint must have a name.
|
||||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) getParent();
|
||||
BlueprintClipboard clipboard = parent.getClipboards().computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
String fileName = args.get(0).toLowerCase(Locale.ENGLISH);
|
||||
if (clipboard.isFull()) {
|
||||
// Check if blueprint had bedrock
|
||||
if (clipboard.getBlueprint().getBedrock() == null) {
|
||||
user.sendMessage("commands.admin.blueprint.bedrock-required");
|
||||
return false;
|
||||
}
|
||||
// Check if file exists
|
||||
File newFile = new File(parent.getBlueprintsFolder(), fileName + BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
if (newFile.exists()) {
|
||||
this.askConfirmation(user, user.getTranslation("commands.admin.blueprint.file-exists"), () -> hideAndSave(user, parent, clipboard, fileName));
|
||||
return false;
|
||||
}
|
||||
return hideAndSave(user, parent, clipboard, fileName);
|
||||
} else {
|
||||
BlueprintClipboard clipboard = ((AdminBlueprintCommand) this.getParent()).getClipboards().
|
||||
computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
|
||||
if (!clipboard.isFull())
|
||||
{
|
||||
// Clipboard is not set up.
|
||||
user.sendMessage("commands.admin.blueprint.copy-first");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (clipboard.getBlueprint() != null && clipboard.getBlueprint().getBedrock() == null)
|
||||
{
|
||||
// Bedrock is required for all blueprints.
|
||||
user.sendMessage("commands.admin.blueprint.bedrock-required");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hideAndSave(User user, AdminBlueprintCommand parent, BlueprintClipboard clipboard, String name) {
|
||||
parent.hideClipboard(user);
|
||||
boolean result = new BlueprintClipboardManager(getPlugin(), parent.getBlueprintsFolder(), clipboard).save(user, name);
|
||||
if (result) {
|
||||
getPlugin().getBlueprintsManager().addBlueprint(getAddon(), clipboard.getBlueprint());
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
AdminBlueprintCommand parent = (AdminBlueprintCommand) this.getParent();
|
||||
BlueprintClipboard clipboard = parent.getClipboards().
|
||||
computeIfAbsent(user.getUniqueId(), v -> new BlueprintClipboard());
|
||||
|
||||
String fileName = Util.sanitizeInput(args.get(0));
|
||||
|
||||
// Check if file exists
|
||||
File newFile = new File(parent.getBlueprintsFolder(), fileName + BlueprintsManager.BLUEPRINT_SUFFIX);
|
||||
|
||||
if (newFile.exists())
|
||||
{
|
||||
this.askConfirmation(user,
|
||||
user.getTranslation("commands.admin.blueprint.file-exists"),
|
||||
() -> this.hideAndSave(user, parent, clipboard, fileName, args.get(0)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.hideAndSave(user, parent, clipboard, fileName, args.get(0));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method saves given blueprint.
|
||||
* @param user User that triggers blueprint save.
|
||||
* @param parent Parent command that contains clipboard.
|
||||
* @param clipboard Active clipboard.
|
||||
* @param name Filename for the blueprint
|
||||
* @param displayName Display name for the blueprint.
|
||||
* @return {@code true} if blueprint is saved, {@code false} otherwise.
|
||||
*/
|
||||
private boolean hideAndSave(User user,
|
||||
AdminBlueprintCommand parent,
|
||||
BlueprintClipboard clipboard,
|
||||
String name,
|
||||
String displayName)
|
||||
{
|
||||
parent.hideClipboard(user);
|
||||
boolean result = new BlueprintClipboardManager(this.getPlugin(),
|
||||
parent.getBlueprintsFolder(), clipboard).
|
||||
save(user, name, displayName);
|
||||
|
||||
if (result && clipboard.isFull())
|
||||
{
|
||||
this.getPlugin().getBlueprintsManager().addBlueprint(this.getAddon(), clipboard.getBlueprint());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@ import world.bentobox.bentobox.database.objects.Island;
|
|||
*/
|
||||
public class NamePrompt extends StringPrompt {
|
||||
|
||||
private @NonNull final Island island;
|
||||
private @NonNull final User user;
|
||||
@NonNull
|
||||
private final Island island;
|
||||
@NonNull
|
||||
private final User user;
|
||||
private final String oldName;
|
||||
private final BentoBox plugin;
|
||||
|
||||
public NamePrompt(BentoBox plugin, @NonNull Island island, User user, String oldName) {
|
||||
public NamePrompt(BentoBox plugin, @NonNull Island island, @NonNull User user, String oldName) {
|
||||
this.plugin = plugin;
|
||||
this.island = island;
|
||||
this.user = user;
|
||||
|
@ -30,14 +32,14 @@ public class NamePrompt extends StringPrompt {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getPromptText(ConversationContext context) {
|
||||
@NonNull
|
||||
public String getPromptText(@NonNull ConversationContext context) {
|
||||
return user.getTranslation("commands.island.renamehome.enter-new-name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Prompt acceptInput(ConversationContext context, String input) {
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -18,6 +17,7 @@ import world.bentobox.bentobox.api.events.island.IslandDeletedEvent;
|
|||
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 AdminPurgeCommand extends CompositeCommand implements Listener {
|
||||
|
||||
|
@ -70,7 +70,7 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
|||
islands.clear();
|
||||
this.user = user;
|
||||
try {
|
||||
Integer days = Integer.parseInt(args.get(0));
|
||||
int days = Integer.parseInt(args.get(0));
|
||||
if (days < 1) {
|
||||
user.sendMessage("commands.admin.purge.days-one-or-more");
|
||||
return false;
|
||||
|
@ -82,7 +82,7 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
|||
user.sendMessage("commands.admin.purge.confirm", TextVariables.LABEL, this.getTopLabel());
|
||||
return false;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
} catch (NumberFormatException e) {
|
||||
user.sendMessage("commands.admin.purge.number-error");
|
||||
return false;
|
||||
}
|
||||
|
@ -120,29 +120,42 @@ public class AdminPurgeCommand extends CompositeCommand implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a set of islands that are older than the parameter in days
|
||||
* @param days days
|
||||
* @return set of islands
|
||||
*/
|
||||
Set<String> getOldIslands(int days) {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
double daysInMilliseconds = days * 1000 * 3600 * 24;
|
||||
Set<String> oldIslands = new HashSet<>();
|
||||
|
||||
// Process islands in one pass, logging and adding to the set if applicable
|
||||
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);
|
||||
});
|
||||
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());
|
||||
.filter(i -> !i.isSpawn()).filter(i -> !i.getPurgeProtected())
|
||||
.filter(i -> i.getWorld().equals(this.getWorld())).filter(Island::isOwned).filter(
|
||||
i -> i.getMemberSet().stream()
|
||||
.allMatch(member -> (currentTimeMillis
|
||||
- Bukkit.getOfflinePlayer(member).getLastPlayed()) > daysInMilliseconds))
|
||||
.forEach(i -> {
|
||||
// Add the unique island ID to the set
|
||||
oldIslands.add(i.getUniqueId());
|
||||
BentoBox.getInstance().log("Will purge island at " + Util.xyz(i.getCenter().toVector()) + " in "
|
||||
+ i.getWorld().getName());
|
||||
// Log each member's last login information
|
||||
i.getMemberSet().forEach(member -> {
|
||||
Date lastLogin = new Date(Bukkit.getOfflinePlayer(member).getLastPlayed());
|
||||
BentoBox.getInstance()
|
||||
.log("Player " + BentoBox.getInstance().getPlayers().getName(member)
|
||||
+ " last logged in "
|
||||
+ (int) ((currentTimeMillis - Bukkit.getOfflinePlayer(member).getLastPlayed())
|
||||
/ 1000 / 3600 / 24)
|
||||
+ " days ago. " + lastLogin);
|
||||
});
|
||||
BentoBox.getInstance().log("+-----------------------------------------+");
|
||||
});
|
||||
|
||||
return oldIslands;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,22 +1,18 @@
|
|||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.List;
|
||||
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");
|
||||
|
@ -24,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 = getIslands().getIsland(getWorld(), targetUUID);
|
||||
int newRange = island.getProtectionRange() + Integer.parseInt(args.get(1));
|
||||
|
||||
if (newRange > island.getRange() * 2) {
|
||||
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),
|
||||
|
@ -85,4 +56,6 @@ public class AdminRangeAddCommand extends CompositeCommand {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -31,4 +31,5 @@ public class AdminRangeCommand extends CompositeCommand {
|
|||
showHelp(this, user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,11 +7,13 @@ import java.util.Map;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
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
|
||||
|
@ -22,9 +24,12 @@ 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 Map<User, Integer> displayRanges = new HashMap<>();
|
||||
private final Map<User, Integer> displayRanges = new HashMap<>();
|
||||
|
||||
public AdminRangeDisplayCommand(CompositeCommand parent) {
|
||||
super(parent, DISPLAY, SHOW, HIDE);
|
||||
|
@ -46,29 +51,15 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
|
||||
if (!displayRanges.containsKey(user)) {
|
||||
switch (label) {
|
||||
case DISPLAY:
|
||||
case SHOW:
|
||||
showZones(user);
|
||||
break;
|
||||
case HIDE:
|
||||
user.sendMessage("commands.admin.range.display.already-off");
|
||||
break;
|
||||
default:
|
||||
showHelp(this, user);
|
||||
break;
|
||||
case DISPLAY, SHOW -> showZones(user);
|
||||
case HIDE -> user.sendMessage("commands.admin.range.display.already-off");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
} else {
|
||||
switch (label) {
|
||||
case DISPLAY:
|
||||
case HIDE:
|
||||
hideZones(user);
|
||||
break;
|
||||
case SHOW:
|
||||
user.sendMessage("commands.admin.range.display.already-on");
|
||||
break;
|
||||
default:
|
||||
showHelp(this, user);
|
||||
break;
|
||||
case DISPLAY, HIDE -> hideZones(user);
|
||||
case SHOW -> user.sendMessage("commands.admin.range.display.already-on");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,15 +76,15 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresent(island -> {
|
||||
// Draw the island protected area
|
||||
drawZone(user, Particle.BARRIER, null, island, island.getProtectionRange());
|
||||
drawZone(user, Particle.BLOCK_MARKER, Material.BARRIER.createBlockData(), island, island.getProtectionRange());
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
@ -104,7 +95,7 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
displayRanges.remove(user);
|
||||
}
|
||||
|
||||
private void drawZone(User user, Particle particle, Particle.DustOptions dustOptions, Island island, int range) {
|
||||
private void drawZone(User user, Particle particle, Object dustOptions, Island island, int range) {
|
||||
Location center = island.getProtectionCenter();
|
||||
// Get player Y coordinate
|
||||
int playerY = user.getPlayer().getLocation().getBlockY() + 1;
|
||||
|
@ -112,10 +103,10 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
// Draw 3 "stages" (one line below, at and above player's y coordinate)
|
||||
for (int stage = -1 ; stage <= 1 ; stage++) {
|
||||
for (int i = -range ; i <= range ; i++) {
|
||||
user.spawnParticle(particle, dustOptions, center.getBlockX() + i, playerY + stage, center.getBlockZ() + range);
|
||||
user.spawnParticle(particle, dustOptions, center.getBlockX() + i, playerY + stage, center.getBlockZ() - range);
|
||||
user.spawnParticle(particle, dustOptions, center.getBlockX() + range, playerY + stage, center.getBlockZ() + i);
|
||||
user.spawnParticle(particle, dustOptions, center.getBlockX() - range, playerY + stage, center.getBlockZ() + i);
|
||||
user.spawnParticle(particle, dustOptions, (double)center.getBlockX() + i, (double)playerY + stage, (double)center.getBlockZ() + range);
|
||||
user.spawnParticle(particle, dustOptions, (double)center.getBlockX() + i, (double)playerY + stage, (double)center.getBlockZ() - range);
|
||||
user.spawnParticle(particle, dustOptions, (double)center.getBlockX() + range, (double)playerY + stage, (double)center.getBlockZ() + i);
|
||||
user.spawnParticle(particle, dustOptions, (double)center.getBlockX() - range, (double)playerY + stage, (double)center.getBlockZ() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.List;
|
||||
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");
|
||||
|
@ -24,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 = 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)
|
||||
|
|
|
@ -2,6 +2,7 @@ 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;
|
||||
|
||||
|
@ -45,7 +46,7 @@ public class AdminRangeResetCommand extends CompositeCommand {
|
|||
}
|
||||
|
||||
// Get island
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
|
||||
|
||||
// Get old range for event
|
||||
int oldRange = island.getProtectionRange();
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
package world.bentobox.bentobox.api.commands.admin.range;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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");
|
||||
|
@ -27,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));
|
||||
|
@ -51,33 +30,30 @@ public class AdminRangeSetCommand extends CompositeCommand {
|
|||
}
|
||||
int range = Integer.parseInt(args.get(1));
|
||||
|
||||
// Get island
|
||||
Island island = 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)
|
||||
|
@ -89,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");
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ 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.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class AdminTeamAddCommand extends CompositeCommand {
|
||||
|
@ -20,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");
|
||||
}
|
||||
|
@ -43,16 +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));
|
||||
getIslands().getIsland(getWorld(), ownerUUID).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;
|
||||
}
|
||||
|
@ -63,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");
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2022
|
||||
//
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* Parent command for all Admin Team commands.
|
||||
*/
|
||||
public class AdminTeamCommand extends CompositeCommand
|
||||
{
|
||||
public AdminTeamCommand(CompositeCommand parent)
|
||||
{
|
||||
super(parent, "team");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
this.setPermission("mod.team");
|
||||
this.setDescription("commands.admin.team.description");
|
||||
|
||||
new AdminTeamAddCommand(this);
|
||||
new AdminTeamDisbandCommand(this);
|
||||
|
||||
new AdminTeamKickCommand(this);
|
||||
new AdminTeamSetownerCommand(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args)
|
||||
{
|
||||
this.showHelp(this, user);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ 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.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -29,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");
|
||||
}
|
||||
|
@ -59,17 +60,18 @@ public class AdminTeamKickCommand extends CompositeCommand {
|
|||
@Override
|
||||
public boolean execute(User user, String label, @NonNull List<String> args) {
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
|
||||
if (island == null) {
|
||||
return false;
|
||||
}
|
||||
if (targetUUID.equals(island.getOwner())) {
|
||||
user.sendMessage("commands.admin.team.kick.cannot-kick-owner");
|
||||
island.showMembers(user);
|
||||
new IslandInfo(island).showMembers(user);
|
||||
return false;
|
||||
}
|
||||
User target = User.getInstance(targetUUID);
|
||||
target.sendMessage("commands.admin.team.kick.admin-kicked");
|
||||
|
||||
getIslands().removePlayer(getWorld(), targetUUID);
|
||||
getPlayers().clearHomeLocations(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
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
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;
|
||||
|
@ -14,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");
|
||||
|
@ -24,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;
|
||||
}
|
||||
|
||||
// Get the User corresponding to the current owner
|
||||
User previousOwner = User.getInstance(previousOwnerUUID);
|
||||
User target = User.getInstance(targetUUID);
|
||||
|
||||
// Fire event so add-ons know
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
// Call the setowner event
|
||||
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();
|
||||
|
||||
// Make new owner
|
||||
getIslands().setOwner(getWorld(), user, targetUUID);
|
||||
user.sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, args.get(0));
|
||||
|
||||
// Call the rank change event for the old island owner
|
||||
// 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(previousOwner))
|
||||
.build();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
// Call the setowner event
|
||||
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();
|
||||
|
||||
// Make new owner
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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(" "));
|
||||
|
@ -78,6 +79,7 @@ public abstract class DefaultPlayerCommand extends CompositeCommand {
|
|||
new IslandSethomeCommand(this);
|
||||
new IslandDeletehomeCommand(this);
|
||||
new IslandRenamehomeCommand(this);
|
||||
new IslandHomesCommand(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,31 +101,30 @@ public abstract class DefaultPlayerCommand extends CompositeCommand {
|
|||
// Check if user has an island.
|
||||
if (this.getIslands().getIsland(this.getWorld(), user.getUniqueId()) != null) {
|
||||
// Default command if user has an island.
|
||||
String command = this.<GameModeAddon>getAddon().getWorldSettings().getDefaultPlayerAction();
|
||||
|
||||
// Perform command or use "go" command.
|
||||
if (command != null && user.performCommand(label + " " + command)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return this.getSubCommand("go").
|
||||
map(goCmd -> goCmd.call(user, goCmd.getLabel(), Collections.emptyList())).
|
||||
orElse(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return runCommand(user, label, this.<GameModeAddon>getAddon().getWorldSettings().getDefaultPlayerAction(), "go");
|
||||
} else {
|
||||
// Default command if user does not have an island.
|
||||
String command = this.<GameModeAddon>getAddon().getWorldSettings().getDefaultNewPlayerAction();
|
||||
return runCommand(user, label, this.<GameModeAddon>getAddon().getWorldSettings().getDefaultNewPlayerAction(), "create");
|
||||
}
|
||||
}
|
||||
|
||||
// Perform command or use "create" command.
|
||||
if (command != null && user.performCommand(label + " " + command)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return this.getSubCommand("create").
|
||||
map(createCmd -> createCmd.call(user, createCmd.getLabel(), Collections.emptyList())).
|
||||
orElse(false);
|
||||
private boolean runCommand(User user, String label, String command, String defaultSubCommand) {
|
||||
if (command == null || command.isEmpty()) {
|
||||
command = defaultSubCommand;
|
||||
}
|
||||
// Call sub command or perform command if it does not exist
|
||||
if (this.getSubCommand(command).isPresent()) {
|
||||
return this.getSubCommand(command).
|
||||
map(c -> c.call(user, c.getLabel(), Collections.emptyList())).
|
||||
orElse(false);
|
||||
} else {
|
||||
// Command is not a known sub command - try to perform it directly - some plugins trap these commands, like Deluxe menus
|
||||
if (command.startsWith("/")) {
|
||||
// If commands starts with Slash, don't append the prefix
|
||||
return user.performCommand(command.substring(1));
|
||||
} else {
|
||||
return user.performCommand(label + " " + command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
|
@ -18,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 {
|
||||
|
@ -46,15 +46,17 @@ 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;
|
||||
}
|
||||
// Check rank to use command
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
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
|
||||
|
@ -68,11 +70,11 @@ 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;
|
||||
}
|
||||
if (getIslands().getIsland(getWorld(), playerUUID).isBanned(targetUUID)) {
|
||||
if (island.isBanned(targetUUID)) {
|
||||
user.sendMessage("commands.island.ban.player-already-banned");
|
||||
return false;
|
||||
}
|
||||
|
@ -95,28 +97,29 @@ public class IslandBanCommand extends CompositeCommand {
|
|||
}
|
||||
|
||||
private boolean ban(@NonNull User issuer, User target) {
|
||||
Island island = getIslands().getIsland(getWorld(), issuer.getUniqueId());
|
||||
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);
|
||||
}
|
||||
|
@ -131,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();
|
||||
|
@ -140,9 +143,8 @@ 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))
|
||||
.map(Player::getName).collect(Collectors.toList());
|
||||
.filter(p -> !island.isBanned(p.getUniqueId())).filter(p -> user.getPlayer().canSee(p))
|
||||
.map(Player::getName).toList();
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
|
|
@ -3,12 +3,12 @@ package world.bentobox.bentobox.api.commands.island;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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 {
|
||||
|
||||
|
@ -41,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;
|
||||
|
@ -57,7 +58,7 @@ public class IslandBanlistCommand extends CompositeCommand {
|
|||
// Title
|
||||
user.sendMessage("commands.island.banlist.the-following");
|
||||
// Create a nicely formatted list
|
||||
List<String> names = island.getBanned().stream().map(u -> getPlayers().getName(u)).sorted().collect(Collectors.toList());
|
||||
List<String> names = island.getBanned().stream().map(u -> getPlayers().getName(u)).sorted().toList();
|
||||
List<String> lines = new ArrayList<>();
|
||||
StringBuilder line = new StringBuilder();
|
||||
// Put the names into lines of no more than 40 characters long, separated by commas
|
||||
|
|
|
@ -5,13 +5,15 @@ 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.
|
||||
|
@ -22,6 +24,7 @@ public class IslandCreateCommand extends CompositeCommand {
|
|||
|
||||
/**
|
||||
* Command to create an island
|
||||
*
|
||||
* @param islandCommand - parent command
|
||||
*/
|
||||
public IslandCreateCommand(CompositeCommand islandCommand) {
|
||||
|
@ -40,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
|
||||
|
@ -63,44 +81,67 @@ public class IslandCreateCommand extends CompositeCommand {
|
|||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Permission check if the name is not the default one
|
||||
if (!args.isEmpty()) {
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), args.get(0).toLowerCase(java.util.Locale.ENGLISH));
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), Util.sanitizeInput(args.get(0)));
|
||||
if (name == null) {
|
||||
// The blueprint name is not valid.
|
||||
user.sendMessage("commands.island.create.unknown-blueprint");
|
||||
return false;
|
||||
}
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, args.get(0))) {
|
||||
// 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,16 +1,18 @@
|
|||
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;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -20,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");
|
||||
}
|
||||
|
@ -32,6 +36,8 @@ public class IslandDeletehomeCommand extends ConfirmableCommand {
|
|||
setOnlyPlayer(true);
|
||||
setParametersHelp("commands.island.deletehome.parameters");
|
||||
setDescription("commands.island.deletehome.description");
|
||||
setConfigurableRankCommand();
|
||||
setDefaultCommandRank(RanksManager.MEMBER_RANK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,25 +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 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));
|
||||
|
||||
// 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(RanksManager.getInstance().getRank(rank)));
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -71,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 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));
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
|
@ -17,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;
|
||||
|
||||
/**
|
||||
|
@ -60,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
|
||||
|
@ -75,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;
|
||||
}
|
||||
|
@ -91,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;
|
||||
}
|
||||
|
||||
|
@ -150,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).collect(Collectors.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;
|
||||
|
@ -32,49 +34,98 @@ public class IslandGoCommand extends DelayedTeleportCommand {
|
|||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Check if the island is reserved
|
||||
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
// Check if mid-teleport
|
||||
if (getIslands().isGoingHome(user)) {
|
||||
// Tell them again that it's in progress
|
||||
user.sendMessage("commands.island.go.teleport");
|
||||
return false;
|
||||
}
|
||||
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()) {
|
||||
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("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)));
|
||||
// Check if the home is known
|
||||
if (!args.isEmpty()) {
|
||||
Map<String, IslandInfo> names = getNameIslandMap(user);
|
||||
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) -> getIslands().setPrimaryIsland(user.getUniqueId(), info.island)));
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
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().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
|
||||
}
|
||||
|
||||
return islandMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
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 IslandHomesCommand extends ConfirmableCommand {
|
||||
|
||||
private List<Island> islands;
|
||||
|
||||
public IslandHomesCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "homes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("island.homes");
|
||||
setOnlyPlayer(true);
|
||||
setDescription("commands.island.homes.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
islands = getIslands().getIslands(getWorld(), user);
|
||||
// Check island
|
||||
if (islands.isEmpty()) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
user.sendMessage("commands.island.sethome.homes-are");
|
||||
islands.forEach(island ->
|
||||
island.getHomes().keySet().stream().filter(s -> !s.isEmpty())
|
||||
.forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)));
|
||||
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> result = new ArrayList<>();
|
||||
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
|
||||
result.addAll(island.getHomes().keySet());
|
||||
}
|
||||
return Optional.of(Util.tabLimit(result, lastArg));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,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.util.IslandInfo;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -37,7 +38,7 @@ public class IslandInfoCommand extends CompositeCommand {
|
|||
}
|
||||
// If there are no args, then the player wants info on the island at this location
|
||||
if (args.isEmpty()) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> i.showInfo(user)).orElse(false)) {
|
||||
if (!getIslands().getIslandAt(user.getLocation()).map(i -> new IslandInfo(i).showInfo(user)).orElse(false)) {
|
||||
user.sendMessage("commands.admin.info.no-island");
|
||||
return false;
|
||||
}
|
||||
|
@ -56,10 +57,10 @@ public class IslandInfoCommand extends CompositeCommand {
|
|||
return false;
|
||||
}
|
||||
// Show info for this player
|
||||
island.showInfo(user);
|
||||
new IslandInfo(island).showInfo(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package world.bentobox.bentobox.api.commands.island;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.conversations.ConversationFactory;
|
||||
|
@ -14,6 +15,7 @@ import world.bentobox.bentobox.api.commands.admin.conversations.NamePrompt;
|
|||
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;
|
||||
|
||||
/**
|
||||
|
@ -35,6 +37,8 @@ public class IslandRenamehomeCommand extends ConfirmableCommand {
|
|||
setOnlyPlayer(true);
|
||||
setParametersHelp("commands.island.renamehome.parameters");
|
||||
setDescription("commands.island.renamehome.description");
|
||||
setConfigurableRankCommand();
|
||||
setDefaultCommandRank(RanksManager.MEMBER_RANK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,6 +61,15 @@ public class IslandRenamehomeCommand extends ConfirmableCommand {
|
|||
this.showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -75,9 +88,9 @@ public class IslandRenamehomeCommand 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 island = getIslands().getIsland(getWorld(), user.getUniqueId());
|
||||
if (island != null) {
|
||||
return Optional.of(Util.tabLimit(new ArrayList<>(island.getHomes().keySet()), lastArg));
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ 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
|
||||
|
@ -31,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");
|
||||
|
@ -78,20 +80,21 @@ public class IslandResetCommand extends ConfirmableCommand {
|
|||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Permission check if the name is not the default one
|
||||
if (!args.isEmpty()) {
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), args.get(0).toLowerCase(java.util.Locale.ENGLISH));
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), Util.sanitizeInput(args.get(0)));
|
||||
if (name == null || name.isEmpty()) {
|
||||
// The blueprint name is not valid.
|
||||
user.sendMessage("commands.island.create.unknown-blueprint");
|
||||
return false;
|
||||
}
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, args.get(0))) {
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, Util.sanitizeInput(args.get(0)))) {
|
||||
return false;
|
||||
}
|
||||
return resetIsland(user, name);
|
||||
} 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);
|
||||
}
|
||||
|
@ -101,52 +104,38 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset island
|
||||
*
|
||||
* @param user user
|
||||
* @param name name of Blueprint Bundle
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean resetIsland(User user, String name) {
|
||||
// Get the player's old island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), user);
|
||||
deleteOldIsland(user, oldIsland);
|
||||
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(Reason.PRECLEAR)
|
||||
.island(oldIsland)
|
||||
.oldIsland(oldIsland)
|
||||
.location(oldIsland.getCenter())
|
||||
.build();
|
||||
|
||||
// Reset the island
|
||||
user.sendMessage("commands.island.create.creating-island");
|
||||
|
||||
// Kick all island members (including the owner)
|
||||
kickMembers(oldIsland);
|
||||
|
||||
// Add a reset
|
||||
getPlayers().addReset(getWorld(), user.getUniqueId());
|
||||
|
||||
// Reset the homes of the player
|
||||
getPlayers().clearHomeLocations(getWorld(), user.getUniqueId());
|
||||
|
||||
// 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());
|
||||
|
@ -157,35 +146,49 @@ public class IslandResetCommand extends ConfirmableCommand {
|
|||
return true;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// Reset the island
|
||||
|
||||
// Kick all island members (including the owner)
|
||||
kickMembers(oldIsland);
|
||||
|
||||
// Add a reset
|
||||
getPlayers().addReset(getWorld(), user.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Objects;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
|
@ -23,22 +27,34 @@ public class IslandResetnameCommand extends CompositeCommand {
|
|||
setDescription("commands.island.resetname.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
|
||||
if (!getIslands().hasIsland(getWorld(), playerUUID)) {
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getIslands().isOwner(getWorld(), playerUUID)) {
|
||||
user.sendMessage("general.errors.not-owner");
|
||||
// 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(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
// Resets the island name
|
||||
getIslands().getIsland(getWorld(), playerUUID).setName(null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
|
||||
// Resets the island name
|
||||
Objects.requireNonNull(getIslands().getIsland(getWorld(), user)).setName(null);
|
||||
user.sendMessage("commands.island.resetname.success");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
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.configuration.WorldSettings;
|
||||
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 IslandSethomeCommand extends ConfirmableCommand {
|
||||
|
||||
|
@ -23,6 +27,8 @@ public class IslandSethomeCommand extends ConfirmableCommand {
|
|||
setPermission("island.sethome");
|
||||
setOnlyPlayer(true);
|
||||
setDescription("commands.island.sethome.description");
|
||||
setConfigurableRankCommand();
|
||||
setDefaultCommandRank(RanksManager.MEMBER_RANK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,12 +43,22 @@ public class IslandSethomeCommand extends ConfirmableCommand {
|
|||
user.sendMessage("commands.island.sethome.must-be-on-your-island");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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(island.getMaxHomes()));
|
||||
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("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;
|
||||
|
@ -51,29 +67,30 @@ public class IslandSethomeCommand extends ConfirmableCommand {
|
|||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
String number = String.join(" ", args);
|
||||
WorldSettings ws = getIWM().getWorldSettings(user.getWorld());
|
||||
// Check if the player is in the Nether
|
||||
if (getIWM().isNether(user.getWorld())) {
|
||||
// Check if he is (not) allowed to set his home here
|
||||
if (!getIWM().getWorldSettings(user.getWorld()).isAllowSetHomeInNether()) {
|
||||
if (!ws.isAllowSetHomeInNether()) {
|
||||
user.sendMessage("commands.island.sethome.nether.not-allowed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a confirmation is required
|
||||
if (getIWM().getWorldSettings(user.getWorld()).isRequireConfirmationToSetHomeInNether()) {
|
||||
if (ws.isRequireConfirmationToSetHomeInNether()) {
|
||||
askConfirmation(user, user.getTranslation("commands.island.sethome.nether.confirmation"), () -> doSetHome(user, number));
|
||||
} else {
|
||||
doSetHome(user, number);
|
||||
}
|
||||
} else if (getIWM().isEnd(user.getWorld())) { // Check if the player is in the End
|
||||
// Check if he is (not) allowed to set his home here
|
||||
if (!getIWM().getWorldSettings(user.getWorld()).isAllowSetHomeInTheEnd()) {
|
||||
if (!ws.isAllowSetHomeInTheEnd()) {
|
||||
user.sendMessage("commands.island.sethome.the-end.not-allowed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a confirmation is required
|
||||
if (getIWM().getWorldSettings(user.getWorld()).isRequireConfirmationToSetHomeInTheEnd()) {
|
||||
if (ws.isRequireConfirmationToSetHomeInTheEnd()) {
|
||||
askConfirmation(user, user.getTranslation("commands.island.sethome.the-end.confirmation"), () -> doSetHome(user, number));
|
||||
} else {
|
||||
doSetHome(user, number);
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package world.bentobox.bentobox.api.commands.island;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
|
@ -25,24 +29,31 @@ public class IslandSetnameCommand extends CompositeCommand {
|
|||
setOnlyPlayer(true);
|
||||
setParametersHelp("commands.island.setname.parameters");
|
||||
setDescription("commands.island.setname.description");
|
||||
setConfigurableRankCommand();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
public boolean canExecute(User user, String label, List<String> args)
|
||||
{
|
||||
// Explain command
|
||||
if (args.isEmpty()) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID playerUUID = user.getUniqueId();
|
||||
Island island = getIslands().getIsland(getWorld(), user);
|
||||
|
||||
if (!getIslands().hasIsland(getWorld(), playerUUID)) {
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().isOwner(getWorld(), playerUUID)) {
|
||||
user.sendMessage("general.errors.not-owner");
|
||||
|
||||
// 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(RanksManager.getInstance().getRank(rank)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -64,15 +75,33 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Naming the island - join all the arguments with spaces.
|
||||
String name = String.join(" ", args);
|
||||
|
||||
// Apply colors
|
||||
if (user.hasPermission(getPermissionPrefix() + "island.name.format")) {
|
||||
name = ChatColor.translateAlternateColorCodes('&', name);
|
||||
}
|
||||
|
||||
// Everything's good!
|
||||
getIslands().getIsland(getWorld(), playerUUID).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;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue