mirror of
https://github.com/kennytv/Maintenance.git
synced 2026-11-04 16:50:07 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36117803fe
|
||
|
|
cb4fead942
|
||
|
|
60375ab964 | ||
|
|
3a94423501 | ||
|
|
4b62c83410 | ||
|
|
2ccfae5d87 | ||
|
|
7f444d0f1c | ||
|
|
46b3a3f14e | ||
|
|
9ddac66d62 | ||
|
|
dd7fa6f08a | ||
|
|
c2b4ceef1c | ||
|
|
b11136bed0 | ||
|
|
7664d40696 | ||
|
|
dcbc8f7407 | ||
|
|
752e9aeb19 | ||
|
|
7fc3f0cbc9 | ||
|
|
c3014e8092 | ||
|
|
7f5a5d8d54 | ||
|
|
27ff56f673 | ||
|
|
db49edaa88 | ||
|
|
b4e331fba3 | ||
|
|
563c184c0b | ||
|
|
6dd9ae0ec3 | ||
|
|
ac50b28659 | ||
|
|
65bf209705 | ||
|
|
6d57f9664e | ||
|
|
1408dee12e | ||
|
|
97f6cb5d68 | ||
|
|
4cd541e158 | ||
|
|
9a9793bb90 | ||
|
|
4005416de1 | ||
|
|
12c9972efd | ||
|
|
41acd5db94 | ||
|
|
337e5739c6 | ||
|
|
3ad5cff521 | ||
|
|
2457cdff71 | ||
|
|
7a9e8676d9 | ||
|
|
5f52fa53f4 | ||
|
|
1b1708aa69 | ||
|
|
fdc6cd9bdd | ||
|
|
1fb7c0ea42 | ||
|
|
8d75af5b46 | ||
|
|
4d0ad57695 | ||
|
|
4c8ab9ce32 | ||
|
|
34bc884a11 | ||
|
|
0ebde0b8db | ||
|
|
82301fd9f9 | ||
|
|
b0d87a94a8 | ||
|
|
a380d8bf35 | ||
|
|
ae8fb9a8db | ||
|
|
724fcd8395 | ||
|
|
cfbcf0975c | ||
|
|
32baaf620f | ||
|
|
06e3405bcc | ||
|
|
d2520eed6c | ||
|
|
24bd5b2618 | ||
|
|
f6b6a45fa8 | ||
|
|
b37bfe6334 | ||
|
|
1f8574fe26 | ||
|
|
7ee3b8a5fe | ||
|
|
cfb7e9e15b | ||
|
|
5d595869ee | ||
|
|
e154b62ef7 | ||
|
|
3d49982e56 | ||
|
|
a1bc66a717 | ||
|
|
c42f0ab912 | ||
|
|
22dd4ce266 | ||
|
|
2e66e1b926 | ||
|
|
ac28c94435 | ||
|
|
4acc809dd8 | ||
|
|
0ff5cd232f | ||
|
|
d49db3dfbe | ||
|
|
b36adb54fa | ||
|
|
91276ab5f6 | ||
|
|
3dd1d7506a | ||
|
|
00abe8588b | ||
|
|
9fba024e16 | ||
|
|
fe7a640e3d | ||
|
|
72c9689b6d | ||
|
|
cfd0dd1be7 | ||
|
|
cfdedfad15 | ||
|
|
32258bc1ef | ||
|
|
c2f297a125 | ||
|
|
036c225c2c | ||
|
|
bc10c6b94c | ||
|
|
211dd1e4f2 | ||
|
|
de500d9cd3 | ||
|
|
99d77b2f55 | ||
|
|
2ddafded74 | ||
|
|
876b66392f | ||
|
|
e59a27d09d | ||
|
|
0c4e9564bd | ||
|
|
9c7f60180b | ||
|
|
bbaa53f428 | ||
|
|
9f910d3027 | ||
|
|
2c3a324ec9 | ||
|
|
9ab902b9ce | ||
|
|
4c5a19fd60 | ||
|
|
342cfa4b03 | ||
|
|
6cf9314aaa | ||
|
|
967fe77753 | ||
|
|
6d6ebee2cc | ||
|
|
0e7bbfd0e2 | ||
|
|
3410f36c10 | ||
|
|
fe2bfda1b9 | ||
|
|
e106aacc47 | ||
|
|
e7aee8c99f | ||
|
|
c84265c1dd | ||
|
|
78b08ca164 | ||
|
|
54151515f4 | ||
|
|
fd1c252594 | ||
|
|
702349c762 | ||
|
|
1f6fb837de | ||
|
|
0284b80e44 | ||
|
|
6f99fe4ce8 | ||
|
|
1ac29de1bf | ||
|
|
2223094461 | ||
|
|
6279ae2477 | ||
|
|
5f90270cc8 | ||
|
|
885c7249a6 | ||
|
|
ffb8fd5767 | ||
|
|
c3717bc8b1 | ||
|
|
665c3816cd | ||
|
|
a586190e1f | ||
|
|
820d5138a9 | ||
|
|
39f240c1cb | ||
|
|
a8092d430a | ||
|
|
8173a69496 | ||
|
|
317afe064a | ||
|
|
7d3e6002f1 | ||
|
|
22a75203cf | ||
|
|
b63ba56f50 | ||
|
|
e0a20eff46 | ||
|
|
77d42f3367 | ||
|
|
09f3ad0384 | ||
|
|
0c2f0cdb96 | ||
|
|
13706a86e5 | ||
|
|
d121772f3c | ||
|
|
8b5234b2ad | ||
|
|
d659fd173e | ||
|
|
8e44e611d0 | ||
|
|
36c2c6183e | ||
|
|
06229ab9ae | ||
|
|
9df156703d | ||
|
|
7ab28b7126 | ||
|
|
f4fe7a4aa4 | ||
|
|
ea6f43f4e0 | ||
|
|
07304e0ad4 | ||
|
|
11bf0287f3 | ||
|
|
1bda7aae24 | ||
|
|
a919227b04 | ||
|
|
796f46dd44 | ||
|
|
3ebd6e627a | ||
|
|
53612fe24a | ||
|
|
cbcbba5678 | ||
|
|
962f7834c6 | ||
|
|
f724014efd | ||
|
|
84f39ca478 | ||
|
|
d06760e83f | ||
|
|
4e27c5b044 | ||
|
|
8480e1b28b | ||
|
|
f56afcf9a7 | ||
|
|
de6c56e1ba | ||
|
|
b37050b317 | ||
|
|
081a34c51b | ||
|
|
ff2ccf0478 | ||
|
|
34c6811295 | ||
|
|
4b50b67abf | ||
|
|
eee4be4ca0 | ||
|
|
f6d5e99a09 | ||
|
|
29c55e53af | ||
|
|
ac38cf143b | ||
|
|
1bd22f73e5 | ||
|
|
a256a10170 | ||
|
|
2e6f1b718a | ||
|
|
a30b833bfb | ||
|
|
4701803045 | ||
|
|
76385f3968 | ||
|
|
9283cb25e7 | ||
|
|
97dbe14127 | ||
|
|
da41f7cfc8 | ||
|
|
69e94ab3e1 | ||
|
|
4458533372 | ||
|
|
ad9251e332 | ||
|
|
ffeebfa4aa | ||
|
|
bc04bf866a | ||
|
|
3a2af01ad2 | ||
|
|
27d884ff31 | ||
|
|
c69b05501e | ||
|
|
6119cb77a8 | ||
|
|
01b0ca9817 | ||
|
|
7e188cadaf | ||
|
|
f12d16d686 | ||
|
|
441f53077b | ||
|
|
cb2b33b9e2 | ||
|
|
f50497b49a | ||
|
|
9fa699d22d | ||
|
|
d94034dc6e | ||
|
|
9b2f44dfaf | ||
|
|
a4f0d85cf7 | ||
|
|
4c21049e59 | ||
|
|
921aea4623 | ||
|
|
465ab57125 | ||
|
|
83be201d0f | ||
|
|
251dad766b | ||
|
|
880d839b52 | ||
|
|
197f986088 | ||
|
|
3925baef3c | ||
|
|
143b1f5d80 | ||
|
|
0461bf4ffc | ||
|
|
5e0809c448 | ||
|
|
b4c3fbeb19 | ||
|
|
44cedde712 | ||
|
|
ba31683d48 | ||
|
|
9780dcdb76 | ||
|
|
c3746996a1 | ||
|
|
58f986f0f7 | ||
|
|
0551558b8f | ||
|
|
3808edafca | ||
|
|
b85c85f4fd | ||
|
|
3956879fb8 | ||
|
|
4c8536faeb | ||
|
|
ef019df6fa | ||
|
|
415833c9b0 | ||
|
|
e844df3f26 | ||
|
|
2678ab40aa | ||
|
|
360725d4c5 | ||
|
|
2288d193fd | ||
|
|
16f8f15111 | ||
|
|
8bec54970b | ||
|
|
607b510bd1 | ||
|
|
71d174a90c | ||
|
|
45fb0d1ead | ||
|
|
f7cfb5d813 | ||
|
|
24598168bf | ||
|
|
7a5f4e317a | ||
|
|
bb8e6d391f | ||
|
|
14ce1934f1 | ||
|
|
a6f362523b | ||
|
|
6cbe823c23 | ||
|
|
5c3a7c3fce | ||
|
|
74399c49dc | ||
|
|
8dd6cd6a1f | ||
|
|
25fe2617dc | ||
|
|
6d4ea72e58 | ||
|
|
29ab1f35f2 | ||
|
|
adfb2a7c86 | ||
|
|
3f434737f8 | ||
|
|
097c8b7ce3 | ||
|
|
bfa229edbd | ||
|
|
de15485d64 | ||
|
|
b4c81b9359 | ||
|
|
ee61f49e63 | ||
|
|
4595c6b00c | ||
|
|
39b9b0e5a2 | ||
|
|
5c34d4fdee | ||
|
|
de4a1222e8 | ||
|
|
62d1ef6a61 | ||
|
|
c7cf0c073c | ||
|
|
6439684c70 | ||
|
|
eb7bbb0dad | ||
|
|
4b909dc85a | ||
|
|
66f1eef91f | ||
|
|
7beccd980b | ||
|
|
13cd8c0348 | ||
|
|
4408508625 | ||
|
|
65a3772b3a | ||
|
|
786dbef1c1 | ||
|
|
c7f1b6af2e | ||
|
|
c81b7b71cc | ||
|
|
159a95e75b | ||
|
|
385846605a | ||
|
|
789b16518c | ||
|
|
2af10d0bca | ||
|
|
5998db8df3 | ||
|
|
78133f3f00 | ||
|
|
10364ef2c9 | ||
|
|
210e738bec | ||
|
|
67dfb659ce | ||
|
|
1d60f62bcc | ||
|
|
fbb0f5c6a2 | ||
|
|
6c6d5b870e | ||
|
|
60ae8a8361 | ||
|
|
1d206d4dc7 | ||
|
|
4bb70ad57a | ||
|
|
2748d23cbf | ||
|
|
282bc50d3e | ||
|
|
40b6d23dd3 | ||
|
|
d236d26657 | ||
|
|
ac3b360c42 | ||
|
|
5eb572dfad | ||
|
|
f76db64995 | ||
|
|
37c0e2a024 | ||
|
|
06fa14bae4 | ||
|
|
1550a6c533 | ||
|
|
4229be161e | ||
|
|
7e7eb62e0a | ||
|
|
a7896ab1f9 | ||
|
|
3db3f55472 | ||
|
|
817c829bee | ||
|
|
1f5b008520 | ||
|
|
db1a0ec601 | ||
|
|
414995a8cd | ||
|
|
a9169367f6 | ||
|
|
ea8bde1fe1 | ||
|
|
12512c96a9 | ||
|
|
6ac5614982 | ||
|
|
694e01ce99 | ||
|
|
77e23811ed | ||
|
|
94fc06283c | ||
|
|
d9ed72b472 | ||
|
|
f8e88fb4bf | ||
|
|
e0aa2d392b | ||
|
|
1282c93fe4 | ||
|
|
bd4a143a0a | ||
|
|
f32efaa68e | ||
|
|
ce82285772 | ||
|
|
1d398287eb | ||
|
|
ed1f227608 | ||
|
|
81fb399932 | ||
|
|
db0758e949 | ||
|
|
3dabc3bc9c | ||
|
|
9f5c2c18c4 | ||
|
|
2f4ba89b17 | ||
|
|
fb93a3dc08 | ||
|
|
50dca0cc52 | ||
|
|
c3dbc9d8dd | ||
|
|
faaf125e13 | ||
|
|
ce7e1a5708 | ||
|
|
3ea42cc786 | ||
|
|
eb712ecf83 | ||
|
|
03f33b524c | ||
|
|
207b2a10de | ||
|
|
24ac8deb08 | ||
|
|
a4583a31ac | ||
|
|
71556f841f | ||
|
|
6a8c2dc99c | ||
|
|
b95a83eba2 | ||
|
|
66d92c1bba | ||
|
|
514a63b80a | ||
|
|
283297a51f | ||
|
|
bd411b5d01 | ||
|
|
bcc8d6e0d8 | ||
|
|
f63f1ba95d | ||
|
|
558c98a8cd | ||
|
|
f011540686 | ||
|
|
e9c7a13548 | ||
|
|
789c31445b | ||
|
|
b4f6fa191f | ||
|
|
a413c588bf | ||
|
|
1e58a75b25 | ||
|
|
309d127ec5 | ||
|
|
a22a2e5fd6 | ||
|
|
0876dac2d2 | ||
|
|
2df8bfad1d | ||
|
|
9d6be94f18 | ||
|
|
bf35fd05fc | ||
|
|
61339381d2 | ||
|
|
63f81fa37b | ||
|
|
c22f430f13 | ||
|
|
4353fc9f0b | ||
|
|
ca95932107 | ||
|
|
8c493c596c | ||
|
|
8445f021f6 | ||
|
|
b363f7ed37 | ||
|
|
389b00e89e | ||
|
|
a9f17f4861 | ||
|
|
6dc0500cdb | ||
|
|
de8370eb4b | ||
|
|
5bcfd7a2a1 | ||
|
|
b9f2203c7c | ||
|
|
ac5854ec0a | ||
|
|
da6987cb53 | ||
|
|
0022be942a | ||
|
|
94bc061c72 | ||
|
|
84aa4d7c69 | ||
|
|
32c0550e5f | ||
|
|
17c6548dd2 | ||
|
|
2d2eef848a | ||
|
|
c6d86dd427 | ||
|
|
ecd8e3aa8a | ||
|
|
7a6f1e981f | ||
|
|
85050fe395 | ||
|
|
24db266358 | ||
|
|
3563ff0f2d | ||
|
|
a18e7cfc20 | ||
|
|
f91b8a9982 | ||
|
|
c6c2fc0ffc | ||
|
|
01cc4a629d | ||
|
|
b5cb619399 | ||
|
|
dd55cb3def | ||
|
|
3516d143b8 | ||
|
|
73c1790e79 | ||
|
|
401879cdfe | ||
|
|
f610a5e2e9 | ||
|
|
6fd0cd0803 | ||
|
|
188007d6e1 | ||
|
|
9019b75248 | ||
|
|
71976a9216 | ||
|
|
f03d420e31 | ||
|
|
41a49d1071 | ||
|
|
331298a22c | ||
|
|
db7d9cc979 | ||
|
|
b8a8388573 | ||
|
|
62f6e9ba7c | ||
|
|
e24887ba45 | ||
|
|
7d70e27472 | ||
|
|
3d57a979f5 | ||
|
|
3eb02d6964 | ||
|
|
3c5bde4a07 | ||
|
|
c93fd06898 | ||
|
|
2ae384daa5 | ||
|
|
f2e6c9669c | ||
|
|
7267e3e6a0 | ||
|
|
ac7fdf5bc3 | ||
|
|
94837b3259 | ||
|
|
1244be40e1 | ||
|
|
284d56853c | ||
|
|
5368b1778a | ||
|
|
597dbfeb64 | ||
|
|
dc6e26ca7c | ||
|
|
9aad734635 | ||
|
|
de4c520045 | ||
|
|
377f754b88 | ||
|
|
934fedf39a | ||
|
|
be133208a2 | ||
|
|
b2c47c9c91 | ||
|
|
b31c630c1b | ||
|
|
0797335934 | ||
|
|
6d075c2a9a | ||
|
|
ef6109c206 | ||
|
|
05bba94e17 | ||
|
|
e7d667d481 | ||
|
|
e1fc49f955 | ||
|
|
0d7a01a81b | ||
|
|
15f8e49ed9 | ||
|
|
32c6ef23cd | ||
|
|
0eeb1ecd70 | ||
|
|
6c55a22921 | ||
|
|
0b3b212a67 | ||
|
|
68e729b823 | ||
|
|
ccc557dc8c | ||
|
|
f260377dcd | ||
|
|
ea2ca734a1 | ||
|
|
44be0bec3b | ||
|
|
4e12762b8f | ||
|
|
68bd84549d | ||
|
|
e57ee84836 | ||
|
|
7085a6b190 | ||
|
|
9cc5564e23 | ||
|
|
30f0cae65a | ||
|
|
360e980900 | ||
|
|
a4bf41bffd | ||
|
|
f340f5b51b | ||
|
|
aadf1daf6e | ||
|
|
75f27cbd6a | ||
|
|
8517624bd9 | ||
|
|
cc0a7205d5 | ||
|
|
8633b7e2de | ||
|
|
747757fa5e | ||
|
|
d8aac30c3a | ||
|
|
e8e9419758 | ||
|
|
a3e4fb4198 | ||
|
|
068ca78259 | ||
|
|
bbef35d793 | ||
|
|
056a6f91a4 | ||
|
|
84daea05b2 | ||
|
|
c63a32f44b | ||
|
|
196abfc5ce | ||
|
|
ffce4f26f2 | ||
|
|
9c9cd79a20 | ||
|
|
5790b920b3 | ||
|
|
ad38a56657 | ||
|
|
dc03eef9c6 | ||
|
|
266019b6ea | ||
|
|
4c7deca61b | ||
|
|
997366d5e2 | ||
|
|
1ed9ad4c9f | ||
|
|
ccee1db149 | ||
|
|
175c608c11 | ||
|
|
ea9a40a297 | ||
|
|
2f1266cdd0 | ||
|
|
e8672ddaa2 | ||
|
|
8cd71508f8 | ||
|
|
f9fafdd642 | ||
|
|
1c21dcaddd | ||
|
|
8174154394 | ||
|
|
ac1213336c | ||
|
|
c7d7c4557b | ||
|
|
ef7aa73031 | ||
|
|
1a60a76fd5 | ||
|
|
c421b96e3b | ||
|
|
1362bfcecb | ||
|
|
fcde435d90 | ||
|
|
2570fc90e7 | ||
|
|
a6eed677ce | ||
|
|
3d8378bcd7 | ||
|
|
e1ae515d23 | ||
|
|
eed4f0e1dd | ||
|
|
34d8e055de | ||
|
|
bc91301c11 | ||
|
|
e60994eb92 | ||
|
|
cf61a8a6e1 | ||
|
|
c7e981fc25 | ||
|
|
76d0f88dbd | ||
|
|
d789fcaf61 | ||
|
|
8b1450a334 | ||
|
|
beb782b50a | ||
|
|
b20d72860e | ||
|
|
82a5c04477 | ||
|
|
cfe6396267 | ||
|
|
0ae9c0ec13 | ||
|
|
8787f7277a | ||
|
|
105a7ddd56 | ||
|
|
436ae975c8 | ||
|
|
12c82f03c5 | ||
|
|
514fd6da1f | ||
|
|
c10dc68a1c | ||
|
|
076c8970b6 | ||
|
|
23ef2c7879 | ||
|
|
654c5feed2 | ||
|
|
d426d03eb2 | ||
|
|
ded6b69ebf | ||
|
|
393c25ce77 | ||
|
|
5a7bfc2921 | ||
|
|
9fa317a662 | ||
|
|
3fa20a2c69 | ||
|
|
f1f48fcfdb | ||
|
|
64a25bc980 | ||
|
|
c66be61fd2 | ||
|
|
b067ec1d36 | ||
|
|
cea6207662 | ||
|
|
b4da98a9a6 | ||
|
|
7467ae9f5f | ||
|
|
1d9313a2c1 | ||
|
|
7c58dbd96e | ||
|
|
aaaa05ea02 | ||
|
|
76d8076172 | ||
|
|
690a89d925 | ||
|
|
2cfd53cb89 | ||
|
|
f1ca524783 | ||
|
|
e9f1b723fd | ||
|
|
288ab56403 | ||
|
|
bc6d1a00db | ||
|
|
7b7c0bbda6 | ||
|
|
ba90b8ad6f | ||
|
|
a08c0a86a3 | ||
|
|
57ad385cee | ||
|
|
9c31d929a2 | ||
|
|
97f317b396 | ||
|
|
55da028e56 | ||
|
|
9fb8bc38b2 | ||
|
|
ccc686cc10 | ||
|
|
06e53921c0 | ||
|
|
79abdc3841 | ||
|
|
f8e7bf9d7b | ||
|
|
ae9811a198 | ||
|
|
faf4f490bf | ||
|
|
8d9e595082 | ||
|
|
8544c0b95b | ||
|
|
bf5dfb3c1a | ||
|
|
749787b9ff | ||
|
|
630ef694db | ||
|
|
793d763e25 | ||
|
|
cafe25101a | ||
|
|
4e99bef678 | ||
|
|
d29c41e805 | ||
|
|
bbd8b131e8 | ||
|
|
f3d5c4b66b | ||
|
|
ef60dad626 | ||
|
|
98537ac168 | ||
|
|
91d3e9756a | ||
|
|
98e62a0576 | ||
|
|
3a6860109b | ||
|
|
6180a5123c | ||
|
|
476b753baa | ||
|
|
32b9ab48c3 | ||
|
|
7788ca6e5e | ||
|
|
988213c981 | ||
|
|
a0c8dbdc22 | ||
|
|
65e0202312 | ||
|
|
1a47dd7c17 | ||
|
|
2117147d76 | ||
|
|
7cfd8d4412 | ||
|
|
3bd96e02ad | ||
|
|
d6a572b27c | ||
|
|
90f241b7fd | ||
|
|
f45b75f07a | ||
|
|
3d771d4b20 | ||
|
|
11ff1c6774 | ||
|
|
abdbec1134 | ||
|
|
e1b4be58ab | ||
|
|
9c80954773 | ||
|
|
17a911d50b | ||
|
|
df62ebdad4 | ||
|
|
5014abc21c | ||
|
|
01f856c3aa | ||
|
|
57a8aafbf4 | ||
|
|
53ef1def47 | ||
|
|
5288bd2aec | ||
|
|
1ea04e84b3 | ||
|
|
74bff29a05 | ||
|
|
d73a84a764 | ||
|
|
7048e775ef | ||
|
|
482ba146dc | ||
|
|
f02582705f | ||
|
|
ea132630c6 | ||
|
|
058342222a | ||
|
|
032d94a7c5 | ||
|
|
182da9da14 | ||
|
|
59cc67b73d | ||
|
|
21b74a06f4 | ||
|
|
5a03398bec | ||
|
|
fcd2757868 | ||
|
|
fdaa62c569 | ||
|
|
f092a1ecc7 | ||
|
|
40a9b0d0ee | ||
|
|
cf504c036b | ||
|
|
016f533a29 | ||
|
|
d7ebcdbd77 | ||
|
|
710d152bb3 | ||
|
|
016ce19b3c | ||
|
|
c7dd702849 | ||
|
|
99ada94f32 | ||
|
|
108d20098f | ||
|
|
e960471ee3 | ||
|
|
68a9f3ebfc | ||
|
|
6cd3088da4 | ||
|
|
069f40f2ca | ||
|
|
246aaf4b26 | ||
|
|
ff73fb0e08 | ||
|
|
c7fe3e2c0e | ||
|
|
4578cd9695 | ||
|
|
595f9a0e69 | ||
|
|
ee7662f96b | ||
|
|
93eeba64c0 | ||
|
|
975ae49594 | ||
|
|
58562fdb53 |
No files matched your search
@@ -0,0 +1 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
+3
-49
@@ -1,52 +1,6 @@
|
||||
# Maintenance Changelog
|
||||
This file contains update logs for this project. The top may contain a `Unreleased` section, gathering update logs for a future update during development.
|
||||
|
||||
## 5.1.1 - October 17th 2026
|
||||
|
||||
### Changed
|
||||
- Velocity/Bungee: Timer commands now accept `global` as the server argument, with an optional mode: `/maintenance starttimer global [mode] <time>`, `/maintenance scheduletimer global [mode] <time> <duration>`, `/maintenance endtimer global <time>`
|
||||
- Timer durations now also accept days, e.g. `2d` or `1d12h`
|
||||
- Folia: Now supports timers
|
||||
|
||||
### Fixed
|
||||
- Folia: Fixed the update check stalling the global region thread
|
||||
- Velocity/Bungee: Fixed the `redis.enabled` confg key
|
||||
- Velocity/Bungee: `/maintenance reload` now keeps the maintenance status from Redis instead of overriding it with the local config
|
||||
- Velocity/Bungee: Fixed `/maintenance aborttimer` tab completion not suggesting servers with running timers
|
||||
|
||||
---
|
||||
## 5.1.0 - May 17th 2026
|
||||
|
||||
### Changed
|
||||
- Made Discord webhooks configurable separately from command messages, including a new `%TIMESTAMP%` parameter for Discord timestamps (e.g. `<t:%TIMESTAMP%:R>`)
|
||||
|
||||
### Fixed
|
||||
- Velocity/Bungee: Fixed proxied-maintenance-servers config loading
|
||||
---
|
||||
## 5.0.0 - April 17th 2026
|
||||
|
||||
This update removes *a lot* of legacy code, making the code-base a great bit more simple and a lot more performant.
|
||||
|
||||
### Requirements
|
||||
- The Paper part now **requires at least Paper 1.20.1** and no longer supports Spigot
|
||||
- The universal jar has been removed. Each platform now has its own jar (that is as small as possible)
|
||||
- Maintenance now **requires at least Java 21**
|
||||
|
||||
### Changed
|
||||
- **Added mode-based maintenance messages** for `ping-message`, `player-count-message`, and `player-list-hover-message`
|
||||
- You can have different MOTDs depending on the pre-configured mode, e.g. a generic `default` or one for `upcoming-release`.
|
||||
- Updated proxy/global toggle syntax: `/maintenance on [mode]`
|
||||
- For proxy servers: `/maintenance on global [mode]`, `/maintenance on <server> [mode]`
|
||||
- Other updated commands: `/maintenance motd [timer] [mode]`, `/maintenance setmotd [timer] [mode] ...`, `/maintenance removemotd [timer] [mode] ...`
|
||||
- **Added `webhook` config option for Discord webhooks** when the maintenance status changes, a timer is started or a join is blocked
|
||||
- **Added `%REASON%` variable to messages**, using the `active-reason` config option. This allows for dynamic MOTD and other messages via a quick command without modifying the messages themselves
|
||||
- Can be changed via the `/maintenance setreason <reason>` command
|
||||
- **Added `/maintenance status` command** on Paper/Sponge to display the current maintenance status as well as any running start or end timers.
|
||||
- Velocity/Bungee: **The existing timer command now displays start and end timers** for proxied servers.
|
||||
- Velocity/Bungee: **Replaced `mysql` section with `redis`**. This is a more suitable database for such reading and sharing of data and no longer means some server pings can take multiple seconds, if you have multiple proxies linked
|
||||
|
||||
### Fixed
|
||||
- Velocity/Bungee: Fixed the `/maintenance schedule` command for single servers having swapped time arguments
|
||||
---
|
||||
## 4.3.0 - September 17th 2024
|
||||
### Changed
|
||||
@@ -110,8 +64,8 @@ This update removes *a lot* of legacy code, making the code-base a great bit mor
|
||||
### Changed
|
||||
* Added support for hex colors in messages and replaced the component parsing with adventure-minimessage
|
||||
* This means that section symbols (`§`) are no longer the intended/supported format
|
||||
* You can use the following page to edit and preview formatted text: https://webui.advntr.dev/
|
||||
* You can find full documentation on the format (including normal colors and formatting, rgb, click/hover events, and more) here: https://docs.papermc.io/adventure/minimessage/format/
|
||||
* You can use the following page to edit and preview formatted text: https://webui.adventure.kyori.net/
|
||||
* You can find full documentation on the format (including normal colors and formatting, rgb, click/hover events, and more) here: https://docs.adventure.kyori.net/minimessage/format
|
||||
* Your config and language file will be updated to the new format automatically, you won't have to change anything manually!
|
||||
* Note that the player count and player count hover messages do not support rgb colors
|
||||
* Updated Sponge module to SpongeAPI v8 (Minecraft 1.15+)
|
||||
@@ -373,4 +327,4 @@ This update removes *a lot* of legacy code, making the code-base a great bit mor
|
||||
### Fixed
|
||||
* Fixed some permission and message bugs
|
||||
* Fixed problems with adding and removing players from the maintenance whitelist
|
||||
* Fixed update checks
|
||||
* Fixed update checks
|
||||
@@ -1,14 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
- package-ecosystem: "gradle"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
@@ -7,22 +7,20 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
- uses: gradle/actions/wrapper-validation@v3
|
||||
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v6
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Maintenance Files
|
||||
path: build/libs
|
||||
@@ -14,7 +14,7 @@ Its features include:
|
||||
* Nearly all messages are editable via the language file, given in a multitude of different languages
|
||||
* Features specifically for Bungee/Velocity
|
||||
* Only want to enable maintenance on a single server? You can also do so by using the `/maintenance <on/off> <servername>` command
|
||||
* Link multiple proxy instances through a Redis connection, so you don't have to change maintenance status or whitelisted players on each proxy by hand
|
||||
* Link multiple proxy instances through a MySQL database connection, so you don't have to change maintenance on each proxy by hand
|
||||
* Use PlaceholderAPI placeholders with the [**MaintenanceAddon**](https://hangar.papermc.io/kennytv/MaintenanceAddon) (for Velocity and Bungee)
|
||||
|
||||
A full list of commands, permissions and configuration options can be found in the wiki listed below.
|
||||
@@ -33,7 +33,7 @@ Join [our Discord](https://discord.gg/vGCUzHq) if you want to get the proofreade
|
||||
Adding translations for languages not yet listed is always appreciated as well!
|
||||
|
||||
## Compiling
|
||||
To create a working jar yourself, simply clone the project and compile it with Gradle (`gradlew build`). To compile, you need a JDK 21+ (although it targets 17).
|
||||
To create a working jar yourself, simply clone the project and compile it with Gradle (`gradlew build`).
|
||||
|
||||
## License
|
||||
This project is licensed under the [GNU General Public License v3](LICENSE.txt).
|
||||
@@ -0,0 +1,24 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
// Shade and relocate adventure in an extra module, so that common/the rest can directly depend on a
|
||||
// relocated adventure without breaking native platform's adventure usage with project wide relocation
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.bundles.adventure) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
exclude("net.kyori", "adventure-bom")
|
||||
exclude("com.google.code.gson", "gson")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
@@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.adventurePlatformBukkit) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
@@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.adventurePlatformBungee) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
@@ -4,7 +4,9 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
api(projects.maintenanceApi)
|
||||
compileOnly(libs.adventureApi)
|
||||
compileOnly(projects.adventure.adventureApi) {
|
||||
targetConfiguration = "shadow"
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@@ -18,26 +18,23 @@
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.api.Maintenance;
|
||||
import java.util.Set;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface MaintenanceProxy extends Maintenance {
|
||||
|
||||
/**
|
||||
* Enables/disables maintenance mode on a proxied server.
|
||||
* If enabled, all non-permitted players will be kicked.
|
||||
* If Redis is enabled, it will also be written into the database.
|
||||
* If MySQL is enabled, it will also be written into the database.
|
||||
*
|
||||
* @param server server to apply the maintenance status to
|
||||
* @param maintenance true to enable, false to disable maintenance mode
|
||||
* @return true if the mode was changed
|
||||
* @see #getServer(String)
|
||||
*/
|
||||
boolean setMaintenanceToServer(Server server, boolean maintenance, @Nullable String mode);
|
||||
|
||||
default boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
return setMaintenanceToServer(server, maintenance, null);
|
||||
}
|
||||
boolean setMaintenanceToServer(Server server, boolean maintenance);
|
||||
|
||||
/**
|
||||
* @param server server to check
|
||||
@@ -62,18 +59,6 @@ public interface MaintenanceProxy extends Maintenance {
|
||||
@Nullable
|
||||
Server getServer(String server);
|
||||
|
||||
/**
|
||||
* Returns a wrapped {@link Server} object of a proxied server, or a dummy server if not registered.
|
||||
*
|
||||
* @param serverName name of the proxied server
|
||||
* @return wrapped server object, or a dummy if not registered
|
||||
* @see Server#isRegisteredServer()
|
||||
*/
|
||||
default Server getServerOrDummy(final String serverName) {
|
||||
final Server server = getServer(serverName);
|
||||
return server != null ? server : new DummyServer(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered proxied servers.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
/**
|
||||
* Wrapper for a proxied server.
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package eu.kennytv.maintenance.api;
|
||||
|
||||
import eu.kennytv.maintenance.api.event.manager.EventManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Maintenance {
|
||||
|
||||
@@ -26,18 +25,13 @@ public interface Maintenance {
|
||||
* Enables/disables maintenance mode.
|
||||
* If enabled, all non-permitted players will be kicked.
|
||||
* <p>
|
||||
* If using the BungeeCord version and Redis is enabled,
|
||||
* If using the BungeeCord version and MySQL is enabled,
|
||||
* it will also be written into the database.
|
||||
* </p>
|
||||
*
|
||||
* @param maintenance true to enable, false to disable maintenance mode
|
||||
* @param mode mode, used for custom messages
|
||||
*/
|
||||
void setMaintenance(boolean maintenance, @Nullable String mode);
|
||||
|
||||
default void setMaintenance(boolean maintenance) {
|
||||
setMaintenance(maintenance, null);
|
||||
}
|
||||
void setMaintenance(boolean maintenance);
|
||||
|
||||
/**
|
||||
* @return true if maintenance is currently enabled
|
||||
|
||||
@@ -19,39 +19,16 @@ package eu.kennytv.maintenance.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Settings {
|
||||
|
||||
/**
|
||||
* Returns whether maintenance is currently enabled.
|
||||
* Note that the value might need a few seconds to update, if you're on BungeeCord with MySQL enabled
|
||||
*
|
||||
* @return true if maintenance is currently enabled
|
||||
*/
|
||||
boolean isMaintenance();
|
||||
|
||||
/**
|
||||
* Returns the current active maintenance mode, or null is set to default.
|
||||
* Used when getting MOTD/player count messages.
|
||||
*
|
||||
* @return the current active maintenance mode, or null if set to default
|
||||
*/
|
||||
@Nullable String activeMode();
|
||||
|
||||
/**
|
||||
* Returns the reason for the current active mode.
|
||||
*
|
||||
* @return variable reason for the current active mode, or empty if no reason is set
|
||||
*/
|
||||
String activeReason();
|
||||
|
||||
/**
|
||||
* Sets the reason for the current active mode, used in %REASON% message placeholders.
|
||||
*
|
||||
* @param reason reason to set for the current active mode, or null to remove the reason
|
||||
*/
|
||||
void setActiveReason(@Nullable String reason);
|
||||
|
||||
/**
|
||||
* @return true if custom ping messages during maintenance should be used
|
||||
*/
|
||||
@@ -96,8 +73,8 @@ public interface Settings {
|
||||
*
|
||||
* @param name name of the player to remove with original lower-/uppercase letters
|
||||
* @return true if removing the player was successful
|
||||
* @see #removeWhitelistedPlayer(UUID)
|
||||
* @deprecated if a player changes their name, the list will still contain the old one
|
||||
* @see #removeWhitelistedPlayer(UUID)
|
||||
*/
|
||||
@Deprecated
|
||||
boolean removeWhitelistedPlayer(String name);
|
||||
|
||||
@@ -22,5 +22,17 @@ import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
|
||||
/**
|
||||
* Notification event fired when maintenance mode has been changed.
|
||||
*/
|
||||
public record MaintenanceChangedEvent(boolean isMaintenance) implements MaintenanceEvent {
|
||||
public final class MaintenanceChangedEvent implements MaintenanceEvent {
|
||||
private final boolean maintenance;
|
||||
|
||||
public MaintenanceChangedEvent(final boolean maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if maintenance has been enabled, false otherwise
|
||||
*/
|
||||
public boolean isMaintenance() {
|
||||
return maintenance;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,5 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
// version must be manually kept in sync with the one in root project settings.gradle.kts
|
||||
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.6.1")
|
||||
implementation("com.gradleup.nmcp:com.gradleup.nmcp.gradle.plugin:1.6.2")
|
||||
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.9")
|
||||
}
|
||||
@@ -6,12 +6,12 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun Project.publishShadowJar() {
|
||||
configurePublication {
|
||||
artifact(tasks["shadowJar"])
|
||||
artifact(tasks["sourcesJar"])
|
||||
artifact(tasks["javadocJar"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,3 +34,7 @@ fun Project.latestCommitHash(): String {
|
||||
commandLine = listOf("git", "rev-parse", "--short", "HEAD")
|
||||
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
|
||||
}
|
||||
|
||||
fun JavaPluginExtension.javaTarget(version: Int) {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
@@ -2,7 +2,6 @@ plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
signing
|
||||
id("com.gradleup.nmcp")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -11,7 +10,7 @@ tasks {
|
||||
val ver = project.version.toString()
|
||||
val desc = project.description
|
||||
filesMatching(listOf("plugin.yml", "bungee.yml", "META-INF/sponge_plugins.json")) {
|
||||
expand(mapOf("version" to ver, "description" to desc))
|
||||
expand("version" to ver, "description" to desc)
|
||||
}
|
||||
}
|
||||
javadoc {
|
||||
@@ -28,10 +27,8 @@ tasks {
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
javaTarget(8)
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
signing {
|
||||
@@ -48,11 +45,6 @@ publishing {
|
||||
name.set("Maintenance")
|
||||
description.set("Paper plugin to enable maintenance mode on your Minecraft server.")
|
||||
url.set("https://github.com/kennytv/Maintenance")
|
||||
scm {
|
||||
url.set("https://github.com/kennytv/Maintenance")
|
||||
connection.set("scm:git:https://github.com/kennytv/Maintenance.git")
|
||||
developerConnection.set("scm:git:ssh://git@github.com/kennytv/Maintenance.git")
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name.set("GNU GPLv3")
|
||||
@@ -67,4 +59,15 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!name.startsWith("adventure")) {
|
||||
repositories.maven {
|
||||
name = "OSSRH"
|
||||
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
credentials {
|
||||
username = System.getenv("OSSRH_USERNAME")
|
||||
password = System.getenv("OSSRH_PASSWORD")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.named
|
||||
|
||||
plugins {
|
||||
id("maintenance.base-conventions")
|
||||
@@ -23,10 +24,6 @@ tasks {
|
||||
publishShadowJar()
|
||||
|
||||
fun ShadowJar.configureRelocations() {
|
||||
relocate("com.zaxxer.hikari", "eu.kennytv.maintenance.lib.hikari")
|
||||
relocate("org.bstats", "eu.kennytv.maintenance.lib.bstats")
|
||||
|
||||
// Proxy
|
||||
relocate("redis.client", "eu.kennytv.maintenance.lib.redis.client")
|
||||
relocate("org.json", "eu.kennytv.maintenance.lib.json")
|
||||
relocate("org.apache.commons.pool2", "eu.kennytv.maintenance.lib.apache.commons.pool2")
|
||||
}
|
||||
+6
-21
@@ -1,10 +1,9 @@
|
||||
import org.gradle.api.plugins.JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME
|
||||
import org.gradle.api.plugins.JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME
|
||||
|
||||
plugins {
|
||||
base
|
||||
id("eclipse")
|
||||
id("maintenance.build-logic")
|
||||
id("com.gradleup.nmcp.aggregation") version "1.6.2"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -15,14 +14,17 @@ allprojects {
|
||||
|
||||
val platforms = setOf(
|
||||
projects.maintenancePaper,
|
||||
projects.maintenanceBungee,
|
||||
projects.maintenanceSponge,
|
||||
projects.maintenanceVelocity
|
||||
).map { it.path }
|
||||
|
||||
val special = setOf(
|
||||
projects.maintenance,
|
||||
projects.maintenanceApi,
|
||||
projects.maintenanceApiProxy
|
||||
projects.maintenanceApiProxy,
|
||||
projects.adventure,
|
||||
projects.adventure.adventureApi,
|
||||
projects.adventure.adventurePlatformBukkit,
|
||||
).map { it.path }
|
||||
|
||||
subprojects {
|
||||
@@ -35,22 +37,5 @@ subprojects {
|
||||
dependencies {
|
||||
TEST_IMPLEMENTATION_CONFIGURATION_NAME(rootProject.libs.bundles.junit)
|
||||
TEST_IMPLEMENTATION_CONFIGURATION_NAME(rootProject.libs.snakeyaml)
|
||||
TEST_RUNTIME_ONLY_CONFIGURATION_NAME("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
allprojects {
|
||||
nmcpAggregation(project(path))
|
||||
}
|
||||
}
|
||||
|
||||
nmcpAggregation {
|
||||
centralPortal {
|
||||
username = System.getenv("MAVEN_CENTRAL_USERNAME")
|
||||
password = System.getenv("MAVEN_CENTRAL_PASSWORD")
|
||||
publishingType = "USER_MANAGED"
|
||||
publicationName = "maintenance:$version"
|
||||
publishingTimeout = java.time.Duration.ZERO
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
dependencies {
|
||||
implementation(projects.maintenanceCoreProxy)
|
||||
implementation(libs.bstatsBungee)
|
||||
compileOnly(libs.bungee)
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.bundles.adventureBungee) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("org.slf4j", "slf4j-api")
|
||||
exclude("net.kyori", "adventure-bom")
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee;
|
||||
|
||||
import eu.kennytv.maintenance.api.Maintenance;
|
||||
import eu.kennytv.maintenance.core.MaintenanceBase;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public final class MaintenanceBungeeBase extends Plugin implements MaintenanceBase {
|
||||
private MaintenanceBungeePlugin maintenance;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
maintenance = new MaintenanceBungeePlugin(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
maintenance.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maintenance getApi() {
|
||||
return maintenance;
|
||||
}
|
||||
|
||||
File getPluginFile() {
|
||||
return getFile();
|
||||
}
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommand;
|
||||
import eu.kennytv.maintenance.bungee.command.MaintenanceBungeeCommandBase;
|
||||
import eu.kennytv.maintenance.bungee.listener.ProxyPingListener;
|
||||
import eu.kennytv.maintenance.bungee.listener.ServerConnectListener;
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeServer;
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeTask;
|
||||
import eu.kennytv.maintenance.bungee.util.ComponentUtil;
|
||||
import eu.kennytv.maintenance.core.dump.PluginDump;
|
||||
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.hook.LuckPermsProxyHook;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProfileLookup;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProxyOfflineSenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.imageio.ImageIO;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import org.bstats.bungeecord.Metrics;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
|
||||
private final MaintenanceBungeeBase plugin;
|
||||
private final BungeeAudiences audiences;
|
||||
private Favicon favicon;
|
||||
|
||||
MaintenanceBungeePlugin(final MaintenanceBungeeBase plugin) {
|
||||
super(plugin.getDescription().getVersion(), ServerType.BUNGEE);
|
||||
this.plugin = plugin;
|
||||
this.audiences = BungeeAudiences.create(plugin);
|
||||
|
||||
settingsProxy = new SettingsProxy(this);
|
||||
settings = settingsProxy;
|
||||
|
||||
sendEnableMessage();
|
||||
|
||||
final PluginManager pm = getProxy().getPluginManager();
|
||||
pm.registerListener(plugin, new ProxyPingListener(this, settingsProxy));
|
||||
pm.registerListener(plugin, new ServerConnectListener(this, settingsProxy));
|
||||
commandManager = new MaintenanceBungeeCommand(this, settingsProxy);
|
||||
pm.registerCommand(plugin, new MaintenanceBungeeCommandBase(commandManager));
|
||||
|
||||
continueLastEndtimer();
|
||||
new Metrics(plugin, 742);
|
||||
|
||||
final Plugin serverListPlus = pm.getPlugin("ServerListPlus");
|
||||
if (serverListPlus != null) {
|
||||
serverListPlusHook = new ServerListPlusHook(serverListPlus);
|
||||
if (settings.isEnablePingMessages()) {
|
||||
serverListPlusHook.setEnabled(!settingsProxy.isMaintenance());
|
||||
}
|
||||
plugin.getLogger().info("Enabled ServerListPlus integration!");
|
||||
}
|
||||
|
||||
if (false && pm.getPlugin("LuckPerms") != null) {
|
||||
LuckPermsProxyHook.<ProxiedPlayer>register(this, player -> {
|
||||
final net.md_5.bungee.api.connection.Server server = player.getServer();
|
||||
return server != null ? server.getInfo().getName() : null;
|
||||
});
|
||||
getLogger().info("Registered LuckPerms context");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMaintenance(final ServerInfo serverInfo) {
|
||||
return settingsProxy.isMaintenance(serverInfo.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void kickPlayersFromProxy() {
|
||||
for (final ProxiedPlayer player : getProxy().getPlayers()) {
|
||||
if (!hasPermission(player, "bypass") && !settingsProxy.isWhitelisted(player.getUniqueId())) {
|
||||
player.disconnect(ComponentUtil.toBadComponents(settingsProxy.getKickMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void kickPlayers(final Server server, final Server fallback) {
|
||||
// Kick players from a proxied server
|
||||
final ServerInfo fallbackServer = fallback != null ? ((BungeeServer) fallback).server() : null;
|
||||
final boolean checkForFallback = fallbackServer != null && !isMaintenance(fallback);
|
||||
for (final ProxiedPlayer player : ((BungeeServer) server).server().getPlayers()) {
|
||||
if (!hasPermission(player, "bypass") && !settingsProxy.isWhitelisted(player.getUniqueId())) {
|
||||
if (checkForFallback && fallbackServer.canAccess(player)) {
|
||||
audiences.player(player).sendMessage(settingsProxy.getMessage("singleMaintenanceActivated", "%SERVER%", server.getName()));
|
||||
player.connect(fallbackServer);
|
||||
} else {
|
||||
player.disconnect(ComponentUtil.toBadComponents(settingsProxy.getFullServerKickMessage(server.getName())));
|
||||
}
|
||||
} else {
|
||||
audiences.player(player).sendMessage(settingsProxy.getMessage("singleMaintenanceActivated", "%SERVER%", server.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void kickPlayersTo(final Server server) {
|
||||
// Kick all players to a single waiting server
|
||||
final ServerInfo serverInfo = ((BungeeServer) server).server();
|
||||
// Notifications done in global method
|
||||
for (final ProxiedPlayer player : getProxy().getPlayers()) {
|
||||
if (hasPermission(player, "bypass") || settingsProxy.isWhitelisted(player.getUniqueId())) continue;
|
||||
if (player.getServer() != null && player.getServer().getInfo().getName().equals(serverInfo.getName()))
|
||||
continue;
|
||||
if (serverInfo.canAccess(player) && !isMaintenance(serverInfo)) {
|
||||
audiences.player(player).sendMessage(settingsProxy.getMessage("sentToWaitingServer", "%SERVER%", server.getName()));
|
||||
player.connect(serverInfo);
|
||||
} else {
|
||||
player.disconnect(ComponentUtil.toBadComponents(settingsProxy.getKickMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task startMaintenanceRunnable(final Runnable runnable) {
|
||||
return new BungeeTask(getProxy().getScheduler().schedule(plugin, runnable, 0, 1, TimeUnit.SECONDS).getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<@Nullable SenderInfo> getOfflinePlayer(final String name) {
|
||||
final ProxiedPlayer player = getProxy().getPlayer(name);
|
||||
if (player != null) {
|
||||
return CompletableFuture.completedFuture(new BungeeSenderInfo(player));
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
final ProfileLookup profile = doUUIDLookup(name);
|
||||
return new ProxyOfflineSenderInfo(profile.uuid(), profile.name());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<@Nullable SenderInfo> getOfflinePlayer(final UUID uuid) {
|
||||
final ProxiedPlayer player = getProxy().getPlayer(uuid);
|
||||
return CompletableFuture.completedFuture(player != null ? new BungeeSenderInfo(player) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Server getServer(final String server) {
|
||||
final ServerInfo serverInfo = getProxy().getServerInfo(server);
|
||||
return serverInfo != null ? new BungeeServer(serverInfo) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getServers() {
|
||||
return getProxy().getServers().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getServerNameOf(final SenderInfo sender) {
|
||||
final ProxiedPlayer player = getProxy().getPlayer(sender.uuid());
|
||||
if (player == null || player.getServer() == null) return null;
|
||||
return player.getServer().getInfo().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(final Runnable runnable) {
|
||||
getProxy().getScheduler().runAsync(plugin, runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeConsoleCommand(final String command) {
|
||||
getProxy().getPluginManager().dispatchCommand(getProxy().getConsole(), command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(final Component component) {
|
||||
audiences.all().sendMessage(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return plugin.getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getPluginFile() {
|
||||
return plugin.getPluginFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOnlinePlayers() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMaxPlayers() {
|
||||
return getProxy().getConfig().getPlayerLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResource(final String name) {
|
||||
return plugin.getResourceAsStream(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return plugin.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PluginDump> getPlugins() {
|
||||
return getProxy().getPluginManager().getPlugins().stream().map(plugin ->
|
||||
new PluginDump(plugin.getDescription().getName(), plugin.getDescription().getVersion(), Arrays.asList(plugin.getDescription().getAuthor()))).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadIcon(final File file) throws IOException {
|
||||
favicon = Favicon.create(ImageIO.read(file));
|
||||
}
|
||||
|
||||
public boolean hasPermission(final CommandSender sender, final String permission) {
|
||||
return sender.hasPermission("maintenance." + permission) || sender.hasPermission("maintenance.admin");
|
||||
}
|
||||
|
||||
public ProxyServer getProxy() {
|
||||
return plugin.getProxy();
|
||||
}
|
||||
|
||||
public Favicon getFavicon() {
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public BungeeAudiences audiences() {
|
||||
return audiences;
|
||||
}
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.command;
|
||||
|
||||
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.command.MaintenanceProxyCommand;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
public final class MaintenanceBungeeCommand extends MaintenanceProxyCommand {
|
||||
private final MaintenanceBungeePlugin plugin;
|
||||
|
||||
public MaintenanceBungeeCommand(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
|
||||
super(plugin, settings);
|
||||
this.plugin = plugin;
|
||||
registerCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServersCompletion(final String s) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final Map.Entry<String, ServerInfo> entry : plugin.getProxy().getServers().entrySet()) {
|
||||
final String serverName = entry.getValue().getName();
|
||||
if (entry.getKey().toLowerCase(Locale.ROOT).startsWith(s) && !plugin.getSettingsProxy().getMaintenanceServers().contains(serverName)) {
|
||||
list.add(serverName);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayersCompletion() {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final ProxiedPlayer p : plugin.getProxy().getPlayers()) {
|
||||
list.add(p.getName());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.command;
|
||||
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
|
||||
import eu.kennytv.maintenance.core.command.MaintenanceCommand;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
|
||||
public final class MaintenanceBungeeCommandBase extends Command implements TabExecutor {
|
||||
private final MaintenanceCommand command;
|
||||
|
||||
public MaintenanceBungeeCommandBase(final MaintenanceCommand command) {
|
||||
super("maintenance", "maintenance.command", "mt");
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSender sender) {
|
||||
return sender.hasPermission("maintenance.admin") || sender.hasPermission("maintenance.command");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final CommandSender sender, final String[] args) {
|
||||
command.execute(new BungeeSenderInfo(sender), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(final CommandSender sender, final String[] args) {
|
||||
return command.getSuggestions(new BungeeSenderInfo(sender), args);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.listener;
|
||||
|
||||
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
|
||||
import eu.kennytv.maintenance.bungee.util.ComponentUtil;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public final class ProxyPingListener implements Listener {
|
||||
private final MaintenanceBungeePlugin plugin;
|
||||
private final SettingsProxy settings;
|
||||
|
||||
public ProxyPingListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
|
||||
this.plugin = plugin;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@EventHandler(priority = 80)
|
||||
public void proxyPing(final ProxyPingEvent event) {
|
||||
if (!settings.isMaintenance()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ServerPing ping = event.getResponse();
|
||||
if (settings.hasCustomPlayerCountMessage()) {
|
||||
ping.setVersion(new ServerPing.Protocol(settings.getLegacyParsedPlayerCountMessage(), 1));
|
||||
}
|
||||
|
||||
if (settings.isEnablePingMessages()) {
|
||||
ping.setDescriptionComponent(ComponentUtil.toBadComponents(settings.getRandomPingMessage()));
|
||||
}
|
||||
|
||||
if (settings.hasCustomPlayerCountHoverMessage()) {
|
||||
ServerPing.Players players = ping.getPlayers();
|
||||
if (players == null) {
|
||||
players = new ServerPing.Players(0, 0, null);
|
||||
ping.setPlayers(players);
|
||||
}
|
||||
|
||||
final String[] lines = settings.getLegacyParsedPlayerCountHoverLines();
|
||||
final ServerPing.PlayerInfo[] samplePlayers = new ServerPing.PlayerInfo[lines.length];
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
samplePlayers[i] = new ServerPing.PlayerInfo(lines[i], "");
|
||||
}
|
||||
players.setSample(samplePlayers);
|
||||
}
|
||||
|
||||
if (settings.hasCustomIcon() && plugin.getFavicon() != null) {
|
||||
ping.setFavicon(plugin.getFavicon());
|
||||
}
|
||||
}
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.listener;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeSenderInfo;
|
||||
import eu.kennytv.maintenance.bungee.util.BungeeServer;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.listener.ProxyJoinListenerBase;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
public final class ServerConnectListener extends ProxyJoinListenerBase implements Listener {
|
||||
private final MaintenanceBungeePlugin plugin;
|
||||
|
||||
public ServerConnectListener(final MaintenanceBungeePlugin plugin, final SettingsProxy settings) {
|
||||
super(plugin, settings);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void initialServerConnect(final ServerConnectEvent event) {
|
||||
// Global maintenance check
|
||||
if (event.isCancelled() || event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY) return;
|
||||
|
||||
final BungeeSenderInfo player = new BungeeSenderInfo(event.getPlayer());
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("Join permission check for " + event.getPlayer().getName()
|
||||
+ " - Permission: " + player.hasMaintenancePermission("bypass") + ", whitelist: " + settings.isWhitelisted(player.uuid()));
|
||||
}
|
||||
|
||||
if (shouldKick(player)) {
|
||||
final Server waitingServer = shouldConnectToWaitingServer(player);
|
||||
if (waitingServer != null) {
|
||||
event.setTarget(((BungeeServer) waitingServer).server());
|
||||
player.send(settings.getMessage("sentToWaitingServer"));
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("Join to waiting server for " + event.getPlayer().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
player.disconnect(settings.getKickMessage());
|
||||
if (settings.isJoinNotifications()) {
|
||||
broadcastJoinNotification(player.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void serverConnect(final ServerConnectEvent event) {
|
||||
// Server specific maintenance check
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
final ProxiedPlayer proxiedPlayer = event.getPlayer();
|
||||
final boolean normalServerConnect = event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY && event.getReason() != ServerConnectEvent.Reason.KICK_REDIRECT
|
||||
&& event.getReason() != ServerConnectEvent.Reason.LOBBY_FALLBACK && event.getReason() != ServerConnectEvent.Reason.SERVER_DOWN_REDIRECT;
|
||||
final BungeeSenderInfo player = new BungeeSenderInfo(proxiedPlayer);
|
||||
final ServerConnectResult connectResult = serverConnect(player, new BungeeServer(event.getTarget()), normalServerConnect);
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("Connectresult for " + player.name() + " to " + event.getTarget().getName() + ": " + connectResult);
|
||||
}
|
||||
|
||||
if (connectResult.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
// Player has no server to connect to
|
||||
if (proxiedPlayer.getServer() == null) {
|
||||
player.disconnect(settings.getKickMessage());
|
||||
}
|
||||
} else if (connectResult.getTarget() != null) {
|
||||
event.setTarget(((BungeeServer) connectResult.getTarget()).server());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void broadcastJoinNotification(final String name) {
|
||||
sendJoinMessage(ProxyServer.getInstance().getPlayers(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void broadcastJoinNotification(final String name, final Server server) {
|
||||
sendJoinMessage(((BungeeServer) server).server().getPlayers(), name);
|
||||
}
|
||||
|
||||
private void sendJoinMessage(final Iterable<ProxiedPlayer> players, final String name) {
|
||||
final Component component = settings.getMessage("joinNotification", "%PLAYER%", name);
|
||||
for (final ProxiedPlayer player : players) {
|
||||
if (plugin.hasPermission(player, "joinnotification")) {
|
||||
plugin.audiences().player(player).sendMessage(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.Connection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class BungeeSenderInfo implements ProxySenderInfo {
|
||||
private final CommandSender sender;
|
||||
|
||||
public BungeeSenderInfo(final CommandSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID uuid() {
|
||||
return sender instanceof ProxiedPlayer proxiedPlayer ? proxiedPlayer.getUniqueId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final Component component) {
|
||||
((MaintenanceBungeePlugin) MaintenanceProvider.get()).audiences().sender(sender).sendMessage(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return sender instanceof ProxiedPlayer;
|
||||
}
|
||||
|
||||
public void sendMessage(final TextComponent textComponent) {
|
||||
sender.sendMessage(textComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccess(final Server server) {
|
||||
return ((BungeeServer) server).server().canAccess(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final Component component) {
|
||||
if (sender instanceof Connection connection) {
|
||||
connection.disconnect(ComponentUtil.toBadComponent(component));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
public record BungeeServer(ServerInfo server) implements Server {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return server.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlayers() {
|
||||
return !server.getPlayers().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(final Component component) {
|
||||
final BaseComponent[] components = ComponentUtil.toBadComponent(component);
|
||||
for (final ProxiedPlayer player : server.getPlayers()) {
|
||||
player.sendMessage(components);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredServer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
name: Maintenance
|
||||
version: ${version}
|
||||
main: eu.kennytv.maintenance.bungee.MaintenanceBungeeBase
|
||||
author: kennytv
|
||||
description: ${description}
|
||||
softDepends: [ServerListPlus, LuckPerms]
|
||||
website: https://hangar.papermc.io/kennytv/Maintenance
|
||||
@@ -1,13 +1,7 @@
|
||||
dependencies {
|
||||
api(projects.maintenanceApiProxy)
|
||||
api(projects.maintenanceCore)
|
||||
|
||||
// Try to reasonably minimize it...
|
||||
implementation(libs.jedis) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("org.slf4j", "slf4j-api")
|
||||
}
|
||||
|
||||
implementation(libs.hikariCP)
|
||||
compileOnly(libs.luckperms)
|
||||
compileOnly(libs.guava)
|
||||
compileOnly(libs.gson)
|
||||
|
||||
+45
-86
@@ -28,15 +28,14 @@ import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceScheduleRunnable;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProfileLookup;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.RateLimitedException;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
@@ -47,8 +46,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -57,8 +54,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implements MaintenanceProxy {
|
||||
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[A-Za-z0-9_.]{1,16}$");
|
||||
private final Map<String, MaintenanceRunnableBase> serverTasks = new HashMap<>();
|
||||
private final Map<String, Task> serverTasks = new HashMap<>();
|
||||
protected SettingsProxy settingsProxy;
|
||||
|
||||
protected MaintenanceProxyPlugin(final String version, final ServerType serverType) {
|
||||
@@ -68,54 +64,49 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
if (settingsProxy.redisHandler() != null) {
|
||||
settingsProxy.redisHandler().close();
|
||||
if (settingsProxy.getMySQL() != null) {
|
||||
settingsProxy.getMySQL().close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
if (settingsProxy.hasMySQL()) {
|
||||
settingsProxy.setMaintenanceToSQL(maintenance);
|
||||
}
|
||||
super.setMaintenance(maintenance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenance(final Server server) {
|
||||
return settingsProxy.isMaintenance(server.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance, @Nullable final String mode) {
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
if (maintenance) {
|
||||
if (settingsProxy.addMaintenanceServer(server.getName(), mode)) {
|
||||
serverActions(server, true);
|
||||
return true;
|
||||
if (!settingsProxy.addMaintenanceServer(server.getName())) {
|
||||
return false;
|
||||
}
|
||||
return mode != null && settingsProxy.setMaintenanceServerMode(server.getName(), mode);
|
||||
}
|
||||
|
||||
if (!settingsProxy.removeMaintenanceServer(server.getName())) {
|
||||
} else if (!settingsProxy.removeMaintenanceServer(server.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
serverActions(server, false);
|
||||
serverActions(server, maintenance);
|
||||
|
||||
for (final String command : (maintenance ? settingsProxy.getCommandsOnMaintenanceEnable(server) : settingsProxy.getCommandsOnMaintenanceDisable(server))) {
|
||||
try {
|
||||
executeConsoleCommand(command.replace("%SERVER%", server.getName()));
|
||||
} catch (final Exception e) {
|
||||
getLogger().severe("Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
return setMaintenanceToServer(server, maintenance, null);
|
||||
}
|
||||
|
||||
public boolean setMaintenanceModeToServer(final Server server, @Nullable final String mode) {
|
||||
if (!settingsProxy.isMaintenance(server.getName())) {
|
||||
return false;
|
||||
}
|
||||
return settingsProxy.setMaintenanceServerMode(server.getName(), mode);
|
||||
}
|
||||
|
||||
public @Nullable String activeMode(final Server server) {
|
||||
return settingsProxy.activeMode(server.getName());
|
||||
}
|
||||
|
||||
public void serverActions(final Server server, final boolean maintenance) {
|
||||
if (server == null) {
|
||||
return;
|
||||
}
|
||||
if (server == null) return;
|
||||
|
||||
// Skip to the even fire for dummy servers
|
||||
if (server.isRegisteredServer()) {
|
||||
@@ -135,19 +126,6 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
}
|
||||
|
||||
eventManager.callEvent(new ServerMaintenanceChangedEvent(server, maintenance));
|
||||
if (maintenance) {
|
||||
sendWebhookMessage("webhookSingleMaintenanceActivated", DiscordWebhook.EventType.MAINTENANCE_ENABLED, "%SERVER%", server.getName());
|
||||
} else {
|
||||
sendWebhookMessage("webhookSingleMaintenanceDeactivated", DiscordWebhook.EventType.MAINTENANCE_DISABLED, "%SERVER%", server.getName());
|
||||
}
|
||||
|
||||
for (final String command : (maintenance ? settingsProxy.getCommandsOnMaintenanceEnable(server) : settingsProxy.getCommandsOnMaintenanceDisable(server))) {
|
||||
try {
|
||||
executeConsoleCommand(command.replace("%SERVER%", server.getName()));
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.SEVERE, "Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,45 +133,28 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
return serverTasks.containsKey(server.getName());
|
||||
}
|
||||
|
||||
public boolean hasServerTasks() {
|
||||
return !serverTasks.isEmpty();
|
||||
}
|
||||
|
||||
public Map<String, MaintenanceRunnableBase> getServerTasks() {
|
||||
return serverTasks;
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase getServerTask(final String server) {
|
||||
return serverTasks.get(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMaintenanceServers() {
|
||||
return Collections.unmodifiableSet(settingsProxy.getMaintenanceServers());
|
||||
}
|
||||
|
||||
public void cancelSingleTask(final Server server) {
|
||||
final MaintenanceRunnableBase task = serverTasks.remove(server.getName());
|
||||
final Task task = serverTasks.remove(server.getName());
|
||||
if (task != null) {
|
||||
task.getTask().cancel();
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable, @Nullable final String mode) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, (int) duration.getSeconds(), enable, server, mode);
|
||||
serverTasks.put(server.getName(), runnable);
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, (int) duration.getSeconds(), enable, server);
|
||||
serverTasks.put(server.getName(), runnable.getTask());
|
||||
return runnable;
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable) {
|
||||
return startSingleMaintenanceRunnable(server, duration, enable, null);
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase scheduleSingleMaintenanceRunnable(final Server server, final Duration enableIn,
|
||||
final Duration maintenanceDuration, @Nullable final String mode) {
|
||||
public MaintenanceRunnableBase scheduleSingleMaintenanceRunnable(final Server server, final Duration enableIn, final Duration maintenanceDuration) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceScheduleRunnable(this, settingsProxy,
|
||||
(int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), server, mode);
|
||||
serverTasks.put(server.getName(), runnable);
|
||||
(int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), server);
|
||||
serverTasks.put(server.getName(), runnable.getTask());
|
||||
return runnable;
|
||||
}
|
||||
|
||||
@@ -231,17 +192,15 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
@Blocking
|
||||
@Nullable
|
||||
protected ProfileLookup doUUIDLookup(final String name) throws IOException {
|
||||
ProfileLookup profileLookup = null;
|
||||
if (USERNAME_PATTERN.matcher(name).matches()) {
|
||||
try {
|
||||
profileLookup = doUUIDLookupMojangAPI(name);
|
||||
} catch (RateLimitedException e) {
|
||||
// Use fallback API if rate limit is reached
|
||||
profileLookup = doUUIDLookupAshconAPI(name);
|
||||
}
|
||||
ProfileLookup profileLookup;
|
||||
try {
|
||||
profileLookup = doUUIDLookupMojangAPI(name);
|
||||
} catch (RateLimitedException e) {
|
||||
// Use fallback API if rate limit is reached
|
||||
profileLookup = doUUIDLookupAshconAPI(name);
|
||||
}
|
||||
|
||||
if (profileLookup == null && settingsProxy.isFallbackToOfflineUUID()) {
|
||||
if (settingsProxy.isFallbackToOfflineUUID() && profileLookup == null) {
|
||||
// Use offline uuid
|
||||
return new ProfileLookup(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)), name);
|
||||
}
|
||||
@@ -254,7 +213,7 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
*/
|
||||
@Nullable
|
||||
private ProfileLookup doUUIDLookupMojangAPI(final String name) throws IOException {
|
||||
final URL url = URI.create("https://api.mojang.com/users/profiles/minecraft/" + name).toURL();
|
||||
final URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
@@ -282,7 +241,7 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
*/
|
||||
@Nullable
|
||||
private ProfileLookup doUUIDLookupAshconAPI(final String name) throws IOException {
|
||||
final URL url = URI.create("https://api.ashcon.app/mojang/v2/user/" + name).toURL();
|
||||
final URL url = new URL("https://api.ashcon.app/mojang/v2/user/" + name);
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
if (connection.getResponseCode() == 403) {
|
||||
@@ -320,4 +279,4 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
protected abstract void kickPlayersTo(Server server);
|
||||
|
||||
protected abstract void kickPlayersFromProxy();
|
||||
}
|
||||
}
|
||||
@@ -17,55 +17,88 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.MaintenanceProxy;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.proxy.redis.RedisHandler;
|
||||
import eu.kennytv.maintenance.core.proxy.mysql.MySQL;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SettingsProxy extends Settings {
|
||||
|
||||
private Map<String, String> maintenanceServers;
|
||||
private final MaintenanceProxyPlugin proxyPlugin;
|
||||
private Set<String> maintenanceServers;
|
||||
private List<String> fallbackServers;
|
||||
private String waitingServer;
|
||||
private boolean fallbackToOfflineUUID;
|
||||
|
||||
private Map<String, List<String>> commandsOnMaintenanceEnable;
|
||||
private Map<String, List<String>> commandsOnMaintenanceDisable;
|
||||
private String mySQLTable;
|
||||
private String serverTable;
|
||||
private String maintenanceQuery;
|
||||
private String serverQuery;
|
||||
private MySQL mySQL;
|
||||
|
||||
private RedisHandler redisHandler;
|
||||
private long millisecondsToCheck;
|
||||
private long lastMySQLCheck;
|
||||
private long lastServerCheck;
|
||||
|
||||
public SettingsProxy(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin);
|
||||
this.proxyPlugin = plugin;
|
||||
}
|
||||
|
||||
private void setupMySQL() {
|
||||
plugin.getLogger().info("Trying to open database connection... (also, you can simply ignore the SLF4J soft-warning if it shows up)");
|
||||
final ConfigSection section = config.getSection("mysql");
|
||||
if (section == null) {
|
||||
plugin.getLogger().warning("Section missing: mysql");
|
||||
return;
|
||||
}
|
||||
|
||||
mySQL = new MySQL(plugin.getLogger(),
|
||||
section.getString("host"),
|
||||
section.getInt("port"),
|
||||
section.getString("username"),
|
||||
section.getString("password"),
|
||||
section.getString("database"),
|
||||
section.getBoolean("use-ssl", true));
|
||||
|
||||
// Varchar as the value regarding the possibility of saving stuff like the motd as well in future updates
|
||||
mySQLTable = section.getString("table", "maintenance_settings");
|
||||
serverTable = section.getString("servertable", "maintenance_servers");
|
||||
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + mySQLTable + " (setting VARCHAR(16) PRIMARY KEY, value VARCHAR(255))");
|
||||
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + serverTable + " (server VARCHAR(64) PRIMARY KEY)");
|
||||
maintenanceQuery = "SELECT * FROM " + mySQLTable + " WHERE setting = ?";
|
||||
serverQuery = "SELECT * FROM " + serverTable;
|
||||
plugin.getLogger().info("Done!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadExtraSettings() {
|
||||
// Open Redis connection if enabled and not already done
|
||||
final ConfigSection redisSection = config.getSection("redis");
|
||||
if (!hasRedis() && redisSection.getBoolean("enabled")) {
|
||||
connectToRedis(redisSection.getString("uri"));
|
||||
}
|
||||
if (hasRedis()) {
|
||||
maintenance = redisHandler.loadMaintenanceStatus();
|
||||
activeMode = normalizeMode(redisHandler.loadGlobalMode());
|
||||
maintenanceServers = redisHandler.loadMaintenanceServers();
|
||||
// Open database connection if enabled and not already done
|
||||
if (!hasMySQL() && config.getBoolean("mysql.use-mysql")) {
|
||||
try {
|
||||
setupMySQL();
|
||||
} catch (final Exception e) {
|
||||
mySQL = null;
|
||||
plugin.getLogger().warning("Error while trying do open database connection!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
final Object fallback = config.getObject("fallback");
|
||||
fallbackServers = fallback instanceof String s ? Collections.singletonList(s) : config.getStringList("fallback", Collections.emptyList());
|
||||
fallbackServers = fallback instanceof String ? Collections.singletonList((String) fallback) : config.getStringList("fallback", Collections.emptyList());
|
||||
|
||||
waitingServer = config.getString("waiting-server", "");
|
||||
if (waitingServer.isEmpty() || waitingServer.equalsIgnoreCase("none")) {
|
||||
@@ -85,36 +118,55 @@ public final class SettingsProxy extends Settings {
|
||||
commandsOnMaintenanceDisable.put(key.toLowerCase(Locale.ROOT), disableCommandsSection.getStringList(key));
|
||||
}
|
||||
|
||||
if (!hasRedis()) {
|
||||
final ConfigSection maintenanceServersSection = config.getSection("proxied-maintenance-servers");
|
||||
maintenanceServers = new LinkedHashMap<>();
|
||||
for (final Map.Entry<String, ?> entry : maintenanceServersSection.getValues().entrySet()) {
|
||||
if (entry.getKey() != null) {
|
||||
maintenanceServers.put(entry.getKey(), normalizeServerMode(entry.getValue()));
|
||||
}
|
||||
}
|
||||
if (hasMySQL()) {
|
||||
maintenance = loadMaintenance();
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
|
||||
final long configValue = config.getInt("mysql.update-interval");
|
||||
// Even if set to 0, only check every 500 millis
|
||||
millisecondsToCheck = configValue > 0 ? configValue * 1000 : 500;
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
} else {
|
||||
final List<String> list = config.getStringList("proxied-maintenance-servers");
|
||||
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
|
||||
}
|
||||
}
|
||||
|
||||
private void connectToRedis(final String redisUri) {
|
||||
redisHandler = new RedisHandler((MaintenanceProxyPlugin) plugin, this);
|
||||
try {
|
||||
redisHandler.setup(redisUri);
|
||||
} catch (final Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error while trying to open Redis connection!", e);
|
||||
e.printStackTrace();
|
||||
redisHandler.close();
|
||||
redisHandler = null;
|
||||
@Override
|
||||
public boolean isMaintenance() {
|
||||
if (hasMySQL() && System.currentTimeMillis() - lastMySQLCheck > millisecondsToCheck) {
|
||||
final boolean databaseValue = loadMaintenance();
|
||||
if (databaseValue != maintenance) {
|
||||
maintenance = databaseValue;
|
||||
plugin.serverActions(maintenance);
|
||||
}
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
}
|
||||
return maintenance;
|
||||
}
|
||||
|
||||
public boolean isMaintenance(final String serverName) {
|
||||
return maintenanceServers.containsKey(serverName);
|
||||
}
|
||||
|
||||
public @Nullable String activeMode(final String serverName) {
|
||||
final String mode = maintenanceServers.get(serverName);
|
||||
return mode == null || mode.equals("default") ? null : mode;
|
||||
if (hasMySQL() && System.currentTimeMillis() - lastServerCheck > millisecondsToCheck) {
|
||||
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.equals(databaseValue)) {
|
||||
// Enable maintenance on yet unlisted servers
|
||||
for (final String s : databaseValue) {
|
||||
if (!maintenanceServers.contains(s)) {
|
||||
proxyPlugin.serverActions(proxyPlugin.getServer(s), true);
|
||||
}
|
||||
}
|
||||
// Disable maintenance on now unlisted servers
|
||||
for (final String s : maintenanceServers) {
|
||||
if (!databaseValue.contains(s)) {
|
||||
proxyPlugin.serverActions(proxyPlugin.getServer(s), false);
|
||||
}
|
||||
}
|
||||
maintenanceServers = databaseValue;
|
||||
}
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
}
|
||||
return maintenanceServers.contains(serverName);
|
||||
}
|
||||
|
||||
public Component getServerKickMessage(final String server) {
|
||||
@@ -122,154 +174,101 @@ public final class SettingsProxy extends Settings {
|
||||
if (message == null) {
|
||||
message = getLanguageString("singleMaintenanceKick", "%SERVER%", server);
|
||||
}
|
||||
return parse(plugin.replacePingVariables(message, activeMode(server)));
|
||||
return parse(plugin.replacePingVariables(message));
|
||||
}
|
||||
|
||||
// Full = being kicked from the proxy, not just a proxied server
|
||||
public Component getFullServerKickMessage(final String server) {
|
||||
String message = getLanguageStringOrNull("singleMaintenanceKicksComplete." + server, "%SERVER%", server);
|
||||
if (message == null) {
|
||||
message = getLanguageString("singleMaintenanceKickComplete", "%SERVER%", server);
|
||||
}
|
||||
return parse(plugin.replacePingVariables(message, activeMode(server)));
|
||||
return parse(plugin.replacePingVariables(message));
|
||||
}
|
||||
|
||||
public boolean hasRedis() {
|
||||
return redisHandler != null;
|
||||
public boolean hasMySQL() {
|
||||
return mySQL != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadWhitelistedPlayers() {
|
||||
if (hasRedis()) {
|
||||
redisHandler.loadPlayers(getWhitelistedPlayers());
|
||||
} else {
|
||||
super.loadWhitelistedPlayers();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance, @Nullable final String mode) {
|
||||
super.setMaintenance(maintenance, mode);
|
||||
if (hasRedis()) {
|
||||
redisHandler.set(maintenance, mode != null ? mode : "default");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveMode(@Nullable final String activeMode) {
|
||||
super.setActiveMode(activeMode);
|
||||
if (hasRedis() && isMaintenance()) {
|
||||
redisHandler.set(true, activeMode != null ? activeMode : "default");
|
||||
}
|
||||
}
|
||||
|
||||
public void setActiveModeDirect(@Nullable final String activeMode) {
|
||||
super.setActiveMode(activeMode);
|
||||
}
|
||||
|
||||
public void setMaintenanceDirect(final boolean maintenance, @Nullable final String mode) {
|
||||
super.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
|
||||
if (super.addWhitelistedPlayer(uuid, name)) {
|
||||
if (hasRedis()) {
|
||||
redisHandler.addPlayer(uuid, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addWhitelistedPlayerDirect(final UUID uuid, final String name) {
|
||||
return super.addWhitelistedPlayer(uuid, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeWhitelistedPlayer(final UUID uuid) {
|
||||
if (super.removeWhitelistedPlayer(uuid)) {
|
||||
if (hasRedis()) {
|
||||
redisHandler.removePlayer(uuid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeWhitelistedPlayerDirect(final UUID uuid) {
|
||||
return super.removeWhitelistedPlayer(uuid);
|
||||
}
|
||||
|
||||
boolean addMaintenanceServer(final String server, @Nullable final String mode) {
|
||||
final String normalizedMode = normalizeServerMode(mode);
|
||||
if (hasRedis()) {
|
||||
if (redisHandler.addServer(server, normalizedMode)) {
|
||||
maintenanceServers.put(server, normalizedMode);
|
||||
return true;
|
||||
}
|
||||
} else if (maintenanceServers.putIfAbsent(server, normalizedMode) == null) {
|
||||
saveServersToConfig();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean setMaintenanceServerMode(final String server, @Nullable final String mode) {
|
||||
final String normalizedMode = normalizeServerMode(mode);
|
||||
final String oldMode = maintenanceServers.get(server);
|
||||
if (oldMode == null || oldMode.equals(normalizedMode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maintenanceServers.put(server, normalizedMode);
|
||||
if (hasRedis()) {
|
||||
redisHandler.setServerMode(server, normalizedMode);
|
||||
void setMaintenanceToSQL(final boolean maintenance) {
|
||||
plugin.async(() -> {
|
||||
final String s = String.valueOf(maintenance);
|
||||
mySQL.executeUpdate("INSERT INTO " + mySQLTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?", "maintenance", s, s);
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
});
|
||||
}
|
||||
|
||||
boolean addMaintenanceServer(final String server) {
|
||||
if (hasMySQL()) {
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.add(server)) return false;
|
||||
plugin.async(() -> mySQL.executeUpdate("INSERT INTO " + serverTable + " (server) VALUES (?)", server));
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
} else {
|
||||
if (!maintenanceServers.add(server)) return false;
|
||||
saveServersToConfig();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean removeMaintenanceServer(final String server) {
|
||||
if (hasRedis()) {
|
||||
if (redisHandler.removeServer(server)) {
|
||||
maintenanceServers.remove(server);
|
||||
return true;
|
||||
}
|
||||
} else if (maintenanceServers.remove(server) != null) {
|
||||
if (hasMySQL()) {
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.remove(server)) return false;
|
||||
|
||||
plugin.async(() -> mySQL.executeUpdate("DELETE FROM " + serverTable + " WHERE server = ?", server));
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
} else {
|
||||
if (!maintenanceServers.remove(server)) return false;
|
||||
|
||||
saveServersToConfig();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean addMaintenanceServerDirect(final String server, @Nullable final String mode) {
|
||||
return maintenanceServers.put(server, normalizeServerMode(mode)) == null;
|
||||
private Set<String> loadMaintenanceServersFromSQL() {
|
||||
final Set<String> maintenanceServers = new HashSet<>();
|
||||
mySQL.executeQuery(serverQuery, rs -> {
|
||||
try {
|
||||
while (rs.next()) {
|
||||
maintenanceServers.add(rs.getString("server"));
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
plugin.getLogger().warning("An error occured while trying to get the list of single servers with maintenance!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return maintenanceServers;
|
||||
}
|
||||
|
||||
public boolean removeMaintenanceServerDirect(final String server) {
|
||||
return maintenanceServers.remove(server) != null;
|
||||
}
|
||||
|
||||
public void setMaintenanceServerModeDirect(final String server, @Nullable final String mode) {
|
||||
if (maintenanceServers.containsKey(server)) {
|
||||
maintenanceServers.put(server, normalizeServerMode(mode));
|
||||
}
|
||||
private boolean loadMaintenance() {
|
||||
final boolean[] databaseValue = {false};
|
||||
mySQL.executeQuery(maintenanceQuery, rs -> {
|
||||
try {
|
||||
if (rs.next()) {
|
||||
databaseValue[0] = Boolean.parseBoolean(rs.getString("value"));
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
plugin.getLogger().warning("An error occured while trying to get the maintenance value from the database!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "maintenance");
|
||||
return databaseValue[0];
|
||||
}
|
||||
|
||||
private void saveServersToConfig() {
|
||||
config.set("proxied-maintenance-servers", new LinkedHashMap<>(maintenanceServers));
|
||||
config.set("proxied-maintenance-servers", new ArrayList<>(maintenanceServers));
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public Set<String> getMaintenanceServers() {
|
||||
return maintenanceServers.keySet();
|
||||
return maintenanceServers;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Server getFallbackServer() {
|
||||
for (final String fallbackServer : fallbackServers) {
|
||||
final Server server = ((MaintenanceProxy) plugin).getServer(fallbackServer);
|
||||
final Server server = proxyPlugin.getServer(fallbackServer);
|
||||
if (server != null && !isMaintenance(server.getName())) {
|
||||
return server;
|
||||
}
|
||||
@@ -287,7 +286,7 @@ public final class SettingsProxy extends Settings {
|
||||
}
|
||||
|
||||
public List<String> getCommandsOnMaintenanceEnable(final Server server) {
|
||||
final List<String> enableCommands = new ArrayList<>(commandsOnMaintenanceEnable.getOrDefault("all", Collections.emptyList()));
|
||||
final List<String> enableCommands = commandsOnMaintenanceEnable.getOrDefault("all", new ArrayList<>());
|
||||
final List<String> serverEnableCommands = commandsOnMaintenanceEnable.get(server.getName().toLowerCase(Locale.ROOT));
|
||||
if (serverEnableCommands != null) {
|
||||
enableCommands.addAll(serverEnableCommands);
|
||||
@@ -296,7 +295,7 @@ public final class SettingsProxy extends Settings {
|
||||
}
|
||||
|
||||
public List<String> getCommandsOnMaintenanceDisable(final Server server) {
|
||||
final List<String> disableCommands = new ArrayList<>(commandsOnMaintenanceDisable.getOrDefault("all", Collections.emptyList()));
|
||||
final List<String> disableCommands = commandsOnMaintenanceDisable.getOrDefault("all", new ArrayList<>());
|
||||
final List<String> serverDisableCommands = commandsOnMaintenanceDisable.get(server.getName().toLowerCase(Locale.ROOT));
|
||||
if (serverDisableCommands != null) {
|
||||
disableCommands.addAll(serverDisableCommands);
|
||||
@@ -304,15 +303,8 @@ public final class SettingsProxy extends Settings {
|
||||
return disableCommands;
|
||||
}
|
||||
|
||||
public @Nullable RedisHandler redisHandler() {
|
||||
return redisHandler;
|
||||
}
|
||||
|
||||
private static String normalizeServerMode(@Nullable final Object mode) {
|
||||
if (mode == null) {
|
||||
return "default";
|
||||
}
|
||||
final String value = String.valueOf(mode).toLowerCase(Locale.ROOT);
|
||||
return value.isBlank() ? "default" : value;
|
||||
@Nullable
|
||||
MySQL getMySQL() {
|
||||
return mySQL;
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -26,7 +26,6 @@ import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
private final MaintenanceProxyPlugin plugin;
|
||||
@@ -41,7 +40,7 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
@Override
|
||||
protected void addToggleAndTimerCommands() {
|
||||
add(new SingleToggleCommand(plugin), "on", "off");
|
||||
add(new ProxyStatusCommand(plugin), "status");
|
||||
add(new StatusCommand(plugin), "status");
|
||||
|
||||
add(new SingleStarttimerCommand(plugin), "starttimer", "start");
|
||||
add(new SingleEndtimerCommand(plugin), "endtimer", "end");
|
||||
@@ -53,7 +52,7 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
public List<String> getMaintenanceServersCompletion(final String s) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String server : settingsBungee.getMaintenanceServers()) {
|
||||
if (server.toLowerCase(Locale.ROOT).startsWith(s)) {
|
||||
if (server.toLowerCase().startsWith(s)) {
|
||||
list.add(server);
|
||||
}
|
||||
}
|
||||
|
||||
-8
@@ -20,8 +20,6 @@ package eu.kennytv.maintenance.core.proxy.command;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ProxyCommandInfo extends CommandInfo {
|
||||
protected final MaintenanceProxyPlugin plugin;
|
||||
@@ -35,10 +33,4 @@ public abstract class ProxyCommandInfo extends CommandInfo {
|
||||
protected SettingsProxy getSettings() {
|
||||
return plugin.getSettingsProxy();
|
||||
}
|
||||
|
||||
protected List<String> getModesCompletion() {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
}
|
||||
+1
-14
@@ -22,10 +22,8 @@ import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class AbortSingleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -69,17 +67,6 @@ public final class AbortSingleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2 || !sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final String prefix = args[1].toLowerCase(Locale.ROOT);
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String server : plugin.getServerTasks().keySet()) {
|
||||
if (server.toLowerCase(Locale.ROOT).startsWith(prefix)) {
|
||||
list.add(server);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1]) : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.Map;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class ProxyStatusCommand extends ProxyCommandInfo {
|
||||
|
||||
public ProxyStatusCommand(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin, "singleserver.status");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
final MaintenanceRunnable task = plugin.getCurrentTask();
|
||||
if (task != null) {
|
||||
final String key = task.shouldEnable() ? "maintenanceStatusOffWithStartTimer" : "maintenanceStatusOnWithEndTimer";
|
||||
sender.send(getMessage(key, "%TIME%", task.getTime()));
|
||||
} else {
|
||||
sender.send(getMessage(plugin.isMaintenance() ? "maintenanceStatusOn" : "maintenanceStatusOff"));
|
||||
}
|
||||
|
||||
if (getSettings().getMaintenanceServers().isEmpty() && !plugin.hasServerTasks()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEmpty"));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceList"));
|
||||
// Enabled servers first
|
||||
for (final String server : getSettings().getMaintenanceServers()) {
|
||||
final MaintenanceRunnableBase serverTask = plugin.getServerTask(server);
|
||||
if (serverTask != null) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntryWithEndTimer", "%SERVER%", server, "%TIME%", serverTask.getTime()));
|
||||
continue;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceListEntry", "%SERVER%", server));
|
||||
}
|
||||
|
||||
// Then enabling tasks
|
||||
for (final Map.Entry<String, MaintenanceRunnableBase> entry : plugin.getServerTasks().entrySet()) {
|
||||
final MaintenanceRunnableBase serverTask = entry.getValue();
|
||||
if (serverTask.shouldEnable()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntryWithStartTimer", "%SERVER%", entry.getKey(), "%TIME%", serverTask.getTime()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getHelpMessage() {
|
||||
return getMessage("helpStatus");
|
||||
}
|
||||
}
|
||||
+36
-73
@@ -21,14 +21,10 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class SingleEndtimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -44,82 +40,49 @@ public final class SingleEndtimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
endGlobal(sender, args[1]);
|
||||
} else if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
endGlobal(sender, args[2]);
|
||||
} else {
|
||||
endSingle(sender, args[1], args[2]);
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (!plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
sender.send(getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
} else if (args.length == 3) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, false);
|
||||
sender.send(getMessage(
|
||||
"singleEndtimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void endGlobal(final SenderInfo sender, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (!plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
|
||||
final Component message = getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
private void endSingle(final SenderInfo sender, final String serverArg, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, false);
|
||||
final Component message = getMessage(
|
||||
"singleEndtimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
);
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookSingleEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer") && plugin.isMaintenance()) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+43
-80
@@ -23,11 +23,8 @@ import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleScheduleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -43,90 +40,56 @@ public final class SingleScheduleTimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 3) {
|
||||
scheduleGlobal(sender, null, args[1], args[2]);
|
||||
} else if (args.length == 4 || args.length == 5) {
|
||||
final String mode = args.length == 5 ? args[2] : null;
|
||||
final String enableInArg = args.length == 5 ? args[3] : args[2];
|
||||
final String durationArg = args.length == 5 ? args[4] : args[3];
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
scheduleGlobal(sender, mode, enableInArg, durationArg);
|
||||
} else {
|
||||
scheduleSingle(sender, args[1], mode, enableInArg, durationArg);
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.scheduleMaintenanceRunnable(duration, enableIn);
|
||||
sender.send(getMessage(
|
||||
"scheduletimerStarted",
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds())
|
||||
));
|
||||
} else if (args.length == 4) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[3], false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.scheduleSingleMaintenanceRunnable(server, enableIn, duration);
|
||||
sender.send(getMessage(
|
||||
"singleScheduletimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds()),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleGlobal(final SenderInfo sender, @Nullable final String mode, final String enableInArg, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, enableInArg);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.scheduleMaintenanceRunnable(enableIn, duration, mode);
|
||||
sender.send(getMessage(
|
||||
"scheduletimerStarted",
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds())
|
||||
));
|
||||
}
|
||||
|
||||
private void scheduleSingle(final SenderInfo sender, final String serverArg, @Nullable final String mode,
|
||||
final String enableInArg, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, enableInArg, false);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.scheduleSingleMaintenanceRunnable(server, enableIn, duration, mode);
|
||||
sender.send(getMessage(
|
||||
"singleScheduletimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds()),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
return sender.hasMaintenancePermission("timer") ? getModesCompletion() : Collections.emptyList();
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer") && plugin.getServer(args[1]) != null) {
|
||||
return getModesCompletion();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+36
-82
@@ -21,15 +21,10 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleStarttimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -45,90 +40,49 @@ public final class SingleStarttimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
startGlobal(sender, null, args[1]);
|
||||
} else if (args.length == 3 || args.length == 4) {
|
||||
final String mode = args.length == 4 ? args[2] : null;
|
||||
final String durationArg = args.length == 4 ? args[3] : args[2];
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
startGlobal(sender, mode, durationArg);
|
||||
} else {
|
||||
startSingle(sender, args[1], mode, durationArg);
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true);
|
||||
sender.send(getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
} else if (args.length == 3) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, true);
|
||||
sender.send(getMessage(
|
||||
"singleStarttimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void startGlobal(final SenderInfo sender, @Nullable final String mode, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true, mode);
|
||||
final Component message = getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
private void startSingle(final SenderInfo sender, final String serverArg, @Nullable final String mode, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, true, mode);
|
||||
final Component message = getMessage(
|
||||
"singleStarttimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
);
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookSingleStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
return sender.hasMaintenancePermission("timer") ? getModesCompletion() : Collections.emptyList();
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer") && plugin.getServer(args[1]) != null) {
|
||||
return getModesCompletion();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+32
-106
@@ -17,15 +17,14 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.DummyServer;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.server.DummyServer;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class SingleToggleCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -40,121 +39,48 @@ public final class SingleToggleCommand extends ProxyCommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 0 || args.length > 3) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
if (args.length == 1) {
|
||||
toggleGlobal(sender, maintenance, null);
|
||||
return;
|
||||
}
|
||||
|
||||
final String server = args[1];
|
||||
final String mode = args.length == 3 ? args[2] : null;
|
||||
if (server.equalsIgnoreCase("global")) {
|
||||
if (!maintenance && args.length == 3) {
|
||||
sender.send(getHelpMessage());
|
||||
if (checkPermission(sender, "toggle")) return;
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
toggleGlobal(sender, maintenance, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!maintenance && args.length != 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
toggleServer(sender, maintenance, server, mode);
|
||||
}
|
||||
|
||||
private void toggleGlobal(final SenderInfo sender, final boolean maintenance, final String mode) {
|
||||
if (checkPermission(sender, "toggle")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance && plugin.isMaintenance()) {
|
||||
if (mode != null) {
|
||||
plugin.getSettings().setActiveMode(mode);
|
||||
return;
|
||||
plugin.setMaintenance(maintenance);
|
||||
} else if (args.length == 2) {
|
||||
if (checkPermission(sender, "singleserver.toggle")) return;
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
Server server = plugin.getServer(args[1]);
|
||||
if (server == null) {
|
||||
if (maintenance) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
// Let servers be removed from the maintenance list, even if they don't exist on the proxy
|
||||
server = new DummyServer(args[1]);
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
private void toggleServer(final SenderInfo sender, final boolean maintenance, final String serverArg, final String mode) {
|
||||
if (checkPermission(sender, "singleserver.toggle")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Server server = plugin.getServer(serverArg);
|
||||
if (server == null) {
|
||||
if (maintenance) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
// Let servers be removed from the maintenance list, even if they don't exist on the proxy
|
||||
server = new DummyServer(serverArg);
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (maintenance && plugin.isMaintenance(server) && mode != null) {
|
||||
if (plugin.setMaintenanceModeToServer(server, mode)) {
|
||||
return;
|
||||
}
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.setMaintenanceToServer(server, maintenance, mode)) {
|
||||
if (!sender.isPlayer() || !server.getName().equals(plugin.getServerNameOf(sender))) {
|
||||
sender.send(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated", "%SERVER%", server.getName()));
|
||||
if (plugin.setMaintenanceToServer(server, maintenance)) {
|
||||
if (!sender.isPlayer() || !server.getName().equals(plugin.getServerNameOf(sender))) {
|
||||
sender.send(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated", "%SERVER%", server.getName()));
|
||||
}
|
||||
} else {
|
||||
sender.send(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
}
|
||||
} else {
|
||||
sender.send(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("toggle") && args[0].equalsIgnoreCase("on")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
|
||||
if (!sender.hasMaintenancePermission("singleserver.toggle")) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
final List<String> serverSuggestions = args[0].equalsIgnoreCase("off")
|
||||
? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase(Locale.ROOT))
|
||||
: plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT));
|
||||
suggestions.addAll(serverSuggestions);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
if (args.length == 3 && args[0].equalsIgnoreCase("on") && (sender.hasMaintenancePermission("toggle") || sender.hasMaintenancePermission("singleserver.toggle"))) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
if (args.length != 2 || !sender.hasMaintenancePermission("singleserver.toggle")) return Collections.emptyList();
|
||||
return args[0].equalsIgnoreCase("off") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase())
|
||||
: plugin.getCommandManager().getServersCompletion(args[1].toLowerCase());
|
||||
}
|
||||
}
|
||||
+14
-19
@@ -15,33 +15,28 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.command.subcommand;
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class StatusCommand extends CommandInfo {
|
||||
public final class StatusCommand extends ProxyCommandInfo {
|
||||
|
||||
public StatusCommand(final MaintenancePlugin plugin) {
|
||||
super(plugin, "status");
|
||||
public StatusCommand(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin, "singleserver.status");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
final MaintenanceRunnable task = plugin.getCurrentTask();
|
||||
if (task != null) {
|
||||
final String key = task.shouldEnable() ? "maintenanceStatusOffWithStartTimer" : "maintenanceStatusOnWithEndTimer";
|
||||
sender.send(getMessage(key, "%TIME%", task.getTime()));
|
||||
} else {
|
||||
sender.send(getMessage(plugin.isMaintenance() ? "maintenanceStatusOn" : "maintenanceStatusOff"));
|
||||
if (getSettings().getMaintenanceServers().isEmpty()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEmpty"));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceList"));
|
||||
for (final String server : getSettings().getMaintenanceServers()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntry", "%SERVER%", server));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getHelpMessage() {
|
||||
return getMessage("helpGlobalStatus");
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -24,7 +24,6 @@ import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
@@ -49,7 +48,7 @@ public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
protected ServerConnectResult serverConnect(final ProxySenderInfo sender, final Server target, final boolean normalServerConnect) {
|
||||
// Check waiting server for global maintenance
|
||||
if (settings.isMaintenance()) {
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())) return ALLOWED;
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) return ALLOWED;
|
||||
|
||||
final Server waitingServer = shouldConnectToWaitingServer(sender);
|
||||
// Should never be null, but just in case
|
||||
@@ -71,13 +70,13 @@ public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
|
||||
// Single server maintenance
|
||||
if (!settings.isMaintenance(target.getName())) return ALLOWED;
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())
|
||||
|| sender.hasMaintenancePermission("singleserver.bypass." + target.getName().toLowerCase(Locale.ROOT))) {
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())
|
||||
|| sender.hasMaintenancePermission("singleserver.bypass." + target.getName().toLowerCase())) {
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
if (settings.isJoinNotifications()) {
|
||||
broadcastJoinNotification(sender.name(), target);
|
||||
broadcastJoinNotification(sender.getName(), target);
|
||||
}
|
||||
|
||||
if (normalServerConnect) {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.mysql;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class MySQL {
|
||||
private final Logger logger;
|
||||
private final HikariDataSource hikariDataSource;
|
||||
|
||||
public MySQL(final Logger logger, final String hostname, final int port, final String username, final String password, final String database, final boolean useSSL) {
|
||||
this.logger = logger;
|
||||
|
||||
final HikariConfig hikariConfig = new HikariConfig();
|
||||
hikariConfig.setMaximumPoolSize(10);
|
||||
hikariConfig.addDataSourceProperty("serverName", hostname);
|
||||
hikariConfig.addDataSourceProperty("user", username);
|
||||
hikariConfig.addDataSourceProperty("password", password);
|
||||
|
||||
String urlProperty = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
|
||||
if (!useSSL) {
|
||||
urlProperty += "?useSSL=false";
|
||||
}
|
||||
hikariConfig.addDataSourceProperty("url", urlProperty);
|
||||
|
||||
hikariConfig.setJdbcUrl(urlProperty);
|
||||
hikariConfig.setDataSourceClassName(findDriver("com.mysql.jdbc.jdbc2.optional.MysqlDataSource", "com.mysql.cj.jdbc.MysqlDataSource", "org.mariadb.jdbc.MariaDbDataSource"));
|
||||
hikariDataSource = new HikariDataSource(hikariConfig);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String findDriver(final String... classNames) {
|
||||
for (final String name : classNames) {
|
||||
try {
|
||||
Class.forName(name);
|
||||
return name;
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No sql driver class found");
|
||||
}
|
||||
|
||||
public void executeUpdate(final String query, final Consumer<Integer> callback, final Object... objects) {
|
||||
try (final Connection connection = hikariDataSource.getConnection()) {
|
||||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
|
||||
int current = 1;
|
||||
for (final Object object : objects) {
|
||||
preparedStatement.setObject(current, object);
|
||||
current++;
|
||||
}
|
||||
|
||||
callback.accept(preparedStatement.executeUpdate());
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.log(Level.SEVERE, "Error while executing update method: " + query);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeQuery(final String query, final Consumer<ResultSet> callback, final Object... objects) {
|
||||
try (final Connection connection = hikariDataSource.getConnection()) {
|
||||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
|
||||
int current = 1;
|
||||
for (final Object object : objects) {
|
||||
preparedStatement.setObject(current, object);
|
||||
current++;
|
||||
}
|
||||
|
||||
try (final ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
callback.accept(resultSet);
|
||||
}
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.log(Level.SEVERE, "Error while executing query method: " + query);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeUpdate(final String query, final Object... objects) {
|
||||
executeUpdate(query, res -> {
|
||||
}, objects);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
hikariDataSource.close();
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
package eu.kennytv.maintenance.core.proxy.redis;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import redis.clients.jedis.ConnectionPoolConfig;
|
||||
import redis.clients.jedis.RedisClient;
|
||||
import redis.clients.jedis.StreamEntryID;
|
||||
import redis.clients.jedis.params.XReadParams;
|
||||
import redis.clients.jedis.resps.StreamEntry;
|
||||
|
||||
public final class RedisHandler {
|
||||
|
||||
private static final String REDIS_STREAM_KEY = "maintenance:stream";
|
||||
private static final String REDIS_MAINTENANCE_KEY = "maintenance:status";
|
||||
private static final String REDIS_MODE_KEY = "maintenance:mode";
|
||||
private static final String REDIS_SERVERS_KEY = "maintenance:servers";
|
||||
private static final String REDIS_SERVER_MODES_KEY = "maintenance:server_modes";
|
||||
private static final String REDIS_WHITELIST_KEY = "maintenance:whitelist";
|
||||
|
||||
private static final String MSG_TYPE_MAINTENANCE_UPDATE = "status";
|
||||
private static final String MSG_TYPE_SERVER_ADD = "server_add";
|
||||
private static final String MSG_TYPE_SERVER_REMOVE = "server_remove";
|
||||
private static final String MSG_TYPE_PLAYER_ADD = "player_add";
|
||||
private static final String MSG_TYPE_PLAYER_REMOVE = "player_remove";
|
||||
private static final String MSG_TYPE = "type";
|
||||
private static final String MSG_VALUE = "val";
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private final MaintenanceProxyPlugin plugin;
|
||||
private final SettingsProxy settings;
|
||||
private RedisClient client;
|
||||
private StreamEntryID lastStreamId = new StreamEntryID();
|
||||
|
||||
public RedisHandler(final MaintenanceProxyPlugin plugin, final SettingsProxy settings) {
|
||||
this.plugin = plugin;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public void setup(final String redisUri) {
|
||||
plugin.getLogger().info("Trying to open Redis connection...");
|
||||
|
||||
final ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();
|
||||
poolConfig.setMaxWait(Duration.ofSeconds(5));
|
||||
poolConfig.setMaxTotal(2);
|
||||
client = RedisClient.builder().poolConfig(poolConfig).fromURI(URI.create(redisUri)).build();
|
||||
|
||||
// Get the latest stream ID to only receive new messages
|
||||
final List<StreamEntry> messages = client.xrevrange(REDIS_STREAM_KEY, (StreamEntryID) null, null, 1);
|
||||
if (!messages.isEmpty()) {
|
||||
lastStreamId = messages.getFirst().getID();
|
||||
}
|
||||
|
||||
running.set(true);
|
||||
plugin.async(this::listenToStream);
|
||||
|
||||
plugin.getLogger().info("Connected to Redis!");
|
||||
}
|
||||
|
||||
public boolean loadMaintenanceStatus() {
|
||||
return Boolean.parseBoolean(client.get(REDIS_MAINTENANCE_KEY));
|
||||
}
|
||||
|
||||
public @Nullable String loadGlobalMode() {
|
||||
return client.get(REDIS_MODE_KEY);
|
||||
}
|
||||
|
||||
public Map<String, String> loadMaintenanceServers() {
|
||||
final Set<String> servers = client.smembers(REDIS_SERVERS_KEY);
|
||||
final Map<String, String> serverModes = new HashMap<>();
|
||||
if (servers == null) {
|
||||
return serverModes;
|
||||
}
|
||||
|
||||
final Map<String, String> persistedModes = client.hgetAll(REDIS_SERVER_MODES_KEY);
|
||||
for (final String server : servers) {
|
||||
serverModes.put(server, normalizeMode(persistedModes.get(server)));
|
||||
}
|
||||
return serverModes;
|
||||
}
|
||||
|
||||
public void loadPlayers(final Map<UUID, String> players) {
|
||||
for (final Map.Entry<String, String> entry : client.hgetAll(REDIS_WHITELIST_KEY).entrySet()) {
|
||||
players.put(UUID.fromString(entry.getKey()), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void set(final boolean maintenance, final String mode) {
|
||||
client.set(REDIS_MAINTENANCE_KEY, Boolean.toString(maintenance));
|
||||
client.set(REDIS_MODE_KEY, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_MAINTENANCE_UPDATE,
|
||||
MSG_VALUE, Boolean.toString(maintenance),
|
||||
"mode", mode
|
||||
));
|
||||
}
|
||||
|
||||
public boolean addServer(final String server, final String mode) {
|
||||
if (client.sadd(REDIS_SERVERS_KEY, server) < 1) {
|
||||
return false;
|
||||
}
|
||||
client.hset(REDIS_SERVER_MODES_KEY, server, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_SERVER_ADD,
|
||||
MSG_VALUE, server,
|
||||
"mode", mode
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setServerMode(final String server, final String mode) {
|
||||
client.hset(REDIS_SERVER_MODES_KEY, server, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_SERVER_ADD,
|
||||
MSG_VALUE, server,
|
||||
"mode", mode
|
||||
));
|
||||
}
|
||||
|
||||
public boolean removeServer(final String server) {
|
||||
if (client.srem(REDIS_SERVERS_KEY, server) < 1) {
|
||||
return false;
|
||||
}
|
||||
client.hdel(REDIS_SERVER_MODES_KEY, server);
|
||||
send(MSG_TYPE_SERVER_REMOVE, server);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addPlayer(final UUID uuid, final String name) {
|
||||
final String value = uuid.toString();
|
||||
client.hset(REDIS_WHITELIST_KEY, value, name);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_PLAYER_ADD,
|
||||
MSG_VALUE, value,
|
||||
"name", name
|
||||
));
|
||||
}
|
||||
|
||||
public void removePlayer(final UUID uuid) {
|
||||
final String value = uuid.toString();
|
||||
client.hdel(REDIS_WHITELIST_KEY, value);
|
||||
send(MSG_TYPE_PLAYER_REMOVE, value);
|
||||
}
|
||||
|
||||
private void send(final String type, final String value) {
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(MSG_TYPE, type, MSG_VALUE, value));
|
||||
}
|
||||
|
||||
private void listenToStream() {
|
||||
while (running.get()) {
|
||||
try {
|
||||
final List<Map.Entry<String, List<StreamEntry>>> result = client.xread(
|
||||
XReadParams.xReadParams().block(5000),
|
||||
Map.of(REDIS_STREAM_KEY, lastStreamId)
|
||||
);
|
||||
if (result != null) {
|
||||
for (final Map.Entry<String, List<StreamEntry>> streamEntries : result) {
|
||||
for (final StreamEntry entry : streamEntries.getValue()) {
|
||||
plugin.sync(() -> processStreamMessage(entry));
|
||||
lastStreamId = entry.getID();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
if (running.get()) {
|
||||
plugin.getLogger().log(Level.WARNING, "Error reading from Redis stream", e);
|
||||
try {
|
||||
Thread.sleep(1000); // retry
|
||||
} catch (final InterruptedException ignored) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processStreamMessage(final StreamEntry message) {
|
||||
final Map<String, String> body = message.getFields();
|
||||
final String type = body.get(MSG_TYPE);
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String value = body.get(MSG_VALUE);
|
||||
switch (type) {
|
||||
case MSG_TYPE_MAINTENANCE_UPDATE -> handleStatus(value, body.get("mode"));
|
||||
case MSG_TYPE_SERVER_ADD -> handleServerStatus(value, body.get("mode"), true, "Server added to maintenance via Redis: ");
|
||||
case MSG_TYPE_SERVER_REMOVE -> handleServerStatus(value, null, false, "Server removed from maintenance via Redis: ");
|
||||
case MSG_TYPE_PLAYER_ADD -> handlePlayerAdd(value, body.get("name"));
|
||||
case MSG_TYPE_PLAYER_REMOVE -> handlePlayerRemove(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStatus(final String value, @Nullable final String mode) {
|
||||
final boolean maintenance = Boolean.parseBoolean(value);
|
||||
if (settings.isMaintenance() != maintenance) {
|
||||
plugin.getLogger().info("Maintenance status updated via Redis: " + maintenance);
|
||||
settings.setMaintenanceDirect(maintenance, mode);
|
||||
plugin.serverActions(maintenance);
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance && !normalizeMode(mode).equals(normalizeMode(settings.activeMode()))) {
|
||||
settings.setActiveModeDirect(mode);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServerStatus(final String value, @Nullable final String mode, final boolean maintenance, final String log) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean success;
|
||||
if (maintenance) {
|
||||
success = settings.addMaintenanceServerDirect(value, mode);
|
||||
settings.setMaintenanceServerModeDirect(value, mode);
|
||||
} else {
|
||||
success = settings.removeMaintenanceServerDirect(value);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
plugin.getLogger().info(log + value);
|
||||
final Server server = plugin.getServerOrDummy(value);
|
||||
plugin.serverActions(server, maintenance);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePlayerAdd(final String uuid, final String name) {
|
||||
settings.addWhitelistedPlayerDirect(UUID.fromString(uuid), name);
|
||||
}
|
||||
|
||||
private void handlePlayerRemove(final String value) {
|
||||
settings.removeWhitelistedPlayerDirect(UUID.fromString(value));
|
||||
}
|
||||
|
||||
public void close() {
|
||||
running.set(false);
|
||||
if (client != null) {
|
||||
client.close();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeMode(@Nullable final String mode) {
|
||||
return mode == null || mode.isBlank() ? "default" : mode.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
+4
-13
@@ -17,23 +17,19 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.api.proxy.MaintenanceProxy;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
protected final Server server;
|
||||
protected final String mode;
|
||||
|
||||
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds,
|
||||
final boolean enable, final Server server, @Nullable final String mode) {
|
||||
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable, final Server server) {
|
||||
super(plugin, settings, seconds, enable);
|
||||
this.server = server;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,12 +39,7 @@ public class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
|
||||
@Override
|
||||
protected void finish() {
|
||||
final MaintenanceProxyPlugin proxyPlugin = (MaintenanceProxyPlugin) plugin;
|
||||
proxyPlugin.setMaintenanceToServer(server, enable, mode);
|
||||
// Make sure no-ops have the platform task cancelled as well
|
||||
if (proxyPlugin.getServerTasks().remove(server.getName(), this)) {
|
||||
getTask().cancel();
|
||||
}
|
||||
((MaintenanceProxy) plugin).setMaintenanceToServer(server, enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-5
@@ -21,16 +21,14 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleMaintenanceScheduleRunnable extends SingleMaintenanceRunnable {
|
||||
private final int maintenanceDurationSeconds;
|
||||
|
||||
public SingleMaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds,
|
||||
final int maintenanceDuration, final Server server, @Nullable final String mode) {
|
||||
super(plugin, settings, seconds, true, server, mode);
|
||||
public SingleMaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final int maintenanceDuration, final Server server) {
|
||||
super(plugin, settings, seconds, true, server);
|
||||
this.maintenanceDurationSeconds = maintenanceDuration;
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -15,11 +15,17 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
package eu.kennytv.maintenance.core.proxy.server;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public record DummyServer(String name) implements Server {
|
||||
public final class DummyServer implements Server {
|
||||
private final String name;
|
||||
|
||||
public DummyServer(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -19,5 +19,20 @@ package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record ProfileLookup(UUID uuid, String name) {
|
||||
public final class ProfileLookup {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public ProfileLookup(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
+19
-2
@@ -18,11 +18,18 @@
|
||||
package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public record ProxyOfflineSenderInfo(UUID uuid, String name) implements ProxySenderInfo {
|
||||
public final class ProxyOfflineSenderInfo implements ProxySenderInfo {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public ProxyOfflineSenderInfo(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccess(final Server server) {
|
||||
@@ -33,6 +40,16 @@ public record ProxyOfflineSenderInfo(UUID uuid, String name) implements ProxySen
|
||||
public void disconnect(final Component component) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
return false;
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public interface ProxySenderInfo extends SenderInfo {
|
||||
|
||||
|
||||
@@ -16,10 +16,9 @@ sourceSets {
|
||||
|
||||
dependencies {
|
||||
api(projects.maintenanceApi)
|
||||
compileOnlyApi(libs.adventureApi)
|
||||
compileOnlyApi(libs.adventureTextMinimessage)
|
||||
compileOnlyApi(libs.adventureTextSerializerPlain)
|
||||
compileOnlyApi(libs.adventureTextSerializerLegacy)
|
||||
api(projects.adventure.adventureApi) {
|
||||
targetConfiguration = "shadow"
|
||||
}
|
||||
compileOnly(libs.luckperms)
|
||||
compileOnly(libs.serverlistplus)
|
||||
compileOnly(libs.guava)
|
||||
|
||||
@@ -32,11 +32,12 @@ import eu.kennytv.maintenance.core.dump.PluginDump;
|
||||
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceScheduleRunnable;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import eu.kennytv.maintenance.core.util.Version;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
@@ -46,7 +47,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -61,8 +62,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class MaintenancePlugin implements Maintenance {
|
||||
@@ -97,30 +96,11 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance, final String mode) {
|
||||
settings.setMaintenance(maintenance, mode);
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
settings.setMaintenance(maintenance);
|
||||
settings.getConfig().set("maintenance-enabled", maintenance);
|
||||
settings.saveConfig();
|
||||
serverActions(maintenance);
|
||||
}
|
||||
|
||||
public void serverActions(final boolean maintenance) {
|
||||
if (isTaskRunning()) {
|
||||
cancelTask();
|
||||
}
|
||||
if (serverListPlusHook != null && settings.isEnablePingMessages()) {
|
||||
serverListPlusHook.setEnabled(!maintenance);
|
||||
}
|
||||
|
||||
broadcast(maintenance ? settings.getMessage("maintenanceActivated") : settings.getMessage("maintenanceDeactivated"));
|
||||
if (maintenance && settings.isKickOnlinePlayers()) {
|
||||
kickPlayers();
|
||||
}
|
||||
|
||||
eventManager.callEvent(new MaintenanceChangedEvent(maintenance));
|
||||
if (maintenance) {
|
||||
sendWebhookMessage("webhookMaintenanceActivated", DiscordWebhook.EventType.MAINTENANCE_ENABLED);
|
||||
} else {
|
||||
sendWebhookMessage("webhookMaintenanceDeactivated", DiscordWebhook.EventType.MAINTENANCE_DISABLED);
|
||||
}
|
||||
|
||||
for (final String command : (maintenance ? settings.getCommandsOnMaintenanceEnable() : settings.getCommandsOnMaintenanceDisable())) {
|
||||
try {
|
||||
@@ -131,35 +111,30 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendWebhookMessage(final String messageKey, final DiscordWebhook.EventType eventType, final String... replacements) {
|
||||
if (!settings.isWebhookEnabled() || !settings.isWebhookEventEnabled(eventType.configKey())) {
|
||||
return;
|
||||
public void serverActions(final boolean maintenance) {
|
||||
if (isTaskRunning()) {
|
||||
cancelTask();
|
||||
}
|
||||
if (serverListPlusHook != null && settings.isEnablePingMessages()) {
|
||||
serverListPlusHook.setEnabled(!maintenance);
|
||||
}
|
||||
|
||||
async(() -> {
|
||||
try {
|
||||
DiscordWebhook.sendMessage(settings.getWebhookMessage(messageKey, replacements), eventType, settings);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.WARNING, "Could not send Discord webhook message", e);
|
||||
if (maintenance) {
|
||||
broadcast(settings.getMessage("maintenanceActivated"));
|
||||
if (settings.isKickOnlinePlayers()) {
|
||||
kickPlayers();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
broadcast(settings.getMessage("maintenanceDeactivated"));
|
||||
}
|
||||
|
||||
eventManager.callEvent(new MaintenanceChangedEvent(maintenance));
|
||||
}
|
||||
|
||||
public String getTargetTimestamp(final Duration duration) {
|
||||
return Long.toString((System.currentTimeMillis() + duration.toMillis()) / TimeUnit.SECONDS.toMillis(1));
|
||||
}
|
||||
|
||||
public String replacePingVariables(final String component) {
|
||||
return replacePingVariables(component, settings.activeMode());
|
||||
}
|
||||
|
||||
public String replacePingVariables(String component, @Nullable final String mode) {
|
||||
public String replacePingVariables(String component) {
|
||||
if (component.contains("%TIMER%")) {
|
||||
component = component.replace("%TIMER%", getTimerMessage());
|
||||
}
|
||||
final String reason = settings.activeReason() == null ? "" : settings.activeReason();
|
||||
component = component.replace("%REASON%", reason);
|
||||
component = component.replace("%MODE%", mode == null ? "default" : mode);
|
||||
component = component.replace("%ONLINE%", String.valueOf(getOnlinePlayers()));
|
||||
component = component.replace("%MAX%", String.valueOf(getMaxPlayers()));
|
||||
return component;
|
||||
@@ -193,18 +168,14 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
|
||||
private void append(final StringBuilder builder, final String timeUnit, final int time) {
|
||||
if (time == 0) return;
|
||||
if (!builder.isEmpty()) {
|
||||
if (builder.length() != 0) {
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append(time).append(' ').append(settings.language.getString(time == 1 ? timeUnit : timeUnit + "s"));
|
||||
}
|
||||
|
||||
public void startMaintenanceRunnable(final Duration duration, final boolean enable) {
|
||||
startMaintenanceRunnable(duration, enable, null);
|
||||
}
|
||||
|
||||
public void startMaintenanceRunnable(final Duration duration, final boolean enable, @Nullable final String mode) {
|
||||
runnable = new MaintenanceRunnable(this, settings, (int) duration.getSeconds(), enable, mode);
|
||||
runnable = new MaintenanceRunnable(this, settings, (int) duration.getSeconds(), enable);
|
||||
// Save the endtimer to be able to continue it after a server stop
|
||||
if (settings.isSaveEndtimerOnStop() && !runnable.shouldEnable()) {
|
||||
settings.setSavedEndtimer(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(runnable.getSecondsLeft()));
|
||||
@@ -212,11 +183,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
public void scheduleMaintenanceRunnable(final Duration enableIn, final Duration maintenanceDuration) {
|
||||
scheduleMaintenanceRunnable(enableIn, maintenanceDuration, null);
|
||||
}
|
||||
|
||||
public void scheduleMaintenanceRunnable(final Duration enableIn, final Duration maintenanceDuration, @Nullable final String mode) {
|
||||
runnable = new MaintenanceScheduleRunnable(this, settings, (int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), mode);
|
||||
runnable = new MaintenanceScheduleRunnable(this, settings, (int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds());
|
||||
}
|
||||
|
||||
public boolean updateAvailable() {
|
||||
@@ -260,7 +227,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
if (compare < 0) {
|
||||
getLogger().warning("Newest version available: Version " + newestVersion + ", you're on " + version);
|
||||
} else if (compare > 0) {
|
||||
if (version.getTag() != null && !version.getTag().isBlank()) {
|
||||
if (version.getTag().equalsIgnoreCase("snapshot")) {
|
||||
getLogger().info("You're running a development version, please report bugs on the Discord server (https://discord.gg/vGCUzHq) or the GitHub issue tracker (https://github.com/kennytv/Maintenance/issues)");
|
||||
} else {
|
||||
getLogger().info("You're running a version, that doesn't exist!");
|
||||
@@ -270,9 +237,11 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
public boolean installUpdate() throws Exception {
|
||||
final String fileName = "Maintenance-" + serverType.name() + "-" + newestVersion + ".jar";
|
||||
// Sponge and Velocity need their own jar
|
||||
final String platformInfix = serverType == ServerType.VELOCITY ? "Velocity-" : serverType == ServerType.SPONGE ? "Sponge-" : "";
|
||||
final String fileName = "Maintenance-" + platformInfix + newestVersion + ".jar";
|
||||
final Path tempFilePath = Paths.get(getPluginFolder() + "Maintenance.tmp");
|
||||
final URLConnection connection = URI.create("https://github.com/kennytv/Maintenance/releases/download/" + newestVersion + "/" + fileName).toURL().openConnection();
|
||||
final URLConnection connection = new URL("https://github.com/kennytv/Maintenance/releases/download/" + newestVersion + "/" + fileName).openConnection();
|
||||
try (final BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
|
||||
final BufferedOutputStream os = new BufferedOutputStream(Files.newOutputStream(tempFilePath))) {
|
||||
writeFile(is, os);
|
||||
@@ -304,10 +273,8 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
private void checkNewestVersion() throws Exception {
|
||||
final URLConnection connection = URI.create("https://hangar.papermc.io/api/v1/projects/Maintenance/latestrelease").toURL().openConnection();
|
||||
final URLConnection connection = new URL("https://hangar.papermc.io/api/v1/projects/Maintenance/latestrelease").openConnection();
|
||||
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
|
||||
connection.setConnectTimeout(5_000);
|
||||
connection.setReadTimeout(10_000);
|
||||
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||
final String newVersionString = reader.readLine();
|
||||
final Version newVersion = new Version(newVersionString);
|
||||
@@ -320,7 +287,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
public String pasteDump() {
|
||||
final MaintenanceDump dump = new MaintenanceDump(this, settings);
|
||||
try {
|
||||
final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.pastes.dev/post").toURL().openConnection();
|
||||
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.pastes.dev/post").openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
|
||||
@@ -361,7 +328,8 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
try {
|
||||
loadIcon(file);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.WARNING, "Could not load the 'maintenance-icon.png' file!", e);
|
||||
getLogger().log(Level.WARNING, "Could not load the 'maintenance-icon.png' file!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,10 +374,6 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
return runnable != null;
|
||||
}
|
||||
|
||||
public @Nullable MaintenanceRunnable getCurrentTask() {
|
||||
return runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
@@ -472,10 +436,6 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
return "plugins/";
|
||||
}
|
||||
|
||||
public void sync(final Runnable runnable) {
|
||||
async(runnable);
|
||||
}
|
||||
|
||||
public abstract void async(Runnable runnable);
|
||||
|
||||
protected abstract void executeConsoleCommand(String command);
|
||||
|
||||
@@ -20,8 +20,11 @@ package eu.kennytv.maintenance.core;
|
||||
import eu.kennytv.maintenance.api.event.MaintenanceReloadedEvent;
|
||||
import eu.kennytv.maintenance.core.config.Config;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.config.DisplayedMessages;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -29,43 +32,34 @@ import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Level;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
public static final String NEW_LINE_REPLACEMENT = "<br>";
|
||||
private static final int CONFIG_VERSION = 12;
|
||||
private static final int LANGUAGE_VERSION = 5;
|
||||
private static final int CONFIG_VERSION = 9;
|
||||
private static final int LANGUAGE_VERSION = 2;
|
||||
private static final Random RANDOM = new Random();
|
||||
protected final MaintenancePlugin plugin;
|
||||
private final Map<UUID, String> whitelistedPlayers = new HashMap<>();
|
||||
private final String[] unsupportedFields;
|
||||
protected boolean maintenance;
|
||||
protected String activeMode;
|
||||
protected String activeReason;
|
||||
private Set<Integer> broadcastIntervals;
|
||||
private DisplayedMessages pingMessages;
|
||||
private DisplayedMessages timerSpecificPingMessages;
|
||||
private List<String> pingMessages;
|
||||
private List<String> timerSpecificPingMessages;
|
||||
private List<String> commandsOnMaintenanceEnable;
|
||||
private List<String> commandsOnMaintenanceDisable;
|
||||
private DisplayedMessages legacyParsedPlayerCountMessages;
|
||||
private DisplayedMessages legacyParsedTimerPlayerCountMessages;
|
||||
private DisplayedMessages legacyParsedPlayerCountHoverLines;
|
||||
private DisplayedMessages legacyParsedTimerPlayerCountHoverLines;
|
||||
private String legacyParsedPlayerCountMessage;
|
||||
private String legacyParsedTimerPlayerCountMessage;
|
||||
private List<String> legacyParsedPlayerCountHoverLines;
|
||||
private List<String> legacyParsedTimerPlayerCountHoverLines;
|
||||
private String prefixString;
|
||||
private String plainTextPrefix;
|
||||
private String languageName;
|
||||
private boolean enablePingMessages;
|
||||
private boolean customPlayerCountMessage;
|
||||
@@ -78,13 +72,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
private boolean debug;
|
||||
private long savedEndtimer;
|
||||
|
||||
// Webhook settings
|
||||
private boolean webhookEnabled;
|
||||
private Set<String> webhookEnabledEvents;
|
||||
private String webhookUrl;
|
||||
private String webhookUsername;
|
||||
private String webhookAvatarUrl;
|
||||
|
||||
protected Config config;
|
||||
protected Config language;
|
||||
protected Config whitelist;
|
||||
@@ -132,7 +119,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
}
|
||||
|
||||
prefixString = language.getString("prefix");
|
||||
plainTextPrefix = PlainTextComponentSerializer.plainText().serialize(parse(prefixString));
|
||||
|
||||
plugin.getEventManager().callEvent(new MaintenanceReloadedEvent());
|
||||
}
|
||||
@@ -175,9 +161,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
if (file.exists()) return;
|
||||
|
||||
try (final InputStream in = plugin.getResource(fileName)) {
|
||||
if (in == null) {
|
||||
throw new IOException("No bundled language file " + fileName);
|
||||
}
|
||||
Files.copy(in, file.toPath());
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().warning("Unable to provide language " + languageName);
|
||||
@@ -196,16 +179,14 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
final ConfigSection pingMessageSection = config.getSection("ping-message");
|
||||
enablePingMessages = pingMessageSection.getBoolean("enabled", true);
|
||||
// Can't store this pre-parsed as components because gradients will break replacements
|
||||
pingMessages = loadPingMessages(pingMessageSection.getSection("messages"));
|
||||
pingMessages = loadPingMessages(pingMessageSection.getStringList("messages"));
|
||||
if (pingMessageSection.getBoolean("enable-timer-specific-messages")) {
|
||||
timerSpecificPingMessages = loadPingMessages(pingMessageSection.getSection("timer-messages"));
|
||||
timerSpecificPingMessages = loadPingMessages(pingMessageSection.getStringList("timer-messages"));
|
||||
} else {
|
||||
timerSpecificPingMessages = null;
|
||||
}
|
||||
|
||||
maintenance = config.getBoolean("maintenance-enabled");
|
||||
activeMode = normalizeMode(config.getString("active-mode"));
|
||||
activeReason = normalizeReason(config.getString("active-reason"));
|
||||
commandsOnMaintenanceEnable = config.getStringList("commands-on-maintenance-enable");
|
||||
commandsOnMaintenanceDisable = config.getStringList("commands-on-maintenance-disable");
|
||||
customMaintenanceIcon = config.getBoolean("custom-maintenance-icon");
|
||||
@@ -216,35 +197,34 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
if (plugin.getServerType() != ServerType.SPONGE) {
|
||||
final ConfigSection playerCountMessageSection = config.getSection("player-count-message");
|
||||
customPlayerCountMessage = playerCountMessageSection.getBoolean("enabled");
|
||||
legacyParsedPlayerCountMessages = loadPlayerCountMessages(playerCountMessageSection.getSection("messages"));
|
||||
legacyParsedPlayerCountMessage = toLegacy(parse(getConfigMessage(playerCountMessageSection, "message")));
|
||||
if (playerCountMessageSection.getBoolean("enable-timer-specific-message")) {
|
||||
legacyParsedTimerPlayerCountMessages = loadPlayerCountMessages(playerCountMessageSection.getSection("timer-messages"));
|
||||
legacyParsedTimerPlayerCountMessage = toLegacy(parse(getConfigMessage(playerCountMessageSection, "timer-message")));
|
||||
} else {
|
||||
legacyParsedTimerPlayerCountMessages = null;
|
||||
legacyParsedTimerPlayerCountMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
final ConfigSection listHoverMessageSection = config.getSection("player-list-hover-message");
|
||||
customPlayerCountHoverMessage = listHoverMessageSection.getBoolean("enabled");
|
||||
legacyParsedPlayerCountHoverLines = loadPlayerCountHoverMessages(listHoverMessageSection.getSection("messages"));
|
||||
legacyParsedPlayerCountHoverLines = new ArrayList<>();
|
||||
for (final String line : listHoverMessageSection.getString("message").split("<br>")) {
|
||||
legacyParsedPlayerCountHoverLines.add(toLegacy(parse(line)));
|
||||
}
|
||||
if (listHoverMessageSection.getBoolean("enable-timer-specific-message")) {
|
||||
legacyParsedTimerPlayerCountHoverLines = loadPlayerCountHoverMessages(listHoverMessageSection.getSection("timer-messages"));
|
||||
legacyParsedTimerPlayerCountHoverLines = new ArrayList<>();
|
||||
for (final String line : listHoverMessageSection.getString("timer-message").split("<br>")) {
|
||||
legacyParsedTimerPlayerCountHoverLines.add(toLegacy(parse(line)));
|
||||
}
|
||||
} else {
|
||||
legacyParsedTimerPlayerCountHoverLines = null;
|
||||
}
|
||||
|
||||
languageName = config.getString("language").toLowerCase(Locale.ROOT);
|
||||
languageName = config.getString("language").toLowerCase();
|
||||
kickOnlinePlayers = config.getBoolean("kick-online-players", true);
|
||||
updateChecks = config.getBoolean("update-checks", true);
|
||||
debug = config.getBoolean("debug");
|
||||
|
||||
final ConfigSection webhookSection = config.getSection("webhook");
|
||||
webhookEnabled = webhookSection.getBoolean("enabled");
|
||||
webhookEnabledEvents = new HashSet<>(webhookSection.getStringList("enabled-events"));
|
||||
webhookUrl = webhookSection.getString("url", "");
|
||||
webhookUsername = webhookSection.getString("username", "Maintenance");
|
||||
webhookAvatarUrl = webhookSection.getString("avatar-url", "");
|
||||
|
||||
final ConfigSection section = config.getSection("continue-endtimer-after-restart");
|
||||
saveEndtimerOnStop = section.getBoolean("enabled");
|
||||
savedEndtimer = section.getLong("end");
|
||||
@@ -253,12 +233,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.loadMaintenanceIcon();
|
||||
}
|
||||
|
||||
loadWhitelistedPlayers();
|
||||
|
||||
loadExtraSettings();
|
||||
}
|
||||
|
||||
protected void loadWhitelistedPlayers() {
|
||||
whitelistedPlayers.clear();
|
||||
for (final Map.Entry<String, Object> entry : whitelist.getValues().entrySet()) {
|
||||
try {
|
||||
@@ -267,6 +241,8 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.getLogger().warning("Invalid WhitelistedPlayers entry: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
loadExtraSettings();
|
||||
}
|
||||
|
||||
private void updatePluginDirectory() {
|
||||
@@ -274,7 +250,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
String oldDirName = "Maintenance" + plugin.getServerType();
|
||||
if (plugin.getServerType() == ServerType.SPONGE || plugin.getServerType() == ServerType.VELOCITY) {
|
||||
oldDirName = oldDirName.toLowerCase(Locale.ROOT);
|
||||
} else if (plugin.getServerType() == ServerType.PAPER) {
|
||||
} else if (plugin.getServerType() == ServerType.SPIGOT) {
|
||||
oldDirName = "MaintenanceSpigot";
|
||||
}
|
||||
|
||||
@@ -314,35 +290,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
config.move("enable-playercounthovermessage", "player-list-hover-message.enabled");
|
||||
config.move("playercounthovermessage", "player-list-hover-message.message");
|
||||
}
|
||||
if (version < 11) {
|
||||
config.move("player-count-message.message", "player-count-message.messages.default");
|
||||
config.move("player-count-message.timer-message", "player-count-message.timer-messages.default");
|
||||
|
||||
config.move("player-list-hover-message.message", "player-list-hover-message.messages.default");
|
||||
config.move("player-list-hover-message.timer-message", "player-list-hover-message.timer-messages.default");
|
||||
|
||||
migrateModeSection("ping-message.messages");
|
||||
migrateModeSection("ping-message.timer-messages");
|
||||
migrateModeSection("player-count-message.messages");
|
||||
migrateModeSection("player-count-message.timer-messages");
|
||||
migrateModeSection("player-list-hover-message.messages");
|
||||
migrateModeSection("player-list-hover-message.timer-messages");
|
||||
|
||||
final Object proxiedMaintenanceServers = config.getObject("proxied-maintenance-servers");
|
||||
if (proxiedMaintenanceServers instanceof List<?> list) {
|
||||
final Map<String, String> migratedServers = new LinkedHashMap<>();
|
||||
for (final Object entry : list) {
|
||||
if (entry != null) {
|
||||
migratedServers.put(String.valueOf(entry), "default");
|
||||
}
|
||||
}
|
||||
config.set("proxied-maintenance-servers", migratedServers);
|
||||
}
|
||||
}
|
||||
if (version < 12) {
|
||||
// Fix typo in the shipped config key :>
|
||||
config.move("redis.enables", "redis.enabled");
|
||||
}
|
||||
|
||||
createFile("config-new.yml", "config.yml");
|
||||
final File file = new File(plugin.getDataFolder(), "config-new.yml");
|
||||
@@ -374,10 +321,11 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.getLogger().info("Updating language file to the latest version...");
|
||||
if (version < 1) {
|
||||
for (final Map.Entry<String, Object> entry : language.getValues().entrySet()) {
|
||||
if (!(entry.getValue() instanceof String value)) {
|
||||
if (!(entry.getValue() instanceof String)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = (String) entry.getValue();
|
||||
value = value.replace("&8[&eMaintenance&8] ", "<prefix>");
|
||||
value = legacyToMinimessage(value);
|
||||
value = value.replace("%NEWLINE%", NEW_LINE_REPLACEMENT);
|
||||
@@ -413,17 +361,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return serialized.replaceAll("</[a-z_]+>", "");
|
||||
}
|
||||
|
||||
private void migrateModeSection(final String path) {
|
||||
final Object section = config.getObject(path);
|
||||
if (section == null || section instanceof Map<?, ?>) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("default", section);
|
||||
config.set(path, map);
|
||||
}
|
||||
|
||||
private String getConfigMessage(final ConfigSection section, final String path) {
|
||||
final String s = section.getString(path);
|
||||
if (s == null) {
|
||||
@@ -456,25 +393,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return replaceNewlineVar(s).replace("<prefix>", prefixString);
|
||||
}
|
||||
|
||||
public String getWebhookMessage(final String path, final String... replacements) {
|
||||
String s = language.getString(path);
|
||||
if (s == null) {
|
||||
plugin.getLogger().warning("The language file is missing the following webhook message: " + path);
|
||||
return path;
|
||||
}
|
||||
if (replacements.length != 0) {
|
||||
if (replacements.length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Invalid replacement count: " + replacements.length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < replacements.length; i += 2) {
|
||||
final String key = replacements[i];
|
||||
s = s.replace(key, replacements[i + 1]);
|
||||
}
|
||||
}
|
||||
return replaceNewlineVar(s);
|
||||
}
|
||||
|
||||
public @Nullable String getLanguageStringOrNull(final String path, final String... replacements) {
|
||||
return language.contains(path) ? getLanguageString(path, replacements) : null;
|
||||
}
|
||||
@@ -485,53 +403,24 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
|
||||
// TODO Cache platform components if there are no replacements
|
||||
public Component getRandomPingMessage() {
|
||||
return getRandomPingMessage(activeMode);
|
||||
}
|
||||
|
||||
public Component getRandomPingMessage(@Nullable final String mode) {
|
||||
if (plugin.isTaskRunning() && !plugin.getRunnable().shouldEnable() && hasTimerSpecificPingMessages()) {
|
||||
return getPingMessage(timerSpecificPingMessages, mode);
|
||||
if (plugin.isTaskRunning() && !plugin.getRunnable().shouldEnable()
|
||||
&& hasTimerSpecificPingMessages() && !timerSpecificPingMessages.isEmpty()) {
|
||||
return getPingMessage(timerSpecificPingMessages);
|
||||
}
|
||||
return pingMessages.isEmpty() ? Component.empty() : getPingMessage(pingMessages, mode);
|
||||
return pingMessages.isEmpty() ? Component.empty() : getPingMessage(pingMessages);
|
||||
}
|
||||
|
||||
private Component getPingMessage(final DisplayedMessages list, @Nullable final String mode) {
|
||||
final String component = list.getRandomEntry(mode);
|
||||
return parse(plugin.replacePingVariables(component, mode));
|
||||
private Component getPingMessage(final List<String> list) {
|
||||
final String component = list.size() == 1 ? list.get(0) : list.get(RANDOM.nextInt(list.size()));
|
||||
return parse(plugin.replacePingVariables(component));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPingMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> list.add(replaceNewlineVar(s)));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPlayerCountHoverMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> {
|
||||
// Split into separate messages (one per player entry)
|
||||
for (final String line : s.split("<br>")) {
|
||||
list.add(toLegacy(parse(line)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPlayerCountMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> list.add(toLegacy(parse(s))));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadDisplayedMessages(final ConfigSection section, final BiConsumer<List<String>, String> messageFunction) {
|
||||
final Map<String, List<String>> modes = new HashMap<>(section.getKeys().size());
|
||||
for (final Map.Entry<String, Object> entry : section.getValues().entrySet()) {
|
||||
final List<String> components = new ArrayList<>();
|
||||
if (entry.getValue() instanceof String s) {
|
||||
messageFunction.accept(components, s);
|
||||
} else if (entry.getValue() instanceof List<?> list) {
|
||||
//noinspection unchecked
|
||||
for (final String s : ((Iterable<String>) list)) {
|
||||
messageFunction.accept(components, s);
|
||||
}
|
||||
}
|
||||
modes.put(entry.getKey(), components);
|
||||
private List<String> loadPingMessages(final List<String> list) {
|
||||
final List<String> components = new ArrayList<>(list.size());
|
||||
for (final String s : list) {
|
||||
components.add(replaceNewlineVar(s));
|
||||
}
|
||||
return new DisplayedMessages(modes);
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -559,19 +448,18 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return false;
|
||||
}
|
||||
|
||||
return removeWhitelistedPlayer(uuid);
|
||||
whitelistedPlayers.remove(uuid);
|
||||
whitelist.remove(uuid.toString());
|
||||
saveWhitelistedPlayers();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
|
||||
final boolean added = !name.equals(whitelistedPlayers.put(uuid, name));
|
||||
if (!added) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean added = whitelistedPlayers.put(uuid, name) == null;
|
||||
whitelist.set(uuid.toString(), name);
|
||||
saveWhitelistedPlayers();
|
||||
return true;
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -589,47 +477,8 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return maintenance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String activeMode() {
|
||||
return activeMode;
|
||||
}
|
||||
|
||||
public void setActiveMode(@Nullable final String activeMode) {
|
||||
final String normalized = normalizeMode(activeMode);
|
||||
if (Objects.equals(this.activeMode, normalized)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeMode = normalized;
|
||||
config.set("active-mode", normalized != null ? normalized : "default");
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String activeReason() {
|
||||
return activeReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveReason(@Nullable final String reason) {
|
||||
final String normalized = normalizeReason(reason);
|
||||
if (Objects.equals(this.activeReason, normalized)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeReason = normalized;
|
||||
config.set("active-reason", normalized);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public void setMaintenance(final boolean maintenance, @Nullable final String mode) {
|
||||
if (this.maintenance != maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
config.set("maintenance-enabled", maintenance);
|
||||
this.activeMode = normalizeMode(mode);
|
||||
config.set("active-mode", this.activeMode != null ? this.activeMode : "default");
|
||||
saveConfig();
|
||||
}
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -686,7 +535,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return config;
|
||||
}
|
||||
|
||||
public DisplayedMessages getPingMessages() {
|
||||
public List<String> getPingMessages() {
|
||||
return pingMessages;
|
||||
}
|
||||
|
||||
@@ -698,7 +547,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return commandsOnMaintenanceDisable;
|
||||
}
|
||||
|
||||
public @Nullable DisplayedMessages getTimerSpecificPingMessages() {
|
||||
public @Nullable List<String> getTimerSpecificPingMessages() {
|
||||
return timerSpecificPingMessages;
|
||||
}
|
||||
|
||||
@@ -706,50 +555,16 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return broadcastIntervals;
|
||||
}
|
||||
|
||||
public boolean isWebhookEnabled() {
|
||||
return webhookEnabled;
|
||||
}
|
||||
|
||||
public boolean isWebhookEventEnabled(final String event) {
|
||||
return webhookEnabledEvents.contains(event);
|
||||
}
|
||||
|
||||
public String getWebhookUrl() {
|
||||
return webhookUrl;
|
||||
}
|
||||
|
||||
public String getWebhookUsername() {
|
||||
return webhookUsername;
|
||||
}
|
||||
|
||||
public String getWebhookAvatarUrl() {
|
||||
return webhookAvatarUrl;
|
||||
}
|
||||
|
||||
public String getPlainTextPrefix() {
|
||||
return plainTextPrefix;
|
||||
}
|
||||
|
||||
public String getLegacyParsedPlayerCountMessage() {
|
||||
return getLegacyParsedPlayerCountMessage(activeMode);
|
||||
}
|
||||
|
||||
public String getLegacyParsedPlayerCountMessage(@Nullable final String mode) {
|
||||
final DisplayedMessages messages = timerDependent(legacyParsedPlayerCountMessages, legacyParsedTimerPlayerCountMessages);
|
||||
final String message = messages.getRandomEntry(mode);
|
||||
return plugin.replacePingVariables(message, mode);
|
||||
final String message = timerDependent(legacyParsedPlayerCountMessage, legacyParsedTimerPlayerCountMessage);
|
||||
return plugin.replacePingVariables(message);
|
||||
}
|
||||
|
||||
public String[] getLegacyParsedPlayerCountHoverLines() {
|
||||
return getLegacyParsedPlayerCountHoverLines(activeMode);
|
||||
}
|
||||
|
||||
public String[] getLegacyParsedPlayerCountHoverLines(@Nullable final String mode) {
|
||||
final DisplayedMessages messages = timerDependent(legacyParsedPlayerCountHoverLines, legacyParsedTimerPlayerCountHoverLines);
|
||||
final List<String> lines = messages.getMessages(mode);
|
||||
final List<String> lines = timerDependent(legacyParsedPlayerCountHoverLines, legacyParsedTimerPlayerCountHoverLines);
|
||||
final String[] parsedLines = new String[lines.size()];
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
parsedLines[i] = plugin.replacePingVariables(lines.get(i), mode);
|
||||
parsedLines[i] = plugin.replacePingVariables(lines.get(i));
|
||||
}
|
||||
return parsedLines;
|
||||
}
|
||||
@@ -783,7 +598,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
}
|
||||
|
||||
/*
|
||||
* Note on why this even exists: YAML will force save all strings containing line breaks '\n' in this rather chunky format:
|
||||
* Note on why this even exists: Yaml will force save all strings containing line breaks '\n' in this rather chunky format:
|
||||
* key: |-
|
||||
* First line text
|
||||
* Second line text.
|
||||
@@ -796,17 +611,6 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return s.replace(NEW_LINE_REPLACEMENT, "\n");
|
||||
}
|
||||
|
||||
protected @Nullable String normalizeMode(@Nullable final String mode) {
|
||||
if (mode == null || mode.isBlank() || mode.equalsIgnoreCase("default")) {
|
||||
return null;
|
||||
}
|
||||
return mode.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
private String normalizeReason(@Nullable final String reason) {
|
||||
return reason == null || reason.isBlank() ? "" : reason;
|
||||
}
|
||||
|
||||
protected void loadExtraSettings() {
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.command;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -28,10 +28,8 @@ import eu.kennytv.maintenance.core.command.subcommand.MotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ReloadCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.RemoveMotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ScheduleTimerCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.SetReasonCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.SetMotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.StarttimerCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.StatusCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ToggleCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.UpdateCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.WhitelistAddCommand;
|
||||
@@ -76,7 +74,6 @@ public abstract class MaintenanceCommand {
|
||||
add(new SetMotdCommand(plugin), "setmotd");
|
||||
add(new RemoveMotdCommand(plugin), "removemotd");
|
||||
add(new MotdCommand(plugin), "motd");
|
||||
add(new SetReasonCommand(plugin), "setreason");
|
||||
|
||||
add(new UpdateCommand(plugin), "update", "forceupdate");
|
||||
add(new DumpCommand(plugin), "dump");
|
||||
@@ -100,7 +97,7 @@ public abstract class MaintenanceCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
final CommandInfo command = commandExecutors.get(args[0].toLowerCase(Locale.ROOT));
|
||||
final CommandInfo command = commandExecutors.get(args[0].toLowerCase());
|
||||
if (command == null) {
|
||||
help.sendUsage(sender);
|
||||
return;
|
||||
@@ -115,7 +112,7 @@ public abstract class MaintenanceCommand {
|
||||
|
||||
public List<String> getSuggestions(final SenderInfo sender, final String[] args) {
|
||||
if (!sender.hasMaintenancePermission("command") || args.length == 0) return Collections.emptyList();
|
||||
final String s = args[0].toLowerCase(Locale.ROOT);
|
||||
final String s = args[0].toLowerCase();
|
||||
if (args.length == 1) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final Map.Entry<String, CommandInfo> entry : commandExecutors.entrySet()) {
|
||||
@@ -132,24 +129,6 @@ public abstract class MaintenanceCommand {
|
||||
return info != null && info.hasPermission(sender) ? info.getTabCompletion(sender, args) : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a user given time like {@code 2d}, {@code 2d12h}, {@code 1h5m}, or {@code 30s} to an ISO-8601 duration string.
|
||||
* Days are supported in addition to hours, minutes, and seconds.
|
||||
*
|
||||
* @return ISO duration string
|
||||
*/
|
||||
private static String toIsoDuration(final String time) {
|
||||
final String upper = time.toUpperCase(Locale.ROOT);
|
||||
final int dayIndex = upper.indexOf('D');
|
||||
if (dayIndex == -1) {
|
||||
return "PT" + upper;
|
||||
}
|
||||
|
||||
final String days = upper.substring(0, dayIndex + 1);
|
||||
final String rest = upper.substring(dayIndex + 1);
|
||||
return rest.isEmpty() ? "P" + days : "P" + days + "T" + rest;
|
||||
}
|
||||
|
||||
public @Nullable Duration parseDurationAndCheckTask(final SenderInfo sender, final String time, final boolean taskCheck) {
|
||||
final Duration duration;
|
||||
if (plugin.isNumeric(time)) {
|
||||
@@ -157,7 +136,8 @@ public abstract class MaintenanceCommand {
|
||||
duration = Duration.ofMinutes(Integer.parseInt(time));
|
||||
} else {
|
||||
try {
|
||||
duration = Duration.parse(toIsoDuration(time));
|
||||
// Only accept hours, minutes, and seconds
|
||||
duration = Duration.parse("PT" + time.toUpperCase(Locale.ROOT));
|
||||
} catch (final DateTimeParseException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -188,7 +168,6 @@ public abstract class MaintenanceCommand {
|
||||
|
||||
protected void addToggleAndTimerCommands() {
|
||||
add(new ToggleCommand(plugin), "on", "off");
|
||||
add(new StatusCommand(plugin), "status");
|
||||
|
||||
add(new StarttimerCommand(plugin), "starttimer", "start");
|
||||
add(new EndtimerCommand(plugin), "endtimer", "end");
|
||||
|
||||
@@ -20,14 +20,12 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import static eu.kennytv.maintenance.core.util.ComponentUtil.clickEvent;
|
||||
|
||||
public final class DumpCommand extends CommandInfo {
|
||||
private long lastDump;
|
||||
@@ -59,7 +57,7 @@ public final class DumpCommand extends CommandInfo {
|
||||
sender.sendPrefixedRich("<red><click:open_url:'" + url + "'>" + url + "</click>");
|
||||
if (sender.isPlayer()) {
|
||||
final TextComponent text = Component.text().content("Click here to copy the link").color(NamedTextColor.GRAY)
|
||||
.clickEvent(clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, url))
|
||||
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, url))
|
||||
.hoverEvent(HoverEvent.showText(Component.text("Click here to copy the link to your clipboard").color(NamedTextColor.GREEN)))
|
||||
.build();
|
||||
sender.send(plugin.prefix().append(text));
|
||||
|
||||
+2
-8
@@ -19,10 +19,9 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class EndtimerCommand extends CommandInfo {
|
||||
|
||||
@@ -45,11 +44,6 @@ public final class EndtimerCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
|
||||
final Component message = getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
sender.send(getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ import com.google.common.base.Preconditions;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class HelpCommand extends CommandInfo {
|
||||
private static final int COMMANDS_PER_PAGE = 8;
|
||||
|
||||
@@ -19,14 +19,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MotdCommand extends CommandInfo {
|
||||
|
||||
@@ -36,29 +32,21 @@ public final class MotdCommand extends CommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
int indexOffset = 1;
|
||||
boolean timer = false;
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (args.length == 1) {
|
||||
sendList(sender, getSettings().getPingMessages());
|
||||
} else if (args.length == 2 && args[1].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
timer = true;
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length > indexOffset + 1) {
|
||||
sendList(sender, getSettings().getTimerSpecificPingMessages());
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final String mode = args.length == indexOffset + 1 ? args[indexOffset].toLowerCase(Locale.ROOT) : "default";
|
||||
final ConfigSection section = getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages");
|
||||
sendList(sender, getModeMessages(section, mode));
|
||||
}
|
||||
|
||||
private void sendList(final SenderInfo sender, @Nullable final List<String> list) {
|
||||
private void sendList(final SenderInfo sender, final List<String> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
sender.send(getMessage("motdListEmpty"));
|
||||
return;
|
||||
@@ -67,43 +55,16 @@ public final class MotdCommand extends CommandInfo {
|
||||
sender.send(getMessage("motdList"));
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
sender.sendRich("<aqua>" + (i + 1) + "<dark_gray><st>---------");
|
||||
sender.sendRich(list.get(i).replace("<br>", "\n"));
|
||||
sender.sendRich(list.get(i));
|
||||
}
|
||||
sender.sendRich("<dark_gray><st>----------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
if (args.length != 2 || !getSettings().hasTimerSpecificPingMessages()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
if (getSettings().hasTimerSpecificPingMessages()) {
|
||||
list.add("timer");
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection("messages").getKeys());
|
||||
modes.remove("default");
|
||||
list.addAll(modes);
|
||||
return list;
|
||||
}
|
||||
|
||||
if (!args[1].equalsIgnoreCase("timer") || !getSettings().hasTimerSpecificPingMessages()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection("timer-messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private @Nullable List<String> getModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value instanceof String s) {
|
||||
return Collections.singletonList(s);
|
||||
}
|
||||
return section.getStringList(mode);
|
||||
return Collections.singletonList("timer");
|
||||
}
|
||||
}
|
||||
+15
-68
@@ -22,10 +22,10 @@ import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class RemoveMotdCommand extends CommandInfo {
|
||||
|
||||
@@ -34,49 +34,32 @@ public final class RemoveMotdCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
int indexOffset = 1;
|
||||
public void execute(final SenderInfo sender, String[] args) {
|
||||
boolean timerPingMessages = false;
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (args.length == 3 && args[1].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
indexOffset++;
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
timerPingMessages = true;
|
||||
}
|
||||
|
||||
if (args.length <= indexOffset) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
String mode = "default";
|
||||
if (!plugin.isNumeric(args[indexOffset])) {
|
||||
mode = args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length != indexOffset + 1 || !plugin.isNumeric(args[indexOffset])) {
|
||||
if (checkArgs(sender, args, 2)) return;
|
||||
if (!plugin.isNumeric(args[1])) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Settings settings = getSettings();
|
||||
final ConfigSection section = settings.getConfig().getSection("ping-message");
|
||||
final ConfigSection messageSection = section.getSection(timerPingMessages ? "timer-messages" : "messages");
|
||||
final List<String> pingMessages = getModeMessages(messageSection, mode);
|
||||
if (pingMessages.isEmpty()) {
|
||||
sender.send(getMessage("motdListEmpty"));
|
||||
return;
|
||||
}
|
||||
if (mode.equals("default") && pingMessages.size() < 2) {
|
||||
final List<String> pingMessages = section.getStringList(timerPingMessages ? "timer-messages" : "messages");
|
||||
if (pingMessages.size() < 2) {
|
||||
sender.send(getMessage("removeMotdError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final int index = Integer.parseInt(args[indexOffset]);
|
||||
final int index = Integer.parseInt(args[1]);
|
||||
if (index == 0 || index > pingMessages.size()) {
|
||||
sender.send(getMessage("setMotdIndexError",
|
||||
"%MOTDS%", Integer.toString(pingMessages.size()),
|
||||
@@ -84,60 +67,24 @@ public final class RemoveMotdCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> pingComponents = timerPingMessages ? settings.getTimerSpecificPingMessages() : settings.getPingMessages();
|
||||
pingComponents.remove(index - 1);
|
||||
pingMessages.remove(index - 1);
|
||||
if (pingMessages.isEmpty()) {
|
||||
messageSection.remove(mode);
|
||||
} else {
|
||||
messageSection.set(mode, pingMessages);
|
||||
}
|
||||
section.set(timerPingMessages ? "timer-messages" : "messages", pingMessages);
|
||||
settings.saveConfig();
|
||||
settings.reloadConfigs();
|
||||
sender.send(getMessage("removedMotd", "%INDEX%", Integer.toString(index)));
|
||||
sender.send(getMessage("removedMotd", "%INDEX%", args[1]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
final int indexOffset;
|
||||
final boolean timer;
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
timer = true;
|
||||
indexOffset = 2;
|
||||
} else {
|
||||
timer = false;
|
||||
indexOffset = 1;
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 && !plugin.isNumeric(args[indexOffset])) {
|
||||
return getModeCompletions(timer);
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 || (args.length == indexOffset + 2 && !plugin.isNumeric(args[indexOffset]))) {
|
||||
final String mode = plugin.isNumeric(args[indexOffset]) ? "default" : args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
final int size = getModeMessages(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages"), mode).size();
|
||||
if (args.length == 2 || (args.length == 3 && args[1].equalsIgnoreCase("timer"))) {
|
||||
final int size = (args.length == 3 ? plugin.getSettings().getTimerSpecificPingMessages() : plugin.getSettings().getPingMessages()).size();
|
||||
final List<String> list = new ArrayList<>(size);
|
||||
for (int i = 1; i <= size; i++) {
|
||||
list.add(Integer.toString(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<String> getModeCompletions(final boolean timer) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private List<String> getModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value == null) {
|
||||
return List.of();
|
||||
}
|
||||
if (value instanceof String s) {
|
||||
return new ArrayList<>(Collections.singletonList(s));
|
||||
}
|
||||
return new ArrayList<>(section.getStringList(mode));
|
||||
}
|
||||
}
|
||||
+29
-76
@@ -26,7 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static eu.kennytv.maintenance.core.Settings.NEW_LINE_REPLACEMENT;
|
||||
|
||||
@@ -37,41 +36,28 @@ public final class SetMotdCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
int indexOffset = 1;
|
||||
public void execute(final SenderInfo sender, String[] args) {
|
||||
boolean timerPingMessages = false;
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
indexOffset++;
|
||||
// remove the "timer" off the args to keep the rest the code cleaner
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
timerPingMessages = true;
|
||||
}
|
||||
|
||||
if (args.length <= indexOffset + 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
String mode = "default";
|
||||
if (!plugin.isNumeric(args[indexOffset])) {
|
||||
mode = args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length <= indexOffset + 2 || !plugin.isNumeric(args[indexOffset])) {
|
||||
if (args.length < 4 || !plugin.isNumeric(args[1])) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Settings settings = getSettings();
|
||||
final List<String> pingComponents = timerPingMessages ? settings.getTimerSpecificPingMessages() : settings.getPingMessages();
|
||||
final ConfigSection section = settings.getConfig().getSection("ping-message");
|
||||
final ConfigSection messageSection = section.getSection(timerPingMessages ? "timer-messages" : "messages");
|
||||
final List<String> pingMessages = getOrCreateModeMessages(messageSection, mode);
|
||||
|
||||
final int index = Integer.parseInt(args[indexOffset]);
|
||||
final List<String> pingMessages = section.getStringList(timerPingMessages ? "timer-messages" : "messages");
|
||||
final int index = Integer.parseInt(args[1]);
|
||||
if (index == 0 || index > pingMessages.size() + 1) {
|
||||
sender.send(getMessage("setMotdIndexError",
|
||||
"%MOTDS%", Integer.toString(pingMessages.size()),
|
||||
@@ -79,96 +65,63 @@ public final class SetMotdCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugin.isNumeric(args[indexOffset + 1])) {
|
||||
if (!plugin.isNumeric(args[2])) {
|
||||
sender.send(getMessage("setMotdLineError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final int line = Integer.parseInt(args[indexOffset + 1]);
|
||||
final int line = Integer.parseInt(args[2]);
|
||||
if (line != 1 && line != 2) {
|
||||
sender.send(getMessage("setMotdLineError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final String message = String.join(" ", Arrays.copyOfRange(args, indexOffset + 2, args.length));
|
||||
final String message = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
|
||||
final String oldMessage = index > pingMessages.size() ? "" : pingMessages.get(index - 1);
|
||||
final String newMessage;
|
||||
if (line == 1) {
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT)
|
||||
? message + NEW_LINE_REPLACEMENT + oldMessage.split(NEW_LINE_REPLACEMENT, 2)[1]
|
||||
: message;
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT) ?
|
||||
message + NEW_LINE_REPLACEMENT + oldMessage.split(NEW_LINE_REPLACEMENT, 2)[1] : message;
|
||||
} else {
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT)
|
||||
? oldMessage.split(NEW_LINE_REPLACEMENT, 2)[0] + NEW_LINE_REPLACEMENT + message
|
||||
: oldMessage + NEW_LINE_REPLACEMENT + message;
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT) ?
|
||||
oldMessage.split(NEW_LINE_REPLACEMENT, 2)[0] + NEW_LINE_REPLACEMENT + message : oldMessage + NEW_LINE_REPLACEMENT + message;
|
||||
}
|
||||
|
||||
// Replace component in config and the cached list
|
||||
final String componentString = newMessage.replace(NEW_LINE_REPLACEMENT, "\n");
|
||||
if (index > pingMessages.size()) {
|
||||
pingMessages.add(newMessage);
|
||||
pingComponents.add(componentString);
|
||||
} else {
|
||||
pingMessages.set(index - 1, newMessage);
|
||||
pingComponents.set(index - 1, componentString);
|
||||
}
|
||||
|
||||
messageSection.set(mode, pingMessages);
|
||||
section.set(timerPingMessages ? "timer-messages" : "messages", pingMessages);
|
||||
settings.saveConfig();
|
||||
settings.reloadConfigs();
|
||||
|
||||
sender.send(settings.getMessage(
|
||||
"setMotd",
|
||||
"%LINE%", Integer.toString(line),
|
||||
"%INDEX%", Integer.toString(index),
|
||||
"%MOTD%", newMessage.replace(NEW_LINE_REPLACEMENT, "\n")
|
||||
"%LINE%", args[2],
|
||||
"%INDEX%", args[1],
|
||||
"%MOTD%", componentString
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
final int indexOffset;
|
||||
final boolean timer;
|
||||
public List<String> getTabCompletion(final SenderInfo sender, String[] args) {
|
||||
boolean timer = false;
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
timer = true;
|
||||
indexOffset = 2;
|
||||
} else {
|
||||
timer = false;
|
||||
indexOffset = 1;
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 2) {
|
||||
return Arrays.asList("1", "2");
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 && !plugin.isNumeric(args[indexOffset])) {
|
||||
return getModeCompletions(timer);
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1) {
|
||||
final String mode = plugin.isNumeric(args[indexOffset]) ? "default" : args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
final ConfigSection section = getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages");
|
||||
final int size = getOrCreateModeMessages(section, mode).size();
|
||||
if (args.length == 3) return Arrays.asList("1", "2");
|
||||
if (args.length == 2) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (int i = 1; i <= size + 1; i++) {
|
||||
for (int i = 1; i <= (timer ? getSettings().getTimerSpecificPingMessages() : getSettings().getPingMessages()).size() + 1; i++) {
|
||||
list.add(String.valueOf(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<String> getModeCompletions(final boolean timer) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private List<String> getOrCreateModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
if (value instanceof String s) {
|
||||
return new ArrayList<>(Collections.singletonList(s));
|
||||
}
|
||||
return new ArrayList<>(section.getStringList(mode));
|
||||
}
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class SetReasonCommand extends CommandInfo {
|
||||
|
||||
public SetReasonCommand(final MaintenancePlugin plugin) {
|
||||
super(plugin, "setreason");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length < 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final String value = String.join(" ", java.util.Arrays.copyOfRange(args, 1, args.length));
|
||||
final String reason;
|
||||
if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("clear") || value.equals("-")) {
|
||||
reason = null;
|
||||
} else {
|
||||
reason = value;
|
||||
}
|
||||
|
||||
getSettings().setActiveReason(reason);
|
||||
sender.send(getMessage("setReason", "%REASON%", reason == null ? "-" : reason));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList("none");
|
||||
}
|
||||
}
|
||||
+2
-8
@@ -19,10 +19,9 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class StarttimerCommand extends CommandInfo {
|
||||
|
||||
@@ -45,11 +44,6 @@ public final class StarttimerCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true);
|
||||
|
||||
final Component message = getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
sender.send(getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
}
|
||||
}
|
||||
+2
-37
@@ -20,10 +20,6 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class ToggleCommand extends CommandInfo {
|
||||
|
||||
@@ -33,45 +29,14 @@ public final class ToggleCommand extends CommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 0 || args.length > 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (checkArgs(sender, args, 1)) return;
|
||||
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
final String mode;
|
||||
if (maintenance && args.length == 2) {
|
||||
mode = args[1].toLowerCase(Locale.ROOT);
|
||||
} else if (!maintenance && args.length == 1) {
|
||||
mode = null;
|
||||
} else if (maintenance) {
|
||||
mode = null;
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
if (mode != null) {
|
||||
plugin.getSettings().setActiveMode(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2 || !args[0].equalsIgnoreCase("on")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
plugin.setMaintenance(maintenance);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -20,11 +20,11 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
|
||||
public final class UpdateCommand extends CommandInfo {
|
||||
|
||||
|
||||
+3
-3
@@ -99,10 +99,10 @@ public final class WhitelistAddCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
private void addPlayerToWhitelist(final SenderInfo sender, final SenderInfo selected) {
|
||||
if (getSettings().addWhitelistedPlayer(selected.uuid(), selected.name())) {
|
||||
sender.send(getMessage("whitelistAdded", "%PLAYER%", selected.name()));
|
||||
if (getSettings().addWhitelistedPlayer(selected.getUuid(), selected.getName())) {
|
||||
sender.send(getMessage("whitelistAdded", "%PLAYER%", selected.getName()));
|
||||
} else {
|
||||
sender.send(getMessage("whitelistAlreadyAdded", "%PLAYER%", selected.name()));
|
||||
sender.send(getMessage("whitelistAlreadyAdded", "%PLAYER%", selected.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,10 +20,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class WhitelistCommand extends CommandInfo {
|
||||
|
||||
|
||||
+5
-6
@@ -24,7 +24,6 @@ import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
@@ -51,9 +50,9 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
if (args.length != 2) return Collections.emptyList();
|
||||
|
||||
final List<String> list = new ArrayList<>();
|
||||
String matchNameLowerCase = args[1].toLowerCase(Locale.ROOT);
|
||||
String matchNameLowerCase = args[1].toLowerCase();
|
||||
for (final String name : getSettings().getWhitelistedPlayers().values()) {
|
||||
if (name.toLowerCase(Locale.ROOT).startsWith(matchNameLowerCase)) {
|
||||
if (name.toLowerCase().startsWith(matchNameLowerCase)) {
|
||||
list.add(name);
|
||||
}
|
||||
}
|
||||
@@ -71,7 +70,7 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
removePlayerFromWhitelist(sender, selected.uuid(), selected.name());
|
||||
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -80,13 +79,13 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
if (selected == null) {
|
||||
removePlayerFromWhitelist(sender, uuid, uuid.toString());
|
||||
} else {
|
||||
removePlayerFromWhitelist(sender, selected.uuid(), selected.name());
|
||||
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removePlayerFromWhitelist(final SenderInfo sender, final UUID uuid, final String toReplace) {
|
||||
if (plugin.getSettings().removeWhitelistedPlayer(uuid)) {
|
||||
if (getSettings().removeWhitelistedPlayer(uuid)) {
|
||||
sender.send(getMessage("whitelistRemoved", "%PLAYER%", toReplace));
|
||||
} else {
|
||||
sender.send(getMessage("whitelistNotFound"));
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -38,20 +40,18 @@ import org.yaml.snakeyaml.Yaml;
|
||||
public final class Config extends ConfigSection {
|
||||
|
||||
private static final String AWESOME_HEADER =
|
||||
"""
|
||||
###################################################################################################################
|
||||
# __ __ _ _ _ _ _ #
|
||||
# | \\/ | __ _(_)_ __ | |_ ___ _ __ __ _ _ __ ___ ___ | |__ _ _ | | _____ _ __ _ __ _ _| |___ __ #
|
||||
# | |\\/| |/ _` | | '_ \\| __/ _ \\ '_ \\ / _` | '_ \\ / __/ _ \\ | '_ \\| | | | | |/ / _ \\ '_ \\| '_ \\| | | | __\\ \\ / / #
|
||||
# | | | | (_| | | | | | || __/ | | | (_| | | | | (_| __/ | |_) | |_| | | < __/ | | | | | | |_| | |_ \\ V / #
|
||||
# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, |\\__| \\_/ #
|
||||
# |___/ |___/ #
|
||||
###################################################################################################################
|
||||
# You can report bugs here: https://github.com/kennytv/Maintenance/issues
|
||||
# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.advntr.dev/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
""";
|
||||
"###################################################################################################################\n" +
|
||||
"# __ __ _ _ _ _ _ #\n" +
|
||||
"# | \\/ | __ _(_)_ __ | |_ ___ _ __ __ _ _ __ ___ ___ | |__ _ _ | | _____ _ __ _ __ _ _| |___ __ #\n" +
|
||||
"# | |\\/| |/ _` | | '_ \\| __/ _ \\ '_ \\ / _` | '_ \\ / __/ _ \\ | '_ \\| | | | | |/ / _ \\ '_ \\| '_ \\| | | | __\\ \\ / / #\n" +
|
||||
"# | | | | (_| | | | | | || __/ | | | (_| | | | | (_| __/ | |_) | |_| | | < __/ | | | | | | |_| | |_ \\ V / #\n" +
|
||||
"# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, |\\__| \\_/ #\n" +
|
||||
"# |___/ |___/ #\n" +
|
||||
"###################################################################################################################\n" +
|
||||
"# You can report bugs here: https://github.com/kennytv/Maintenance/issues\n" +
|
||||
"# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq\n" +
|
||||
"# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.adventure.kyori.net/ to edit and preview the formatted text.\n" +
|
||||
"# For a full list of formats and fancy examples of MiniMessage, see https://docs.adventure.kyori.net/minimessage/format.html\n";
|
||||
private final Yaml yaml = createYaml();
|
||||
private final File file;
|
||||
private final Set<String> unsupportedFields;
|
||||
@@ -61,11 +61,11 @@ public final class Config extends ConfigSection {
|
||||
public Config(final File file, final String... unsupportedFields) {
|
||||
super(null, "");
|
||||
this.file = file;
|
||||
this.unsupportedFields = unsupportedFields.length == 0 ? Collections.emptySet() : Set.of(unsupportedFields);
|
||||
this.unsupportedFields = unsupportedFields.length == 0 ? Collections.emptySet() : Sets.newHashSet(unsupportedFields);
|
||||
}
|
||||
|
||||
public void load() throws IOException {
|
||||
final String data = Files.readString(this.file.toPath());
|
||||
final String data = new String(Files.readAllBytes(this.file.toPath()), StandardCharsets.UTF_8);
|
||||
final Map<String, Object> map = yaml.load(data);
|
||||
this.values = map != null ? map : new LinkedHashMap<>();
|
||||
this.comments = ConfigSerializer.deserializeComments(data);
|
||||
@@ -101,11 +101,12 @@ public final class Config extends ConfigSection {
|
||||
}
|
||||
|
||||
public void saveTo(final File file) throws IOException {
|
||||
final byte[] bytes = toString().getBytes(StandardCharsets.UTF_8);
|
||||
if (file.getParentFile() != null) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
file.createNewFile();
|
||||
Files.writeString(file.toPath(), toString());
|
||||
Files.write(file.toPath(), bytes);
|
||||
}
|
||||
|
||||
public void replaceComments(final Config fromConfig) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -35,7 +36,7 @@ public class ConfigSection {
|
||||
protected Map<String, Object> values;
|
||||
|
||||
ConfigSection(final Config root, final String currentPath) {
|
||||
this(root, currentPath, new LinkedHashMap<>());
|
||||
this(root, currentPath, new HashMap<>());
|
||||
}
|
||||
|
||||
ConfigSection(final Config root, final String currentPath, final Map<String, Object> values) {
|
||||
@@ -62,18 +63,20 @@ public class ConfigSection {
|
||||
|
||||
@Nullable
|
||||
public Object getObject(final String key, final Object def) {
|
||||
final String[] parts = key.split("\\.");
|
||||
int nextSeparatorIndex = -1;
|
||||
int sectionStartIndex;
|
||||
ConfigSection section = this;
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
section = section.getSection(parts[i]);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
while ((nextSeparatorIndex = key.indexOf('.', sectionStartIndex = nextSeparatorIndex + 1)) != -1) {
|
||||
section = section.getSection(key.substring(sectionStartIndex, nextSeparatorIndex));
|
||||
if (section == null) return def;
|
||||
}
|
||||
|
||||
final String valueKey = parts[parts.length - 1];
|
||||
final Object o = section.values.get(valueKey);
|
||||
return o != null ? o : def;
|
||||
final String subKey = key.substring(sectionStartIndex);
|
||||
if (section == this) {
|
||||
final Object result = values.get(subKey);
|
||||
return result != null ? result : def;
|
||||
}
|
||||
return section.getObject(subKey, def);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -161,7 +164,7 @@ public class ConfigSection {
|
||||
@Nullable
|
||||
public String getString(final String key, @Nullable final String def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof String s ? s : def;
|
||||
return o instanceof String ? (String) o : def;
|
||||
}
|
||||
|
||||
public int getInt(final String key) {
|
||||
@@ -170,7 +173,7 @@ public class ConfigSection {
|
||||
|
||||
public int getInt(final String key, final int def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number number ? number.intValue() : def;
|
||||
return o instanceof Number ? ((Number) o).intValue() : def;
|
||||
}
|
||||
|
||||
public double getDouble(final String key) {
|
||||
@@ -179,7 +182,7 @@ public class ConfigSection {
|
||||
|
||||
public double getDouble(final String key, final double def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number number ? number.doubleValue() : def;
|
||||
return o instanceof Number ? ((Number) o).doubleValue() : def;
|
||||
}
|
||||
|
||||
public long getLong(final String key) {
|
||||
@@ -188,7 +191,7 @@ public class ConfigSection {
|
||||
|
||||
public long getLong(final String key, final long def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number number ? number.longValue() : def;
|
||||
return o instanceof Number ? ((Number) o).longValue() : def;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -250,6 +253,6 @@ public class ConfigSection {
|
||||
}
|
||||
|
||||
protected String getFullKeyInPath(final String key) {
|
||||
return currentPath.isEmpty() ? key : currentPath + '.' + key;
|
||||
return currentPath.isEmpty() ? key : currentPath + "." + key;
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,11 @@ public final class ConfigSerializer {
|
||||
multiLineValue = false;
|
||||
}
|
||||
|
||||
// YAML list items are values, not keys - skip without touching key/indent state
|
||||
if (line.length() > indent && line.charAt(indent) == '-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this is a level lower
|
||||
if (indents <= currentIndents) {
|
||||
final String[] array = key.split(PATH_SEPARATOR_QUOTED);
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class DisplayedMessages {
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
private final Map<String, List<String>> messages;
|
||||
private final List<String> defaultMessages;
|
||||
|
||||
public DisplayedMessages(final Map<String, List<String>> messages) {
|
||||
this.messages = messages;
|
||||
this.defaultMessages = messages.get("default");
|
||||
}
|
||||
|
||||
public List<String> getMessages(@Nullable final String key) {
|
||||
Preconditions.checkNotNull(defaultMessages, "no default message configured in messages list");
|
||||
if (key == null || messages.size() == 1) {
|
||||
return defaultMessages;
|
||||
}
|
||||
return messages.getOrDefault(key, defaultMessages);
|
||||
}
|
||||
|
||||
public String getRandomEntry(@Nullable final String key) {
|
||||
final List<String> messages = getMessages(key);
|
||||
return messages.get(RANDOM.nextInt(messages.size()));
|
||||
}
|
||||
|
||||
public List<String> getDefaultMessages() {
|
||||
return defaultMessages;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return messages.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getKeys() {
|
||||
return messages.keySet();
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import eu.kennytv.maintenance.core.Settings;
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class MaintenanceDump {
|
||||
@@ -36,8 +35,12 @@ public final class MaintenanceDump {
|
||||
general = new ServerDump(plugin.getVersion(), plugin.getServerType().toString(), plugin.getServerVersion(), plugin.getMaintenanceServersDump());
|
||||
|
||||
configuration = new LinkedHashMap<>(settings.getConfig().getValues());
|
||||
addDBSettings("redis", "enabled");
|
||||
redact("webhook", "url");
|
||||
final Object o = configuration.get("mysql");
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
map.keySet().removeIf(key -> !key.equals("use-mysql") && !key.equals("update-interval"));
|
||||
configuration.put("mysql", map);
|
||||
}
|
||||
configuration.put("whitelisted-players", settings.getWhitelistedPlayers());
|
||||
configuration.put("icon-exists", new File(plugin.getDataFolder(), "maintenance-icon.png").exists());
|
||||
|
||||
@@ -45,28 +48,4 @@ public final class MaintenanceDump {
|
||||
jsonObject.add("plugins", MaintenancePlugin.GSON.toJsonTree(plugin.getPlugins()));
|
||||
plugins = jsonObject;
|
||||
}
|
||||
|
||||
private void redact(final String key, final String... subKeys) {
|
||||
final Object o = configuration.get(key);
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
for (final String subKey : subKeys) {
|
||||
final Object value = map.get(subKey);
|
||||
if (value != null) {
|
||||
map.put(subKey, value.toString().isEmpty() ? "" : "<redacted>");
|
||||
}
|
||||
}
|
||||
configuration.put(key, map);
|
||||
}
|
||||
}
|
||||
|
||||
private void addDBSettings(final String key, final String... allowedSubKeys) {
|
||||
final Set<String> allowedSubKeysSet = Set.of(allowedSubKeys);
|
||||
final Object o = configuration.get(key);
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
map.keySet().removeIf(subKey -> !allowedSubKeysSet.contains(subKey));
|
||||
configuration.put(key, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,12 @@ package eu.kennytv.maintenance.core.dump;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record PluginDump(String name, String version, List<String> authors) {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class PluginDump {
|
||||
private final String name;
|
||||
private final String version;
|
||||
private final List<String> authors;
|
||||
|
||||
public PluginDump(final String name, final String version, final List<String> authors) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
|
||||
@@ -19,5 +19,17 @@ package eu.kennytv.maintenance.core.dump;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record ServerDump(String pluginVersion, String platform, String serverVersion, List<String> maintenance) {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class ServerDump {
|
||||
private final String pluginVersion;
|
||||
private final String platform;
|
||||
private final String serverVersion;
|
||||
private final List<String> maintenance;
|
||||
|
||||
public ServerDump(final String pluginVersion, final String platform, final String serverVersion, final List<String> maintenance) {
|
||||
this.pluginVersion = pluginVersion;
|
||||
this.platform = platform;
|
||||
this.serverVersion = serverVersion;
|
||||
this.maintenance = maintenance;
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@ public final class ServerListPlusHook {
|
||||
private final ServerListPlusCore serverListPlusCore;
|
||||
|
||||
public ServerListPlusHook(final Object serverListPlus) {
|
||||
if (!(serverListPlus instanceof ServerListPlusPlugin serverListPlusPlugin)) {
|
||||
if (!(serverListPlus instanceof ServerListPlusPlugin)) {
|
||||
throw new IllegalArgumentException("Couldn't parse ServerListPlus instance!");
|
||||
}
|
||||
this.serverListPlusCore = serverListPlusPlugin.getCore();
|
||||
this.serverListPlusCore = ((ServerListPlusPlugin) serverListPlus).getCore();
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enable) {
|
||||
|
||||
@@ -19,19 +19,17 @@ package eu.kennytv.maintenance.core.listener;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.TextDecoration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import static eu.kennytv.maintenance.core.util.ComponentUtil.clickEvent;
|
||||
|
||||
public abstract class JoinListenerBase {
|
||||
protected final MaintenancePlugin plugin;
|
||||
@@ -50,16 +48,13 @@ public abstract class JoinListenerBase {
|
||||
* @return true if the sender should be kicked
|
||||
*/
|
||||
protected boolean shouldKick(final SenderInfo sender, final boolean updateCheck) {
|
||||
if (!settings.isMaintenance() || sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())) {
|
||||
if (!settings.isMaintenance() || sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) {
|
||||
if (updateCheck) {
|
||||
updateCheck(sender);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.isWebhookEnabled()) {
|
||||
plugin.sendWebhookMessage("webhookJoinNotification", DiscordWebhook.EventType.BLOCKED_JOIN, "%PLAYER%", sender.name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -69,19 +64,19 @@ public abstract class JoinListenerBase {
|
||||
|
||||
protected void updateCheck(final SenderInfo sender) {
|
||||
if (!settings.hasUpdateChecks()) return;
|
||||
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.uuid())) return;
|
||||
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.getUuid())) return;
|
||||
plugin.async(() -> {
|
||||
if (!plugin.updateAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedPlayers.add(sender.uuid());
|
||||
notifiedPlayers.add(sender.getUuid());
|
||||
sender.sendPrefixedRich("<red>There is a newer version available: <green>Version " + plugin.getNewestVersion() + "<red>, you're on <green>" + plugin.getVersion());
|
||||
|
||||
final TextComponent text = Component.text().content("Download it at: ").color(NamedTextColor.RED)
|
||||
.append(Component.text().content(MaintenancePlugin.HANGAR_URL).color(NamedTextColor.GOLD))
|
||||
.append(Component.text().content(" (CLICK ME)").color(NamedTextColor.GRAY).decorate(TextDecoration.BOLD))
|
||||
.clickEvent(clickEvent(ClickEvent.Action.OPEN_URL, MaintenancePlugin.HANGAR_URL))
|
||||
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, MaintenancePlugin.HANGAR_URL))
|
||||
.hoverEvent(HoverEvent.showText(Component.text("Download the latest version").color(NamedTextColor.GREEN)))
|
||||
.build();
|
||||
sender.send(plugin.prefix().append(text));
|
||||
|
||||
@@ -19,24 +19,17 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public class MaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
protected final String mode;
|
||||
|
||||
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable) {
|
||||
this(plugin, settings, seconds, enable, null);
|
||||
}
|
||||
|
||||
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable, @Nullable final String mode) {
|
||||
super(plugin, settings, seconds, enable);
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finish() {
|
||||
plugin.setMaintenance(enable, mode);
|
||||
plugin.setMaintenance(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public abstract class MaintenanceRunnableBase implements Runnable {
|
||||
protected final MaintenancePlugin plugin;
|
||||
|
||||
+2
-7
@@ -19,19 +19,14 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MaintenanceScheduleRunnable extends MaintenanceRunnable {
|
||||
private final int maintenanceDuration;
|
||||
|
||||
public MaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int secondsToEnable, final int maintenanceDuration) {
|
||||
this(plugin, settings, secondsToEnable, maintenanceDuration, null);
|
||||
}
|
||||
|
||||
public MaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int secondsToEnable, final int maintenanceDuration, @Nullable final String mode) {
|
||||
super(plugin, settings, secondsToEnable, true, mode);
|
||||
super(plugin, settings, secondsToEnable, true);
|
||||
this.maintenanceDuration = maintenanceDuration;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class ComponentUtil {
|
||||
|
||||
private static final MethodHandle LEGACY_CLICK_EVENT = legacyClickEvent();
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static ClickEvent clickEvent(final ClickEvent.Action action, final String value) {
|
||||
if (LEGACY_CLICK_EVENT != null) {
|
||||
try {
|
||||
return (ClickEvent) LEGACY_CLICK_EVENT.invoke(action, value);
|
||||
} catch (final Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return ClickEvent.clickEvent(action, ClickEvent.Payload.string(value));
|
||||
}
|
||||
|
||||
private static @Nullable MethodHandle legacyClickEvent() {
|
||||
try {
|
||||
return MethodHandles.publicLookup().unreflect(ClickEvent.class.getDeclaredMethod("clickEvent", ClickEvent.Action.class, String.class));
|
||||
} catch (final NoSuchMethodException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
|
||||
public final class DiscordWebhook {
|
||||
|
||||
private static final int COLOR_MAINTENANCE_ENABLED = 0xED4245; // Red
|
||||
private static final int COLOR_MAINTENANCE_DISABLED = 0x57F287; // Green
|
||||
private static final int COLOR_STARTTIMER = 0xFEE75C; // Yellow
|
||||
private static final int COLOR_ENDTIMER = 0x5865F2; // Blue
|
||||
private static final int COLOR_BLOCKED_JOIN = 0xE67E22; // Orange
|
||||
|
||||
public static void sendMessage(final String message, final EventType event, final Settings settings) throws IOException, InterruptedException {
|
||||
final JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("username", settings.getWebhookUsername());
|
||||
|
||||
final String avatarUrl = settings.getWebhookAvatarUrl();
|
||||
if (!avatarUrl.isEmpty()) {
|
||||
jsonObject.addProperty("avatar_url", avatarUrl);
|
||||
}
|
||||
|
||||
final JsonObject embed = new JsonObject();
|
||||
embed.addProperty("description", message);
|
||||
embed.addProperty("color", getColorForEvent(event));
|
||||
|
||||
final JsonArray embeds = new JsonArray();
|
||||
embeds.add(embed);
|
||||
jsonObject.add("embeds", embeds);
|
||||
|
||||
try (final HttpClient client = HttpClient.newHttpClient()) {
|
||||
final HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(settings.getWebhookUrl()))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(jsonObject.toString()))
|
||||
.build();
|
||||
client.send(request, HttpResponse.BodyHandlers.discarding());
|
||||
}
|
||||
}
|
||||
|
||||
private static int getColorForEvent(final EventType event) {
|
||||
return switch (event) {
|
||||
case MAINTENANCE_ENABLED -> COLOR_MAINTENANCE_ENABLED;
|
||||
case MAINTENANCE_DISABLED -> COLOR_MAINTENANCE_DISABLED;
|
||||
case STARTTIMER_STARTED -> COLOR_STARTTIMER;
|
||||
case ENDTIMER_STARTED -> COLOR_ENDTIMER;
|
||||
case BLOCKED_JOIN -> COLOR_BLOCKED_JOIN;
|
||||
};
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
MAINTENANCE_ENABLED("maintenance_status"),
|
||||
MAINTENANCE_DISABLED("maintenance_status"),
|
||||
STARTTIMER_STARTED("starttimer_started"),
|
||||
ENDTIMER_STARTED("endtimer_started"),
|
||||
BLOCKED_JOIN("blocked_join");
|
||||
|
||||
private final String configKey;
|
||||
|
||||
EventType(final String configKey) {
|
||||
this.configKey = configKey;
|
||||
}
|
||||
|
||||
public String configKey() {
|
||||
return configKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,28 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
public record DummySenderInfo(UUID uuid, String name) implements SenderInfo {
|
||||
import java.util.UUID;
|
||||
|
||||
public final class DummySenderInfo implements SenderInfo {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public DummySenderInfo(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
|
||||
@@ -19,15 +19,15 @@ package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
|
||||
public interface SenderInfo {
|
||||
|
||||
UUID uuid();
|
||||
UUID getUuid();
|
||||
|
||||
String name();
|
||||
String getName();
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.util;
|
||||
public enum ServerType {
|
||||
|
||||
BUNGEE("Bungee"),
|
||||
PAPER("Paper"),
|
||||
SPIGOT("Spigot"),
|
||||
SPONGE("Sponge"),
|
||||
VELOCITY("Velocity");
|
||||
|
||||
|
||||
@@ -89,7 +89,8 @@ public final class Version implements Comparable<Version> {
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Version other)) return false;
|
||||
if (!(o instanceof Version)) return false;
|
||||
final Version other = (Version) o;
|
||||
return version.equals(other.version);
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
###################################################################################################################
|
||||
# You can report bugs here: https://github.com/kennytv/Maintenance/issues
|
||||
# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.advntr.dev/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.adventure.kyori.net/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
|
||||
# Changes the language of command feedback/messages.
|
||||
# If you find missing translations or want to contribute, see https://crowdin.com/project/maintenance
|
||||
@@ -18,26 +18,16 @@
|
||||
language: en
|
||||
|
||||
# Enables maintenance mode.
|
||||
maintenance-enabled: false
|
||||
|
||||
# The currently active maintenance mode key (used for mode-specific messages/icons).
|
||||
# Use 'default' or leave empty to use fallback messages.
|
||||
active-mode: default
|
||||
|
||||
# Value for the %REASON% placeholder in maintenance messages.
|
||||
# This can be changed via /maintenance setreason <text>.
|
||||
active-reason: ""
|
||||
maintenance-enabled: true
|
||||
|
||||
# Enables maintenance on certain servers managed by your proxy instance(s).
|
||||
# The value is the mode key used for ping/player count messages for that server.
|
||||
proxied-maintenance-servers:
|
||||
PaperServer1: default
|
||||
# AnotherServer: release
|
||||
# - AServer
|
||||
|
||||
# If maintenance is enabled on a proxied server with players on it, they will be sent to the fallback server instead of being kicked off the network.
|
||||
# If the fallback server is not reachable/not set, they will just be kicked off the network.
|
||||
# This can also be set to an array to set multiple fallback servers, in case one server is not always reachable: 'fallback: [s1, s2, s3, ...]'
|
||||
fallback: lobby
|
||||
fallback: unreachable
|
||||
|
||||
# If maintenance is enabled globally, you can define a "waiting" lobby for players to be sent to instead of being kicked.
|
||||
# Leave this empty to disable.
|
||||
@@ -45,53 +35,35 @@ waiting-server: ""
|
||||
|
||||
# The message (MOTD) shown in the multiplayer server list motd when maintenance is enabled.
|
||||
# If you put in multiple entries, one of them will be chosen randomly on every ping.
|
||||
# The type of mode can be defined in the command, or will be the default mode.
|
||||
# If running an endtimer, the time left can be displayed by including '%TIMER%' in a ping message.
|
||||
ping-message:
|
||||
enabled: true
|
||||
# Always uses 'default' if not defined in the command or not present in the config.
|
||||
# Additional examples could look as follows:
|
||||
# default:
|
||||
# - "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>We will be back soon!"
|
||||
# - "<red>Wooow you found our secondary MOTD!"
|
||||
# reason:
|
||||
# - "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>%REASON%"
|
||||
# release:
|
||||
# - "<gold>We're currently preparing the release, come back soon!"
|
||||
messages:
|
||||
default:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>We will be back soon!"
|
||||
- "<bold><green>True<red>OG</bold> <yellow>Network</yellow> <aqua>》<red> Updating... </red><aqua>《 <gold>[1.8.0-1.21.11]<br><yellow>⚠ <dark_red>Maintenance in progress! <yellow>We'll be back <dark_aqua>soon™"
|
||||
# If set to true and an endtimer is currently running, a message from this pool will be chosen
|
||||
# instead of the ones above, so you can have different messages for when an endtimer is running/not running.
|
||||
enable-timer-specific-messages: true
|
||||
# If running an endtimer, the time left can be displayed by including '%TIMER%' in a ping message.
|
||||
timer-messages:
|
||||
default:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#fffff>Come back in:</gradient> <color:#aa55ee>%TIMER%"
|
||||
- "<bold><green>True<red>OG</bold> <yellow>Network</yellow> <aqua>》<red>Maintenance Mode</red><aqua>《 <gold>[1.8.0-1.21.11]<br><dark_red>Maintenance ends in <yellow>%TIMER% <gray>| <green>Thanks for waiting!"
|
||||
|
||||
# If enabled, the message below will be shown in the top right corner of the server in the server list, where the player count would normally be displayed.
|
||||
# Same as the ping-message, you can define messages for different modes.
|
||||
# You can use '%ONLINE%' and '%MAX%' if you want to include the player count in a custom message (e.g. "Maintenance %ONLINE%/%MAX%").
|
||||
# DOES NOT SUPPORT RGB!
|
||||
player-count-message:
|
||||
enabled: true
|
||||
messages:
|
||||
default: "<dark_red>Maintenance"
|
||||
message: "<dark_red>Maintenance"
|
||||
# If set to true and an endtimer is currently running, the timer message will be used instead of the normal one.
|
||||
enable-timer-specific-message: false
|
||||
timer-messages:
|
||||
default: "<dark_red>Come back in: <yellow>%TIMER%"
|
||||
enable-timer-specific-message: true
|
||||
timer-message: "<dark_red>Come back in: <yellow>%TIMER%"
|
||||
|
||||
# Is shown when you move your mouse above the text in the top right corner of the server in the server list, where the player count would normally be displayed.
|
||||
# Same as the ping-message, you can define messages for different modes.
|
||||
# DOES NOT SUPPORT RGB!
|
||||
player-list-hover-message:
|
||||
enabled: true
|
||||
messages:
|
||||
default: "<red>Currently under<br><red>maintenance"
|
||||
message: "<red>Currently under<br><red>maintenance"
|
||||
# If set to true and an endtimer is currently running, the timer message will be used instead of the normal one.
|
||||
enable-timer-specific-message: false
|
||||
timer-messages:
|
||||
default: "<red>Come back in:<br><red><yellow>%TIMER%"
|
||||
enable-timer-specific-message: true
|
||||
timer-message: "<red>Come back in:<br><red><yellow>%TIMER%"
|
||||
|
||||
# Any extra commands inside the arrays will be executed when maintenance is enabled/disabled.
|
||||
# Example: commands-on-maintenance-enable: ["say hello!", "stop"]
|
||||
@@ -112,7 +84,7 @@ custom-maintenance-icon: false
|
||||
|
||||
# If set to true, players with the 'maintenance.joinnotification' permission will receive a message,
|
||||
# that a player tried to join the server while maintenance is enabled.
|
||||
send-join-notification: false
|
||||
send-join-notification: true
|
||||
|
||||
# Set this to false if you do not want players to be kicked when you enable maintenance (new connections will still be blocked).
|
||||
kick-online-players: true
|
||||
@@ -131,32 +103,28 @@ continue-endtimer-after-restart:
|
||||
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
|
||||
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1]
|
||||
|
||||
# Allows sending a Discord webhook on certain events.
|
||||
webhook:
|
||||
enabled: false
|
||||
# Possible values: maintenance_status, starttimer_started, endtimer_started, blocked_join
|
||||
enabled-events: ["maintenance_status", "starttimer_started", "endtimer_started"]
|
||||
# Copy and paste the webhook url from Server Settings --> Apps Integrations --> Webhooks
|
||||
url: ""
|
||||
# The username displayed for the webhook bot message.
|
||||
username: "Maintenance"
|
||||
# The avatar URL used for the webhook bot message. Leave empty to use the default Discord webhook avatar.
|
||||
avatar-url: ""
|
||||
|
||||
# If you have 2 or more proxy instances, the Redis connection will make sure all proxies
|
||||
# have the same maintenance status (global as well as per server) and whitelisted players,
|
||||
# so you won't have to update these on every proxy by hand.
|
||||
redis:
|
||||
enabled: false
|
||||
# Make sure your Redis instance is properly protected.
|
||||
# URI format: redis[s]://[[username][:password]@][host][:port][/db-number]
|
||||
# E.g. an SSL connection to a password protected redis could look like this: "rediss://user:password@127.0.0.1:6379"
|
||||
uri: "redis://localhost:6379"
|
||||
# If you have 2 or more proxy instances, the database connection will make sure all proxies
|
||||
# have the same maintenance status, so you won't have to enable/disable it on every proxy by hand.
|
||||
mysql:
|
||||
use-mysql: false
|
||||
host: host
|
||||
port: 3306
|
||||
database: database
|
||||
username: username
|
||||
password: password
|
||||
# Requests to the database will only be made at least x seconds after the last request,
|
||||
# so there won't be a request on every single ping on a server with many players.
|
||||
#
|
||||
# Set this to 0 to make a database request on (almost) every single ping.
|
||||
# (0 is not recommended if having more than a hundred concurrent players, then I'd recommend keeping it from 10-60).
|
||||
update-interval: 15
|
||||
# If you for some reason cannot establish SSL connections to your database, you may disable it here (not recommended).
|
||||
use-ssl: true
|
||||
|
||||
# If disabled, you will no longer receive any messages if there is an update.
|
||||
# Not recommended to disable, as new versions generally tend to run better and with fewer bugs.
|
||||
# However, you can always check for updates manually using the '/maintenance update' command.
|
||||
update-checks: true
|
||||
update-checks: false
|
||||
|
||||
# Used for autoupdating the config, do not change this value.
|
||||
config-version: 12
|
||||
config-version: 9
|
||||
@@ -1,124 +0,0 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>No tens permís per executar aquesta ordre."
|
||||
kickmessage: "<red>El servidor està en manteniment!<br>Torna-ho a provar més tard!"
|
||||
maintenanceActivated: "<prefix><gold>El mode de manteniment s'ha activat."
|
||||
maintenanceDeactivated: "<prefix><gold>El mode de manteniment s'ha desactivat."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>El manteniment ja està activat!"
|
||||
alreadyDisabled: "<prefix><red>El manteniment ja està desactivat!"
|
||||
endtimerBroadcast: "<prefix><gray>El mode de manteniment es desactivarà en <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment es desactivarà en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El mode de manteniment s'activarà en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment s'activarà en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>El mode de manteniment s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>Ja hi ha un temporitzador programat!"
|
||||
timerNotRunning: "<prefix><red>No hi ha cap temporitzador en marxa."
|
||||
timerCancelled: "<prefix><red>S'ha cancel·lat el temporitzador actual."
|
||||
timerTooLong: "<prefix><red>La durada ha de ser inferior a 28 dies!"
|
||||
timerMotdDisabled: "<prefix><red>Has de configurar 'enable-timerspecific-messages' a 'true' al fitxer de configuració per utilitzar/editar missatges MOTD específics del temporitzador."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>ha intentat unir-se al servidor."
|
||||
motdList: "<prefix><gray>Llista dels teus missatges MOTD de manteniment:"
|
||||
motdListEmpty: "<prefix><red>No tens cap missatge MOTD de manteniment configurat!"
|
||||
reload: "<prefix><green>S'han recarregat la configuració, la llista de jugadors permitits, el fitxer d'idioma i la icona de manteniment."
|
||||
removedMotd: "<prefix><green>S'ha eliminat el missatge MOTD número %INDEX%."
|
||||
removeMotdError: "<prefix><red>Només tens un missatge MOTD, no en pots eliminar cap!"
|
||||
setMotd: "<prefix><green>S'ha configurat la línia %LINE% del missatge MOTD de manteniment %INDEX% a %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Actualment tens %MOTDS% missatges MOTD, has de triar un número entre 1 i %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>El segon argument ha de ser el número de línia (1 o 2)!"
|
||||
updateDownloading: "<prefix><red><bold>S'està descarregant l'actualització..."
|
||||
updateFailed: "<prefix><dark_red><bold>L'actualització ha fallat!"
|
||||
updateFinished: "<prefix><green><bold>L'actualització s'ha completat! Per evitar problemes amb tasques i completar l'actualització, has de reiniciar el servidor!"
|
||||
whitelistedPlayers: "<prefix><gold>Jugadors permesos durant el manteniment:"
|
||||
whitelistedPlayersFormat: "<dark_gray>- <yellow>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>S'ha afegit <aqua>%PLAYER% <green>a la llista blanca de manteniment!"
|
||||
whitelistAlreadyAdded: "<prefix><aqua>%PLAYER% <red>ja està a la llista blanca de manteniment!"
|
||||
whitelistRemoved: "<prefix><green>S'ha eliminat <aqua>%PLAYER% <green>de la llista blanca de manteniment!"
|
||||
whitelistNotFound: "<prefix><red>Aquest jugador no està a la llista blanca de manteniment!"
|
||||
whitelistEmpty: "<prefix><red>La llista blanca de manteniment està buida! Utilitza <yellow>/maintenance add <player/uuid> <red>per afegir algú!"
|
||||
playerNotFound: "<prefix><red>No s'ha trobat cap jugador amb aquest nom al servidor."
|
||||
playerNotFoundUuid: "<prefix><red>No s'ha trobat cap jugador amb aquesta UUID."
|
||||
playerNotOnline: "<prefix><red>No hi ha cap jugador en línia amb aquest nom."
|
||||
offlinePlayerFetchError: "<prefix><red>Hi ha hagut un error en obtenir les dades del jugador fora de línia. Torna-ho a provar més tard."
|
||||
invalidUuid: "<prefix><red>Format d'UUID no vàlid!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Se t'ha enviat a un servidor d'espera!"
|
||||
forceWaitingServer: "<prefix><red>No pots abandonar el servidor d'espera mentre el manteniment estigui actiu!"
|
||||
serverNotFound: "<prefix><red>No hi ha cap servidor amb aquest nom registrat al proxy!"
|
||||
singleTimerAlreadyRunning: "<prefix><red>Ja hi ha un temporitzador programat per a aquest servidor!"
|
||||
singleTimerCancelled: "<prefix><red>S'ha cancel·lat el temporitzador actual per al servidor <yellow>%SERVER%<red>."
|
||||
singleTimerNotRunning: "<prefix><red>No hi ha cap temporitzador en marxa per a aquest servidor."
|
||||
singleEndtimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% es desactivarà en <gold>%TIME%<gray>."
|
||||
singleEndtimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% es desactivarà en <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME%<gray>."
|
||||
singleStarttimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
singleScheduletimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
singleMaintenanceKick: "<prefix><red>El servidor %SERVER% està en manteniment! Torna-ho a provar més tard!"
|
||||
singleMaintenanceKickComplete: "<red>El servidor %SERVER% està en manteniment!<br>Pots tornar a connectar-te per anar a un altre servidor!"
|
||||
singleMaintenanceActivated: "<prefix><gold>El mode de manteniment s'ha activat al servidor <yellow>%SERVER%<gold>."
|
||||
singleMaintenanceDeactivated: "<prefix><gold>El mode de manteniment s'ha desactivat al servidor <yellow>%SERVER%<gold>."
|
||||
singleServerAlreadyEnabled: "<prefix><red>El manteniment ja està activat al servidor <yellow>%SERVER%<red>!"
|
||||
singleServerAlreadyDisabled: "<prefix><red>El manteniment ja està desactivat al servidor <yellow>%SERVER%<red>!"
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidors proxy que tenen el manteniment activat:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>No hi ha cap servidor proxy en manteniment."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "segon"
|
||||
seconds: "segons"
|
||||
minute: "minut"
|
||||
minutes: "minuts"
|
||||
hour: "hora"
|
||||
hours: "hores"
|
||||
helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MAX% <dark_gray>]========"
|
||||
helpPageNotFound: "<prefix><red>No hi ha cap pàgina amb aquest número!"
|
||||
helpNextPage: "<gray>Fes servir <aqua>/maintenance help %PAGE% <gray>per anar a la següent pàgina d'ajuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Si està actiu, cancel·la el temporitzador actual)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <desactivar en> <gray>(Després del temps indicat, p. ex. 1h5m, es desactivarà el manteniment)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <activar en> <gray>(Després del temps indicat, p. ex. 1h5m, s'activarà el manteniment)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <activar en> <durada del manteniment> <gray>(Després del temps indicat, p. ex. 1h5m, s'activarà el manteniment)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Activa el registre de depuració)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Extreu informació del servidor, útil per informes d'errors)"
|
||||
helpHelp: "<gold>/maintenance help [pàgina] <gray>(Mostra aquesta finestra d'ajuda)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Mostra els missatges MOTD de manteniment. Si s'especifica 'timer', es mostraran els MOTD del temporitzador)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <índex> <gray>(Elimina un missatge MOTD de manteniment. Si s'usa 'timer', s'eliminarà un missatge específic del temporitzador)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <índex> <1/2> <missatge> <gray>(Configura un missatge MOTD per al manteniment. Si s'usa 'timer', es configurarà un missatge específic del temporitzador)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recarrega el fitxer de configuració, la llista de permitits i la icona del servidor)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Descarrega la versió més recent del plugin al servidor)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Mostra tots els jugadors permitits durant el manteniment)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nom/uuid> <gray>(Afegeix el jugador a la llista de permitits del manteniment)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nom/uuid> <gray>(Elimina el jugador de la llista de permitits del manteniment)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <gray>(Si està actiu, cancel·la el temporitzador del servidor)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Mostra tots els servidors proxy en manteniment)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Du har ikke tilladelse til at udføre denne kommando."
|
||||
kickmessage: "<red>Serveren er i øjeblikket under vedligeholdelse!<br>Prøv igen senere!"
|
||||
maintenanceActivated: "<prefix><gold>Vedligeholdelsestilstand er nu aktiveret."
|
||||
maintenanceDeactivated: "<prefix><gold>Vedligeholdelsestilstand er nu deaktiveret."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Vedligeholdelsestilstand er allerede aktiveret!"
|
||||
alreadyDisabled: "<prefix><red>Vedligeholdelsestilstand er allerede deaktiveret!"
|
||||
endtimerBroadcast: "<prefix><gray>Vedligeholdelsestilstand vil blive deaktiveret om <gold>%TIME%<gray>."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Genindlæs konfigurationsfilen, hvidlistede spillere, sp
|
||||
removedMotd: "<prefix><green>Slet motd nummer %INDEX%."
|
||||
removeMotdError: "<prefix><red>Du har kun én motd, så du kan ikke slette nogen!"
|
||||
setMotd: "<prefix><green>Angiv linje %LINE% af %INDEX%. vedligeholdelses motd til %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Du har %MOTDS% motds, så du skal angive et nummer mellem 1 og %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Det andet argument skal være linjenummer (1 or 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Downloader opdatering..."
|
||||
@@ -49,7 +44,7 @@ whitelistEmpty: "<prefix><red>Vedligeholdelseshvidlisten er tom! Brug <yellow>/m
|
||||
playerNotFound: "<prefix><red>Ingen spillere med dette navn har spillet på denne server før."
|
||||
playerNotFoundUuid: "<prefix><red>Ingen spiller med den uuid kunne findes."
|
||||
playerNotOnline: "<prefix><red>Der er ingen spiller online med det navn."
|
||||
offlinePlayerFetchError: "<prefix><red>Der opstod en fejl under hentning af offline afspiller. Prøv igen senere."
|
||||
offlinePlayerFetchError: "<prefix><red>There was an error while fetching offline player. Please try again later."
|
||||
invalidUuid: "<prefix><red>Ugyldigt uuid-format!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Du er blevet sendt til en venteserver!"
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>Vedligeholdelsestilstand er allerede
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxyservere, der har Vedligeholdelsestilstand aktiveret:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Der er ingen proxy-servere, der er under vedligeholdelse."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "sekund"
|
||||
seconds: "sekunder"
|
||||
minute: "minut"
|
||||
@@ -94,31 +87,18 @@ helpHelp: "<gold>/maintenance help [page] <gray>(Viser dette smukke hjælpevindu
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Viser den aktuelle vedligeholdelses motds. Hvis 'timer' er angivet, bliver dennes motds vist)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Sletter en vedligeholdelses motd. Hvis 'timer' er angivet, vil en tidsspecifik pingbesked blive slettet)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Angiver en motd for vedligeholdelsestilstand. Hvis 'timer' er angivet, vil en tidsspecifik pingbesked blive angivet)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Genindlæser konfigurationsfilen, hvidlisten og serverikonet)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Aktiverer/deaktiverer vedligeholdelsestilstand)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Downloader den nyeste version af plugin'et på din server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Viser alle hvidlistede spillere for vedligeholdelsestilstand)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Tilføjer spilleren til vedligeholdelseshvidlisten, så de kan forbinde til serveren, selvom vedligeholdelsestilstand er aktiveret)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Sletter spilleren fra vedligeholdelseshvidlisten)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Hvis timeren kører, vil den blive afbrudt)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Aktiverer/deaktiverer vedligeholdelsestilstand)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Viser alle proxyservere, der har Vedligeholdelsestilstand aktiveret)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Du hast nicht die erforderliche Berechtigung, um diesen Befehl auszuführen."
|
||||
kickmessage: "<red>Der Server befindet sich momentan im Wartungsmodus!<br>Bitte versuche es später nochmal!"
|
||||
maintenanceActivated: "<prefix><gold>Der Wartungsmodus ist jetzt aktiviert."
|
||||
maintenanceDeactivated: "<prefix><gold>Der Wartungsmodus ist nun deaktiviert."
|
||||
maintenanceStatusOn: "<prefix><gold>Wartungsmodus ist derzeit <green>aktiviert<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Wartungsmodus ist momentan <red>deaktiviert<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Wartungsmodus ist momentan <green>aktiviert <grey>und wird deaktiviert in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Wartungsmodus ist momentan <red>deaktiviert <grey>und wird aktiviert in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Der Wartungsmodus ist bereits aktiviert!"
|
||||
alreadyDisabled: "<prefix><red>Der Wartungsmodus ist bereits deaktiviert!"
|
||||
endtimerBroadcast: "<prefix><gray>Der Wartungsmodus wird deaktiviert in: <gold>%TIME%<gray>."
|
||||
@@ -30,10 +26,9 @@ joinNotification: "<prefix><yellow>%PLAYER% <red>hat versucht dem Server beizutr
|
||||
motdList: "<prefix><gray>Liste deiner Motds, die während Maintenance angezeigt werden:"
|
||||
motdListEmpty: "<prefix><red>Du hast keine Maintenance MOTDs gesetzt!"
|
||||
reload: "<prefix><green>Die Config, die Liste der Spieler die während Maintenance beitreten können, die Sprachdateien und das Icon, das während der Maintenance angezeigt wird, wurden reloaded."
|
||||
removedMotd: "<prefix><green>Die %INDEX%. Maintenance MOTD wurde entfernt."
|
||||
removedMotd: "<prefix><green>Die %INDEX%. Wartungs-MOTD wurde entfernt."
|
||||
removeMotdError: "<prefix><red>Du hast nur eine Maintenance MOTD eingestellt, daher kannst du auch keine entfernen!"
|
||||
setMotd: "<prefix><green>Die %LINE%. Zeile der %INDEX%. Maintenance MOTD wurde geändert zu: %MOTD%"
|
||||
setReason: "<prefix><green>Grund für die Wartung gesetzt auf: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Momentan gibt es %MOTDS% MOTDs, du musst also eine Zahl, die zwischen 1 und %NEWAMOUNT% liegt, wählen."
|
||||
setMotdLineError: "<prefix><red>Das zweite Argument des Befehls muss die Zeilennummer sein (1 oder 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Das Update wird heruntergeladen..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>Der Wartungsmodus ist bereits aus auf
|
||||
singleServerMaintenanceList: "<prefix><gray>Unterserver, die im Wartungsmodus sind:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Es befindet sich momentan kein Unterserver im Wartungsmodus."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>startet in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>endet in <gold>%TIME%"
|
||||
second: "Sekunde"
|
||||
seconds: "Sekunden"
|
||||
minute: "Minute"
|
||||
@@ -91,34 +84,21 @@ helpScheduleTimer: "<gold>/maintenance scheduletimer <Aktiviere in> <Wartungsdau
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Aktiviert Debug Nachrichten in der Konsole)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Sammelt wichtige Informationen für Bugreports)"
|
||||
helpHelp: "<gold>/maintenance help [Seite] <gray>(Zeigt diese wunderschöne Hilfe)"
|
||||
helpMotd: "<gold>/maintenance motd [Timer] [Modus] <gray>(Zeigt die momentan gesetzten Maintenance Motds an. Mit dem 'timer' Argument werden die timerspezifischen Motds angezeigt)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [Timer] [Modus] <Index> <gray>(Entfernt eine Maintenance Motd. Mit dem 'timer' Argument wird eine timerspezifischen Motd entfernt)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [Timer] [Modus] <Index> <1/2> <Nachricht> <gray>(Setzte eine Motd für den Wartungsmodus. Mit dem 'timer' Argument wird eine timerspezifische Motd gesetzt)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Setzt oder löscht den %REASON% Platzhalter)"
|
||||
helpMotd: "<gold>/maintenance motd [Timer] <gray>(Zeigt die momentan gesetzten Maintenance Motds an. Mit dem 'timer' Argument werden die timerspezifischen Motds angezeigt)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [Timer] <Index> <gray>(Entfernt eine Maintenance Motd. Mit dem 'timer' Argument wird eine timerspezifischen Motd entfernt)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [Timer] <Index> <1/2> <Nachricht> <gray>(Setzte eine Motd für den Wartungsmodus. Mit dem 'timer' Argument wird eine timerspezifische Motd gesetzt)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Lädt Config, Language und Whitelist Dateien sowie das Maintenance Icon neu)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Zeigt den aktuellen Wartungsstatus und alle laufenden Timer an)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Aktiviert/deaktiviert den Wartungsmodus mit einem optionalen Anzeigemodus beim Aktivieren)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Aktiviert/deaktiviert den Wartungsmodus)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Sucht nach neuen Updates für das Plugin und lädt diese auf den Server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Zeigt alle gewhitelisteten Spieler für den Wartungsmodus an)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <Name/UUID> <gray>(Whitelistet einen Spieler für den Wartungsmodus, sodass dieser während Wartungen den Server betreten kann)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <Name/UUID> <gray>(Entfernt einen Spieler aus der Wartungsmodus Whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [Server] <gray>(Falls momentan ein Timer läuft, wird dieser abgebrochen)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Aktiviert/deaktiviert den Wartungsmodus global oder auf einem bestimmten Server mit optionalem Anzeigemodus beim Aktivieren)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [Server] <Deaktiviere in> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus deaktiviert)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [Server] <Aktiviere in> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus aktiviert)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [Server] <Starte in> <Wartungsdauer> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus für die gegebene Länge aktiviert)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [Server] <gray>(Aktiviert/deaktiviert den Wartungsmodus)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Zeigt alle Server an, auf denen momentan der Wartungsmodus aktiviert ist)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Wartungsmodus aktiviert.**"
|
||||
webhookMaintenanceDeactivated: "**Wartungsmodus deaktiviert.**"
|
||||
webhookStarttimerStarted: "Der Wartungsmodus wird aktiviert in <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Der Wartungsmodus wird deaktiviert in <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Beitritt gesperrt: `%PLAYER%` hat versucht, während den Wartungsarbeiten beizutreten."
|
||||
webhookSingleMaintenanceActivated: "Der Wartungsmodus wurde aktiviert auf `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Der Wartungsmodus wurde deaktiviert auf `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Der Wartungsmodus wird aktiviert auf `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Der Wartungsmodus wird deaktiviert auf `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 4
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>You do not have the permission to execute that command."
|
||||
kickmessage: "<red>The server is currently under maintenance!<br>Try again later!"
|
||||
maintenanceActivated: "<prefix><gold>Maintenance mode is now activated."
|
||||
maintenanceDeactivated: "<prefix><gold>Maintenance mode is now deactivated."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Maintenance is already enabled!"
|
||||
alreadyDisabled: "<prefix><red>Maintenance is already disabled!"
|
||||
endtimerBroadcast: "<prefix><gray>Maintenance mode will be disabled in <gold>%TIME%<gray>."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Reloaded config, whitelistedplayers, language file and t
|
||||
removedMotd: "<prefix><green>Removed motd number %INDEX%."
|
||||
removeMotdError: "<prefix><red>You only have one motd, so you cannot remove any!"
|
||||
setMotd: "<prefix><green>Set line %LINE% of the %INDEX%. maintenance motd to %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>You currently have %MOTDS% motds, so you have to pick a number between 1 and %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>The second argument has to be the line number (1 or 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Downloading update..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>Maintenance is already disabled on se
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxied servers, that have maintenance enabled:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>There are no proxied servers that are under maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "second"
|
||||
seconds: "seconds"
|
||||
minute: "minute"
|
||||
@@ -91,34 +84,21 @@ helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance du
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Enables some debug logging)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Dumps some server information, used for bug reports)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Shows this beautiful help window)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] [mode] <gray>(Lists maintenance motds. If 'timer' is used, timer-specific motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] [mode] <index> <gray>(Removes a maintenance motd in the selected mode)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] [mode] <index> <1/2> <message> <gray>(Sets a maintenance motd in the selected mode)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Removes a maintenance motd. If using 'timer' as an argument, a timerspecific pingmessage will be removed)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Sets a motd for maintenance mode. If using 'timer' as an argument, a timerspecific pingmessage will be set)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Reloads the config file, whitelist file and the server-icon)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Enables/disables maintenance mode)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Remotely downloads the newest version of the plugin onto your server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Shows all whitelisted players for the maintenance mode)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Removes the player from the maintenance whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(If running, the current timer will be aborted)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Enables/disables maintenance mode)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lists all proxied servers, that are currently under maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,44 +1,39 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<prefix><dark_red>No tienes permiso para ejecutar este comando."
|
||||
kickmessage: "<red>¡El servidor se encuentra en mantenimiento!<br>¡Intentalo de nuevo más tarde!"
|
||||
maintenanceActivated: "<prefix><gold>Modo Mantenimiento activado."
|
||||
maintenanceDeactivated: "<prefix><gold>Modo Mantenimiento desactivado."
|
||||
maintenanceStatusOn: "<prefix><gold>El modo de mantenimiento está actualmente <green>activado<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>El modo de mantenimiento está actualmente <red>desactivado<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>El modo de mantenimiento está actualmente <green>habilitado <grey>y se desactivará en <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>El modo de mantenimiento está actualmente <red>desactivado <grey>y se activará en <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>¡Modo mantenimiento ya está activado!"
|
||||
alreadyDisabled: "<prefix><red>¡Modo mantenimiento ya está desactivado!"
|
||||
maintenanceActivated: "<prefix><gold>Mantenimiento <gray>activado."
|
||||
maintenanceDeactivated: "<prefix><gold>Modo mantenimiento desactivado."
|
||||
alreadyEnabled: "<prefix><gray>¡Modo mantenimiento se encuentra habilitado!"
|
||||
alreadyDisabled: "<prefix><gray>¡Modo mantenimiento se encuentra deshabilitado!"
|
||||
endtimerBroadcast: "<prefix><gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Temporizador iniciado: <gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Temporizador iniciado: <gray>El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME% <gray>y durará <gold>%DURATION%<gray>."
|
||||
endtimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El modo mantenimiento se habilitara en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME% <gray>y durará <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>¡Ya hay un temporizador programado!"
|
||||
timerNotRunning: "<prefix><red>Actualmente no hay ningún temporizador."
|
||||
timerAlreadyRunning: "<prefix><red>Ya hay un temporizador programado!"
|
||||
timerNotRunning: "<prefix><gray>Actualmente no hay temporizador."
|
||||
timerCancelled: "<prefix><red>El Temporizador actual ha sido deshabilitado."
|
||||
timerTooLong: "<prefix><red>¡La duración debe ser menor a 28 días!"
|
||||
timerMotdDisabled: "<prefix><red>Debes configurar 'enable-timerspecific-messages' en la configuración a 'true', si quieres usar/editar motds por temporizador."
|
||||
timerTooLong: "<prefix><gray>El numero debe ser menor a 40320 <dark_gray>(<gold>28 días<dark_gray>)"
|
||||
timerMotdDisabled: "<prefix><red>Tienes que configurar <green>'enable-timerspecific-messages'<red> en la configuración en <green>'true'<red>, si quieres usar / editar motdspecers específicos."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>intentó unirse al servidor."
|
||||
joinNotification: "<prefix><red>%PLAYER% <gray>Intenta unirse al servidor."
|
||||
motdList: "<prefix><gray>Lista de motds de mantenimiento:"
|
||||
motdListEmpty: "<prefix><red>¡No tienes ningún motd(s) de mantenimiento establecido!"
|
||||
motdListEmpty: "<prefix><red>¡No tiene ningún motd(s<dark_gray>) de mantenimiento establecido!"
|
||||
reload: "<prefix><green>Configuracion recargada"
|
||||
removedMotd: "<prefix><green>Numero de motd eliminado <gold>%INDEX%<green>."
|
||||
removeMotdError: "<prefix>&Solo tienes un motd, por lo que no puedes eliminar ninguno!"
|
||||
setMotd: "<prefix><green>Establecer linea <gold>%LINE%<green> sobre <gold>%INDEX%<green>. Para mantenimiento para %MOTD%"
|
||||
setReason: "<prefix><green>Se estableció el motivo de mantenimiento a: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><green>Actualmente tiene <gold>%MOTDS%<green> Motd(s<dark_gray>), por lo que debe elegir un número entre 1 y %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><gray>El segundo argumento tiene que ser el numero de línea.(1 ó 2<dark_gray>)!"
|
||||
updateDownloading: "<prefix><green>Descargando actualización..."
|
||||
updateFailed: "<prefix><red>Actualizacion fallida!"
|
||||
updateFinished: "<prefix><green><bold>The update was successful! To prevent issues with tasks and to complete the update, you have to restart the server!"
|
||||
updateFinished: "<prefix><green>La actualización fue exitosa!, debes reiniciar el servidor!"
|
||||
whitelistedPlayers: "<prefix><gold>Jugadores en lista blanca:"
|
||||
whitelistedPlayersFormat: "<gray>- <green>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>%PLAYER% <gray>Añadido a la lista de mantenimiento!"
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><gray>El modo mantenimiento se encuentra d
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidores proxy, que tienen habilitado el mantenimiento:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>No hay servidores proxy que están en mantenimiento."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <yellow>Abriendo <grey>%SERVER% <yellow>en <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <yellow>Cerrando <aqua>%SERVER% <yellow>en <gold>%TIME%"
|
||||
second: "Segundo"
|
||||
seconds: "Segundos"
|
||||
minute: "Minuto"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><gray>No hay pagina con ese número."
|
||||
helpNextPage: "<gray>Utilice <aqua>/maintenance help %PAGE% <gray>Para pasar a la siguiente ventana de ayuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <dark_gray>(<gray>Si se ejecuta, se abortará el temporizador actual<dark_gray>)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray> (Después del tiempo establecido, ej. 1h5m, el modo de mantenimiento será desactivado)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(Después del tiempo indicado, ej: 1h5m, El modo mantenimiento se habilita.)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(Después del tiempo indicado, ej. 1h5m, el modo mantenimiento se habilitará.)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Activa algunos registros de depuración)"
|
||||
helpDump: "<gold>/maintenance dump <dark_gray>(<gray>Descarga información del servidor, usada para informes de errores<dark_gray>)"
|
||||
helpHelp: "<gold>/maintenance help [page] <dark_gray>(<gray>Muestra la pagina de ayuda<dark_gray>)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <dark_gray>(<gray>Enumera los motivos de mantenimiento establecidos actualmente. Si se especifica el 'temporizador', se muestran los motivos del temporizador<dark_gray>)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <dark_gray>(<gray>Elimina un mantenimiento motd. Si se usa 'timer' como argumento, se eliminará un pingmessage de temporizador específico<dark_gray>)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <dark_gray>(<gray>Establece un motd para el modo de mantenimiento. Si usa 'timer' como argumento, se establecerá un mensaje de ping específico para el tiempo<dark_gray>)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Configura o reestablece el valor por defecto de %REASON%)"
|
||||
helpReload: "<gold>/maintenance reload <dark_gray>(<gray>Vuelve a cargar el archivo de configuración, el archivo de la lista blanca y el ícono del servidor<dark_gray>)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Muestra el estado de mantenimiento actual y cualquier temporizador activo)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Habilita/desactiva el modo de mantenimiento con un modo de visualización opcional al habilitar)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <dark_gray>(<gray>Habilita / deshabilita el modo de mantenimiento<dark_gray>)"
|
||||
helpUpdate: "<gold>/maintenance update <dark_gray>(<gray>Descarga de forma remota la versión más reciente del complemento en su servidor<dark_gray>)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <dark_gray>(<gray>Muestra todos los jugadores en lista blanca para el modo de mantenimiento<dark_gray>)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <dark_gray>(<gray>Agrega al jugador a la lista blanca de mantenimiento, para que puedan unirse al servidor aunque el mantenimiento esté habilitado<dark_gray>)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <dark_gray>(<gray>Quita al jugador de la lista blanca de mantenimiento<dark_gray>)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <dark_gray>(<gray>Si está funcionando, se abortará el temporizador actual<dark_gray>)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [servidor|global] [mode] <gray> (Habilita/desactiva el modo de mantenimiento globalmente o en un servidor específico con un modo de visualización opcional al habilitar)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <dark_gray>(<gray>Habilita / deshabilita el modo de mantenimiento<dark_gray>)"
|
||||
helpStatus: "<gold>/maintenance status <dark_gray>(<gray>Enumera todos los servidores proxy, que están actualmente en mantenimiento<dark_gray>)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Modo de mantenimiento activado.**"
|
||||
webhookMaintenanceDeactivated: "**Modo de mantenimiento desactivado.**"
|
||||
webhookStarttimerStarted: "<prefix><gray>El modo mantenimiento se activará en <gold>%TIME%<gray>`)."
|
||||
webhookEndtimerStarted: "<prefix><gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>`)."
|
||||
webhookJoinNotification: "Bloqueado: `%PLAYER%` intentó unirse durante el mantenimiento."
|
||||
webhookSingleMaintenanceActivated: "Modo de mantenimiento activado en %SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Modo de mantenimiento desactivado en `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "El modo de mantenimiento se activará en `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "El modo de mantenimiento se desactivará en `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Vous n'avez pas la permission d'exécuter cette commande."
|
||||
kickmessage: "<red>Le serveur est actuellement en maintenance !<br>Réessayez plus tard !"
|
||||
maintenanceActivated: "<prefix><gold>Le mode maintenance est maintenant activé."
|
||||
maintenanceDeactivated: "<prefix><gold>Le mode maintenance est maintenant désactivé."
|
||||
maintenanceStatusOn: "<prefix><gold>Le mode maintenance est actuellement <green>activé<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Le mode maintenance est actuellement <red>désactivé<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Le mode maintenance est actuellement <green>activé<grey> et sera désactivé dans <gold>%TIME%"
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Le mode maintenance est actuellement <red>désactivé<grey> et sera activé dans <gold>%TIME%"
|
||||
alreadyEnabled: "<prefix><red>La maintenance est déjà activée !"
|
||||
alreadyDisabled: "<prefix><red>La maintenance est déjà désactivée !"
|
||||
endtimerBroadcast: "<prefix><gray>Le mode maintenance sera désactivé dans <gold>%TIME%<gray>."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Fichier de configuration, liste blanche (whitelist) des
|
||||
removedMotd: "<prefix><green>Numéro de motd supprimé %INDEX%."
|
||||
removeMotdError: "<prefix><red>Vous n’avez qu’un motd, vous ne pouvez donc pas en supprimer !"
|
||||
setMotd: "<prefix><green>Ligne %LINE% du motd %INDEX%. fixée à %MOTD%"
|
||||
setReason: "<prefix><green>Raison de la maintenance configurée à : <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Vous avez actuellement %MOTDS% motd(s), vous devez donc choisir un nombre compris entre 1 et %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Le deuxième argument doit être le numéro de ligne (1 ou 2) !"
|
||||
updateDownloading: "<prefix><red><bold>Téléchargement de la mise à jour..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>La maintenance est déjà désactivé
|
||||
singleServerMaintenanceList: "<prefix><gray>Serveurs proxy ayant la maintenance activée :"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Il n'y a pas de serveurs proxy en maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>comme dans <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>termine dans <gold>%TIME%"
|
||||
second: "seconde"
|
||||
seconds: "secondes"
|
||||
minute: "minute"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Il n'y a pas cette page !"
|
||||
helpNextPage: "<gray>Utilisez <aqua>/maintenance help %PAGE% <gray>pour accéder à la fenêtre d’aide suivante."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Si en cours d'exécution, le minuteur actuel sera abandonné)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <désactiver dans> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera désactiver)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <activer dans> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera activé)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <activer dans> <durée de maintenance> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera activé)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Active certains enregistrements de débogage)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Enregistre certaines informations sur le serveur, utilisées pour les rapports de bug)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Montre cette belle fenêtre d'aide)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Répertorie les paramètres de maintenance actuellement définis. Si vous spécifiez 'timer', les mots de la minuterie seront affichés)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Supprime un motd de maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique au temporisateur sera supprimé)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Définit un motd pour le mode maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique à un temporisateur sera défini)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(définit ou efface la valeur du placeholder %REASON%)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recharge le fichier de configuration, la liste blanche, le fichier de langue et l'icône du serveur)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Affiche les états de maintenance et les minuteurs actifs)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Active/désactive le mode maintenance)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Active/désactive le mode maintenance)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Télécharge la dernière version du plugin sur votre serveur)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Affiche les joueurs de la liste blanche pour le mode maintenance)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Ajoute un joueur à la liste blanche de maintenance afin qu'il puisse rejoindre le serveur même si la maintenance est activée)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Supprime un joueur de la liste blanche de maintenance)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Si en cours d'exécution, le minuteur actuel sera abandonné)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Active/désactive le mode maintenance globalement, ou sur un serveur spécifique avec un mode d'affichage facultatif lors de l'activation)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Active/désactive le mode maintenance)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Répertorie tous les serveurs mandatés actuellement en maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "\n\n**Mode maintenance activé.**"
|
||||
webhookMaintenanceDeactivated: "\n\n**Mode maintenance désactivé.**"
|
||||
webhookStarttimerStarted: "Le mode maintenance sera activé dans <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookEndtimerStarted: "Le mode maintenance sera désactivé dans <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookJoinNotification: "Connexion bloquée : `%PLAYER%` a cherché à rejoindre durant une maintenance."
|
||||
webhookSingleMaintenanceActivated: "Mode maintenance activé sur `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Mode maintenance désactivé sur `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Le mode maintenance sera activé sur `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Le mode maintenance sera désactivé sur `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Nincs engedélyed a parancs használatához."
|
||||
kickmessage: "<red>A szerver karbantartás alatt áll!<br>Próbáld újra később!"
|
||||
maintenanceActivated: "<prefix><gold>Karbantartás elindítva."
|
||||
maintenanceDeactivated: "<prefix><gold>Karbantartás befejezve."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Már engedélyezve van!"
|
||||
alreadyDisabled: "<prefix><red>Már le van tiltva!"
|
||||
endtimerBroadcast: "<prefix><gray>Felléphetsz <gold>%TIME%<gray> múlva."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Újratöltve."
|
||||
removedMotd: "<prefix><green>Motd szám törölve: %INDEX%."
|
||||
removeMotdError: "<prefix><red>Csak egy motd van,nem törölheted!"
|
||||
setMotd: "<prefix><green>Sor %LINE% beállítva %INDEX%-re. motd %MOTD%-ra"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Csak %MOTDS%-d van, úgyhogy válassz egy számot 1 és %NEWAMOUNT% között."
|
||||
setMotdLineError: "<prefix><red>Ennek egy sornak kell lennie (1 vagy 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Frissítés letöltése..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>A karbantartás már le van tiltva a(
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxy szerverek,karbantartási móddal engedélyezve:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nincsenek proxy szerverek karbantartás alatt."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "másodperc"
|
||||
seconds: "másodperc"
|
||||
minute: "perc"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Nincs ilyen oldal!"
|
||||
helpNextPage: "<gray>Használd a <aqua>/maintenance help %PAGE% <gray>parancsot,hogy lapozz."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Az időzítő,ha fut nem lesz figelembe vévve)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(Azután a megadott időben pl. 1h5m, a karbantartásnak vége lesz)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(Azután a megadott időben pl. 1h5m, karbantartás elkezdödik)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(Azután a megadott időben pl. 1h5m, a karbantartás elkezdödik)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Hibakeresés bekapcsolása)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(A hibajelentési előzményeket törli)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Megjelenítí a segítség ablakot)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Megjeleníti a motd-ket)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Törli a megadott motd-t)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Beállít egy motd-t)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Újratölti a plugint)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Karbantartás mód ki-be kapcsolása)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Frissíti a plugin verziót)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Megmutatja a karbantartás fehérlistázottak listáját)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Hozzáadja a játékost a karbantartás fehérlistához)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Kitörli a játékost a karbantartás fehérlistáról)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Ha van karbantartás,akkor figyelmen kívül veszi az időzítőt)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Ki-be kapcsolja a karbantartás módot)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Kiírja az összes proxy szervert, ami karbantartás alatt van)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,23 +1,19 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Non hai il permesso per eseguire questo comando."
|
||||
noPermission: "<red>Non hai i permessi necessari per eseguire quel comando."
|
||||
kickmessage: "<red>Il server è momentaneamente in manutenzione!<br>Riprova più tardi!"
|
||||
maintenanceActivated: "<prefix><gold>Modalità manutenzione ora attivata."
|
||||
maintenanceDeactivated: "<prefix><gold>Modalità manutenzione ora disattivata."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>La modalità manutenzione è già attiva!"
|
||||
alreadyDisabled: "<prefix><red>La modalità manutenzione è già disattivata!"
|
||||
alreadyDisabled: "<prefix><red>La modalità mantenzione è già disattivata!"
|
||||
endtimerBroadcast: "<prefix><gray>La modalità manutenzione verrà disattivata tra <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione verrà disattivata tra <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>La modalità manutenzione verrà attivata tra <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione verrà attivata tra <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>La modalità manutenzione sarà abilitata tra <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Timer avviato: la modalità di manutenzione <gray>sarà abilitata in <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>C'è già un timer programmato!"
|
||||
timerNotRunning: "<prefix><red>Non c'è nessun timer attivo al momento."
|
||||
@@ -27,19 +23,18 @@ timerMotdDisabled: "<prefix><red>Devi impostare 'enable-timerspecific-messages'
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>ha tentato di accedere al server."
|
||||
motdList: "<prefix><gray>Lista delle tue MOTD di manutenzione:"
|
||||
motdListEmpty: "<prefix><red>Non hai ancora nessuna MOTD di manutenzione!"
|
||||
reload: "<prefix><green>Ricaricata config, whitelistedplayers, file dei linguaggi e l'icona di manutenzione."
|
||||
removedMotd: "<prefix><green>Rimossa MOTD numero %INDEX%."
|
||||
removeMotdError: "<prefix><red>Hai soltanto una MOTD, quindi non puoi rimuoverla!"
|
||||
setMotd: "<prefix><green>Impostata MOTD di manutenzione numero %INDEX%, linea %LINE% a: %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Hai attualmente %MOTDS% MOTD, devi scegliere un numero tra 1 e %NEWAMOUNT%."
|
||||
motdList: "<prefix><gray>Lista delle tue motds di manutenzione:"
|
||||
motdListEmpty: "<prefix><red>Non hai ancora nessuna motds di manutenzione!"
|
||||
reload: "<prefix><green>Ricaricata config, whitelistedplayers, file dei linguaggi e la icona di manutenzione."
|
||||
removedMotd: "<prefix><green>Rimossa motd numero %INDEX%."
|
||||
removeMotdError: "<prefix><red>Hai soltanto una motd, quindi non puoi rimuoverla!"
|
||||
setMotd: "<prefix><green>Impostata linea %LINE% in %INDEX%. motd manutenzione a %MOTD%"
|
||||
setMotdIndexError: "<prefix><red>Hai attualmente %MOTDS% motds, quindi devi scegliere un numero fra 1 e %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Il secondo argomento deve corrispondere alla linea (1 o 2)!"
|
||||
updateDownloading: "<prefix><red><bold> Sto scaricando l'aggiornamento..."
|
||||
updateDownloading: "<prefix><red><bold>Scaricando aggiornamento..."
|
||||
updateFailed: "<prefix><dark_red><bold>Aggiornamento non riuscito!"
|
||||
updateFinished: "<prefix><green><bold>L'aggiornamento è completato! Per prevenire problemi e completare l'aggiornamento dovresti riavviare il server!"
|
||||
whitelistedPlayers: "<prefix><gold>Giocatori in whitelist per la manutenzione:"
|
||||
whitelistedPlayers: "<prefix><gold>Player in whitelist per la manutenzione:"
|
||||
whitelistedPlayersFormat: "<dark_gray>- <yellow>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>Aggiunto <aqua>%PLAYER% <green>alla whitelist della manutenzione!"
|
||||
whitelistAlreadyAdded: "<prefix><aqua>%PLAYER% <red>è già nella whitelist della manutenzione!"
|
||||
@@ -47,34 +42,32 @@ whitelistRemoved: "<prefix><green>Rimosso <aqua>%PLAYER% <green>dalla lista dell
|
||||
whitelistNotFound: "<prefix><red>Questo giocatore non fa parte della whitelist della manutenzione!"
|
||||
whitelistEmpty: "<prefix><red>La whitelist di manutenzione è vuota! Usa <yellow>/maintenance add <player/uuid> <red>per aggiungere qualcuno!"
|
||||
playerNotFound: "<prefix><red>Nessun giocatore con questo username è mai entrato nel server."
|
||||
playerNotFoundUuid: "<prefix><red>Nessun giocatore con quell'uuid è stato trovato."
|
||||
playerNotFoundUuid: "<prefix><red>Nessun player con quell'uuid è stato trovato."
|
||||
playerNotOnline: "<prefix><red>Non c'è nessun giocatore online con quell'username."
|
||||
offlinePlayerFetchError: "<prefix><red>C'è stato un errore cercando il giocatore offline. Riprova più tardi."
|
||||
offlinePlayerFetchError: "<prefix><red>C'è stato un errore cercando il player offline. Riprova più tardi."
|
||||
invalidUuid: "<prefix><red>L'uuid presenta un formato invalido!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Sei stato inviato su un server d'attesa!"
|
||||
forceWaitingServer: "<prefix><red>Non puoi abbandonare il server d'attesa durante una manutenzione!"
|
||||
serverNotFound: "<prefix><red>Nessun server con questo nome è registrato sul proxy server!"
|
||||
serverNotFound: "<prefix><red>Nessun server con questo nome è registrato sulla proxy!"
|
||||
singleTimerAlreadyRunning: "<prefix><red>È già presente un timer pianificato per quel server!"
|
||||
singleTimerCancelled: "<prefix><red>Il timer attuale per il server <yellow>%SERVER% <red>è stato rimosso."
|
||||
singleTimerNotRunning: "<prefix><red>Non c'è nessun timer correntemente attivo per quel server."
|
||||
singleEndtimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà disabilitata tra <gold>%TIME%<gray>."
|
||||
singleEndtimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione per il server %SERVER% verrà disattivata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà attivata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà disabilitata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione per il server %SERVER% verrà attivata tra <gold>%TIME%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>La modalità manutenzione sul server %SERVER% sarà abilitata tra <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>Maintenance mode on server %SERVER% will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
singleScheduletimerStarted: "<prefix><green>Timer avviato: <gray>Modalità di manutenzione sul server %SERVER% sarà attivato in <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
singleMaintenanceKick: "<prefix><red>Il server %SERVER% è in manutenzione al momento! Ritenta più tardi!"
|
||||
singleMaintenanceKickComplete: "<red>Il server %SERVER% è in manutenzione!<br>Prova a rientrare per accedere a un altro server!"
|
||||
singleMaintenanceKickComplete: "<red>Il server %SERVER% è in manutenzione!<br>Prova a rientrare per accedere ad un'altro server!"
|
||||
singleMaintenanceActivated: "<prefix><gold>La modalità manutenzione è ora attiva sul server <yellow>%SERVER%<gold>."
|
||||
singleMaintenanceDeactivated: "<prefix><gold>La modalità manutenzione è ora disattivata sul server <yellow>%SERVER%<gold>."
|
||||
singleServerAlreadyEnabled: "<prefix><red>La modalità manutenzione è già attiva sul server <yellow>%SERVER%<red>!"
|
||||
singleServerAlreadyDisabled: "<prefix><red>La modalità manutenzione è già disattivata sul server <yellow>%SERVER%<red>!"
|
||||
singleServerMaintenanceList: "<prefix><gray>Server collegati con manutenzione attiva:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nessun server sotto proxy server ha la modalità manutenzione attiva."
|
||||
singleServerMaintenanceList: "<prefix><gray>Servers sotto proxy che hanno la modalità manutenzione attiva:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nessun server sotto proxy ha la modalità manutenzione attiva."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "secondo"
|
||||
seconds: "secondi"
|
||||
minute: "minuto"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Non c'è alcuna pagina con quel numero!"
|
||||
helpNextPage: "<gray>Usa <aqua>/maintenance help %PAGE% <gray>per andare alla prossima pagina d'aiuto."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Se attivo, l'attuale timer verrà fermato)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <tempo di disattivazione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà disattivata)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <tempo di attivazione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà attivata)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <tempo di attivazione> <durata manutenzione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà attivata e durerà per il tempo indicato)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Attiva la registrazione di debug)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Enables some debug logging)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Copia alcune informazioni dal server, usato per segnalare problemi)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Mostra questa fantastica pagina d'aiuto)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Elenca le attuali motds di manutenzione impostate. Se specifichi 'timer', verranno mostrati i motds dei timer)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Rimuove una motd di manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà rimosso)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Imposta il motd per la manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà impostato)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Ricarica il file di configurazione, whitelist server e icona)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Abilita/Disabilita modalità manutenzione)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Scarica dall'esterno l'ultima versione del plugin nel server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Elenca tutti i giocatori nella whitelist per la manutenzione)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Aggiunge il giocatore alla whitelist di manutenzione, così possono entrare in un server durante la manutenzione)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Rimuovi il giocatore dalla whitelist della manutenzione)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Rimuovi il player dalla whitelist della manutenzione)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Se attivo, il timer attuale verrà fermato)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Abilita/disabilita la modalità di manutenzione)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Elenca tutti i server sotto proxy che hanno la modalità manutenzione attiva)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>このコマンドを実行する権限がありません。"
|
||||
kickmessage: "<red>メンテナンス中です。<br>しばらくたってから、もう一度お試しください"
|
||||
maintenanceActivated: "<prefix><green>メンテナンスを有効にしました。"
|
||||
maintenanceDeactivated: "<prefix><yellow>メンテナンスを解除しました。"
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>メンテナンスは既に有効です。"
|
||||
alreadyDisabled: "<prefix><red>メンテナンスは既に解除されています。"
|
||||
endtimerBroadcast: "<prefix><gray>メンテナンスモードは、<gold>%TIME%<gray>で無効になります。"
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>再読み込みが完了しました。"
|
||||
removedMotd: "<prefix><green>motd番号%INDEX%を削除しました。"
|
||||
removeMotdError: "<prefix><red>motdは1つしかないので、削除することはできません。"
|
||||
setMotd: "<prefix><greenINDEX%.の行 %LINE% を %MOTD% に設定します。"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>現在、%MOTDS%のMOTDを持っているので、1から%NEWAMOUNT%の間の数字を選ぶ必要があります。"
|
||||
setMotdLineError: "<prefix><red>第2引数には、行番号(1または2)を指定する必要があります。"
|
||||
updateDownloading: "<prefix><red><bold>アップデートをダウンロード中です..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><yellow>%SERVER%<red> のメンテナン
|
||||
singleServerMaintenanceList: "<prefix><gray>プロキシサーバーで、メンテナンスが有効になっているもの: "
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>メンテナンス中のプロキシサーバーはありません。"
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "秒"
|
||||
seconds: "秒"
|
||||
minute: "分"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>その番号のページがありません。"
|
||||
helpNextPage: "<gray>Use <aqua>/maintenance help %PAGE% <gray>で次のヘルプウィンドウに移動します。"
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(タイマーを実行していた場合、タイマーの実行を中止します。)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(指定された時間(例えば1時間5分)が経過すると、メンテナンス・モードは無効になる)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(指定された時間後、例えば1時間5分後にメンテナンス・モードが有効になる)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(指定された時間(例えば1時間5分)が経過すると、メンテナンスモードが有効になる)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(デバッグロギングを有効にします。)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(バグレポートに使用される、いくつかのサーバ情報をダンプします。)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(このようなヘルプページが表示されます。)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(現在設定されているメンテナンスMOTDを一覧表示します。'timer'を指定した場合は、タイマーの場合のMOTDを表示します。)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(メンテナンスの場合に使用されるMOTDを削除します。引数として'timer'を使用した場合にはタイマー固有のピングメッセージが表示されます。)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(メンテナンスの場合に使用されるMOTDを設定します。引数として'timer'を使用した場合にはタイマー固有のピングメッセージが表示されます。)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(設定ファイル、ホワイトリストファイル、サーバーアイコンを再読み込みします。)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(メンテナンスモードの有効/解除を設定します。)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(最新版のプラグインをサーバーにリモートでダウンロードします。)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(メンテナンスモードのホワイトリストに登録されているすべてのプレーヤーを表示します。)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(メンテナンスのホワイトリストにユーザーを追加し、メンテナンスが有効な状態でもサーバーに参加できるようにします。)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(メンテナンスのホワイトリストからプレーヤーを削除します。)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(もし、タイマーが実行中の場合、現在のタイマーを中止します。)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(メンテナンスモードの有効化/無効化を設定します。)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(現在メンテナンス中のプロキシサーバーをすべてリストアップします。)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>권한이 없습니다."
|
||||
kickmessage: "<red>서버가 현재 점검 중입니다!<br>나중에 다시 시도하세요!"
|
||||
maintenanceActivated: "<prefix><gold>유지 관리 모드가 활성화되었습니다."
|
||||
maintenanceDeactivated: "<prefix><gold>유지 관리 모드가 비활성화되었습니다."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>유지 관리가 이미 활성화되었습니다!"
|
||||
alreadyDisabled: "<prefix><red>유지보수가 이미 비활성화되었습니다!"
|
||||
endtimerBroadcast: "<prefix><gray>유지 관리 모드는<gold>%TIME%<gray>에 비활성화됩니다.."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>설정, 화이트리스트 플레이어, 언어 파일
|
||||
removedMotd: "<prefix><green>%INDEX%번째 motd를 삭제했습니다."
|
||||
removeMotdError: "<prefix><red>motd가 하나만 있으므로 제거할 수 없습니다!"
|
||||
setMotd: "<prefix><green>INDEX%의 %LINE% 줄을 %MOTD%로 설정합니다."
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>현재 %MOTDS% motd가 있으므로 1에서 %NEWAMOUNT% 사이의 숫자를 선택해야 합니다."
|
||||
setMotdLineError: "<prefix><red>두 번째 인수는 줄 번호(1 또는 2)여야 합니다!"
|
||||
updateDownloading: "<prefix><red><bold>업데이트 다운로드 중..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>Maintenance is already disabled on se
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxied servers, that have maintenance enabled:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>There are no proxied servers that are under maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "second"
|
||||
seconds: "seconds"
|
||||
minute: "minute"
|
||||
@@ -94,31 +87,18 @@ helpHelp: "<gold>/maintenance help [page] <gray>(Shows this beautiful help windo
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Removes a maintenance motd. If using 'timer' as an argument, a timerspecific pingmessage will be removed)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Sets a motd for maintenance mode. If using 'timer' as an argument, a timerspecific pingmessage will be set)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Reloads the config file, whitelist file and the server-icon)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Enables/disables maintenance mode)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Remotely downloads the newest version of the plugin onto your server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Shows all whitelisted players for the maintenance mode)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Removes the player from the maintenance whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(If running, the current timer will be aborted)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Enables/disables maintenance mode)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lists all proxied servers, that are currently under maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,18 +1,14 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Prace techniczne<dark_gray>] "
|
||||
noPermission: "<red>Nie posiadasz permisji na użycie tej komendy."
|
||||
kickmessage: "<red>Serwer jest w trakcie przerwy technicznej!<br>Spróbuj ponownie później!"
|
||||
maintenanceActivated: "<prefix><gold>Tryb konserwacji włączony."
|
||||
maintenanceDeactivated: "<prefix><gold>Tryb konserwacji wyłączony."
|
||||
maintenanceStatusOn: "<prefix><gold>Tryb konserwacji jest obecnie <green>włączony<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Tryb konserwacji jest obecnie <red>wyłączony<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Tryb konserwacji jest obecnie <green>włączony <grey>i zostanie wyłączony za <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Tryb konserwacji jest obecnie <red>wyłączony <grey>i zostanie włączony za <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Tryb konserwacji jest już włączony!"
|
||||
alreadyDisabled: "<prefix><red>Tryb konserwacji jest już wyłączony!"
|
||||
alreadyEnabled: "<prefix><red>Przerwa techniczna już jest włącznona!"
|
||||
alreadyDisabled: "<prefix><red>Przerwa techniczna już jest wyłącznona!"
|
||||
endtimerBroadcast: "<prefix><gray>Przerwa techniczna zostanie zakończona za <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Rozpoczęto timer: <gray>Tryb konserwacji zostanie wyłączony za <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>Przerwa techniczna zacznie się za <gold>%TIME%<gray>."
|
||||
@@ -22,7 +18,7 @@ scheduletimerStarted: "<prefix><green>Rozpoczęto timer: <gray>Przerwa techniczn
|
||||
timerAlreadyRunning: "<prefix><red>Timer został już zaplanowany!"
|
||||
timerNotRunning: "<prefix><red>Aktualnie nie ma żadnego działającego timera."
|
||||
timerCancelled: "<prefix><red>Bieżący timer został anulowany."
|
||||
timerTooLong: "<prefix><red>Podany czas musi być krótszy niż 28 dni!"
|
||||
timerTooLong: "<prefix><red>Liczba musi byc mniejsz niż 40320 (28 dni)!"
|
||||
timerMotdDisabled: "<prefix><red>Musisz ustawić 'enable-timerspecific-messages' w konfiguracji na 'true', jeśli chcesz używać motd z timerem."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Ponownie załadowano plik konfiguracji, białą listę,
|
||||
removedMotd: "<prefix><green>Usunięto motd numer %INDEX%."
|
||||
removeMotdError: "<prefix><red>Masz tylko jedno motd, którego nie możesz usunąć!"
|
||||
setMotd: "<prefix><green>Ustawiono wiersz %LINE% od %INDEX%. motd konserwacji na %MOTD%"
|
||||
setReason: "<prefix><green>Ustawiono powód konserwacji na: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Masz aktualnie %MOTDS% motd, więc musisz wybrać liczbę między 1 a %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Drugi argument musi być numerem lini (1 lub 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Pobieranie aktualizacji..."
|
||||
@@ -49,7 +44,7 @@ whitelistEmpty: "<prefix><red>Biała lista konserwacji jest pusta! Użyj <yellow
|
||||
playerNotFound: "<prefix><red>Ten gracz nigdy nie grał na serwerze."
|
||||
playerNotFoundUuid: "<prefix><red>Nie można znaleźć gracza z tym uuid."
|
||||
playerNotOnline: "<prefix><red>Nie ma gracza online z tym nickiem."
|
||||
offlinePlayerFetchError: "<prefix><red>Wystąpił błąd podczas pobierania gracza offline. Spróbuj ponownie później."
|
||||
offlinePlayerFetchError: "<prefix><red>There was an error while fetching offline player. Please try again later."
|
||||
invalidUuid: "<prefix><red>Nieprawidłowy format uuid!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Zostałeś wysłany do poczekalni!"
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>Tryb konserwacji jest już wyłączon
|
||||
singleServerMaintenanceList: "<prefix><gray>Serwery z włączonym trybem konserwacji:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Brak serwerów pod nadzorem."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>zaczyna się za <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>kończy się za <gold>%TIME%"
|
||||
second: "sekunda"
|
||||
seconds: "sekund"
|
||||
minute: "minuta"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Strona z tym numerem nie istnieje!"
|
||||
helpNextPage: "<gray>Użyj <aqua>/maintenance help %PAGE% <gray>aby przejść do następnej strony pomocy."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Jeśli aktywny, timer zostanie anulowany)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <czas> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie wyłączony)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <czas> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie włączony)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <czas do włączenia> <czas trwania> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie włączony)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Włacza logowanie dodatkowych informcji do debugowania)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Daje informacje o serwerze, używane do raportowania błędów)"
|
||||
helpHelp: "<gold>/maintenance help [strona] <gray>(Pokazuje tą piękną stronę pomocy)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Wyświetla aktualnie ustawione motd. Jeśli wstawiono 'timer', motd z timerem zostaną pokazane)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Usuwa motd konserwacji. Jeśli wstawiono 'timer', motd z timerem zostanie usunięte)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <wiadomość> <gray>(Ustawia motd konserwacji. Jeśli wstawiono 'timer', motd z timerem zostanie ustawione)"
|
||||
helpSetReason: "<gold>/maintenance setreason <powód/none> <gray>(Ustawia albo usuwa powód trybu konserwacji w wiadomościach. Wpisz \"none\" jako powód, aby wyczyścić)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Przeładowuje plik konfiguracji, białej listy i ikonę serwera)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Pokazuje status trybu konserwacji i wszystkie minutniki)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [tryb] <gray>(Włącza/Wyłącza tryb konserwacji, opcjonalnie z trybem podanym podczas włączania)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Włącza/wyłącza tryb konserwacji)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Pobiera najnowszą wersję plugina)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Pokazuje białą listę trybu konserwacji)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nazwa/uuid> <gray>(Dodaje gracza do listy konserwacji, aby mogli dołączyć do serwera w trakcie konserwacji)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nazwa/uuid> <gray>(Usuwa gracza z listy trybu konserwacji)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [serwer] <gray>(Jeśli aktywny, timer zostanie anulowany)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [serwer/global] [tryb] <gray>(Włącza/Wyłącza tryb konserwacji globalnie lub na podanym serwerze, opcjonalnie z trybem podanym podczas włączania)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [serwer] <gray>(Włącza/wyłącza tryb konserwacji)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Wyświetla wszystkie serwery w trybie konserwacji)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Tryb konserwacji włączony.**"
|
||||
webhookMaintenanceDeactivated: "**Tryb konserwacji wyłączony.**"
|
||||
webhookStarttimerStarted: "Tryb konserwacji zostanie włączony <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Tryb konserwacji zostanie wyłączony <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Zablokowano dołączenie: `%PLAYER%` próbował(a) dołączyć podczas konserwacji."
|
||||
webhookSingleMaintenanceActivated: "Tryb konserwacji włączony dla `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Tryb konserwacji wyłączony dla `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Tryb konserwacji zostanie włączony dla `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Tryb konserwacji zostanie wyłączony dla `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
@@ -1,16 +1,12 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Você não tem permissão para executar esse comando."
|
||||
kickmessage: "<red>O servidor está em manutenção!<br>Tente novamente mais tarde!"
|
||||
maintenanceActivated: "<prefix><gold>O modo de manutenção agora está ativado."
|
||||
maintenanceDeactivated: "<prefix><gold>O modo de manutenção agora está desativado."
|
||||
maintenanceStatusOn: "<prefix><gold>O modo de manutenção está atualmente <green>ativo<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>O modo de manutenção está atualmente <red>desativado<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>O modo de manutenção está atualmente <green>habilitado <grey>e será desabilitado em <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>O modo de manutenção está atualmente <red>desabilitado <grey>e será habilitado em <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>A manutenção já está ativada!"
|
||||
alreadyDisabled: "<prefix><red>A manutenção já está desativada!"
|
||||
endtimerBroadcast: "<prefix><gray>O modo de manutenção será desativado em <gold>%TIME%<gray>."
|
||||
@@ -33,7 +29,6 @@ reload: "<prefix><green>Recarregou a configuração, lista de jogadores com perm
|
||||
removedMotd: "<prefix><green>Motd número %INDEX% removida."
|
||||
removeMotdError: "<prefix><red>Você possui apenas uma motd, portanto, não pode remover nenhuma!"
|
||||
setMotd: "<prefix><green>Definiu a linha %LINE% da motd de manutenção %INDEX% para %MOTD%"
|
||||
setReason: "<prefix><green>Definir motivo de manutenção para: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>No momento, você possui %MOTDS% motds, portanto, deve escolher um número entre 1 e %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>O segundo argumento deve ser o número da linha (1 ou 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Baixando atualização..."
|
||||
@@ -73,8 +68,6 @@ singleServerAlreadyDisabled: "<prefix><red>A manutenção já está desativada n
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidores proxy com manutenção ativada:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Não há servidores proxy em manutenção no momento."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>iniciando em <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>terminando em <gold>%TIME%"
|
||||
second: "segundo"
|
||||
seconds: "segundos"
|
||||
minute: "minuto"
|
||||
@@ -85,40 +78,27 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Não há página com esse número!"
|
||||
helpNextPage: "<gray>Use <aqua>/maintenance help %PAGE% <gray>para ir para a próxima janela de ajuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Se estiver em execução, o temporizador atual será abortado)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <desabilitar em> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo manutenção será desabilitado)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <habilitar em> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo de manutenção será habilitado)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <habilitar em> <duração da manutenção> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo de manutenção será habilitado)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Ativa alguns registros de depuração)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Exibe algumas informações do servidor, usadas para relatórios de bugs)"
|
||||
helpHelp: "<gold>/maintenance help [página] <gray>(Mostra esta bela janela de ajuda)"
|
||||
helpMotd: "<gold>/maintenance motd [temporizador] <gray>(Lista as motds de manutenção atualmente definidas. Se 'temporizador' for especificado, as motds de temporizador serão mostradas)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [temporizador] <índice> <gray>(Remove uma motd de manutenção. Se usar 'temporizador' como argumento, uma mensagem de ping específica do temporizador será removida)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [temporizador] <índice> <1/2> <mensagem> <gray>(Define uma motd para o modo de manutenção. Se usar 'temporizador' como argumento, uma mensagem de ping específica do temporizador será definida)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Define ou limpa o valor %REASON% comum)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recarrega o arquivo de configuração, arquivo de lista branca e o ícone do servidor)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Mostra o estado atual da manutenção e qualquer timer em execução)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Ativa/desativa modo de manutenção com modo de exibição opcional quando ativado)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Ativa/desativa o modo de manutenção)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Baixa remotamente a versão mais recente do plugin para o seu servidor)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Mostra todos os jogadores na lista branca para o modo de manutenção)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nome/uuid> <gray>(Adiciona o jogador à lista branca de manutenção, permitindo que eles entrem no servidor mesmo com a manutenção ativada)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nome/uuid> <gray>(Remove o jogador da lista branca de manutenção)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <gray>(Se estiver em execução, o temporizador atual será abortado)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Ativa/desativa modo de manutenção globalmente ou em um servidor especifico com um modo de exibição opcional quando ativado)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [servidor] <gray>(Ativa/desativa o modo de manutenção)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lista todos os servidores proxy que estão atualmente em manutenção)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Modo de manutenção ativado.**"
|
||||
webhookMaintenanceDeactivated: "**Modo de manutenção desativado.**"
|
||||
webhookStarttimerStarted: "Manutenção será ativada em <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Manutenção será desativada em <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Entrada bloqueada: `%PLAYER%` tentou conectar durante a manutenção."
|
||||
webhookSingleMaintenanceActivated: "Manutenção será ativada em `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Manutenção será desativada em `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: ""
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
language-version: 2
|
||||
Loaded 100 of 146 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user