mirror of
https://codeberg.org/Andre601/AdvancedServerList.git
synced 2026-11-05 17:02:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5df2e05a14 | ||
|
|
d4e4173cc3 | ||
|
|
562ad481c5 | ||
|
|
a0ee2a4322 | ||
|
|
2c92efdb43 | ||
|
|
555dc9d6a5 | ||
|
|
27742c5e1b | ||
|
|
280aeb8d2e | ||
|
|
92a868f0fa | ||
|
|
189ac5e09b | ||
|
|
833cb81d65 | ||
|
|
ab09422da5 | ||
|
|
64cad6dc26 | ||
|
|
ce78b493f4 | ||
|
|
c43048ea3f | ||
|
|
6d4d1600ab | ||
|
|
f114e99b9b | ||
|
|
3d587bc86d | ||
|
|
bd8c6be7c6 | ||
|
|
b5d5d508e2 | ||
|
|
3001b65fe8 | ||
|
|
c82771db59 | ||
|
|
9880836c25 | ||
|
|
f12ae28722 | ||
|
|
42b0f0e94f | ||
|
|
0a4b872051 | ||
|
|
b1322105ed | ||
|
|
831ca57fbb | ||
|
|
6502639cd3 | ||
|
|
5059b80db2 | ||
|
|
ecdaf72963 | ||
|
|
28e2ca69ed | ||
|
|
9cad78b6e4 | ||
|
|
af8654666b | ||
|
|
6cd474b35d | ||
|
|
3802ab556c | ||
|
|
3a520eeaf0 | ||
|
|
204f43c112 | ||
|
|
fc8ed8e49e | ||
|
|
56082c308b | ||
|
|
205e563095 | ||
|
|
5b01940c60 | ||
|
|
cbb087e3d1 | ||
|
|
524b926244 | ||
|
|
4059bbfe93 | ||
|
|
9b0b69a4f4 | ||
|
|
10a82eb951 | ||
|
|
690f7dfaf0 | ||
|
|
6a22d20b3a | ||
|
|
b1072bb1fa | ||
|
|
d20da91bab | ||
|
|
17e9692028 | ||
|
|
45dc8a5fe6 | ||
|
|
a237ac1ce4 | ||
|
|
27e66a16b9 | ||
|
|
8f98846bc3 | ||
|
|
bbcab59845 | ||
|
|
3130e07070 | ||
|
|
7bc61ddf4d | ||
|
|
53d15a9011 | ||
|
|
8718e4a0ae | ||
|
|
06a49956af | ||
|
|
38ec131b69 | ||
|
|
1bdaa61dd9 | ||
|
|
080d5055c4 | ||
|
|
423b363964 | ||
|
|
6b9abfccfc | ||
|
|
f589a8da35 | ||
|
|
465581306f | ||
|
|
6b2919961b | ||
|
|
adb6e797b2 | ||
|
|
b410b9438f | ||
|
|
c1d5b4efa9 | ||
|
|
4785dd127e | ||
|
|
9e8e2f7e74 | ||
|
|
c14dfe0f3a | ||
|
|
ed92e7002c | ||
|
|
8f93d9732c | ||
|
|
96f8fa5860 | ||
|
|
bfb857bd5c | ||
|
|
5fe3b5811c | ||
|
|
2a7eff0092 | ||
|
|
1907f5d47e | ||
|
|
aa92350b52 | ||
|
|
869b9bd3b7 | ||
|
|
fe31dcf0a4 | ||
|
|
6b44438f52 | ||
|
|
6b0c654f41 | ||
|
|
c28ff3a891 | ||
|
|
f424b41c3b | ||
|
|
b5f901d8f5 | ||
|
|
29d52492fc | ||
|
|
2d6af20bdc | ||
|
|
59c913ecf8 | ||
|
|
4a50beb4e0 | ||
|
|
c099127272 | ||
|
|
15974b5c54 | ||
|
|
483afe63c4 | ||
|
|
f0cb458a34 | ||
|
|
2c547cd6d0 | ||
|
|
e7282b4a97 | ||
|
|
4fc0ad97fc | ||
|
|
3ae02167b9 | ||
|
|
e407b38565 | ||
|
|
c98d52ed46 | ||
|
|
266913e4b4 | ||
|
|
a3d4a009a5 | ||
|
|
18e00d082e | ||
|
|
6a3979743b | ||
|
|
3a29ad54ca | ||
|
|
987c520160 | ||
|
|
4b6197f6e0 | ||
|
|
01611d4130 | ||
|
|
531aa65fcc | ||
|
|
fb101c4a14 | ||
|
|
7bd97f5f5a | ||
|
|
52c3edd0ea | ||
|
|
368e544051 | ||
|
|
12b2f5a208 | ||
|
|
adc88a8640 | ||
|
|
817db44492 | ||
|
|
f74f7dfa6b | ||
|
|
e9c8730090 | ||
|
|
861ada0396 | ||
|
|
a2fb9c3d81 | ||
|
|
f747461018 | ||
|
|
f408146d57 | ||
|
|
c684001fcf | ||
|
|
6dc53c8c4f | ||
|
|
64ab958c67 | ||
|
|
7a66c9a0c9 | ||
|
|
0ff658632a | ||
|
|
ee32347bd0 | ||
|
|
9e11038e98 | ||
|
|
008ddbb98a | ||
|
|
f084c17d76 | ||
|
|
9dd73aec9d | ||
|
|
3ebf151f3a | ||
|
|
872c194a62 | ||
|
|
d122603c70 | ||
|
|
489fce2031 | ||
|
|
1651151f26 | ||
|
|
aa61ea826f | ||
|
|
0877eb4187 | ||
|
|
6e89cdb3cc | ||
|
|
1eb0b30356 | ||
|
|
417f5dc5d0 | ||
|
|
01a73b9ea3 | ||
|
|
c06788a55c | ||
|
|
fd924107bc | ||
|
|
dce90b91f0 | ||
|
|
aa968b7d25 | ||
|
|
137d089e4a | ||
|
|
bfa27f92e1 | ||
|
|
b405706b50 | ||
|
|
89f44d7bec | ||
|
|
28e9b6ed96 | ||
|
|
19b3eec401 | ||
|
|
c712b3b715 | ||
|
|
5c379c3b13 | ||
|
|
f6f48708d9 | ||
|
|
83890fa5cb | ||
|
|
d7653a6a6f | ||
|
|
676c4c8f1f | ||
|
|
b66870c942 | ||
|
|
af97a0dac2 | ||
|
|
d43ef090ef | ||
|
|
e7451ae567 | ||
|
|
cf4f095624 | ||
|
|
9280809ab0 | ||
|
|
875ae4d43d | ||
|
|
dbd45ac65e | ||
|
|
7c15778ebc | ||
|
|
2699856a75 | ||
|
|
b49c105620 | ||
|
|
2ffbfeec48 | ||
|
|
bd885e25e2 | ||
|
|
e2c6eb142c | ||
|
|
db11e42c6d | ||
|
|
36e5829943 | ||
|
|
7bbb2bbfa7 | ||
|
|
6acd536f43 | ||
|
|
64d1440ad2 | ||
|
|
6f1dd78aa7 | ||
|
|
4330978816 | ||
|
|
935603b852 | ||
|
|
9671938a66 | ||
|
|
5cc974eb9c | ||
|
|
e526cc6750 | ||
|
|
34fea78b01 | ||
|
|
072547005c | ||
|
|
cdb5852e8b | ||
|
|
050477c19f | ||
|
|
52b24bb3e9 | ||
|
|
df8a063369 | ||
|
|
3fc4a788b8 | ||
|
|
15e5108ec7 | ||
|
|
b8fa694e26 | ||
|
|
f1b55cba79 | ||
|
|
e76dd78cd5 | ||
|
|
09a668493b | ||
|
|
1ef466d2a4 | ||
|
|
e15ddbf2d4 | ||
|
|
1c0ce073e5 | ||
|
|
5964be18ed | ||
|
|
06ad4f106b | ||
|
|
adf343468f | ||
|
|
5a0bb3ce03 | ||
|
|
b3edb2833e | ||
|
|
83c2017544 | ||
|
|
42ecf8ec2a | ||
|
|
fe53c28f77 | ||
|
|
44e8b395f5 | ||
|
|
13828897a2 | ||
|
|
965a9898ca | ||
|
|
d3c9d1e7e2 | ||
|
|
ff3df14a90 | ||
|
|
374f477645 | ||
|
|
11bcbc7918 | ||
|
|
f91f77dba0 | ||
|
|
ac36bc7c6c | ||
|
|
184aa7cd83 | ||
|
|
e20a80b410 | ||
|
|
43f5cbdcf1 | ||
|
|
7c8d6067f5 | ||
|
|
5500239146 | ||
|
|
62844f3111 | ||
|
|
37df1c6376 | ||
|
|
abe1dea027 | ||
|
|
66500050fe | ||
|
|
2bc2f11fb1 | ||
|
|
4b88c78036 | ||
|
|
5a98301b7d | ||
|
|
2cf7fd4ffc | ||
|
|
83349e1c37 | ||
|
|
d928991ca5 | ||
|
|
8b3cd0fcee | ||
|
|
2afd7483df | ||
|
|
ae108d1bed | ||
|
|
37e343e92e | ||
|
|
8b01a12ef9 | ||
|
|
91ea80fbde | ||
|
|
deec676180 | ||
|
|
5fb22a505f | ||
|
|
539a1300d2 | ||
|
|
915fe7b134 | ||
|
|
da393a66c1 | ||
|
|
6563b93721 | ||
|
|
c8e51ab82e | ||
|
|
435fbe721d | ||
|
|
3677e90ad1 | ||
|
|
cd96a87028 | ||
|
|
3b1e5244e4 | ||
|
|
07a1baff36 | ||
|
|
c87f6d5a0d | ||
|
|
36f6c41059 | ||
|
|
fa0170fa16 | ||
|
|
c66936861f | ||
|
|
8933c39ce0 | ||
|
|
34865b5bb8 | ||
|
|
271ebed7b6 | ||
|
|
08e7eca34f | ||
|
|
0162bcdaaf | ||
|
|
39e76862d5 | ||
|
|
a7aeffa52a | ||
|
|
9f847ca1db | ||
|
|
6f4a429123 | ||
|
|
60db6eb445 | ||
|
|
5c06fec00a | ||
|
|
12eb80d4d7 | ||
|
|
c371bf323c | ||
|
|
8dca20c73d | ||
|
|
aabfb5273e | ||
|
|
a282382402 | ||
|
|
e86733052b | ||
|
|
a112036c2e | ||
|
|
6c07bfb5a3 | ||
|
|
7668a3e881 | ||
|
|
f53f2c724d | ||
|
|
5ea6f9307c | ||
|
|
8bdaa232ca | ||
|
|
1ad945a1a9 | ||
|
|
85d11e7896 | ||
|
|
bcd940d808 | ||
|
|
dd837b96e8 | ||
|
|
57295756fc | ||
|
|
9f1307f559 | ||
|
|
c489764b06 | ||
|
|
845b1b2022 | ||
|
|
3662a66ec9 | ||
|
|
e1e0083633 | ||
|
|
58e4624cf5 | ||
|
|
df069ebcdc | ||
|
|
82f2c476d8 | ||
|
|
3545cac908 | ||
|
|
cb95b833e6 | ||
|
|
e2c1c44537 | ||
|
|
aeb0587263 | ||
|
|
3471876687 | ||
|
|
82d58564ee | ||
|
|
d3918a487a | ||
|
|
a25232be6a | ||
|
|
bfa05f943a | ||
|
|
dc40a54999 | ||
|
|
682621e196 | ||
|
|
41fa678591 | ||
|
|
e7557da944 | ||
|
|
c7c9885e18 | ||
|
|
62c665a598 | ||
|
|
6d687d391d | ||
|
|
2ac6b89368 | ||
|
|
b8d4829e02 | ||
|
|
a9b4355ebf | ||
|
|
b7f3ecdc5d | ||
|
|
0428280480 | ||
|
|
31e7fb9a22 | ||
|
|
b3fc768ea7 | ||
|
|
7b990e798d | ||
|
|
7e1e00d246 | ||
|
|
15677e948d | ||
|
|
457f85d697 | ||
|
|
f3a3df648f | ||
|
|
000f3dd680 | ||
|
|
db3b0e39b5 | ||
|
|
e5a5cf9f7e | ||
|
|
0c3853de2b | ||
|
|
0146e594de | ||
|
|
1a790bca41 | ||
|
|
fc039ebe93 | ||
|
|
22561f6848 | ||
|
|
8a7ccc07ae | ||
|
|
b43f7b9f31 | ||
|
|
69b3086c65 | ||
|
|
e5b05b5859 | ||
|
|
a07994adb1 | ||
|
|
8d83b45657 | ||
|
|
22371715c5 | ||
|
|
8a7d042476 | ||
|
|
26205cdd67 | ||
|
|
ccb9cd5522 | ||
|
|
2383214b7e | ||
|
|
a82b6bf0e9 | ||
|
|
3e541e65ed | ||
|
|
314becdc45 | ||
|
|
8f662ced5c | ||
|
|
3ff782e128 | ||
|
|
6a6a708ee7 | ||
|
|
1751a77e6f | ||
|
|
3069244f21 | ||
|
|
99d4232304 | ||
|
|
ec408316bd | ||
|
|
eee5271966 | ||
|
|
34e4816517 | ||
|
|
7bde6dedb5 | ||
|
|
6864f57917 | ||
|
|
0b705ca897 | ||
|
|
4661d72f8c | ||
|
|
2b7053c724 | ||
|
|
8d81367354 | ||
|
|
facb358404 | ||
|
|
fd49e101ca | ||
|
|
a55e19bb4a | ||
|
|
07c1893895 | ||
|
|
eed3c37bcb | ||
|
|
42d9a54668 | ||
|
|
51811452fd | ||
|
|
0b21958826 | ||
|
|
f3fdc68dce | ||
|
|
3b76a2abdd | ||
|
|
87964d42a7 | ||
|
|
2529195097 | ||
|
|
62e54fe9ea | ||
|
|
ad49a0659e | ||
|
|
a703fba542 | ||
|
|
bc57b549d5 | ||
|
|
eed64e0f60 | ||
|
|
a673050489 | ||
|
|
d07890112d | ||
|
|
9cbd7fb6b7 | ||
|
|
5055c89cde | ||
|
|
eb04cab549 | ||
|
|
db2e56a382 | ||
|
|
71313afb01 | ||
|
|
039f2f7b8a | ||
|
|
b34c7b3cec | ||
|
|
40e1fb1f02 | ||
|
|
9292a46a86 | ||
|
|
fbb7e0f103 | ||
|
|
c6b6187fe8 | ||
|
|
937929c3c5 | ||
|
|
04534e18c3 | ||
|
|
6a3adee315 | ||
|
|
dddea9c022 | ||
|
|
a5029f22ad | ||
|
|
e425ae4ce3 | ||
|
|
48163610a4 | ||
|
|
78fc37c2d7 | ||
|
|
61aceb3fe8 | ||
|
|
2ccb2a470f | ||
|
|
849ea169a2 | ||
|
|
da7ae22535 | ||
|
|
fbd8d9fffa | ||
|
|
df10bdcc65 | ||
|
|
da1ada5a10 | ||
|
|
21f083dda1 | ||
|
|
e7882d1be8 | ||
|
|
81ed3a441f | ||
|
|
41381f498e | ||
|
|
e669a995a7 | ||
|
|
aad10a1146 | ||
|
|
eb4455797a | ||
|
|
02f1e68522 | ||
|
|
933d5f1e48 | ||
|
|
50e2fa95bf | ||
|
|
c908e6dc21 | ||
|
|
ccbe2afffb | ||
|
|
3d94259160 | ||
|
|
ee6d596493 | ||
|
|
8c608b60bd | ||
|
|
2b5e7d98c8 | ||
|
|
ee6e879c08 | ||
|
|
639084806a | ||
|
|
74a929d0ad | ||
|
|
5caffcb49a | ||
|
|
ce73d3c0e7 | ||
|
|
a0b59aecc8 | ||
|
|
3758a99ae2 | ||
|
|
1f45f5c3e5 | ||
|
|
937dc93366 | ||
|
|
b4dffedd09 | ||
|
|
ae1e16ca8b | ||
|
|
775482ea0f | ||
|
|
6fa848f730 | ||
|
|
6a1d720f08 | ||
|
|
7d72af0e44 | ||
|
|
ef1a34bdec | ||
|
|
c30334d2af | ||
|
|
da71fc0af9 | ||
|
|
f5ff4702e5 | ||
|
|
257031827d | ||
|
|
5e9c6f43fe | ||
|
|
bfc76290a7 | ||
|
|
4d8139bb3e | ||
|
|
77cc783855 | ||
|
|
d01605ee47 | ||
|
|
8128f3e4af | ||
|
|
10436a55bb | ||
|
|
740bf63afa | ||
|
|
9508f34cc2 | ||
|
|
10de3a42f4 | ||
|
|
407008284b | ||
|
|
e2fd877e91 | ||
|
|
ca16f618d8 | ||
|
|
80731117a3 | ||
|
|
dc62ef0989 | ||
|
|
13209e7a79 | ||
|
|
8edb7b194a | ||
|
|
354b5f83b2 | ||
|
|
5e568c68c4 | ||
|
|
5cc9678b5a | ||
|
|
ae5a5973aa | ||
|
|
5a589b2297 | ||
|
|
e6bc14fca5 | ||
|
|
95d67a270b | ||
|
|
559d5a2d9b | ||
|
|
a60bffa04d | ||
|
|
1a5dd75157 | ||
|
|
f5113d3d45 | ||
|
|
cddd2dbeb7 | ||
|
|
10da7c9eeb | ||
|
|
e50bbf4620 | ||
|
|
fe1b6dc0e5 | ||
|
|
a20acf5378 | ||
|
|
1d74640d67 | ||
|
|
20e3f908f9 | ||
|
|
8b2a499d20 | ||
|
|
d8ba5ffaea | ||
|
|
608c617b17 | ||
|
|
50d47a0c65 | ||
|
|
1d41072767 | ||
|
|
2ffd7f479b | ||
|
|
38f1e4f21d | ||
|
|
33f29b5694 | ||
|
|
4b6901467f | ||
|
|
62dc420d55 | ||
|
|
d7cb52d785 | ||
|
|
67bdd98a5b | ||
|
|
ffa0da8f1c | ||
|
|
abb2378bf2 | ||
|
|
d10c6ffb78 | ||
|
|
e2b4fdf72f | ||
|
|
993c665445 | ||
|
|
607b95b723 | ||
|
|
8476e72e9a | ||
|
|
57b782d7d7 | ||
|
|
2dd3b04dbe | ||
|
|
38d6ac3972 | ||
|
|
360b961221 | ||
|
|
ef22ede56d | ||
|
|
afa18b81fe | ||
|
|
ec9ea799cf | ||
|
|
99f762ff18 | ||
|
|
2bd59ff554 | ||
|
|
53157a7c06 | ||
|
|
bfc39ab172 | ||
|
|
fa44192bd3 | ||
|
|
53fc434bdd | ||
|
|
b6152372a8 | ||
|
|
5441d2bd96 | ||
|
|
2d358f76c0 | ||
|
|
d1cbaa3ef6 | ||
|
|
29513d953d | ||
|
|
365ec3d6f5 | ||
|
|
d4babddc31 | ||
|
|
648b656dd4 | ||
|
|
b2b71144d9 | ||
|
|
17357345ab | ||
|
|
f696fc2160 | ||
|
|
b9885c1249 | ||
|
|
e357f370e0 | ||
|
|
d777ac84f0 | ||
|
|
5da627b1b6 | ||
|
|
8ee063daec | ||
|
|
ad46149bb6 | ||
|
|
528226401f | ||
|
|
97a71958e1 | ||
|
|
b15d5f0633 | ||
|
|
b4e39ca985 | ||
|
|
5aae2cccdc | ||
|
|
c7ccd48037 | ||
|
|
2b6c904fbf | ||
|
|
eeefea3f6a | ||
|
|
2840c29a90 | ||
|
|
862e631405 | ||
|
|
f00737b0f0 | ||
|
|
2d4d1d3136 | ||
|
|
04d255bb54 | ||
|
|
f77db9c760 | ||
|
|
9cde35aa2f | ||
|
|
13ca53140c | ||
|
|
bc1d0722fa | ||
|
|
6201342ca7 | ||
|
|
801e0a2749 | ||
|
|
10718e6d03 | ||
|
|
03203345c0 | ||
|
|
3ade0952e2 | ||
|
|
f0e30d47dc | ||
|
|
bb94510858 | ||
|
|
c9d94619dd | ||
|
|
7ab8749421 | ||
|
|
a9216cc82c | ||
|
|
f14ef643b8 | ||
|
|
cc876d2f21 | ||
|
|
0f8693add2 | ||
|
|
dcc9d18dbe | ||
|
|
f579aa0088 | ||
|
|
579b945fbd | ||
|
|
664bea8109 |
No files matched your search
@@ -9,7 +9,7 @@ body:
|
||||
Please make sure you've checked the following things first:
|
||||
|
||||
- You're using the latest release of AdvancedServerList [[Download from Modrinth](https://modrinth.com/plugin/advancedserverlist)] and the right API version.
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19.x supported.
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19+ supported.
|
||||
- The Feature you suggest hasn't been suggested before.
|
||||
- type: dropdown
|
||||
attributes:
|
||||
|
||||
@@ -9,7 +9,7 @@ body:
|
||||
Please make sure you've checked the following things first:
|
||||
|
||||
- You're using the latest release of AdvancedServerList [[Download from Modrinth](https://modrinth.com/plugin/advancedserverlist)]
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19.x supported.
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19+ supported.
|
||||
- The issue happens with just AdvancedServerList installed.
|
||||
- type: dropdown
|
||||
attributes:
|
||||
|
||||
@@ -5,4 +5,4 @@ contact_links:
|
||||
url: https://discord.gg/6dazXp6
|
||||
- name: Wiki
|
||||
about: Check the Wiki for explanations about the features and examples.
|
||||
url: https://github.com/Andre601/AdvancedServerList/wiki
|
||||
url: https://docs.andre601.ch/AdvancedServerList
|
||||
@@ -9,7 +9,7 @@ body:
|
||||
Please make sure you've checked the following things first:
|
||||
|
||||
- You're using the latest release of AdvancedServerList [[Download from Modrinth](https://modrinth.com/plugin/advancedserverlist)]
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19.x supported.
|
||||
- You're using a supported Proxy/Server version. As of right now is only 1.19+ supported.
|
||||
- The Feature you suggest hasn't been suggested before.
|
||||
- type: dropdown
|
||||
attributes:
|
||||
|
||||
+30
-14
@@ -4,19 +4,19 @@ AdvancedServerList is a plugin that allowys you to customize your server's MOTD,
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/spigot_vector.svg" width="64" alt="platform-spigot" title="Tested on Spigot">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/spigot_vector.svg&w=64 alt="platform-spigot" title="Tested on Spigot">
|
||||
</a>
|
||||
<a href="https://papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/paper_vector.svg" width="64" alt="platform-paper" title="Tested on Paper">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/paper_vector.svg&w=64 alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/bungeecord_vector.svg" width="64" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/bungeecord_vector.svg&w=64 alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
</a>
|
||||
<a href="https://www.papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/waterfall_vector.svg" width="64" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/waterfall_vector.svg&w=64 alt="platform-waterfall" title="Tested on Waterfall">
|
||||
</a>
|
||||
<a href="https://velocitypowered.com" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/velocity_vector.svg" width="64" alt="platform-velocity" title="Tested on Velocity">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/velocity_vector.svg&w=64 alt="platform-velocity" title="Tested on Velocity">
|
||||
</a>
|
||||
|
||||
## What is a Server List Profile?
|
||||
@@ -24,12 +24,14 @@ A Server List Profile refers to a YAML file located in the plugin's `profiles` d
|
||||
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
|
||||
|
||||
> [*Read More*][profiles]
|
||||
|
||||
### Conditions
|
||||
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
|
||||
|
||||
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
|
||||
|
||||
> [*Read More*][conditions]
|
||||
|
||||
### Placeholders
|
||||
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
|
||||
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
|
||||
@@ -37,17 +39,20 @@ The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlu
|
||||
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
|
||||
|
||||
> [*Read More*][placeholders]
|
||||
|
||||
### Formatting
|
||||
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
|
||||
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
|
||||
|
||||
> [*Read More*][minimessage]
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Platforms | Required? |
|
||||
| ---------------- | ------------- | --------- |
|
||||
|------------------|---------------|-----------|
|
||||
| [ProtocolLib] | Spigot | Yes |
|
||||
| [PlaceholderAPI] | Spigot, Paper | No |
|
||||
| [ViaVersion] | Spigot, Paper | No |
|
||||
|
||||
## Statistics
|
||||
|
||||
@@ -58,31 +63,42 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
- [Paper/Spigot][bstats-spigot]
|
||||
- [Velocity][bstats-velocity]
|
||||
|
||||
## Videos
|
||||
Do you have your own video to share? Contact me and I will add it to this section.
|
||||
|
||||
<details><summary>Click to Show/Hide Videos</summary>
|
||||
|
||||
Spanish Video by Ajneb97
|
||||
<iframe width="560" height="auto" src="https://www.youtube.com/embed/rIbljm_4HVI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
|
||||
</details>
|
||||
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/modrinth-gallery_vector.svg" width="208" alt="gallery" title="Check out the Gallery">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/modrinth-gallery_vector.svg&w=208" alt="gallery" title="Check out the Gallery">
|
||||
</a>
|
||||
|
||||
## Support
|
||||
<a href="https://discord.gg/6dazXp6" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/discord-singular_vector.svg" width="64" alt="discord" title="Join my Discord Server">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/discord-singular_vector.svg&w=64" alt="discord" title="Join my Discord Server">
|
||||
</a>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/revolt-singular_vector.svg" width="64" alt="revolt" title="Join my Revolt Server">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/revolt-singular_vector.svg&w=64" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/mastodon-singular_vector.svg" width="64" alt="revolt" title="Chat with me on Mastodon">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/mastodon-singular_vector.svg&w=64" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
|
||||
<!-- Links -->
|
||||
[profiles]: https://andre601.ch/AdvancedServerList/profiles
|
||||
[conditions]: https://andre601.ch/AdvancedServerList/profiles/#conditions
|
||||
[placeholders]: https://andre601.ch/AdvancedServerList/profiles/placeholders
|
||||
[minimessage]: https://andre601.ch/AdvancedServerList/profiles/formatting
|
||||
[profiles]: https://docs.andre601.ch/AdvancedServerList/latest/profiles
|
||||
[conditions]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/#conditions
|
||||
[placeholders]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/placeholders
|
||||
[minimessage]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/formatting
|
||||
|
||||
[protocollib]: https://www.spigotmc.org/resources/1997/
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
[viaversion]: https://www.spigotmc.org/resources/19254/
|
||||
|
||||
[bstats]: https://bstats.org
|
||||
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<!-- pr-build comment -->
|
||||
|
||||
![badge]
|
||||
|
||||
Building jar file from Pull request. Please wait...
|
||||
|
||||
[badge]: https://img.shields.io/badge/Building...-0d1117?style=for-the-badge&labelColor=7a8490&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNNC43NSAyaDE0LjVhLjc1Ljc1IDAgMCAxIDAgMS41aC0uNzV2Mi45ODJhNC43NSA0Ljc1IDAgMCAxLTIuMjE1IDQuMDE3bC0yLjA0NCAxLjI5YS4yNS4yNSAwIDAgMCAwIC40MjJsMi4wNDQgMS4yOWE0Ljc1IDQuNzUgMCAwIDEgMi4yMTUgNC4wMTdWMjAuNWguNzVhLjc1Ljc1IDAgMCAxIDAgMS41SDQuNzVhLjc1Ljc1IDAgMCAxIDAtMS41aC43NXYtMi45ODJhNC43NSA0Ljc1IDAgMCAxIDIuMjE1LTQuMDE3bDIuMDQ0LTEuMjlhLjI1LjI1IDAgMCAwIDAtLjQyMmwtMi4wNDQtMS4yOUE0Ljc1IDQuNzUgMCAwIDEgNS41IDYuNDgyVjMuNWgtLjc1YS43NS43NSAwIDAgMSAwLTEuNVpNMTcgMy41SDd2Mi45ODJBMy4yNSAzLjI1IDAgMCAwIDguNTE2IDkuMjNsMi4wNDQgMS4yOWExLjc1IDEuNzUgMCAwIDEgMCAyLjk2bC0yLjA0NCAxLjI5QTMuMjUgMy4yNSAwIDAgMCA3IDE3LjUxOFYyMC41aDEwdi0yLjk4MmEzLjI1IDMuMjUgMCAwIDAtMS41MTYtMi43NDhsLTIuMDQ0LTEuMjlhMS43NSAxLjc1IDAgMCAxIDAtMi45NmwyLjA0NC0xLjI5QTMuMjUgMy4yNSAwIDAgMCAxNyA2LjQ4MloiPjwvcGF0aD48L3N2Zz4=
|
||||
@@ -0,0 +1,12 @@
|
||||
<!-- pr-build comment -->
|
||||
![badge]
|
||||
|
||||
**Compiling of jar files failed!**
|
||||
Please check the logs below for any errors.
|
||||
|
||||
| Name | Link |
|
||||
| ------ | -------------------------------- |
|
||||
| Commit | {{ .commit }} |
|
||||
| Logs | {{ .logs | mdlink "View Logs" }} |
|
||||
|
||||
[badge]: https://img.shields.io/badge/Build_Failure!-0d1117?style=for-the-badge&labelColor=f85149&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNNS43MiA1LjcyYS43NS43NSAwIDAgMSAxLjA2IDBMMTIgMTAuOTRsNS4yMi01LjIyYS43NDkuNzQ5IDAgMCAxIDEuMjc1LjMyNi43NDkuNzQ5IDAgMCAxLS4yMTUuNzM0TDEzLjA2IDEybDUuMjIgNS4yMmEuNzQ5Ljc0OSAwIDAgMS0uMzI2IDEuMjc1Ljc0OS43NDkgMCAwIDEtLjczNC0uMjE1TDEyIDEzLjA2bC01LjIyIDUuMjJhLjc1MS43NTEgMCAwIDEtMS4wNDItLjAxOC43NTEuNzUxIDAgMCAxLS4wMTgtMS4wNDJMMTAuOTQgMTIgNS43MiA2Ljc4YS43NS43NSAwIDAgMSAwLTEuMDZaIj48L3BhdGg+PC9zdmc+
|
||||
@@ -0,0 +1,15 @@
|
||||
<!-- pr-build comment -->
|
||||
![badge]
|
||||
|
||||
The compiling of the jar files was successful!
|
||||
You can find a direct download for the artifact below.
|
||||
|
||||
File expires: `{{ .expire | date "02 Jan 2006 15:04 MST" }}`
|
||||
|
||||
| Name | Link |
|
||||
| -------- | -------------------------------------------- |
|
||||
| Commit | {{ .commit }} |
|
||||
| Logs | {{ .logs | mdlink "View Logs" }} |
|
||||
| Download | {{ .download | mdlink "Download Artifact" }} |
|
||||
|
||||
[badge]: https://img.shields.io/badge/Build_Success!-0d1117?style=for-the-badge&labelColor=3fb950&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNMjEuMDMgNS43MmEuNzUuNzUgMCAwIDEgMCAxLjA2bC0xMS41IDExLjVhLjc0Ny43NDcgMCAwIDEtMS4wNzItLjAxMmwtNS41LTUuNzVhLjc1Ljc1IDAgMSAxIDEuMDg0LTEuMDM2bDQuOTcgNS4xOTVMMTkuOTcgNS43MmEuNzUuNzUgMCAwIDEgMS4wNiAwWiI+PC9wYXRoPjwvc3ZnPg==
|
||||
@@ -1,58 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: maven
|
||||
directory: "/bungeecord"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: BungeeCord'
|
||||
- package-ecosystem: maven
|
||||
directory: "/core"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: Core'
|
||||
- package-ecosystem: maven
|
||||
directory: "/paper"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: PaperMC'
|
||||
- package-ecosystem: maven
|
||||
directory: "/spigot"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: Spigot'
|
||||
- package-ecosystem: maven
|
||||
directory: "/velocity"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: Velocity'
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: GitHub Action'
|
||||
- package-ecosystem: pip
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: MkDocs'
|
||||
@@ -0,0 +1,14 @@
|
||||
"Target: All":
|
||||
- all: ["bukkit/**", "bungeecord/**", "core/**", "velocity/**"]
|
||||
|
||||
"Target: Bukkit":
|
||||
- all: ["bukkit/**", "!bungeecord/**", "!core/**", "!velocity/**"]
|
||||
|
||||
"Target: BungeeCord":
|
||||
- all: ["!bukkit/**", "bungeecord/**", "!core/**", "!velocity/**"]
|
||||
|
||||
"Target: Core":
|
||||
- all: ["!bukkit/**", "!bungeecord/**", "core/**", "!velocity/**"]
|
||||
|
||||
"Target: Velocity":
|
||||
- all: ["!bukkit/**", "!bungeecord/**", "!core/**", "velocity/**"]
|
||||
@@ -2,22 +2,27 @@ name: 'Deploy Site (Push)'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
- 'mkdocs-theme/**'
|
||||
- 'requirements.txt'
|
||||
branches:
|
||||
- master
|
||||
tags-ignore:
|
||||
- '**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
GITHUB_REPO_INSTANCE: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
@@ -31,5 +36,14 @@ jobs:
|
||||
run: |
|
||||
python -m pip install --upgrade pip setuptools
|
||||
python -m pip install -r requirements.txt
|
||||
- name: Deploy Files
|
||||
run: mkdocs gh-deploy --force
|
||||
- name: Build docs
|
||||
run: mkdocs build
|
||||
- name: Configure GitHub Pages
|
||||
uses: actions/configure-pages@v3
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v2
|
||||
with:
|
||||
path: 'site/'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v2
|
||||
@@ -1,88 +0,0 @@
|
||||
name: 'Build PR changes'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
paths:
|
||||
- 'bukkit/src/**'
|
||||
- 'bungeecord/src/**'
|
||||
- 'core/src/**'
|
||||
- 'velocity/src/**'
|
||||
|
||||
concurrency: 'pr-preview'
|
||||
|
||||
jobs:
|
||||
buildJars:
|
||||
name: 'Build Jars from Pull request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v3
|
||||
- name: 'Setup Java 16'
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '16'
|
||||
cache: 'maven'
|
||||
- name: 'Build Jar files'
|
||||
run: mvn clean install
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-files
|
||||
path: '*/target/AdvancedServerList-*.jar'
|
||||
if-no-files-found: error
|
||||
updateCommentSuccess:
|
||||
name: 'Create or update Comment (On Success).'
|
||||
needs: [buildJars]
|
||||
if: success()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Find comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
- name: Update Comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
body: |-
|
||||
## Build Preview
|
||||
|
||||
Below is a URL to the Jar files made using this Pull request.
|
||||
Please note that artifacts build by this GitHub Action only exist for at most 90 days since last run!
|
||||
|
||||
| Name | Link |
|
||||
|-----------|-------------------------------------------------------------------------------------|
|
||||
| Commit | ${{ github.event.pull_request.head.sha }} |
|
||||
| Logs | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
|
||||
| Jar Files | <!-- What can I put here? --> |
|
||||
UpdateCommentFailure:
|
||||
name: 'Create or update Comment (On Success).'
|
||||
needs: [buildJars]
|
||||
if: failure()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Find comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
- name: Update Comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
body: |-
|
||||
## Build Preview
|
||||
|
||||
There was an issue generating the Jar files from your Pull request.
|
||||
Please review the logs linked below for further information.
|
||||
|
||||
| Name | Link |
|
||||
|--------|-------------------------------------------------------------------------------------|
|
||||
| Commit | ${{ github.event.pull_request.head.sha }} |
|
||||
| Logs | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
|
||||
@@ -1,131 +0,0 @@
|
||||
#
|
||||
# Big thank you to @Kir-Antipov for providing this workflow file.
|
||||
# Check out his mc-publish action here: https://github.com/Kir-Antipov/mc-publish
|
||||
#
|
||||
|
||||
name: Publish Assets
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
buildJars:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
plugin_release: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Get Version from Release
|
||||
id: github-release
|
||||
run: |
|
||||
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
|
||||
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
|
||||
- name: Set up JDK 1.16
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '16'
|
||||
cache: 'maven'
|
||||
- name: Build Jar files
|
||||
run: mvn clean install
|
||||
- name: Save All files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-files
|
||||
path: |
|
||||
*/target/AdvancedServerList-*.jar
|
||||
hangar-uploader/target/HangarUploader.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
publish:
|
||||
needs: [buildJars]
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- platforms: BungeeCord, Waterfall
|
||||
directory: bungeecord
|
||||
loaders: |
|
||||
bungeecord
|
||||
waterfall
|
||||
- platforms: Spigot, Paper
|
||||
directory: bukkit
|
||||
loaders: |
|
||||
spigot
|
||||
paper
|
||||
- platforms: Velocity
|
||||
directory: velocity
|
||||
loaders: velocity
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get Jar files
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: asl-files
|
||||
- name: Upload AdvancedServerList v${{ needs.buildJars.outputs.plugin_release }} (${{ matrix.loaders }}) to GitHub and Modrinth
|
||||
if: '!github.event.release.prerelease'
|
||||
uses: Kir-Antipov/mc-publish@v3.2
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
|
||||
version: ${{ needs.buildJars.outputs.plugin_release }}
|
||||
version-type: release
|
||||
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
|
||||
files-secondary: ""
|
||||
loaders: ${{ matrix.loaders }}
|
||||
version-resolver: releases
|
||||
game-versions: |
|
||||
1.19
|
||||
1.19.1
|
||||
1.19.2
|
||||
1.19.3
|
||||
1.19.4
|
||||
java: 16
|
||||
modrinth-id: xss83sOY
|
||||
modrinth-featured: false
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload AdvancedServerList v${{ needs.buildJars.outputs.plugin_release }} (${{ matrix.loaders }}) to GitHub and Modrinth [Pre-Release]
|
||||
if: 'github.event.release.prerelease'
|
||||
uses: Kir-Antipov/mc-publish@v3.2
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
|
||||
version: ${{ needs.buildJars.outputs.plugin_release }}
|
||||
version-type: beta
|
||||
files: ${{ matrix.directory }}/target/AdvancedServerList-*.jar
|
||||
files-secondary: ""
|
||||
loaders: ${{ matrix.loaders }}
|
||||
version-resolver: releases
|
||||
game-versions: |
|
||||
1.19
|
||||
1.19.1
|
||||
1.19.2
|
||||
1.19.3
|
||||
1.19.4
|
||||
java: 16
|
||||
modrinth-id: xss83sOY
|
||||
modrinth-featured: false
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publishHangar:
|
||||
needs: [buildJars]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up JDK 1.16
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '16'
|
||||
- name: Download Release Assets
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: asl-files
|
||||
- name: Move HangarUploader.jar
|
||||
working-directory: hangar-uploader/target/
|
||||
run: mv HangarUploader.jar ../../
|
||||
- name: Execute HangarUploader.jar
|
||||
run: java -jar HangarUploader.jar ${{ secrets.HANGAR_TOKEN }} ${{ needs.buildJars.outputs.plugin_release }} ${{ github.event.release.prerelease }}
|
||||
env:
|
||||
GITHUB_RELEASE_BODY: ${{ github.event.release.body }}
|
||||
@@ -2,3 +2,4 @@
|
||||
/.idea/
|
||||
/**/dependency-reduced-pom.xml
|
||||
/**/target/
|
||||
/**/__pycache__/
|
||||
@@ -0,0 +1,33 @@
|
||||
when:
|
||||
- event: tag
|
||||
branch: master
|
||||
|
||||
steps:
|
||||
createFiles:
|
||||
image: maven:3.9.5-eclipse-temurin-17
|
||||
secrets:
|
||||
- source: cb_token
|
||||
target: codeberg_api_token
|
||||
- source: modrinth_api_token
|
||||
target: modrinth_api_token
|
||||
- source: hangar_api_token
|
||||
target: hangar_api_token
|
||||
commands:
|
||||
# Create the jar files.
|
||||
- mvn clean install
|
||||
# Move VersionUploader jar file
|
||||
- cd version-uploader/target/
|
||||
- mv VersionUploader.jar ../../
|
||||
- cd ../../
|
||||
# Execute Jar file
|
||||
- java -jar VersionUploader.jar --modrinth
|
||||
uploadToCodeberg:
|
||||
image: woodpeckerci/plugin-gitea-release
|
||||
settings:
|
||||
base_url: https://codeberg.org
|
||||
files:
|
||||
- "bungeecord/target/AdvancedServerList-*.jar"
|
||||
- "paper/target/AdvancedServerList-*.jar"
|
||||
- "velocity/target/AdvancedServerList-*.jar"
|
||||
api_key:
|
||||
from_secret: CB_TOKEN
|
||||
@@ -0,0 +1,36 @@
|
||||
when:
|
||||
- branch: master
|
||||
event: push
|
||||
path:
|
||||
include: ['requirements.txt', 'mkdocs.yml', 'docs/**']
|
||||
|
||||
variables:
|
||||
setup_git: &setup_git
|
||||
- apk add git
|
||||
- git config --global user.email "github@andre601.ch"
|
||||
- git config --global user.name "ASL Docs Builder"
|
||||
|
||||
steps:
|
||||
cloneTargetRepo:
|
||||
image: alpine:3.18.4
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- <<: *setup_git
|
||||
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
|
||||
- chmod -R a+w site
|
||||
buildDocs:
|
||||
image: woodpeckerci/plugin-mkdocs:latest
|
||||
settings:
|
||||
pip_install_file: requirements.txt
|
||||
commitAndPush:
|
||||
image: alpine:3.18.4
|
||||
secrets:
|
||||
- cb_token
|
||||
commands:
|
||||
- <<: *setup_git
|
||||
- mv domains site/.domains
|
||||
- cd site
|
||||
- git remote set-url origin https://$CB_TOKEN@codeberg.org/Andre601/AdvancedServerList.git
|
||||
- git add --all
|
||||
- git commit -m "Update AdvancedServerList Docs ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
|
||||
- git push
|
||||
@@ -3,23 +3,19 @@
|
||||
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
|
||||
|
||||
## Downloads
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg" height="46" alt="modrinth" title="Available on Modrinth">
|
||||
</a>
|
||||
<br>
|
||||
<!--
|
||||
<a href="https://hangar.papermc.io/Andre_601/AdvancedServerList" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg" height="46" alt="hangar" title="Available on Hangar">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://www.spigotmc.org/resources/102910" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@b9ff12b/assets/compact/available/spigot_vector.svg" height="46" alt="spigot" title="Available on SpigotMC">
|
||||
</a>
|
||||
-->
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
|
||||
</a>
|
||||
<a href="https://papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
@@ -47,10 +43,10 @@ When multiple profiles exist that have valid conditions will the one with the hi
|
||||
> [*Read More*][conditions]
|
||||
|
||||
### Placeholders
|
||||
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
|
||||
Placeholders can be used within conditions to further customize them. They can also be used in any other text option to display their respective values.
|
||||
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
|
||||
|
||||
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
|
||||
When using the SpigotMC/PaperMC version, or while PAPIProxyBridge is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
|
||||
|
||||
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
|
||||
|
||||
@@ -64,11 +60,14 @@ Only certain options are usable for each option. As an example does motd support
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Platforms | Required? |
|
||||
|------------------|---------------|-----------|
|
||||
| [ProtocolLib] | Spigot | Yes |
|
||||
| [PlaceholderAPI] | Spigot, Paper | No |
|
||||
| [ViaVersion] | Spigot, Paper | No |
|
||||
All listed dependencies are optional.
|
||||
|
||||
| Dependency | Platforms |
|
||||
|-------------------|----------------------|
|
||||
| [PlaceholderAPI] | Paper |
|
||||
| [ViaVersion] | Paper |
|
||||
| [PAPIProxyBridge] | BungeeCord, Velocity |
|
||||
| [Maintenance] | All |
|
||||
|
||||
## Statistics
|
||||
|
||||
@@ -86,6 +85,7 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
</a>
|
||||
|
||||
## Support
|
||||
|
||||
<a href="https://discord.gg/6dazXp6" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
|
||||
</a>
|
||||
@@ -97,16 +97,17 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
</a>
|
||||
|
||||
<!-- Links -->
|
||||
[profiles]: https://www.andre601.ch/AdvancedServerList/profiles/
|
||||
[conditions]: https://www.andre601.ch/AdvancedServerList/profiles/#conditions
|
||||
[placeholders]: https://www.andre601.ch/AdvancedServerList/profiles/placeholders/
|
||||
[minimessage]: https://www.andre601.ch/AdvancedServerList/profiles/formatting/
|
||||
[profiles]: https://asl.andre601.ch/profiles/
|
||||
[conditions]: https://asl.andre601.ch/profiles/#conditions
|
||||
[placeholders]: https://asl.andre601.ch/profiles/placeholders/
|
||||
[minimessage]: https://asl.andre601.ch/profiles/formatting/
|
||||
|
||||
[modrinth]: https://modrinth.com/plugin/advancedserverlist
|
||||
|
||||
[protocollib]: https://www.spigotmc.org/resources/1997/
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
[viaversion]: https://www.spigotmc.org/resources/19254/
|
||||
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
|
||||
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
|
||||
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
|
||||
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
|
||||
|
||||
[bstats]: https://bstats.org
|
||||
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
|
||||
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bukkit.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.paper.commands.PaperCmdSender;
|
||||
import ch.andre601.advancedserverlist.spigot.commands.SpigotCmdSender;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class CmdAdvancedServerList extends Command implements CommandExecutor{
|
||||
|
||||
private final PluginCore<?> plugin;
|
||||
private final BukkitAudiences audiences;
|
||||
|
||||
public CmdAdvancedServerList(PluginCore<?> plugin){
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public CmdAdvancedServerList(PluginCore<?> plugin, BukkitAudiences audiences){
|
||||
super(
|
||||
"advancedserverlist",
|
||||
"Main command of the plugin",
|
||||
"/asl [reload|help]",
|
||||
Collections.singletonList("asl")
|
||||
);
|
||||
|
||||
this.plugin = plugin;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args){
|
||||
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args){
|
||||
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
|
||||
return true;
|
||||
}
|
||||
|
||||
private CmdSender getSender(CommandSender sender){
|
||||
return audiences == null ? new PaperCmdSender(sender) : new SpigotCmdSender(sender, audiences);
|
||||
}
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bukkit.objects;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.spigot.objects.SpigotPlayer;
|
||||
|
||||
public class BukkitPlayerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
public BukkitPlayerPlaceholders(){
|
||||
super("player");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
SpigotPlayer bukkitPlayer = (SpigotPlayer)player;
|
||||
|
||||
return switch(placeholder){
|
||||
case "name" -> bukkitPlayer.getName();
|
||||
case "protocol" -> String.valueOf(bukkitPlayer.getProtocol());
|
||||
case "uuid" -> bukkitPlayer.getUUID().toString();
|
||||
case "hasPlayedBefore" -> returnValue(bukkitPlayer, bukkitPlayer.hasPlayedBefore());
|
||||
case "isBanned" -> returnValue(bukkitPlayer, bukkitPlayer.isBanned());
|
||||
case "isWhitelisted" -> returnValue(bukkitPlayer, bukkitPlayer.isWhitelisted());
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String returnValue(SpigotPlayer player, Object value){
|
||||
return player.getPlayer() == null ? null : String.valueOf(value);
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot;
|
||||
|
||||
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.BukkitPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.spigot.events.LoadEvent;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPing.CompressedImage>{
|
||||
|
||||
private final PluginLogger logger = new BukkitLogger(getLogger());
|
||||
|
||||
private AdvancedServerList core;
|
||||
FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
try{
|
||||
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
|
||||
|
||||
printPaperInfo();
|
||||
}catch(ClassNotFoundException ex){
|
||||
try{
|
||||
// Above class only exists since 1.19+, so this is a fallback for older versions.
|
||||
Class.forName("com.destroystokyo.paper.PaperConfig");
|
||||
|
||||
printPaperInfo();
|
||||
}catch(ClassNotFoundException ignored){}
|
||||
}
|
||||
|
||||
this.core = new AdvancedServerList(this, new BukkitPlayerPlaceholders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable(){
|
||||
getCore().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommands(){
|
||||
PluginCommand cmd = getServer().getPluginCommand("advancedserverlist");
|
||||
if(cmd == null){
|
||||
getPluginLogger().warn("Unable to register command /advancedserverlist");
|
||||
return;
|
||||
}
|
||||
cmd.setExecutor(new CmdAdvancedServerList(this, BukkitAudiences.create(this)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadEvents(){
|
||||
new LoadEvent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMetrics(){
|
||||
new Metrics(this, 15584).addCustomChart(new SimplePie("profiles",
|
||||
() -> String.valueOf(core.getFileHandler().getProfiles().size())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFaviconCache(){
|
||||
if(faviconHandler == null)
|
||||
return;
|
||||
|
||||
faviconHandler.clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList getCore(){
|
||||
return core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFolderPath(){
|
||||
return getDataFolder().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginLogger getPluginLogger(){
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaviconHandler<WrappedServerPing.CompressedImage> getFaviconHandler(){
|
||||
if(faviconHandler == null)
|
||||
faviconHandler = new FaviconHandler<>(core);
|
||||
|
||||
return faviconHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName(){
|
||||
return getServer().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion(){
|
||||
return getServer().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoader(){
|
||||
return "spigot";
|
||||
}
|
||||
|
||||
private void printPaperInfo(){
|
||||
getPluginLogger().warn("======================================================================================");
|
||||
getPluginLogger().warn("You are using the Spigot version of AdvancedServerList on a Paper server.");
|
||||
getPluginLogger().warn("It is recommended to use the dedicated Paper version, to benefit from the");
|
||||
getPluginLogger().warn("following improvements:");
|
||||
getPluginLogger().warn(" - No need to download external libraries already provided by PaperMC.");
|
||||
getPluginLogger().warn(" - No dependency on ProtocolLib thanks to provided Events.");
|
||||
getPluginLogger().warn("");
|
||||
getPluginLogger().warn("AdvancedServerList may work as normal, but consider using the PaperMC version instead!");
|
||||
getPluginLogger().warn("======================================================================================");
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.bukkit.events.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.PAPIPlaceholders;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerLoadEvent;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public class LoadEvent implements Listener{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
|
||||
public LoadEvent(SpigotCore plugin){
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerLoad(ServerLoadEvent event){
|
||||
PluginManager manager = plugin.getServer().getPluginManager();
|
||||
|
||||
if(!manager.isPluginEnabled("ProtocolLib")){
|
||||
plugin.getCore().getPlugin().getPluginLogger().warn("ProtocolLib not found! AdvancedServerList requires it to work on Spigot!");
|
||||
|
||||
manager.disablePlugin(plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
manager.registerEvents(new JoinEvent(plugin), plugin);
|
||||
manager.registerEvents(new ProtocolLibEvents(plugin, ProtocolLibrary.getProtocolManager()), plugin);
|
||||
|
||||
if(manager.isPluginEnabled("PlaceholderAPI"))
|
||||
new PAPIPlaceholders(plugin);
|
||||
}
|
||||
}
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.bukkit.events.PreServerListSetEventImpl;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.SpigotPlayerImpl;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServerPing.CompressedImage, SpigotPlayerImpl>{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
private final PacketEvent event;
|
||||
private final WrappedServerPing ping;
|
||||
|
||||
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event){
|
||||
this.plugin = plugin;
|
||||
this.event = event;
|
||||
this.ping = event.getPacket().getServerPings().read(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServerListEvent callEvent(ProfileEntry entry){
|
||||
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
ping.setPlayersMaximum(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setMotD(AdventureComponentConverter.fromComponent(component));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayers(){
|
||||
ping.setPlayersVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerCount(String name){
|
||||
ping.setVersionName(name);
|
||||
ping.setVersionProtocol(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> lines, SpigotPlayerImpl player, GenericServer server){
|
||||
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
|
||||
|
||||
for(String line : lines){
|
||||
String parsed = ComponentParser.text(line)
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> {
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toString();
|
||||
|
||||
players.add(new WrappedGameProfile(UUID.randomUUID(), parsed));
|
||||
}
|
||||
|
||||
ping.setPlayers(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavicon(WrappedServerPing.CompressedImage favicon){
|
||||
ping.setFavicon(favicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFavicon(){
|
||||
ping.setFavicon(ping.getFavicon());
|
||||
}
|
||||
|
||||
// Not used in ProtocolLib
|
||||
@Override
|
||||
public void updateEvent(){
|
||||
event.getPacket().getServerPings().write(0, ping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return event.getPlayer().getAddress() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return ping.getVersionProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayers(){
|
||||
return ping.getPlayersOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPlayers(){
|
||||
return ping.getPlayersMaximum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerIP(){
|
||||
return event.getPlayer().getAddress() == null ? "UNKNOWN" : event.getPlayer().getAddress().getHostString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, SpigotPlayerImpl player){
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualHost(){
|
||||
String host = this.resolveHost(event.getPlayer().getAddress());
|
||||
if(host == null)
|
||||
return null;
|
||||
|
||||
return ProtocolLibEvents.getHostAddresses().get(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<WrappedServerPing.CompressedImage> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpigotPlayerImpl createPlayer(CachedPlayer player, int protocol){
|
||||
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
|
||||
return new SpigotPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedServerPing.CompressedImage createFavicon(BufferedImage image) throws Exception{
|
||||
return WrappedServerPing.CompressedImage.fromPng(image);
|
||||
}
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProtocolLibEvents implements Listener{
|
||||
|
||||
private final ProtocolManager protocolManager;
|
||||
|
||||
private static final Map<String, String> hostAddresses = new HashMap<>();
|
||||
|
||||
public ProtocolLibEvents(SpigotCore plugin, ProtocolManager protocolManager){
|
||||
this.protocolManager = protocolManager;
|
||||
|
||||
loadPacketListener(plugin);
|
||||
}
|
||||
|
||||
public static Map<String, String> getHostAddresses(){
|
||||
return hostAddresses;
|
||||
}
|
||||
|
||||
private void loadPacketListener(SpigotCore spigotPlugin){
|
||||
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Handshake.Client.SET_PROTOCOL){
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event){
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if(address == null)
|
||||
return;
|
||||
|
||||
String host = event.getPacket().getStrings().read(0);
|
||||
|
||||
hostAddresses.put(address.getHostString(), host);
|
||||
}
|
||||
});
|
||||
|
||||
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event){
|
||||
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -67,39 +67,39 @@
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.1</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.1</version>
|
||||
<type>javadoc</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bungeecord</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<version>4.3.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bungeecord</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -111,7 +111,7 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<version>4.12.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -133,7 +133,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
|
||||
+6
-5
@@ -26,10 +26,11 @@
|
||||
package ch.andre601.advancedserverlist.bungeecord;
|
||||
|
||||
import ch.andre601.advancedserverlist.bungeecord.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.bungeecord.events.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.events.PingEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.BungeePlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.BungeeServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
@@ -43,13 +44,13 @@ import java.nio.file.Path;
|
||||
|
||||
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
|
||||
private AdvancedServerList core;
|
||||
private AdvancedServerList<Favicon> core;
|
||||
private FaviconHandler<Favicon> faviconHandler = null;
|
||||
private final PluginLogger logger = new BungeeLogger(getLogger());
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
this.core = new AdvancedServerList(this, new BungeePlayerPlaceholders());
|
||||
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +86,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList getCore(){
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
}
|
||||
|
||||
|
||||
+40
-2
@@ -23,13 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.events;
|
||||
package ch.andre601.advancedserverlist.bungeecord.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.BungeePlayerImpl;
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.BungeeProxyImpl;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
@@ -40,11 +42,14 @@ import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePlayerImpl>{
|
||||
@@ -128,6 +133,14 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
return protocol == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenanceModeActive(){
|
||||
if(plugin.getProxy().getPluginManager().getPlugin("Maintenance") == null)
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return this.protocol.getProtocol();
|
||||
@@ -150,7 +163,25 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, BungeePlayerImpl player){
|
||||
return text;
|
||||
if(plugin.getProxy().getPluginManager().getPlugin("PAPIProxyBridge") == null)
|
||||
return text;
|
||||
|
||||
if(!PingEventHandler.getPAPIUtil().isCompatible())
|
||||
return text;
|
||||
|
||||
String server = PingEventHandler.getPAPIUtil().getServer();
|
||||
if(server == null || server.isEmpty())
|
||||
return text;
|
||||
|
||||
ServerInfo serverInfo = plugin.getProxy().getServerInfo(server);
|
||||
if(serverInfo == null || serverInfo.getPlayers().isEmpty())
|
||||
return text;
|
||||
|
||||
ProxiedPlayer carrier = PingEventHandler.getPAPIUtil().getPlayer(serverInfo.getPlayers());
|
||||
if(carrier == null)
|
||||
return text;
|
||||
|
||||
return PingEventHandler.getPAPIUtil().parse(text, carrier.getUniqueId(), player.getUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +199,13 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
return new BungeePlayerImpl(player, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
|
||||
Map<String, ServerInfo> servers = plugin.getProxy().getServers();
|
||||
|
||||
return new BungeeProxyImpl(servers, playersOnline, playersMax, host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
|
||||
return Favicon.create(image);
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.events;
|
||||
package ch.andre601.advancedserverlist.bungeecord.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.events;
|
||||
package ch.andre601.advancedserverlist.bungeecord.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
+2
-2
@@ -23,10 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bukkit.events;
|
||||
package ch.andre601.advancedserverlist.bungeecord.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bungeecord.events.PreServerListSetEvent;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.spigot.events.PreServerListSetEvent;
|
||||
|
||||
public class PreServerListSetEventImpl extends PreServerListSetEvent{
|
||||
|
||||
+5
-1
@@ -33,10 +33,14 @@ import java.util.Locale;
|
||||
|
||||
public class BungeePlayerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
public BungeePlayerPlaceholders(){
|
||||
private BungeePlayerPlaceholders(){
|
||||
super("player");
|
||||
}
|
||||
|
||||
public static BungeePlayerPlaceholders init(){
|
||||
return new BungeePlayerPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
return switch(placeholder.toLowerCase(Locale.ROOT)){
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record BungeeProxyImpl(Map<String, ServerInfo> servers, int playersOnline, int playersMax, String host) implements BungeeProxy{
|
||||
@Override
|
||||
public Map<String, ServerInfo> getServers(){
|
||||
return servers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayersOnline(){
|
||||
return playersOnline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayersMax(){
|
||||
return playersMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost(){
|
||||
return host;
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class BungeeServerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private BungeeServerPlaceholders(){
|
||||
super("server");
|
||||
}
|
||||
|
||||
public static BungeeServerPlaceholders init(){
|
||||
return new BungeeServerPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
if(!(server instanceof BungeeProxy proxy))
|
||||
return null;
|
||||
|
||||
String[] args = placeholder.split("\\s", 2);
|
||||
|
||||
return switch(args[0]){
|
||||
case "playersOnline" -> {
|
||||
if(args.length >= 2){
|
||||
String[] servers = args[1].split(",");
|
||||
|
||||
int players = 0;
|
||||
for(String serverName : servers){
|
||||
if(serverName.isEmpty())
|
||||
continue;
|
||||
|
||||
ServerInfo info = proxy.getServers().get(serverName);
|
||||
if(info == null)
|
||||
continue;
|
||||
|
||||
players += info.getPlayers().size();
|
||||
}
|
||||
|
||||
yield String.valueOf(players);
|
||||
}
|
||||
|
||||
yield String.valueOf(proxy.getPlayersOnline());
|
||||
}
|
||||
case "playersMax" -> {
|
||||
// ServerInfo doesn't provide the max players that could join, so we won't allow an extra argument
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
|
||||
yield String.valueOf(proxy.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length > 2)
|
||||
yield null;
|
||||
|
||||
if(args.length == 2){
|
||||
ServerInfo info = proxy.getServers().get(args[1]);
|
||||
|
||||
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
|
||||
}
|
||||
|
||||
yield proxy.getHost();
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,8 @@ author: 'Andre_601'
|
||||
version: '${plugin.version}'
|
||||
description: '${plugin.description}'
|
||||
|
||||
softDepends:
|
||||
- PAPIProxyBridge
|
||||
- Maintenance
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.bungeecord.BungeeCordCore'
|
||||
+27
-7
@@ -48,6 +48,14 @@
|
||||
<id>flexver-repo</id>
|
||||
<url>https://repo.sleeping.town/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>papiproxybridge-repo</id>
|
||||
<url>https://repo.william278.net/releases/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
@@ -66,19 +74,19 @@
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -90,19 +98,31 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<version>4.12.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.unascribed</groupId>
|
||||
<artifactId>flexver-java</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<version>32.1.3-jre</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>eu.kennytv.maintenance</groupId>
|
||||
<artifactId>maintenance-api</artifactId>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -132,7 +152,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
||||
@@ -31,17 +31,18 @@ import ch.andre601.advancedserverlist.core.check.UpdateChecker;
|
||||
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
|
||||
import ch.andre601.advancedserverlist.core.file.FileHandler;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.objects.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class AdvancedServerList{
|
||||
public class AdvancedServerList<F>{
|
||||
|
||||
private final PluginCore<?> plugin;
|
||||
private final PluginCore<F> plugin;
|
||||
private final FileHandler fileHandler;
|
||||
private final CommandHandler commandHandler;
|
||||
private final PlayerHandler playerHandler;
|
||||
@@ -51,19 +52,22 @@ public class AdvancedServerList{
|
||||
|
||||
private String version;
|
||||
|
||||
public AdvancedServerList(PluginCore<?> plugin, PlaceholderProvider player){
|
||||
private AdvancedServerList(PluginCore<F> plugin, List<PlaceholderProvider> placeholders){
|
||||
this.plugin = plugin;
|
||||
this.fileHandler = new FileHandler(this);
|
||||
this.commandHandler = new CommandHandler(this);
|
||||
this.playerHandler = new PlayerHandler(this);
|
||||
|
||||
this.api.addPlaceholderProvider(player);
|
||||
this.api.addPlaceholderProvider(new ServerPlaceholders());
|
||||
placeholders.forEach(this.api::addPlaceholderProvider);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
public PluginCore<?> getPlugin(){
|
||||
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
|
||||
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
|
||||
}
|
||||
|
||||
public PluginCore<F> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -121,6 +125,16 @@ public class AdvancedServerList{
|
||||
return;
|
||||
}
|
||||
|
||||
if(getFileHandler().isOldConfig()){
|
||||
getPlugin().getPluginLogger().info("Detected old config.yml. Attempting to migrate...");
|
||||
if(getFileHandler().migrateConfig()){
|
||||
getPlugin().getPluginLogger().info("Migration completed successfully!");
|
||||
}else{
|
||||
getPlugin().getPluginLogger().warn("Couldn't migrate config.yml! Check previous lines for errors.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(getFileHandler().loadProfiles()){
|
||||
getPlugin().getPluginLogger().info("Successfully loaded " + getFileHandler().getProfiles().size() + " profiles!");
|
||||
}else{
|
||||
@@ -149,7 +163,7 @@ public class AdvancedServerList{
|
||||
|
||||
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
|
||||
|
||||
if(getFileHandler().getBoolean("check_updates"))
|
||||
if(getFileHandler().getBoolean("checkUpdates"))
|
||||
this.updateChecker = new UpdateChecker(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.util.concurrent.ThreadFactory;
|
||||
public class UpdateCheckThread implements ThreadFactory{
|
||||
@Override
|
||||
public Thread newThread(@NotNull Runnable r){
|
||||
return new Thread(r, "AdvancedServerList Update-Thread");
|
||||
Thread t = new Thread(r, "AdvancedServerList-UpdateThread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class UpdateChecker{
|
||||
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=[\"%s\"]";
|
||||
private final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final AdvancedServerList<?> core;
|
||||
private final PluginLogger logger;
|
||||
private final String loader;
|
||||
|
||||
@@ -65,7 +65,7 @@ public class UpdateChecker{
|
||||
|
||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
|
||||
|
||||
public UpdateChecker(AdvancedServerList core){
|
||||
public UpdateChecker(AdvancedServerList<?> core){
|
||||
this.core = core;
|
||||
this.logger = core.getPlugin().getPluginLogger();
|
||||
this.loader = core.getPlugin().getLoader();
|
||||
|
||||
+6
-12
@@ -36,7 +36,7 @@ public class CommandHandler{
|
||||
|
||||
private final List<PluginCommand> subCommands = new ArrayList<>();
|
||||
|
||||
public CommandHandler(AdvancedServerList core){
|
||||
public CommandHandler(AdvancedServerList<?> core){
|
||||
subCommands.add(new Help());
|
||||
subCommands.add(new Reload(core));
|
||||
subCommands.add(new ClearCache(core));
|
||||
@@ -78,7 +78,7 @@ public class CommandHandler{
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<aqua>/asl <white>help <grey>- Shows this help");
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<aqua>/asl <white>reload <grey>- Reloads the plugin and clears caches");
|
||||
sender.sendMsg("<aqua>/asl <white>reload <grey>- Reloads the config.yml and profiles");
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<aqua>/asl <white>clearCache <grey>- Clears the Player and Favicon cache");
|
||||
}
|
||||
@@ -86,9 +86,9 @@ public class CommandHandler{
|
||||
|
||||
private static class Reload extends PluginCommand{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public Reload(AdvancedServerList core){
|
||||
public Reload(AdvancedServerList<?> core){
|
||||
super("reload");
|
||||
|
||||
this.core = core;
|
||||
@@ -110,21 +110,15 @@ public class CommandHandler{
|
||||
sender.sendErrorMsg("<red>Error while loading profile(s)!");
|
||||
}
|
||||
|
||||
core.clearFaviconCache();
|
||||
sender.sendPrefixedMsg("<green>Successfully cleared Favicon Cache!");
|
||||
|
||||
core.clearPlayerCache();
|
||||
sender.sendPrefixedMsg("<green>Successfully cleared Player Cache!");
|
||||
|
||||
sender.sendPrefixedMsg("<green>Reload complete!");
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClearCache extends PluginCommand{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public ClearCache(AdvancedServerList core){
|
||||
public ClearCache(AdvancedServerList<?> core){
|
||||
super("clearCache");
|
||||
|
||||
this.core = core;
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.compat.maintenance;
|
||||
|
||||
import eu.kennytv.maintenance.api.Maintenance;
|
||||
import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
|
||||
public class MaintenanceUtil{
|
||||
|
||||
private final Maintenance api;
|
||||
|
||||
public MaintenanceUtil(){
|
||||
this.api = MaintenanceProvider.get();
|
||||
}
|
||||
|
||||
public boolean isMaintenanceEnabled(){
|
||||
return api.isMaintenance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.compat.papi;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PAPICache{
|
||||
|
||||
private CacheValue cache = null;
|
||||
|
||||
public PAPICache(){}
|
||||
|
||||
public String get(Supplier<String> supplier){
|
||||
if(cache == null || cache.isExpired())
|
||||
cache = new CacheValue(supplier.get(), System.currentTimeMillis());
|
||||
|
||||
return cache.server();
|
||||
}
|
||||
|
||||
private record CacheValue(String server, long timestamp){
|
||||
// Consider the cache expired if it is older than 5 seconds.
|
||||
public boolean isExpired(){
|
||||
return (timestamp < 0L) || System.currentTimeMillis() - timestamp >= 5000L;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.compat.papi;
|
||||
|
||||
import net.william278.papiproxybridge.api.PlaceholderAPI;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
public class PAPIUtil{
|
||||
|
||||
private final PlaceholderAPI papi;
|
||||
|
||||
private final PAPICache cache = new PAPICache();
|
||||
|
||||
public PAPIUtil(){
|
||||
this.papi = PlaceholderAPI.createInstance();
|
||||
}
|
||||
|
||||
// Make sure the version of PAPIProxyBridge we get has the required methods we need...
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isCompatible(){
|
||||
try{
|
||||
papi.getClass().getMethod("findServers");
|
||||
return true;
|
||||
}catch(NoSuchMethodException ex){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getServer(){
|
||||
return cache.get(() -> {
|
||||
List<String> servers;
|
||||
try{
|
||||
servers = papi.findServers().getNow(Collections.emptyList());
|
||||
}catch(CancellationException | CompletionException ex){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(servers == null || servers.isEmpty())
|
||||
return null;
|
||||
|
||||
return servers.get(0);
|
||||
});
|
||||
}
|
||||
|
||||
public <P> P getPlayer(Collection<P> players){
|
||||
if(players.isEmpty())
|
||||
return null;
|
||||
|
||||
return List.copyOf(players).get(0);
|
||||
}
|
||||
|
||||
public String parse(String text, UUID carrier, UUID player){
|
||||
try{
|
||||
CompletableFuture<String> future = papi.formatPlaceholders(text, carrier, player);
|
||||
return future.getNow(text);
|
||||
}catch(IllegalArgumentException | CancellationException | CompletionException ex){
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
-5
@@ -29,9 +29,10 @@ import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.GenericServerImpl;
|
||||
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
|
||||
@@ -39,8 +40,11 @@ import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
|
||||
public class PingEventHandler{
|
||||
|
||||
private static PAPIUtil papiUtil = null;
|
||||
private static MaintenanceUtil maintenanceUtil = null;
|
||||
|
||||
public static <F, P extends GenericPlayer> void handleEvent(GenericEventWrapper<F, P> event){
|
||||
if(event.isInvalidProtocol())
|
||||
if(event.isInvalidProtocol() || event.isMaintenanceModeActive())
|
||||
return;
|
||||
|
||||
PluginCore<F> plugin = event.getPlugin();
|
||||
@@ -53,7 +57,7 @@ public class PingEventHandler{
|
||||
plugin.getCore().getPlayerHandler().getCachedPlayer(event.getPlayerIP()),
|
||||
event.getProtocolVersion()
|
||||
);
|
||||
GenericServer server = new GenericServerImpl(online, max, host);
|
||||
GenericServer server = event.createGenericServer(online, max, host);
|
||||
|
||||
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
|
||||
|
||||
@@ -68,12 +72,19 @@ public class PingEventHandler{
|
||||
if(entry.isInvalid())
|
||||
return;
|
||||
|
||||
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
|
||||
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
|
||||
|
||||
if(extraPlayers){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
event.setMaxPlayers(max);
|
||||
}
|
||||
|
||||
GenericServer finalServer = new GenericServerImpl(online, max, host);
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers){
|
||||
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
|
||||
event.setMaxPlayers(max);
|
||||
}
|
||||
|
||||
GenericServer finalServer = event.createGenericServer(online, max, host);
|
||||
|
||||
if(ProfileManager.checkOption(entry.motd())){
|
||||
event.setMotd(
|
||||
@@ -124,4 +135,18 @@ public class PingEventHandler{
|
||||
|
||||
event.updateEvent();
|
||||
}
|
||||
|
||||
public static PAPIUtil getPAPIUtil(){
|
||||
if(papiUtil != null)
|
||||
return papiUtil;
|
||||
|
||||
return (papiUtil = new PAPIUtil());
|
||||
}
|
||||
|
||||
public static MaintenanceUtil getMaintenanceUtil(){
|
||||
if(maintenanceUtil != null)
|
||||
return maintenanceUtil;
|
||||
|
||||
return (maintenanceUtil = new MaintenanceUtil());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.file;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.NodePath;
|
||||
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
||||
import org.spongepowered.configurate.transformation.TransformAction;
|
||||
|
||||
public class ConfigMigrator{
|
||||
|
||||
public static final int LATEST = 1;
|
||||
|
||||
private ConfigMigrator(){}
|
||||
|
||||
public static ConfigurationTransformation.Versioned create(){
|
||||
return ConfigurationTransformation.versionedBuilder()
|
||||
.versionKey("configVersion")
|
||||
.addVersion(LATEST, oneToTwo())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfigurationTransformation oneToTwo(){
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(NodePath.path("unknown_player"), (path, value) -> new Object[]{"unknownPlayer", "name"})
|
||||
.addAction(NodePath.path("unknown_player_uuid"), (path, value) -> new Object[]{"unknownPlayer", "uuid"})
|
||||
.addAction(NodePath.path("disable_cache"), TransformAction.rename("disableCache"))
|
||||
.addAction(NodePath.path("check_updates"), TransformAction.rename("checkUpdates"))
|
||||
.addAction(NodePath.path("send_statistics"), TransformAction.rename("sendStatistics"))
|
||||
.addAction(NodePath.path(), (path, value) -> {
|
||||
value.node("configVersion").set(LATEST);
|
||||
|
||||
return null;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <N extends ConfigurationNode> N updateNode(final N node, PluginLogger logger) throws ConfigurateException{
|
||||
if(!node.virtual()){
|
||||
final ConfigurationTransformation.Versioned versioned = create();
|
||||
final int startVersion = versioned.version(node);
|
||||
versioned.apply(node);
|
||||
final int endVersion = versioned.version(node);
|
||||
if(startVersion < endVersion)
|
||||
logger.info("Migrated config.yml from " + startVersion + " to " + endVersion);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,9 @@ import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.yaml.NodeStyle;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
@@ -38,13 +40,16 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class FileHandler{
|
||||
|
||||
private final AdvancedServerList plugin;
|
||||
private final AdvancedServerList<?> plugin;
|
||||
private final PluginLogger logger;
|
||||
|
||||
private final Path config;
|
||||
@@ -54,7 +59,7 @@ public class FileHandler{
|
||||
|
||||
private ConfigurationNode node = null;
|
||||
|
||||
public FileHandler(AdvancedServerList core){
|
||||
public FileHandler(AdvancedServerList<?> core){
|
||||
this.plugin = core;
|
||||
this.logger = core.getPlugin().getPluginLogger();
|
||||
|
||||
@@ -68,7 +73,7 @@ public class FileHandler{
|
||||
|
||||
public boolean loadConfig(){
|
||||
logger.info("Loading config.yml...");
|
||||
File folder = config.toFile().getParentFile();
|
||||
File folder = plugin.getPlugin().getFolderPath().toFile();
|
||||
if(!folder.exists() && !folder.mkdirs()){
|
||||
logger.warn("Couldn't create folder for plugin. Is it missing Write permissions?");
|
||||
return false;
|
||||
@@ -82,6 +87,7 @@ public class FileHandler{
|
||||
}
|
||||
|
||||
Files.copy(stream, config);
|
||||
logger.info("Created new config.yml!");
|
||||
}catch(IOException ex){
|
||||
logger.warn("Cannot create config.yml for plugin.", ex);
|
||||
return false;
|
||||
@@ -112,6 +118,26 @@ public class FileHandler{
|
||||
return reloadProfiles();
|
||||
}
|
||||
|
||||
public boolean migrateConfig(){
|
||||
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
|
||||
.path(config)
|
||||
.nodeStyle(NodeStyle.BLOCK)
|
||||
.build();
|
||||
|
||||
if(!makeBackup())
|
||||
return false;
|
||||
|
||||
try{
|
||||
node = ConfigMigrator.updateNode(loader.load(), logger);
|
||||
loader.save(node);
|
||||
|
||||
return true;
|
||||
}catch(ConfigurateException ex){
|
||||
logger.warn("Error while trying to migrate config.yml.", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean reloadConfig(){
|
||||
return (node = getConfigurationNode(config)) != null;
|
||||
}
|
||||
@@ -164,4 +190,36 @@ public class FileHandler{
|
||||
public boolean getBoolean(Object... path){
|
||||
return node.node(path).getBoolean();
|
||||
}
|
||||
|
||||
public boolean isOldConfig(){
|
||||
return node.node("configVersion").virtual() || node.node("configVersion").getInt(0) < ConfigMigrator.LATEST;
|
||||
}
|
||||
|
||||
private boolean makeBackup(){
|
||||
logger.info("Making backup of old config.yml...");
|
||||
|
||||
File backups = plugin.getPlugin().getFolderPath().resolve("backups").toFile();
|
||||
if(!backups.exists() && !backups.mkdirs()){
|
||||
logger.warn("Cannot create backups folder for migration!");
|
||||
return false;
|
||||
}
|
||||
|
||||
String date = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now());
|
||||
|
||||
File configBackup = new File(backups, "config_" + date.replace(":", "_") + ".yml");
|
||||
try{
|
||||
if(!configBackup.exists() && !configBackup.createNewFile()){
|
||||
logger.warn("Cannot create backup file for config.yml!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Files.copy(config, configBackup.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
logger.info("Saved backup as '" + configBackup.getName() + "'!");
|
||||
|
||||
return true;
|
||||
}catch(IOException ex){
|
||||
logger.warn("Encountered IOException while trying to create a backup.", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -25,6 +25,8 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.interfaces.commands;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class PluginCommand{
|
||||
|
||||
private final String argument;
|
||||
@@ -38,7 +40,7 @@ public abstract class PluginCommand{
|
||||
}
|
||||
|
||||
public String getPermission(){
|
||||
return "advancedserverlist.command." + getArgument();
|
||||
return "advancedserverlist.command." + getArgument().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public abstract void handle(CmdSender sender);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public interface PluginCore<F>{
|
||||
|
||||
void clearFaviconCache();
|
||||
|
||||
AdvancedServerList getCore();
|
||||
AdvancedServerList<F> getCore();
|
||||
|
||||
Path getFolderPath();
|
||||
|
||||
|
||||
+4
@@ -59,6 +59,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
|
||||
|
||||
boolean isInvalidProtocol();
|
||||
|
||||
boolean isMaintenanceModeActive();
|
||||
|
||||
int getProtocolVersion();
|
||||
|
||||
int getOnlinePlayers();
|
||||
@@ -75,6 +77,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
|
||||
|
||||
P createPlayer(CachedPlayer player, int protocol);
|
||||
|
||||
GenericServer createGenericServer(int playersOnline, int playersMax, String host);
|
||||
|
||||
F createFavicon(BufferedImage image) throws Exception;
|
||||
|
||||
default String resolveHost(InetSocketAddress address){
|
||||
|
||||
+13
-1
@@ -127,12 +127,24 @@ public class Expression{
|
||||
return left.equals(right);
|
||||
}
|
||||
},
|
||||
EQUALS_IGNORE_CASE('~', '='){
|
||||
@Override
|
||||
public boolean evaluate(String left, String right){
|
||||
return left.equalsIgnoreCase(right);
|
||||
}
|
||||
},
|
||||
NOT_EQUAL('!', '='){
|
||||
@Override
|
||||
public boolean evaluate(String left, String right){
|
||||
return !left.equals(right);
|
||||
}
|
||||
},
|
||||
NOT_EQUAL_IGNORE_CASE('!', '~'){
|
||||
@Override
|
||||
public boolean evaluate(String left, String right){
|
||||
return !left.equalsIgnoreCase(right);
|
||||
}
|
||||
},
|
||||
GREATER('>', '\0'){
|
||||
@Override
|
||||
public boolean evaluate(String left, String right){
|
||||
@@ -172,7 +184,7 @@ public class Expression{
|
||||
public static Operator getOperand(char first, char second){
|
||||
for(Operator operator : VALUES){
|
||||
if(operator.first == first){
|
||||
if((!operator.hasSecond() && second != '=') || operator.second == second)
|
||||
if((!operator.hasSecond() && second != '=' && second != '~') || operator.second == second)
|
||||
return operator;
|
||||
}
|
||||
}
|
||||
|
||||
+28
-15
@@ -39,32 +39,27 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FaviconHandler<F>{
|
||||
|
||||
private final Cache<String, F> favicons = CacheBuilder.newBuilder()
|
||||
private final Cache<String, CompletableFuture<F>> favicons = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final AdvancedServerList<F> core;
|
||||
private final ThreadPoolExecutor faviconThreadPool;
|
||||
|
||||
public FaviconHandler(AdvancedServerList core){
|
||||
public FaviconHandler(AdvancedServerList<F> core){
|
||||
this.core = core;
|
||||
this.faviconThreadPool = createFaviconThreadPool();
|
||||
}
|
||||
|
||||
public F getFavicon(String input, Function<BufferedImage, F> function){
|
||||
try{
|
||||
return favicons.get(input, () -> {
|
||||
BufferedImage image = resolveImage(core, input);
|
||||
if(image == null)
|
||||
return null;
|
||||
|
||||
return function.apply(image);
|
||||
});
|
||||
}catch(ExecutionException ignored){
|
||||
return favicons.get(input, () -> convert(input, function)).getNow(null);
|
||||
}catch(ExecutionException e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -73,7 +68,17 @@ public class FaviconHandler<F>{
|
||||
favicons.invalidateAll();
|
||||
}
|
||||
|
||||
private BufferedImage resolveImage(AdvancedServerList core, String input){
|
||||
private CompletableFuture<F> convert(String input, Function<BufferedImage, F> function){
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
BufferedImage img = resolveImage(core, input);
|
||||
if(img == null)
|
||||
return null;
|
||||
|
||||
return function.apply(img);
|
||||
}, faviconThreadPool);
|
||||
}
|
||||
|
||||
private BufferedImage resolveImage(AdvancedServerList<F> core, String input){
|
||||
InputStream stream;
|
||||
|
||||
if(input.toLowerCase(Locale.ROOT).startsWith("https://")){
|
||||
@@ -126,7 +131,7 @@ public class FaviconHandler<F>{
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getFromUrl(AdvancedServerList core, String url){
|
||||
private InputStream getFromUrl(AdvancedServerList<F> core, String url){
|
||||
try{
|
||||
URL faviconUrl = new URL(url);
|
||||
URLConnection connection = faviconUrl.openConnection();
|
||||
@@ -140,4 +145,12 @@ public class FaviconHandler<F>{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ThreadPoolExecutor createFaviconThreadPool(){
|
||||
return new ThreadPoolExecutor(3, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024), r -> {
|
||||
Thread t = new Thread(r, "AdvancedServerList-FaviconThread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
}
|
||||
+22
-16
@@ -31,33 +31,31 @@ import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import com.google.gson.Gson;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public class PlayerHandler{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final AdvancedServerList<?> core;
|
||||
private final PluginLogger logger;
|
||||
private final Path cache;
|
||||
private List<CachedPlayer> cachedPlayers = new ArrayList<>();
|
||||
|
||||
private final Type listType = new TypeToken<ArrayList<CachedPlayer>>(){}.getType();
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
// UUID of MHF_Question
|
||||
private final String defaultUUID = "606e2ff0-ed77-4842-9d6c-e1d3321c7838";
|
||||
private final UUID defaultUUID = UUID.fromString("606e2ff0-ed77-4842-9d6c-e1d3321c7838");
|
||||
|
||||
private List<CachedPlayer> cachedPlayers = new ArrayList<>();
|
||||
private CachedPlayer defaultPlayer = null;
|
||||
|
||||
public PlayerHandler(AdvancedServerList core){
|
||||
public PlayerHandler(AdvancedServerList<?> core){
|
||||
this.core = core;
|
||||
this.logger = core.getPlugin().getPluginLogger();
|
||||
this.cache = core.getPlugin().getFolderPath().resolve("playercache.json");
|
||||
@@ -69,13 +67,13 @@ public class PlayerHandler{
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().getBoolean("disable_cache")){
|
||||
if(core.getFileHandler().getBoolean("disableCache")){
|
||||
logger.info("'disable_cache' is set to true. Skipping playercache.json loading...");
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
Reader reader = Files.newBufferedReader(cache);
|
||||
BufferedReader reader = Files.newBufferedReader(cache);
|
||||
|
||||
cachedPlayers = gson.fromJson(reader, listType);
|
||||
|
||||
@@ -85,6 +83,14 @@ public class PlayerHandler{
|
||||
return;
|
||||
}
|
||||
|
||||
// In case Gson messes up... I guess.
|
||||
if(cachedPlayers == null){
|
||||
logger.warn("Couldn't load players from playercache.json file. Is the JSON valid?");
|
||||
// Create new ArrayList instance to avoid further issues.
|
||||
cachedPlayers = new ArrayList<>();
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Loaded %d players into cache!", cachedPlayers.size());
|
||||
}
|
||||
|
||||
@@ -94,7 +100,7 @@ public class PlayerHandler{
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().getBoolean("disable_cache")){
|
||||
if(core.getFileHandler().getBoolean("disableCache")){
|
||||
logger.info("'disable_cache' is set to true. Skipping saving of cached players...");
|
||||
return;
|
||||
}
|
||||
@@ -110,14 +116,14 @@ public class PlayerHandler{
|
||||
}
|
||||
|
||||
public void addPlayer(String ip, String name, UUID uuid){
|
||||
if(contains(ip) || core.getFileHandler().getBoolean("disable_cache"))
|
||||
if(contains(ip) || core.getFileHandler().getBoolean("disableCache"))
|
||||
return;
|
||||
|
||||
cachedPlayers.add(new CachedPlayer(ip, name, uuid));
|
||||
}
|
||||
|
||||
public CachedPlayer getCachedPlayer(String key){
|
||||
if(!contains(key) || core.getFileHandler().getBoolean("disable_cache"))
|
||||
if(!contains(key) || core.getFileHandler().getBoolean("disableCache"))
|
||||
return getDefaultPlayer();
|
||||
|
||||
for(CachedPlayer player : cachedPlayers){
|
||||
@@ -157,8 +163,8 @@ public class PlayerHandler{
|
||||
|
||||
return (defaultPlayer = new CachedPlayer(
|
||||
"0.0.0.0",
|
||||
core.getFileHandler().getString("Anonymous", "unknown_player"),
|
||||
convertToUUID(core.getFileHandler().getString(defaultUUID, "unknown_player_uuid"))
|
||||
core.getFileHandler().getString("Anonymous", "unknownPlayer", "name"),
|
||||
convertToUUID(core.getFileHandler().getString(defaultUUID.toString(), "unknownPlayer", "uuid"))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -167,7 +173,7 @@ public class PlayerHandler{
|
||||
return UUID.fromString(uuid);
|
||||
}catch(IllegalArgumentException ex){
|
||||
// This is always a valid UUID.
|
||||
return UUID.fromString(defaultUUID);
|
||||
return defaultUUID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-7
@@ -53,13 +53,16 @@ public class ProfileManager{
|
||||
String favicon = resolveFavicon(entry, defEntry);
|
||||
boolean isHidePlayersEnabled = resolveHidePlayersEnabled(entry, defEntry);
|
||||
boolean isExtraPlayersEnabled = resolveExtraPlayersEnabled(entry, defEntry);
|
||||
boolean isMaxPlayersEnabled = resolveMaxPlayersEnabled(entry, defEntry);
|
||||
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
|
||||
Integer maxPlayersCount = resolveMaxPlayersCount(entry, defEntry);
|
||||
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon,
|
||||
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), extraPlayersCount);
|
||||
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), NullBool.resolve(isMaxPlayersEnabled),
|
||||
extraPlayersCount, maxPlayersCount);
|
||||
}
|
||||
|
||||
public static ServerListProfile resolveProfile(AdvancedServerList core, GenericPlayer player, GenericServer server){
|
||||
public static ServerListProfile resolveProfile(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
|
||||
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
@@ -78,7 +81,9 @@ public class ProfileManager{
|
||||
String favicon = node.node("favicon").getString("");
|
||||
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
|
||||
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
|
||||
Integer extraPlayers = resolveNullableInt(node);
|
||||
NullBool maxPlayersEnabled = resolveNullBool(node, "playerCount", "maxPlayers", "enabled");
|
||||
Integer extraPlayers = resolveNullableInt(node, "playerCount", "extraPlayers", "amount");
|
||||
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
|
||||
|
||||
return new ProfileEntry.Builder()
|
||||
.setMotd(motd)
|
||||
@@ -87,7 +92,9 @@ public class ProfileManager{
|
||||
.setFavicon(favicon)
|
||||
.setHidePlayersEnabled(hidePlayers)
|
||||
.setExtraPlayersEnabled(extraPlayersEnabled)
|
||||
.setExtraPlayerCount(extraPlayers)
|
||||
.setMaxPlayersEnabled(maxPlayersEnabled)
|
||||
.setExtraPlayersCount(extraPlayers)
|
||||
.setMaxPlayersCount(maxPlayers)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -150,6 +157,13 @@ public class ProfileManager{
|
||||
return profile.extraPlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static boolean resolveMaxPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.maxPlayersEnabled()))
|
||||
return defaultProfile.maxPlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.maxPlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.extraPlayersCount() == null)
|
||||
return defaultProfile.extraPlayersCount() == null ? 0 : defaultProfile.extraPlayersCount();
|
||||
@@ -157,6 +171,13 @@ public class ProfileManager{
|
||||
return profile.extraPlayersCount();
|
||||
}
|
||||
|
||||
private static Integer resolveMaxPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.maxPlayersCount() == null)
|
||||
return defaultProfile.maxPlayersCount() == null ? 0 : defaultProfile.maxPlayersCount();
|
||||
|
||||
return profile.maxPlayersCount();
|
||||
}
|
||||
|
||||
private static List<String> resolveList(ConfigurationNode node, Object... path){
|
||||
try{
|
||||
return node.node(path).getList(String.class);
|
||||
@@ -172,10 +193,10 @@ public class ProfileManager{
|
||||
return NullBool.resolve(node.node(path).getBoolean());
|
||||
}
|
||||
|
||||
private static Integer resolveNullableInt(ConfigurationNode node){
|
||||
if(node.node("playerCount", "extraPlayers", "amount").virtual())
|
||||
private static Integer resolveNullableInt(ConfigurationNode node, Object... path){
|
||||
if(node.node(path).virtual())
|
||||
return null;
|
||||
|
||||
return node.node("playerCount", "extraPlayers", "amount").getInt();
|
||||
return node.node(path).getInt();
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -52,8 +52,10 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
node.node("playerCount", "hover").set(profile.players());
|
||||
node.node("playerCount", "text").set(profile.playerCountText());
|
||||
node.node("favicon").set(profile.favicon());
|
||||
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "amount").set(profile.extraPlayersCount());
|
||||
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? 0 : profile.extraPlayersCount());
|
||||
node.node("playerCount", "maxPlayers", "enabled").set(profile.maxPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? 0 : profile.maxPlayersCount());
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,25 @@
|
||||
#
|
||||
# Used for when AdvancedServerList doesn't have a cached player to use for ${player name}
|
||||
# Used for when AdvancedServerList doesn't have a cached player to use for player placeholders.
|
||||
#
|
||||
# Defaults to 'Anonymous' when not present.
|
||||
#
|
||||
unknown_player: "Anonymous"
|
||||
|
||||
#
|
||||
# UUID used for when AdvancedServerList doesn't have a cached player to use for the ${player uuid}
|
||||
# placeholder.
|
||||
#
|
||||
# Defaults to the UUID of MHF_Question (606e2ff0-ed77-4842-9d6c-e1d3321c7838) when not present.
|
||||
#
|
||||
unknown_player_uuid: "606e2ff0-ed77-4842-9d6c-e1d3321c7838"
|
||||
unknownPlayer:
|
||||
#
|
||||
# The name to use. Defaults to Anonymous.
|
||||
#
|
||||
name: "Anonymous"
|
||||
#
|
||||
# The UUID to use. Defaults to 606e2ff0-ed77-4842-9d6c-e1d3321c7838 (UUID of MHF_Question).
|
||||
#
|
||||
uuid: "606e2ff0-ed77-4842-9d6c-e1d3321c7838"
|
||||
|
||||
#
|
||||
# Should the Caching of players be disabled?
|
||||
#
|
||||
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
|
||||
# Placeholders that rely on the player being cached (such as ${player isWhitelisted}) will not work while this option is enabled.
|
||||
# Placeholders that rely on the player being cached (such as ${player name}) will not work while this option is enabled.
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
disable_cache: false
|
||||
disableCache: false
|
||||
|
||||
#
|
||||
# Should AdvancedServerList check for new versions?
|
||||
@@ -31,4 +29,12 @@ disable_cache: false
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
check_updates: true
|
||||
checkUpdates: true
|
||||
|
||||
#
|
||||
# DO NOT EDIT!
|
||||
#
|
||||
# This is used internally to determine if the config needs to be migrated.
|
||||
# Changing or even removing this option could result in your config being broken.
|
||||
#
|
||||
config-version: 2
|
||||
@@ -2,7 +2,7 @@
|
||||
# Set the priority of this profile.
|
||||
# Higher number = Higher priority.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#priority
|
||||
# Read more: https://asl.andre601.ch/profiles/#priority
|
||||
#
|
||||
priority: 0
|
||||
|
||||
@@ -10,7 +10,7 @@ priority: 0
|
||||
# Set conditions that needs to be met.
|
||||
# Only when all conditions return true will the profile be shown (Given no profile with higher priority is used).
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#conditions
|
||||
# Read more: https://asl.andre601.ch/profiles/#conditions
|
||||
#
|
||||
#conditions:
|
||||
# - '{playerVersion} < 759'
|
||||
@@ -25,7 +25,7 @@ priority: 0
|
||||
#
|
||||
# Remove this option or set it to profiles: [] to use the global options of this file.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#profiles
|
||||
# Read more: https://asl.andre601.ch/profiles/#profiles
|
||||
#
|
||||
#profiles:
|
||||
# - motd:
|
||||
@@ -49,7 +49,7 @@ priority: 0
|
||||
#
|
||||
# Remove this option or set it to motd: [] to not alter the MOTD.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motds
|
||||
# Read more: https://asl.andre601.ch/profiles/#motd
|
||||
#
|
||||
motd:
|
||||
- '<grey>Line 1'
|
||||
@@ -64,14 +64,14 @@ motd:
|
||||
#
|
||||
# Remove this option or set to favicon: '' to not replace the Favicon.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#favicon
|
||||
# Read more: https://asl.andre601.ch/profiles/#favicon
|
||||
#
|
||||
favicon: ''
|
||||
|
||||
#
|
||||
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#playercount
|
||||
# Read more: https://asl.andre601.ch/profiles/#playercount
|
||||
#
|
||||
playerCount:
|
||||
#
|
||||
@@ -82,7 +82,7 @@ playerCount:
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
|
||||
# Read more: https://asl.andre601.ch/profiles/#hideplayers
|
||||
#
|
||||
hidePlayers: false
|
||||
#
|
||||
@@ -90,7 +90,7 @@ playerCount:
|
||||
#
|
||||
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hover
|
||||
# Read more: https://asl.andre601.ch/profiles/#hover
|
||||
#
|
||||
hover:
|
||||
- '<grey>Line 1'
|
||||
@@ -104,24 +104,24 @@ playerCount:
|
||||
#
|
||||
# Remove this option or set it to text: '' to not modify the player count text.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#text
|
||||
# Read more: https://asl.andre601.ch/profiles/#text
|
||||
#
|
||||
text: ''
|
||||
#
|
||||
# Allows you to modify the max player count displayed.
|
||||
# Note that this will affect ${server playersMax} (Except for when used in conditions).
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#extraPlayers
|
||||
# Read more: https://asl.andre601.ch/profiles/#extraplayers
|
||||
#
|
||||
extraPlayers:
|
||||
#
|
||||
# Enables/Disables the extraPlayers option.
|
||||
# When enabled will the total amount of players allowed be modified to the current
|
||||
# When enabled will the total amount of players allowed to join be modified to the current
|
||||
# number of online players + 'amount'
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#enabled
|
||||
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
|
||||
#
|
||||
enabled: false
|
||||
#
|
||||
@@ -134,6 +134,35 @@ playerCount:
|
||||
#
|
||||
# Defaults to 0 when not present.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#amount
|
||||
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
#
|
||||
# Allows you to set the max players that could join your server.
|
||||
# Note that this option influences the '${server playersMax}' placeholder.
|
||||
#
|
||||
# The settings of this option have no effect should 'extraPlayers' be enabled
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers
|
||||
#
|
||||
maxPlayers:
|
||||
#
|
||||
# Enables/Disables the maxPlayers option.
|
||||
# When enabled will the total amount of players allowed to join be changed to what 'amount' is set to.
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
|
||||
#
|
||||
enabled: false
|
||||
#
|
||||
# Sets the number to display for the max number of players allowed to join your server.
|
||||
#
|
||||
# Example:
|
||||
# Setting this option to 0 (Default) while 1 player is online would display '1/0'
|
||||
#
|
||||
# Defaults to 0 if not set.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
@@ -0,0 +1,57 @@
|
||||
#
|
||||
# Modified version of Squidfunk's shortcodes.py file for Material for MkDocs.
|
||||
#
|
||||
# It was altered to create compact admonition-like boxes to display in the documentation.
|
||||
#
|
||||
# Original shortcodes.py file:
|
||||
# https://github.com/squidfunk/mkdocs-material/blob/56b96b4d799174d48d36613d70ffac9b964171cc/material/overrides/hooks/shortcodes.py
|
||||
#
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import posixpath
|
||||
import re
|
||||
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
from mkdocs.structure.files import File, Files
|
||||
from mkdocs.structure.pages import Page
|
||||
from re import Match
|
||||
|
||||
def on_page_markdown(
|
||||
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
|
||||
):
|
||||
|
||||
# Replace callback
|
||||
def replace(match: Match):
|
||||
type, args = match.groups()
|
||||
args = args.strip()
|
||||
if type == "abstract": return _admo(text = args, type = "abstract")
|
||||
elif type == "info": return _admo(text = args, type = "info")
|
||||
elif type == "tip": return _admo(text = args, type = "tip")
|
||||
elif type == "success": return _admo(text = args, type = "success")
|
||||
elif type == "question": return _admo(text = args, type = "question")
|
||||
elif type == "warning": return _admo(text = args, type = "warning")
|
||||
elif type == "failure": return _admo(text = args, type = "failure")
|
||||
elif type == "danger": return _admo(text = args, type = "danger")
|
||||
elif type == "bug": return _admo(text = args, type = "bug")
|
||||
elif type == "example": return _admo(text = args, type = "example")
|
||||
elif type == "quote": return _admo(text = args, type = "quote")
|
||||
else: return _admo(text = args)
|
||||
|
||||
# Otherwise, raise an error
|
||||
raise RuntimeError(f"Unknown shortcode: {type}")
|
||||
|
||||
# Find and replace all external asset URLs in current page
|
||||
return re.sub(
|
||||
r"<!-- admo:(\w+)(.*?) -->",
|
||||
replace, markdown, flags = re.I | re.M
|
||||
)
|
||||
|
||||
def _admo(text: str = "", type: str = ""):
|
||||
classes = f"mdx-grid-wrapper mdx-admo--{type}" if type else "mdx-grid-wrapper"
|
||||
return "".join([
|
||||
f"<div class=\"{classes}\">",
|
||||
f"<div class=\"mdx-grid-child mdx-grid-child--icon\"></div>",
|
||||
f"<div class=\"mdx-grid-child\">{text}</div>"
|
||||
"</div>",
|
||||
])
|
||||
@@ -0,0 +1,35 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "api-objects/info-template.html" as info %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/content.html" %}
|
||||
{% if page.meta %}
|
||||
<!--
|
||||
Object summaries
|
||||
-->
|
||||
{% if page.meta.constructors %}
|
||||
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor') }}
|
||||
{% endif %}
|
||||
{% if page.meta.classes %}
|
||||
{{ info.summary('Class Summary', page.meta.classes, details_type='class') }}
|
||||
{% endif %}
|
||||
{% if page.meta.enums %}
|
||||
{{ info.summary('Enum Constant Summary', page.meta.enums, details_type='enum') }}
|
||||
{% endif %}
|
||||
{% if page.meta.methods or page.meta.inherits %}
|
||||
{{ info.summary('Method Summary', page.meta.methods, page.meta.inherits, details_type='method') }}
|
||||
{% endif %}
|
||||
<!--
|
||||
Detailed object info
|
||||
-->
|
||||
{% if page.meta.constructors %}
|
||||
{{ info.info('Constructor Detail', page.meta.constructors) }}
|
||||
{% endif %}
|
||||
{% if page.meta.enums %}
|
||||
{{ info.info('Enum Constant Detail', page.meta.enums, true) }}
|
||||
{% endif %}
|
||||
{% if page.meta.methods %}
|
||||
{{ info.info('Method Detail', page.meta.methods)}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,218 @@
|
||||
{% macro summary(title, summaries, inherits, details_type = 'unknown') -%}
|
||||
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
|
||||
{{ title }}
|
||||
</h2>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
{% if summaries %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if details_type and details_type == "method" %}
|
||||
<th>Modifier and Type</th>
|
||||
{% endif %}
|
||||
<th>{{ details_type | capitalize() }}</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for summary in summaries %}
|
||||
<tr>
|
||||
{% set modifiers = namespace(name = "") %}
|
||||
{% for attribute in summary.attributes %}
|
||||
{% set modifiers.name = modifiers.name ~ attribute %}
|
||||
{% if loop.revindex > 0 %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if modifiers.name %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
|
||||
|
||||
{% if summary.type and summary.type.name %}
|
||||
{% set modifiers.name = modifiers.name ~ summary.type.name %}
|
||||
{% else %}
|
||||
{% set modifiers.name = modifiers.name ~ "void" %}
|
||||
{% endif %}
|
||||
|
||||
{% set desc = "" %}
|
||||
{% if summary.deprecated %}
|
||||
{% set desc = "<api__deprecated></api__deprecated><br>" ~ summary.deprecated.split("<br>")[0] %}
|
||||
{% elif summary.description %}
|
||||
{% set desc = summary.description.split("<br>")[0] %}
|
||||
{% endif %}
|
||||
|
||||
{% set final_name = namespace(name = "") %}
|
||||
{% if details_type and details_type == "enum" %}
|
||||
{% set final_name.name = summary.name | upper() %}
|
||||
{% else %}
|
||||
{% set final_name.name = summary.name ~ "(" %}
|
||||
{% endif %}
|
||||
|
||||
{% for parameter in summary.parameters %}
|
||||
{% set final_name.name = final_name.name ~ parameter.type %}
|
||||
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if details_type != "enum" %}
|
||||
{% set final_name.name = final_name.name ~ ")" %}
|
||||
{% endif %}
|
||||
|
||||
{% if details_type and details_type == "method" %}
|
||||
{% if modifiers.name %}
|
||||
<td><code>{{ modifiers.name }}</code></td>
|
||||
{% else %}
|
||||
<td></td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td>
|
||||
{% if summary.link %}
|
||||
<a href="{{ summary.link }}"><code>{{ final_name.name | e}}</code></a>
|
||||
{% else %}
|
||||
<a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}"><code>{{ final_name.name | e}}</code></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ desc }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if inherits %}
|
||||
{% for classpath, inherit in inherits.items() %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Methods inherited from <a href="{{ inherit.link }}"><code>{{ classpath }}</code></a></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
{% for inh in inherit.list %}
|
||||
<a href="{{ inherit.link }}#{{ inh | lower() | replace(' ', '-') | e }}">
|
||||
<code>{{- inh | e -}}</code>
|
||||
</a>
|
||||
{%- if loop.revindex > 1 %}, {% endif -%}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro info(title, details, enum = false) -%}
|
||||
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
|
||||
{{ title }}
|
||||
</h2>
|
||||
{% for detail in details %}
|
||||
<div class="api-detail">
|
||||
{% set final_name = namespace(name = "") %}
|
||||
{% if enum %}
|
||||
{% set final_name.name = detail.name | upper() %}
|
||||
{% else %}
|
||||
{% set final_name.name = detail.name ~ "(" %}
|
||||
{% endif %}
|
||||
|
||||
{% for parameter in detail.parameters %}
|
||||
{% set final_name.name = final_name.name ~ parameter.type %}
|
||||
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if not enum %}
|
||||
{% set final_name.name = final_name.name ~ ")" %}
|
||||
{% endif %}
|
||||
|
||||
<h3 id="{{ final_name.name | lower() | replace(' ', '-') | e }}">
|
||||
{% if detail.deprecated %}
|
||||
<api__deprecated></api__deprecated>
|
||||
{% endif %}
|
||||
|
||||
{% for attribute in detail.attributes %}
|
||||
<api__{{- attribute -}}></api__{{- attribute -}}>
|
||||
{% endfor %}
|
||||
|
||||
{% if enum %}
|
||||
<api__static></api__static> <api__final></api__final>
|
||||
{% endif %}
|
||||
|
||||
{% if detail.type %}
|
||||
{% if detail.type.link %}
|
||||
<a href="{{ detail.type.link }}" class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</a>
|
||||
{% else %}
|
||||
<span class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<code>{{ final_name.name | e }}</code><a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}" class="headerlink" title="Permanent link">¶</a>
|
||||
</h3>
|
||||
|
||||
{% if detail.deprecated %}
|
||||
<div class="admonition deprecated">
|
||||
<div class="admonition-title">Deprecation Warning</div>
|
||||
<p>
|
||||
{{ detail.deprecated }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if detail.description %}
|
||||
<p class="api-detail__description">
|
||||
{{ detail.description }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if detail.parameters %}
|
||||
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-parameters">
|
||||
Parameters:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-parameters" class="headerlink" title="Permanent link">¶</a>
|
||||
</h4>
|
||||
<ul>
|
||||
{% for parameter in detail.parameters %}
|
||||
<li>
|
||||
{% for attribute in parameter.attribute %}
|
||||
<api__{{- attribute -}}></api__{{- attribute -}}>
|
||||
{% endfor %}
|
||||
<code>{{ parameter.type | e }}: {{ parameter.name }}</code>{% if parameter.description %} - {{ parameter.description }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if detail.returns %}
|
||||
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-returns">
|
||||
Returns:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-returns" class="headerlink" title="Permanent link">¶</a>
|
||||
</h4>
|
||||
<p class="api-detail__description">
|
||||
{{ detail.returns }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if detail.throws %}
|
||||
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-throws">
|
||||
Throws:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-throws" class="headerlink" title="Permanent link">¶</a>
|
||||
</h4>
|
||||
<ul>
|
||||
{% for throw in detail.throws %}
|
||||
<li>
|
||||
<code>{{ throw.name }}</code>{% if throw.description %} - {{ throw.description }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if seealso %}
|
||||
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-see-also">
|
||||
See also:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-see-also" class="headerlink" title="Permanent link">¶</a>
|
||||
</h4>
|
||||
<ul>
|
||||
{% for see in detail.seealso %}
|
||||
<li>
|
||||
<a href="{{ see.link }}"><code>{{ see.name }}</code></a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
@@ -0,0 +1,42 @@
|
||||
<!-- Tags -->
|
||||
{% if "material/tags" in config.plugins and tags %}
|
||||
{% include "partials/tags.html" %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Actions -->
|
||||
{% include "partials/actions.html" %}
|
||||
|
||||
{% if config.extra.github_repository %}
|
||||
<div class="admonition info">
|
||||
<p class="admonition-title">Moved</p>
|
||||
<p>
|
||||
The documenation has been moved and can now be found at <a href="https://asl.andre601.ch" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch</strong></a>.<br>
|
||||
This page in particular can be found at <a href="https://asl.andre601.ch/{{ page.url }}" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch/{{ page.url }}</strong></a>.
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!--
|
||||
Hack: check whether the content contains a h1 headline. If it doesn't, the
|
||||
page title (or respectively site name) is used as the main headline.
|
||||
-->
|
||||
{% if "\x3ch1" not in page.content %}
|
||||
<h1>{{ page.title | d(config.site_name, true)}}</h1>
|
||||
{% endif %}
|
||||
|
||||
<!-- Page content -->
|
||||
{{ page.content }}
|
||||
|
||||
<!-- Source file information -->
|
||||
{% if page.meta and (
|
||||
page.meta.git_revision_date_localized or
|
||||
page.meta.revision_date
|
||||
) %}
|
||||
{% include "partials/source-file.html" %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Was this page helpful? -->
|
||||
{% include "partials/feedback.html" %}
|
||||
|
||||
<!-- Comment system -->
|
||||
{% include "partials/comments.html" %}
|
||||
@@ -0,0 +1,9 @@
|
||||
nav:
|
||||
- Home: index.md
|
||||
- getting-started
|
||||
- commands
|
||||
- profiles
|
||||
- examples
|
||||
- migration
|
||||
- api
|
||||
- PlaceholderAPI: placeholderapi
|
||||
@@ -0,0 +1 @@
|
||||
<div class="mdx-badge"><span class="mdx-badge__icon">[:octicons-tag-24:](changelog.md#v3.1.0 'View latest Release Changelog')</span><span class="mdx-badge__text">[v3.1.0](changelog.md#v3.1.0 'View latest Release Changelog')</span></div>
|
||||
@@ -0,0 +1 @@
|
||||
<div class="mdx-badge"><span class="mdx-badge__icon" >[:octicons-alert-24:](changelog.md)</span><span class="mdx-badge__text">[v3.1.0](changelog.md#v3.1.0 'View latest Release Changelog')</span></div>
|
||||
@@ -0,0 +1,2 @@
|
||||
nav:
|
||||
- ...
|
||||
+62
-6
@@ -1,16 +1,69 @@
|
||||
---
|
||||
icon: octicons/log-24
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
This page lists the recent changes made towards the AdvancedServerListAPI.
|
||||
They are ordered newest to oldest.
|
||||
|
||||
## v2.1.0
|
||||
## v3.1.0 { #v3.1.0 }
|
||||
|
||||
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.1.0-added }
|
||||
|
||||
- New getters in [`ProfileEntry`][profileentry]:
|
||||
- [`maxPlayersEnabled()`][maxplayersenabled] - Returns the value for `playerCount -> maxPlayers -> enabled` as `NullBool`
|
||||
- [`maxPlayersCount()`][maxplayerscount] - Returns the value of `playerCount -> maxPlayers -> amount` as nullable `Integer`
|
||||
- New setters in [`ProfileEntry.Builder`][profileentry.builder]:
|
||||
- [`setMaxPlayersEnabled(NullBool)`][setmaxplayersenabled] - Sets whether the max players feature is enabled or not.
|
||||
- [`setMaxPlayersCount(Integer)`][setmaxplayerscount] - Sets the number to use for the max players count.
|
||||
- [`setExtraPlayersCount(Integer)`][setextraplayersecount] - Replacement for [deprecated `setExtraPlayerCount(Integer)` method](#v3.1.0-deprecated).
|
||||
|
||||
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v3.1.0-deprecated }
|
||||
|
||||
- `setExtraPlayerEnabled(Integer)` in `ProfileEntry.Builder` - Typo in method name.
|
||||
|
||||
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
|
||||
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled()
|
||||
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount()
|
||||
|
||||
[profileentry.builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
|
||||
[setmaxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayersenabled(nullbool)
|
||||
[setmaxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayerscount(integer)
|
||||
[setextraplayersecount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setextraplayerscount(integer)
|
||||
|
||||
----
|
||||
|
||||
## v3.0.0 { #v3.0.0 }
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v3-breaking }
|
||||
|
||||
- Removed `platform-spigot` API in favour of a more generic sounding `platform-bukkit`
|
||||
- Renamed all platform-specific packages from `ch.andre601.advancedserverlist.<platform>` to `ch.andre601.advancedserverlist.api.<platform>`
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3-added }
|
||||
|
||||
- New platform-specific `GenericServer` instances with their own methods to use.
|
||||
- `BukkitServer` - Contains a `getWorlds()` method that returns a `Map<String, World>` of all loaded worlds in the server.
|
||||
- `BungeeProxy` - Contains a `getServers()` method that returns a `Map<String, ServerInfo>` of all known Servers for BungeeCord.
|
||||
- `VelocityProxy` - Contains a `getServers()` method that returns a `Map<String, RegisteredServer>` of all known Servers for Velocity.
|
||||
|
||||
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v3-removed }
|
||||
|
||||
- All previously deprecated `getX()` methods from the `ProfileEntry` record
|
||||
|
||||
----
|
||||
|
||||
## v2.1.0 { #v2.1.0 }
|
||||
|
||||
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v2.1.0-changed }
|
||||
|
||||
- Turned `ProfileEntry` class into a record
|
||||
- Former `getX()` methods are now deprecated in favour of the recor's own `x()` methods (i.e. `getMotd()` -> `motd()`)
|
||||
- Former `getX()` methods are now deprecated in favour of the record's own `x()` methods (i.e. `getMotd()` -> `motd()`)
|
||||
|
||||
## v2.0.0
|
||||
----
|
||||
|
||||
## v2.0.0 { #v2.0.0 }
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v2-breaking }
|
||||
|
||||
@@ -39,7 +92,9 @@ They are ordered newest to oldest.
|
||||
|
||||
- `UnsupportedAPIAccessException` as it is no longer used in the API itself.
|
||||
|
||||
## v1.0.0
|
||||
----
|
||||
|
||||
## v1.0.0 { #v1.0.0 }
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v1-added }
|
||||
|
||||
@@ -56,5 +111,6 @@ Templates for changelog
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v-added }
|
||||
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
|
||||
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v-removed }
|
||||
### :octicons-zap-24:{ .changelog-deprecated title="Deprecated" } Deprecated { #v-deprecated }
|
||||
|
||||
-->
|
||||
-->
|
||||
+331
-87
@@ -1,3 +1,7 @@
|
||||
---
|
||||
icon: octicons/command-palette-24
|
||||
---
|
||||
|
||||
# API
|
||||
|
||||
AdvancedServerList v2 introduced a new API that plugins can hook into to use.
|
||||
@@ -5,80 +9,94 @@ It provides a way for your plugin to provide its own placeholders that should be
|
||||
|
||||
## Add dependency
|
||||
|
||||
Add the following to your `build.gradle` or `pom.xml` file to use the API:
|
||||
Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depending on what you use:
|
||||
|
||||
=== ":simple-gradle: Gradle"
|
||||
/// tab | :simple-apachemaven: Maven
|
||||
```xml title="pom.xml"
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack</id>
|
||||
<url>https://jitpack.io/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>{apiVersion}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional platform dependencies -->
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bukkit</artifactId>
|
||||
<version>{apiVersion}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bungeecord</artifactId>
|
||||
<version>{apiVersion}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-velocity</artifactId>
|
||||
<version>{apiVersion}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
///
|
||||
|
||||
/// tab | :simple-gradle: Gradle
|
||||
```groovy title="build.gradle"
|
||||
repositorories {
|
||||
maven { url = 'https://jitpack.io/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'ch.andre601.asl-api:api:{apiVersion}'
|
||||
|
||||
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
|
||||
// Optional platform dependencies
|
||||
compileOnly 'ch.andre601.asl-api:platform-bukkit:{apiVersion}'
|
||||
compileOnly 'ch.andre601.asl-api:platform-bungeecord:{apiVersion}'
|
||||
compileOnly 'ch.andre601.asl-api:platform-velocity:{apiVersion}'
|
||||
}
|
||||
```
|
||||
///
|
||||
|
||||
/// tab | :simple-gradle: Gradle (KTS)
|
||||
```kotlin title="build.gradle.kts"
|
||||
repositories {
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("ch.andre601.asl-api:api:{apiVersion}")
|
||||
|
||||
```groovy
|
||||
repositorories {
|
||||
maven { url = 'https://jitpack.io/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'ch.andre601.asl-api:api:{version}'
|
||||
|
||||
// Optional platform dependencies
|
||||
implementation 'ch.andre601.asl-api:platform-bungeecord:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-spigot:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-velocity:{version}'
|
||||
}
|
||||
```
|
||||
// Optional platform dependencies
|
||||
compileOnly("ch.andre601.asl-api:platform-bukkit:{apiVersion}")
|
||||
compileOnly("ch.andre601.asl-api:platform-bungeecord:{apiVersion}")
|
||||
compileOnly("ch.andre601.asl-api:platform-velocity:{apiVersion}")
|
||||
}
|
||||
```
|
||||
///
|
||||
|
||||
=== ":simple-apachemaven: Maven"
|
||||
|
||||
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack</id>
|
||||
<url>https://jitpack.io/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional platform dependencies -->
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bungeecord</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-spigot</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-velocity</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
## Adding your own Placeholders
|
||||
|
||||
[api-repo]: https://github.com/Andre601/asl-api
|
||||
<!-- admo:info This requires the main api module -->
|
||||
|
||||
## Add own placeholders
|
||||
The API allows you to add your own placeholders which would be available through the `${<identifier> <values>}` placeholder Pattern in a Server List profile.
|
||||
|
||||
To add your own placeholders will you need to do a few steps.
|
||||
To add your own placeholders, follow these steps:
|
||||
|
||||
### 1) Get API instance
|
||||
### 1. Create a Placeholder class
|
||||
|
||||
Use `AdvancedServerListAPI.get()` to retrieve an instance of the currently used AdvancedServerList API.
|
||||
It will be needed at a later point.
|
||||
You should first create a new class and make it extend the abstract [`PlaceholderProvider`][placeholderprovider]. This class includes a constructor and a method you need to add, so do that:
|
||||
|
||||
### 2) Create a Placeholder class
|
||||
|
||||
Make a new class that you want to use for the placeholders and let it extend the `PlaceholderProvider` class of AdvancedServerList.
|
||||
Your IDE should now tell you to implement/override some methods. Confirm this action and your class should look something alongside this:
|
||||
```java
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
@@ -93,20 +111,24 @@ public class MyPlaceholders extends PlaceholderProvider {
|
||||
}
|
||||
```
|
||||
|
||||
It's recommended to replace your generated constructor with a no-args one and set the identifier directly in the `super()`.
|
||||
For example:
|
||||
/// tip
|
||||
You can replace the Constructor with a String argument with a no-args constructor and set the identifier directly in the `super`:
|
||||
```java
|
||||
public MyPlaceholders() {
|
||||
super("myplaceholders");
|
||||
}
|
||||
```
|
||||
///
|
||||
|
||||
The next step now would be to handle the different placeholders. These are handled in the `parsePlaceholder` method you had to override.
|
||||
The `placeholder` String is whatever value was provided after the identifier in `${<identifier> <placeholder>}`. It can contain spaces.
|
||||
The [`parsePlaceholder(String, GenericPlayer, GenericServer)`][parseplaceholder] method is used by AdvancedServerList to replace a matching placeholder with a value.
|
||||
What you return is completely up to you. Just keep in mind that returning `null` will be treated as an invalid placeholder by AdvancedServerList, resulting in the placeholder being returned as-is without any changes.
|
||||
|
||||
Something to note is, that when returning `null` will AdvancedServerList understand it as an invalid placeholder and return it unchanged.
|
||||
[placeholderprovider]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
|
||||
[parseplaceholder]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md#parseplaceholder(string,-genericplayer,-genericserver)
|
||||
|
||||
/// details | Example of final class
|
||||
type: example
|
||||
|
||||
Here is a small example of the final class:
|
||||
```java
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
@@ -116,36 +138,258 @@ public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
|
||||
if(placeholder.equals("hello"))
|
||||
return "Hi!";
|
||||
if(placeholder.equalsIgnoreCase("hello"))
|
||||
return "Hello " + player.getName();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
///
|
||||
|
||||
### 3) Register the placeholder class
|
||||
### 2. Register the Placeholders
|
||||
|
||||
All that is left to do now is to register your class as a new PlaceholderProvider instance. To do this, get the API instance you retrieved earlier and use `addPlaceholderProvider` with a new instance of your class.
|
||||
Next step should be to register the placeholder. To achieve this, first obtain an instance of the [`AdvancedServerListAPI`][advancedserverlistapi] by using the static [`get()`][get] method. After that call [`addPlaceholderProvider(PlaceholderProvider placeholderProvider)`][addplaceholderprovider].
|
||||
Your code may look similar to this:
|
||||
|
||||
Example:
|
||||
```java
|
||||
AdvancedServerListAPI api = AdvancedServerListAPI.get();
|
||||
|
||||
api.addPlaceholderProvider(new MyPlaceholders());
|
||||
```java title="Registering PlaceholderProvider class"
|
||||
public class MyPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
AdvancedServerListAPI api = AdvancedServerListAPI.get();
|
||||
|
||||
api.addPlaceholderProvider(new MyPlaceholders());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Events
|
||||
[advancedserverlistapi]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
|
||||
[get]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#get()
|
||||
[addplaceholderprovider]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)
|
||||
|
||||
!!! info "Note"
|
||||
The mentioned event is only accessible through one of the platform dependencies, as those are used in the platform's respective event handler system.
|
||||
This should register your PlaceholderExpansion as long as it is valid, meaning that the identifier...
|
||||
|
||||
v2 of the API adds the `PreServerListSetEvent` to the different platform dependencies to use.
|
||||
It allows you to modify the ProfileEntry used for the player pinging the server/proxy or even cancelling the event altogether.
|
||||
- ...is not `null`
|
||||
- ...is not containing spaces
|
||||
- ...is not using a name already registered in the API
|
||||
|
||||
### 3. Declare AdvancedServerList as (soft)depend
|
||||
|
||||
The final thing you should make sure is to define AdvancedServerList as a depend or soft-depend for your plugin, to make sure it loads after AdvancedServerList.
|
||||
|
||||
Below are example setups for Spigot, Paper, BungeeCord and Velocity:
|
||||
|
||||
/// tab | :simple-spigotmc: Spigot
|
||||
//// tab | Softdepend
|
||||
```yaml title="plugin.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
softdepend:
|
||||
- AdvancedServerList
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Depend
|
||||
```yaml title="plugin.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
depend:
|
||||
- AdvancedServerList
|
||||
```
|
||||
////
|
||||
///
|
||||
|
||||
/// tab | :fontawesome-solid-paper-plane: Paper
|
||||
//// tab | Softdepend
|
||||
```yaml title="paper-plugin.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
dependencies:
|
||||
server:
|
||||
AdvancedServerList:
|
||||
load: BEFORE
|
||||
required: false # Default, not required
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Depend
|
||||
```yaml title="paper-plugin.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
dependencies:
|
||||
server:
|
||||
AdvancedServerList:
|
||||
load: BEFORE
|
||||
required: true
|
||||
```
|
||||
////
|
||||
///
|
||||
|
||||
/// tab | :octicons-git-merge-24: BungeeCord
|
||||
//// tab | Softdepend
|
||||
```yaml title="bungee.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
softDepends:
|
||||
- AdvancedServerList
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Depend
|
||||
```yaml title="bungee.yml"
|
||||
name: "MyPlugin"
|
||||
author: "author"
|
||||
version: "1.0.0"
|
||||
|
||||
main: "com.example.plugin.ExamplePlugin"
|
||||
|
||||
depends:
|
||||
- AdvancedServerList
|
||||
```
|
||||
////
|
||||
///
|
||||
|
||||
/// tab | :octicons-git-merge-24: Velocity
|
||||
//// tab | Softdepend (File)
|
||||
```json title="velocity-plugin.json"
|
||||
{
|
||||
"id": "myplugin",
|
||||
"name": "MyPlugin",
|
||||
"version": "1.0.0",
|
||||
"authors": [
|
||||
"author"
|
||||
],
|
||||
"main": "com.example.plugin.ExamplePlugin",
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "advancedserverlist",
|
||||
"optional": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Depend (File)
|
||||
```json title="velocity-plugin.json"
|
||||
{
|
||||
"id": "myplugin",
|
||||
"name": "MyPlugin",
|
||||
"version": "1.0.0",
|
||||
"authors": [
|
||||
"author"
|
||||
],
|
||||
"main": "com.example.plugin.ExamplePlugin",
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "advancedserverlist",
|
||||
"optional": false // Default, not required
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Softdepend (Annotation)
|
||||
```java title="MyPlugin.java"
|
||||
@Plugin(
|
||||
id = "myplugin",
|
||||
name = "MyPlugin",
|
||||
version = "1.0.0",
|
||||
authors = {"author"},
|
||||
dependencies = {
|
||||
@Dependency(
|
||||
id = "advancedserverlist",
|
||||
optional = true
|
||||
)
|
||||
}
|
||||
)
|
||||
public class MyPlugin {
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Depend (Annotation)
|
||||
```java title="MyPlugin.java"
|
||||
@Plugin(
|
||||
id = "myplugin",
|
||||
name = "MyPlugin",
|
||||
version = "1.0.0",
|
||||
authors = {"author"},
|
||||
dependencies = {
|
||||
@Dependency(
|
||||
id = "advancedserverlist",
|
||||
optional = false // Default, not required
|
||||
)
|
||||
}
|
||||
)
|
||||
public class MyPlugin {
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
```
|
||||
////
|
||||
///
|
||||
|
||||
### 4. You're done!
|
||||
|
||||
Your plugin should now hook into AdvancedServerList and register its own custom placeholders to use.
|
||||
|
||||
## Listening for events
|
||||
|
||||
<!-- admo:info This requires the platform specific dependencies -->
|
||||
|
||||
AdvancedServerList provides an Event that your plugin can listen for.
|
||||
The event is called `PreServerListSetEvent` and provides the following methods to use:
|
||||
|
||||
- [`getEntry()`][getentry] - Gets the currently set [`ProfileEntry`][profileentry].
|
||||
- [`setEntry(ProfileEntry)`][setentry] - Sets a new [`ProfileEntry`][profileentry] to use.
|
||||
- [`isCancelled()`][iscancelled] - Gets the current cancelled state of the event.
|
||||
- [`setCancelled(boolean)`][setcancelled] - Sets the current cancelled state.
|
||||
|
||||
Setting the event's cancelled state to true will result in AdvancedServerList not altering the Server list.
|
||||
|
||||
Please check the server/proxy's documentation on how to listen for events with your plugin.
|
||||
|
||||
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()
|
||||
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry(profileentry)
|
||||
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled()
|
||||
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled(boolean)
|
||||
|
||||
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
|
||||
|
||||
### ProfileEntry
|
||||
|
||||
The ProfileEntry class has been moved to the API in v2 allowing you to create your own versions using the available Builder class.
|
||||
The ProfileEntry record is the core class used within the `PreServerListSetEvent`. It sets what values (MOTD, Favicon, Players, etc.) should be displayed.
|
||||
Note that the record is - by nature - immutable and that the [`Builder`][builder] class should be used to create a new ProfileEntry instance to use.
|
||||
|
||||
This class contains values from a Server List Profile file. The values can either be from a `profiles` list entry, one of the global options in the file, or a mix of both, depending on what options are present.
|
||||
You can create a new entry or copy an existing one (i.e. from the [`PreServerListSetEvent`](#events)) to modify and use in the server list by setting it in the aforementioned `PreServerListSetEvent`.
|
||||
A convenience method exists to create a `Builder` instance from an existing `ProfileEntry` in case you only want to alter certain options while everything else unchanged.
|
||||
|
||||
This allows you to customize the Server list using your plugin. Just keep in mind that other plugins may also do the same, overriding your changes.
|
||||
|
||||
[builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
template: redirect.html
|
||||
|
||||
location: https://docs.andre601.ch/asl-api
|
||||
|
||||
title: Javadocs
|
||||
icon: octicons/link-external-24
|
||||
---
|
||||
|
||||
<!-- Comment to trigger proper build -->
|
||||
@@ -0,0 +1,6 @@
|
||||
nav:
|
||||
- index.md
|
||||
- api: api
|
||||
- platform-bukkit: platform-bukkit
|
||||
- platform-bungeecord: platform-bungeecord
|
||||
- platform-velocity: platform-velocity
|
||||
@@ -0,0 +1,3 @@
|
||||
nav:
|
||||
- index.md
|
||||
- ch.andre601.advancedserverlist.api: ch.andre601.advancedserverlist.api
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'get'
|
||||
description: |
|
||||
Retrieve the instance used of this API.<br>
|
||||
If no instance has been made so far will a new one be created.
|
||||
returns: 'Instance of this API.'
|
||||
attributes:
|
||||
- static
|
||||
type:
|
||||
name: 'AdvancedServerListAPI'
|
||||
type: 'object'
|
||||
- name: 'addPlaceholderProvider'
|
||||
description: |
|
||||
Adds the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to the list, if it passes the following checks:<br>
|
||||
<ul>
|
||||
<li>Provided PlaceholderProvider instance is not null.</li>
|
||||
<li>The identifier is not null nor empty.</li>
|
||||
<li>The identifier does not contain any spaces.</li>
|
||||
<li>A PlaceholderProvider with the same identifier doesn't exist already.</li>
|
||||
</ul>
|
||||
Not passing any of the above checks results in a <a href="./../exceptions/invalidplaceholderproviderexception/"><code>InvalidPlaceholderProviderException</code></a> being thrown.
|
||||
parameters:
|
||||
- name: 'placeholderProvider'
|
||||
description: 'The <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to add.'
|
||||
type: PlaceholderProvider
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'InvalidPlaceholderProviderException'
|
||||
description: 'When the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a> is null, has a null or empty identifier, the identifier contains spaces, or another PlaceholderProvider with the same identifier is already in use.'
|
||||
type:
|
||||
name: 'void'
|
||||
- name: 'retrievePlaceholderProvider'
|
||||
description: 'Retrieves the <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> associated with the provided identifier, or <code>null</code> should no such entry exist.'
|
||||
parameters:
|
||||
- name: 'identifier'
|
||||
description: 'The identifier to find a matching <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> for.'
|
||||
type: String
|
||||
returns: 'Possibly-null <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a>.'
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: PlaceholderProvider
|
||||
type: object
|
||||
link: './../placeholderprovider'
|
||||
---
|
||||
|
||||
# <api__class></api__class> AdvancedServerListAPI
|
||||
|
||||
Core class of the API for AdvancedServerList.
|
||||
Use [`get()`](#get) to retrieve the instance currently used.
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getEntry'
|
||||
description: 'Gets the <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> currently set.'
|
||||
returns: The currently used ProfileEntry.
|
||||
type:
|
||||
name: ProfileEntry
|
||||
type: object
|
||||
link: '../../profiles/profileentry/'
|
||||
- name: 'setEntry'
|
||||
description: |-
|
||||
Sets the new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.<br>
|
||||
This may not be <code>null</code>.
|
||||
parameters:
|
||||
- name: 'entry'
|
||||
description: 'The new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.'
|
||||
type: ProfileEntry
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'When the provided ProfileEntry is <code>null</code>'
|
||||
type:
|
||||
name: 'void'
|
||||
- name: 'isCancelled'
|
||||
description: Returns whether this event has been cancelled or not.
|
||||
returns: Whether this event has been cancelled or not.
|
||||
type:
|
||||
name: boolean
|
||||
- name: 'setCancelled'
|
||||
description: Sets the event's cancel state
|
||||
parameters:
|
||||
- name: 'cancelled'
|
||||
description: 'Boolean to set the event''s cancelled state.'
|
||||
type: boolean
|
||||
type:
|
||||
name: 'void'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> GenericServerListEvent
|
||||
|
||||
Interface used for the platform-specific PreServerListSetEvent instances.
|
||||
This allows the plugin to pull common info such as ProfileEntry or if the event has been cancelled by another plugin.
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
---
|
||||
template: 'api-doc.html'
|
||||
|
||||
constructors:
|
||||
- name: 'InvalidPlaceholderProviderException'
|
||||
parameters:
|
||||
- name: msg
|
||||
type: String
|
||||
---
|
||||
|
||||
# <api__class></api__class> InvalidPlaceholderProviderException
|
||||
|
||||
RuntimeException thrown whenever an invalid [`PlaceholderProvider`](../placeholderprovider.md) has been given.
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getName'
|
||||
description: |
|
||||
Returns the name of the player.<br>
|
||||
Note that on Spigot, Paper and other forks can the name differ from the one cached by AdvancedServerList, if the plugin was able to retrieve an OfflinePlayer instance from the server. On BungeeCord and Velocity will the returned String always be the name from the cache.<br>
|
||||
<br>
|
||||
Name may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by the plugin.
|
||||
returns: 'String representing the player''s name'
|
||||
type:
|
||||
name: String
|
||||
type: object
|
||||
- name: 'getProtocol'
|
||||
description: |
|
||||
Returns the protocol ID the player is using.<br>
|
||||
The protocol ID is an integer used by Minecraft to determine what version a server or client is running.
|
||||
returns: 'Integer representing the protocol version of this player.'
|
||||
type:
|
||||
name: int
|
||||
- name: 'getUUID'
|
||||
description: |
|
||||
Returns the unique ID associated with this player.<br>
|
||||
<br>
|
||||
UUID may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by AdvancedServerList.
|
||||
returns: 'UUID of the player'
|
||||
type:
|
||||
name: UUID
|
||||
type: object
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> GenericPlayer
|
||||
|
||||
A basic interface used to store generic player data to use in placeholder resolving.
|
||||
The different variants of AdvancedServerList implement this into their own class and may provide additional data not available through this interface.
|
||||
|
||||
The following values will always be present, no matter the platform this interface is used on:
|
||||
|
||||
- [Name of the Player](#getname())
|
||||
- [Protocol version of the Player](#getprotocol())
|
||||
- [UUID of the Player](#getuuid())
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getPlayersOnline'
|
||||
description: 'Returns the number of players currently online on the server.'
|
||||
returns: 'Number of players online on the server.'
|
||||
type:
|
||||
name: int
|
||||
- name: 'getPlayersMax'
|
||||
description: 'Returns the number of total players that can join the server.'
|
||||
returns: 'Number of total players that can join the server.'
|
||||
type:
|
||||
name: int
|
||||
- name: 'getHost'
|
||||
description: 'Returns the IP/Domain that got pinged by the player.'
|
||||
returns: 'Possibly-null String containing the IP/Domain that got pinged by the player'
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> GenericServer
|
||||
|
||||
Simple class used to wrap around some generic server data such as online player count, number of total players that can join and the host (IP/Domain) that got pinged by the player.
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
enums:
|
||||
- name: 'true'
|
||||
description: 'Boolean value <code>true</code>'
|
||||
- name: 'false'
|
||||
description: 'Boolean value <code>false</code>'
|
||||
- name: 'not_set'
|
||||
description: 'Boolean value <code>null</code>'
|
||||
|
||||
methods:
|
||||
- name: 'resolve'
|
||||
description: |
|
||||
Returns a NullBool instance based on the provided <code>Boolean</code> value.<br>
|
||||
In case of <code>null</code> being provided will <a href="#not_set"><code>NullBool.NOT_SET</code></a> be returned, otherwise will the corresponding NullBool instance matching the Boolean value be returned.
|
||||
returns: 'NullBool instance based on the provided <code>Boolean</code> value.'
|
||||
parameters:
|
||||
- name: 'bool'
|
||||
description: 'The <code>Boolean</code> value to receive a NullBool instance for.'
|
||||
type: Boolean
|
||||
attributes:
|
||||
- nullable
|
||||
attributes:
|
||||
- static
|
||||
type:
|
||||
name: 'NullBool'
|
||||
type: 'object'
|
||||
- name: 'isNotSet'
|
||||
description: 'Returns whether the NullBool is <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
|
||||
returns: 'True if the instance is <a href="#not_set"><code>NullBool.NOT_SET</code></a>, otherwise false.'
|
||||
type:
|
||||
name: 'boolean'
|
||||
type: 'primitive'
|
||||
- name: 'getOrDefault'
|
||||
description: |
|
||||
Gets the corresponding boolean value associated with the NullBool instance.<br>
|
||||
In the case of NullBool <a href="#isnotset()">not being set</a> will the provided default value be returned.
|
||||
returns: 'True or false depending on the NullBool instance and the provided default value.'
|
||||
parameters:
|
||||
- name: 'def'
|
||||
description: 'The default boolean value to return should the NullBool instance be <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
|
||||
type: boolean
|
||||
type:
|
||||
name: 'boolean'
|
||||
type: 'primitive'
|
||||
---
|
||||
|
||||
# <api__enum></api__enum> NullBool
|
||||
|
||||
Enum used to return a `Boolean` value with a default one should no value be set.
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'PlaceholderProvider'
|
||||
description: 'Constructor used to set the identifier for the class extending the PlaceholderProvider class itself.'
|
||||
parameters:
|
||||
- name: 'identifier'
|
||||
description: 'The identifier to use for the placeholder. Cannot be empty.'
|
||||
type: String
|
||||
attributes:
|
||||
- notnull
|
||||
|
||||
methods:
|
||||
- name: 'parsePlaceholder'
|
||||
description: |
|
||||
Method called by AdvancedServerList's StringReplacer class to replace any appearances of <code>${<identifier> <placeholder>}</code> with whatever value a matching PlaceholderProvider may return.<br>
|
||||
<br>
|
||||
Returning <code>null</code> will be treated as an invalid placeholder by the plugin, making it return the placeholder as-is without any changes.
|
||||
parameters:
|
||||
- name: 'placeholder'
|
||||
type: String
|
||||
description: 'The part of the Placeholder that comes after the identifier and before the closing curly bracket.'
|
||||
- name: 'player'
|
||||
type: GenericPlayer
|
||||
description: 'The <a href="./../objects/genericplayer/"><code>GenericPlayer</code> instance</a> used.'
|
||||
- name: 'server'
|
||||
type: GenericServer
|
||||
description: 'The <a href="./../objects/genericserver/"><code>GenericServer</code> instance</a> used.'
|
||||
returns: 'Possibly-parsed or possibly-null String to replace the placeholder with.'
|
||||
attributes:
|
||||
- nullable
|
||||
- abstract
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
- name: 'getIdentifier'
|
||||
description: 'Returns the identifier used by this PlaceholderProvider instance.'
|
||||
returns: 'String representing the identifier of this PlaceholderProvider instance.'
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
---
|
||||
|
||||
# <api__abstract></api__abstract> <api__class></api__class> PlaceholderProvider
|
||||
|
||||
Abstract class that is used to provide your own Placeholder patterns for AdvancedServerList to parse.
|
||||
|
||||
In order for your class to be considered a valid PlaceholderProvider will you need to set the `identifier` to a non-null, non-empty value without having any spaces in it.
|
||||
Once set, use [`AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)`](advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)) to register your class for AdvancedServerList to use.
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'Builder'
|
||||
|
||||
methods:
|
||||
- name: 'setMotd'
|
||||
description: |
|
||||
Sets a new MOTD to use.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the MOTD.<br>
|
||||
Only the first two entries of the list will be considered and any additional ones discarded.
|
||||
returns: 'This Builder after the motd has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'motd'
|
||||
description: 'The MOTD to use.'
|
||||
type: 'List<String>'
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayers'
|
||||
description: |
|
||||
Sets the players (lines) to use for the hover.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the hover text.
|
||||
returns: 'This Builder after the players have been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'players'
|
||||
description: 'The lines to set for the hover.'
|
||||
type: 'List<String>'
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayerCountText'
|
||||
description: |
|
||||
Sets the text to override the player count with.<br>
|
||||
<br>
|
||||
Set to an empty String or <code>null</code> to not alter the player count text.
|
||||
returns: 'This Builder after the player count text has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'playerCountText'
|
||||
description: 'The text to show in the player count.'
|
||||
type: String
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setFavicon'
|
||||
description: |
|
||||
Sets the value to use for the favicon.<br>
|
||||
The following values are supported:
|
||||
<ul>
|
||||
<li>URL to a valid PNG file.</li>
|
||||
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
|
||||
<li><code>${player uuid}</code> to display the avatar of the player.</li>
|
||||
</ul>
|
||||
returns: 'This Builder after the favicon has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'favicon'
|
||||
description: 'The favicon to set'
|
||||
type: String
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setHidePlayersEnabled'
|
||||
description: |
|
||||
Sets whether the player count should be hidden or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'hidePlayersEnabled'
|
||||
description: 'Whether the player count should be hidden or not.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the extra players feature should be enabled or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the max players feature should be enabled.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayerCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attributes:
|
||||
- nullable
|
||||
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersCount'
|
||||
description: |
|
||||
Sets the number of max players allowed to join this server.<br>
|
||||
This option has no effect when <a href="../#maxplayersenabled()"><code>maxPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setmaxplayersenabled(nullbool)"><code>setMaxPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersCount'
|
||||
description: 'The number of max players to set.'
|
||||
type: Integer
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'build'
|
||||
description: 'Creates a new <a href="./.."><code>ProfileEntry</code> instance</a> with the values set in this Builder.'
|
||||
returns: 'New <a href="./.."><code>ProfileEntry</code> instance</a>.'
|
||||
type:
|
||||
name: 'ProfileEntry'
|
||||
type: 'object'
|
||||
link: './..'
|
||||
---
|
||||
|
||||
# <api__class></api__class> Builder
|
||||
|
||||
Builder class to create a new [`ProfileEntry` instance](index.md).
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'ProfileEntry'
|
||||
description: |
|
||||
Creates a new instance of a ProfileEntry with the given values.<br>
|
||||
It's recommended to use the <a href="./builder/"><code>Builder</code> class</a> for a more convenient configuration of the Settings.
|
||||
parameters:
|
||||
- name: 'motd'
|
||||
description: 'The MOTD to use.'
|
||||
type: 'List<String>'
|
||||
attributes:
|
||||
- notnull
|
||||
- name: 'players'
|
||||
description: 'The players (Lines) to show in the hover.'
|
||||
type: 'List<String>'
|
||||
attributes:
|
||||
- notnull
|
||||
- name: 'playerCountText'
|
||||
description: 'The text to display instead of the player count.'
|
||||
type: String
|
||||
attributes:
|
||||
- nullable
|
||||
- name: 'favicon'
|
||||
description: 'The favicon to use.'
|
||||
type: String
|
||||
attributes:
|
||||
- nullable
|
||||
- name: 'hidePlayersEnabled'
|
||||
description: 'Whether player count should be hidden.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
- name: 'extraPlayersEnabled'
|
||||
description: 'Whether the extra players option should be enabled.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
- name: 'maxPlayersEnabled'
|
||||
description: 'Whether the max players option should be enabled.'
|
||||
type: NullBool
|
||||
attributes:
|
||||
- notnull
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number to add to the online players for the max players number.'
|
||||
type: Integer
|
||||
attributes:
|
||||
- nullable
|
||||
- name: 'maxPlayersCount'
|
||||
description: 'The number to use for the max players count.'
|
||||
type: Integer
|
||||
attributes:
|
||||
- nullable
|
||||
seealso:
|
||||
- name: 'ProfileEntry.Builder'
|
||||
link: './builder/'
|
||||
|
||||
classes:
|
||||
- name: 'Builder'
|
||||
description: 'Builder class to create a new ProfileEntry instance.'
|
||||
type: 'static class'
|
||||
link: 'builder/'
|
||||
|
||||
methods:
|
||||
- name: 'empty'
|
||||
description: |
|
||||
Creates an "empty" PlayerEntry with the following values set:<br>
|
||||
<ul>
|
||||
<li><a href="#motd()"><code>motd</code></a>: Empty List</li>
|
||||
<li><a href="#players()"><code>players</code></a>: Empty List</li>
|
||||
<li><a href="#playercounttext()"><code>playerCountText</code></a>: Empty String</li>
|
||||
<li><a href="#favicon()"><code>favicon</code></a>: Empty String</li>
|
||||
<li><a href="#hideplayersenabled()"><code>hidePlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
|
||||
<li><a href="#extraplayersenabled()"><code>extraPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
|
||||
<li><a href="#maxplayersenabled()"><code>maxPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
|
||||
<li><a href="#extraplayerscount()"><code>extraPlayersCount</code></a>: <code>null</code></li>
|
||||
<li><a href="#maxplayerscount()"><code>maxPlayersCount</code></a>: <code>null</code></li>
|
||||
</ul>
|
||||
returns: 'New ProfileEntry instance with empty/null values defined'
|
||||
attributes:
|
||||
- static
|
||||
type:
|
||||
name: 'ProfileEntry'
|
||||
type: 'object'
|
||||
- name: 'copy'
|
||||
description: |
|
||||
Creates a copy of this ProfileEntry instance.<br>
|
||||
<br>
|
||||
This is simply a convenience method to not have to call <a href="#builder()"><code>builder()</code></a><code>.</code><a href="./builder/#build()"><code>build()</code></a>.<br>
|
||||
If you want to modify the ProfileEntry <a href="#builder()"><code>builder()</code></a> is preferred.
|
||||
returns: 'A copy of this ProfileEntry instance.'
|
||||
seealso:
|
||||
- name: 'builder()'
|
||||
link: '#builder()'
|
||||
type:
|
||||
name: 'ProfileEntry'
|
||||
type: 'object'
|
||||
- name: 'builder'
|
||||
description: |
|
||||
Creates a <a href="./builder/"><code>Builder</code> instance</a> with the values from this ProfileEntry set.<br>
|
||||
Use this method if you would like to modify the ProfileEntry.
|
||||
returns: 'A new <a href="./builder/"><code>Builder</code> instance</a> with the values of this ProfileEntry set.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
link: './builder/'
|
||||
- name: 'motd'
|
||||
description: 'Gets the currently set MOTD of this ProfileEntry.'
|
||||
returns: 'The current MOTD used by this ProfileEntry.'
|
||||
type:
|
||||
name: 'List<String>'
|
||||
type: 'object'
|
||||
- name: 'players'
|
||||
description: 'Gets the currently set players of this ProfileEntry.'
|
||||
returns: 'The current list of players used by this ProfileEntry.'
|
||||
type:
|
||||
name: 'List<String>'
|
||||
type: 'object'
|
||||
- name: 'playerCountText'
|
||||
description: 'Gets the currently set player count text of this ProfileEntry.'
|
||||
returns: 'The current player count text used by this ProfileEntry.'
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
- name: 'favicon'
|
||||
description: |
|
||||
Gets the currently set favicon of this ProfileEntry.<br>
|
||||
Note that the favicon usually is and supports one of the following options:
|
||||
<ul>
|
||||
<li>URL to a valid PNG file</li>
|
||||
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList</li>
|
||||
<li><code>${player uuid}</code> to display the avatar of the player</li>
|
||||
</ul>
|
||||
returns: 'The current favicon used by this ProfileEntry.'
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
- name: 'hidePlayersEnabled'
|
||||
description: |
|
||||
Whether the player count should be hidden or not in this ProfileEntry.<br>
|
||||
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault()"><code>getOrDefault(boolean)</code></a>.
|
||||
returns: 'Whether the player count should be hidden or not in this ProfileEntry.'
|
||||
type:
|
||||
name: 'NullBool'
|
||||
type: 'object'
|
||||
link: '../../objects/nullbool/'
|
||||
- name: 'extraPlayersEnabled'
|
||||
description: |
|
||||
Whether the extra players feature should be used or not in this ProfileEntry.<br>
|
||||
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault()"><code>getOrDefault(boolean)</code></a>.
|
||||
returns: 'Whether the extra players feature should be used or not in this ProfileEntry.'
|
||||
type:
|
||||
name: 'NullBool'
|
||||
type: 'object'
|
||||
link: '../../objects/nullbool/'
|
||||
- name: 'maxPlayersEnabled'
|
||||
description: |
|
||||
Whether the max players feature should be used or not.<br>
|
||||
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault()"><code>getOrDefault(boolean)</code></a>.
|
||||
returns: 'Whether the max players feature should be used or not.'
|
||||
type:
|
||||
name: 'NullBool'
|
||||
type: 'object'
|
||||
link: '../../objects/nullbool/'
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'Gets the currently set number of extra players to use by this ProfileEntry. May be <code>null</code>.'
|
||||
returns: 'Possibly-null integer number of extra players used by this ProfileEntry.'
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Integer'
|
||||
type: 'object'
|
||||
- name: 'maxPlayersCount'
|
||||
description: 'Gets the currently set number of max players of this ProfileEntry.'
|
||||
returns: 'The current number of max players used by this ProfileEntry.'
|
||||
attributes:
|
||||
- nullable
|
||||
type:
|
||||
name: 'Integer'
|
||||
type: 'object'
|
||||
- name: 'isInvalid'
|
||||
description: |
|
||||
Whether this ProfileEntry is considered invalid or not.<br>
|
||||
The ProfileEntry is considered invalid if all the following is true:
|
||||
<ul>
|
||||
<li><a href="#motd()"><code>motd()</code></a> is empty.</li>
|
||||
<li><a href="#players()"><code>players()</code></a> is empty.</li>
|
||||
<li><a href="#playercounttext()"><code>playerCountText()</code></a> is null/empty <b>and</b> <a href="#hideplayersenabled()"><code>hidePlayersEnabled()</code></a> is <code>false</code>.</li>
|
||||
<li><a href="#favicon()"><code>favicon()</code></a> is null/empty.</li>
|
||||
</ul>
|
||||
As long as one of the above is <b>not</b> true is this ProfileEntry considered valid and <code>false</code> will be returned.
|
||||
returns: 'Whether this ProfileEntry is invalid or not.'
|
||||
type:
|
||||
name: 'boolean'
|
||||
type: 'primitive'
|
||||
---
|
||||
|
||||
# <api__record></api__record> ProfileEntry
|
||||
|
||||
This record represents the content found in a server list profile YAML file.
|
||||
The content may come from either the "profiles" list, the options in the file itself (global options) or a mix of both.
|
||||
|
||||
This class is immutable. Use [`builder()`](#builder()) to get a [`Builder` instance](builder.md) with the values of this class added.
|
||||
@@ -0,0 +1,7 @@
|
||||
# API Module
|
||||
|
||||
The `api` module is the main part of the AdvancedServerList API. It contains all necessary classes and methods you would want to use to interact with AdvancedServerList.
|
||||
|
||||
## Module Structure
|
||||
|
||||
{nav}
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
icon: octicons/file-code-24
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
This page contains the various classes and methods that the AdvancedServerList API provides to you for use.
|
||||
Please note that while the nav and page content is auto-generated, the data used for the page content is not. So information may be out of date.
|
||||
|
||||
## API Structure
|
||||
|
||||
{nav}
|
||||
@@ -0,0 +1,3 @@
|
||||
nav:
|
||||
- index.md
|
||||
- ch.andre601.advancedserverlist.api.bukkit: ch.andre601.advancedserverlist.api.bukkit
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'PreServerListSetEvent'
|
||||
parameters:
|
||||
- name: 'entry'
|
||||
type: ProfileEntry
|
||||
|
||||
methods:
|
||||
- name: 'getHandlerList'
|
||||
returns: 'Static <code>HandlerList</code> instance.'
|
||||
attributes:
|
||||
- static
|
||||
type:
|
||||
name: 'HandlerList'
|
||||
type: 'object'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
|
||||
list:
|
||||
- 'getEntry()'
|
||||
- 'setEntry(ProfileEntry)'
|
||||
- 'isCancelled()'
|
||||
- 'setCancelled(boolean)'
|
||||
'org.bukkit.event.Event':
|
||||
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
|
||||
list:
|
||||
- 'getHandlers()'
|
||||
---
|
||||
|
||||
# <api__class></api__class> PreServerListSetEvent
|
||||
|
||||
Called **before** AdvancedServerList modifies the server list.
|
||||
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getPlayer'
|
||||
description: 'Gives the OfflinePlayer embedded in this BukkitPlayer.'
|
||||
returns: 'OfflinePlayer instance'
|
||||
type:
|
||||
name: 'OfflinePlayer'
|
||||
type: 'object'
|
||||
- name: 'hasPlayedBefore'
|
||||
description: |
|
||||
Returns whether this player has played on the server before.<br>
|
||||
<br>
|
||||
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
|
||||
returns: 'Boolean indicating whether this player has played on the server before.'
|
||||
type:
|
||||
name: 'boolean'
|
||||
- name: 'isBanned'
|
||||
description: |
|
||||
Returns whether this player has been banned from the server.<br>
|
||||
<br>
|
||||
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
|
||||
returns: 'Boolean indicating whether this player has been banned from the server.'
|
||||
type:
|
||||
name: 'boolean'
|
||||
- name: 'isWhitelisted'
|
||||
description: |
|
||||
Returns whether this player is whitelisted on the server.<br>
|
||||
<br>
|
||||
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
|
||||
returns: 'Boolean indicating whether this player is whitelisted on the server.'
|
||||
type:
|
||||
name: 'boolean'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
|
||||
list:
|
||||
- 'getName()'
|
||||
- 'getProtocol()'
|
||||
- 'getUUID()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> BukkitPlayer
|
||||
|
||||
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the SpigotMC/Paper server implementation of AdvancedServerList.
|
||||
This interface includes a [`OfflinePlayer` instance](#getplayer()) obtained from the server the plugin runs on alongside some getters to get if the player [has played on the server before](#hasplayedbefore()), [is banned](#isbanned()) or [is whitelisted](#iswhitelisted()). These options actually require a proper OfflinePlayer instance to be present or will otherwise default to `false`.
|
||||
|
||||
This class is useful for cases where you want to use the OfflinePlayer. Simply cast the GenericPlayer instance to a SpigotPlayer (Granted that it actually is an instance of it to begin with).
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getWorlds'
|
||||
description: 'Returns a <code>Map<String, World></code> where the key is the name of the World and the value the world of the server.'
|
||||
returns: 'Possibly-empty Map containing pairs of Strings and Worlds.'
|
||||
type:
|
||||
name: 'Map<String, World>'
|
||||
type: 'object'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericServer':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
|
||||
list:
|
||||
- 'getPlayersOnline()'
|
||||
- 'getPlayersMax()'
|
||||
- 'getHost()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> BukkitServer
|
||||
|
||||
Spigot/Paper specific instance of a [`GenericServer`](../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md).
|
||||
This interface includes a [Map of Worlds](#getworlds()) the server currently has.
|
||||
|
||||
This interface is useful for cases where you want to get the worlds of the Server itself, by simply casting your GenericServer instance to a BukkitServer one. Make sure to do proper instanceof checks first before attempting to cast.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Bukkit Module
|
||||
|
||||
The `platform-bukkit` module contains classes for platform-specific things such as Server events or a Server-specific CachedPlayer instance.
|
||||
|
||||
## Module Structure
|
||||
|
||||
{nav}
|
||||
@@ -0,0 +1,3 @@
|
||||
nav:
|
||||
- index.md
|
||||
- ch.andre601.advancedserverlist.api.bungeecord: ch.andre601.advancedserverlist.api.bungeecord
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'PreServerListSetEvent'
|
||||
parameters:
|
||||
- name: 'entry'
|
||||
type: ProfileEntry
|
||||
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
|
||||
list:
|
||||
- 'getEntry()'
|
||||
- 'setEntry(ProfileEntry)'
|
||||
- 'isCancelled()'
|
||||
- 'setCancelled(boolean)'
|
||||
---
|
||||
|
||||
# <api__class></api__class> PreServerListSetEvent
|
||||
|
||||
Called **before** AdvancedServerList modifies the server list.
|
||||
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
|
||||
list:
|
||||
- 'getName()'
|
||||
- 'getProtocol()'
|
||||
- 'getUUID()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> BungeePlayer
|
||||
|
||||
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the BungeeCord proxy implementation of AdvancedServerList.
|
||||
|
||||
To get an instance of this class from a GenericPlayer instance, simply cast it to a BungeePlayer (Granted that the GenericPlayer instance actually is a BungeePlayer instance).
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getServers'
|
||||
description: 'Returns a <code>Map<String, ServerInfo></code> where the key is the name of the server and the value the ServerInfo of the proxy.'
|
||||
returns: 'Possibly-empty Map containing pairs of Strings and ServerInfos.'
|
||||
type:
|
||||
name: 'Map<String, ServerInfo>'
|
||||
type: 'object'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericServer':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
|
||||
list:
|
||||
- 'getPlayersOnline()'
|
||||
- 'getPlayersMax()'
|
||||
- 'getHost()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> BungeeProxy
|
||||
@@ -0,0 +1,7 @@
|
||||
# BungeeCord Module
|
||||
|
||||
The `platform-bungeecord` module contains classes for platform-specific things such as Proxy events or a Proxy-specific CachedPlayer instance.
|
||||
|
||||
## Module Structure
|
||||
|
||||
{nav}
|
||||
@@ -0,0 +1,3 @@
|
||||
nav:
|
||||
- index.md
|
||||
- ch.andre601.advancedserverlist.api.velocity: ch.andre601.advancedserverlist.api.velocity
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'PreServerListSetEvent'
|
||||
parameters:
|
||||
- name: 'entry'
|
||||
type: ProfileEntry
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
|
||||
list:
|
||||
- 'getEntry()'
|
||||
- 'setEntry(ProfileEntry)'
|
||||
- 'isCancelled()'
|
||||
- 'setCancelled(boolean)'
|
||||
---
|
||||
|
||||
# <api__class></api__class> PreServerListSetEvent
|
||||
|
||||
Called **before** AdvancedServerList modifies the server list.
|
||||
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getVersion'
|
||||
description: 'Returns the <a href="../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/#getprotocol()">protocol version</a> of the player in a readable MC version format (i.e. 1.19.3).'
|
||||
returns: 'The readable MC version the player uses.'
|
||||
type:
|
||||
name: 'String'
|
||||
type: 'object'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
|
||||
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
|
||||
list:
|
||||
- 'getName()'
|
||||
- 'getProtocol()'
|
||||
- 'getUUID()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> VelocityPlayer
|
||||
|
||||
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the Velocity proxy implementation of AdvancedServerList.
|
||||
Provides a [`getVersion()` method](#getversion()) to get the MC version used as a readable String (i.e. 1.19.3) rather than just the protocol version.
|
||||
|
||||
To get an instance of this class from a GenericPlayer instance, simply cast it to a VelocityPlayer (Granted that the GenericPlayer instance actually is a VelocityPlayer instance).
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
methods:
|
||||
- name: 'getServers'
|
||||
description: 'Returns a <code>Map<String, RegisteredServer></code> where the key is the name of the server and the value the RegisteredServer of the proxy.'
|
||||
returns: 'Possibly-empty Map containing pairs of Strings and RegisteredServers.'
|
||||
type:
|
||||
name: 'Map<String, RegisteredServer>'
|
||||
type: 'object'
|
||||
|
||||
inherits:
|
||||
'ch.andre601.advancedserverlist.api.objects.GenericServer':
|
||||
link: '../../../api/objects/genericserver/'
|
||||
list:
|
||||
- 'getPlayersOnline()'
|
||||
- 'getPlayersMax()'
|
||||
- 'getHost()'
|
||||
---
|
||||
|
||||
# <api__interface></api__interface> VelocityProxy
|
||||
@@ -0,0 +1,7 @@
|
||||
# Velocity Module
|
||||
|
||||
The `platform-velocity` module contains classes for platform-specific things such as Proxy events or a Proxy-specific CachedPlayer instance.
|
||||
|
||||
## Module Structure
|
||||
|
||||
{nav}
|
||||
@@ -0,0 +1,204 @@
|
||||
# API Reference Docs Structure
|
||||
|
||||
The Reference docs follow a specific mixture of manually created and auto-generated page content.
|
||||
|
||||
A page may look something like this:
|
||||
```markdown
|
||||
---
|
||||
template: api-doc.html
|
||||
|
||||
constructors:
|
||||
- name: 'Constructor'
|
||||
description: 'Creates a new instance of this class.'
|
||||
|
||||
methods:
|
||||
- name: 'getString'
|
||||
description: 'Gets a String.'
|
||||
type:
|
||||
name: String
|
||||
type: object
|
||||
---
|
||||
|
||||
# <api__class></api__class> Constructor
|
||||
|
||||
An example class to show how the page structure may look like.
|
||||
```
|
||||
|
||||
## custom HTML tags
|
||||
|
||||
There is a collection of custom HTML tags that are used to render specific text in certain styles.
|
||||
Below is a list of all custom tags. Note that these tags only render on the actual site and not within the repository when viewing the source.
|
||||
|
||||
- `<api__class></api__class>`: <api__class></api__class>
|
||||
- `<api__interface></api__interface>`: <api__interface></api__interface>
|
||||
- `<api__enum></api__enum>`: <api__enum></api__enum>
|
||||
- `<api__record></api__record>`: <api__record></api__record>
|
||||
- `<api__abstract></api__abstract>`: <api__abstract></api__abstract>
|
||||
- `<api__static></api__static>`: <api__static></api__static>
|
||||
- `<api__final></api__final>`: <api__final></api__final>
|
||||
- `<api__notnull></api__notnull>`: <api__notnull></api__notnull>
|
||||
- `<api__nullable></api__nullable>`: <api__nullable></api__nullable>
|
||||
- `<api__deprecated></api__deprecated>`: <api__deprecated></api__deprecated>
|
||||
|
||||
In addition are there two classes used within `span` tags to colour the text, to indicate their type:
|
||||
|
||||
- `<span class="api-type__object">Object</span>`: <span class="api-type__object">Object</span>
|
||||
- `<span class="api-type__primitive">primitive</span>`: <span class="api-type__primitive">primitive</span>
|
||||
|
||||
## Auto-generated content
|
||||
|
||||
A page template is used to auto-generate the page content based on available YAML frontmatter.
|
||||
Depending on the frontmatter available will the template call a jinja2 Macro to generate a Summary and Detailed info on the page for the respective frontmatter data.
|
||||
|
||||
There are 5 frontmatter options, each following a specific structure:
|
||||
|
||||
- [`Constructors`](#constructors)
|
||||
- [`Nested Classes`](#nested-classes)
|
||||
- [`Enum Constants`](#enum constants)
|
||||
- [`Methods`](#methods)
|
||||
- [`Inherits`](#inherits)
|
||||
|
||||
### Constructors
|
||||
|
||||
```yaml
|
||||
constructors:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
parameters:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
type: '<string>'
|
||||
attributes:
|
||||
- '<string>'
|
||||
deprecated: '<string>'
|
||||
throws:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
seealso:
|
||||
- name: '<string>'
|
||||
link: '<string>'
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `name` - The name to display for the Constructor summary and detail. This should include any parameters the Constructor has, but without any parameter name.
|
||||
- `description` - The description to display for the Constructor.
|
||||
- `parameters` - List of parameters to display.
|
||||
- `name` - Name of the parameter to display.
|
||||
- `description` - Description of the parameter.
|
||||
- `type` - The type this parameter is.
|
||||
- `attributes` - List of attributes (i.e. nullability) to display. The provided values will be turned into `<api__{name}></api__{name}>` tags that will be prependet to the parameter name.
|
||||
- `deprecated` - Adds a notice about the deprecation of this Constructor in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
|
||||
- `throws` - List of possible throws to display.
|
||||
- `name` - Name of the throw to display.
|
||||
- `description` - Description of the throw.
|
||||
- `seealso` - List of "See also" text to display.
|
||||
- `name` - Name of the See also link.
|
||||
- `link` - Link (Relative, absolute or URL) to use for the See also text.
|
||||
|
||||
### Nested Classes
|
||||
|
||||
```yaml
|
||||
classes:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
type: '<string>'
|
||||
link: '<string>'
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `name` - The name to display for the Nested Classes Summary.
|
||||
- `description` - The description of the nested class.
|
||||
- `type` - Modifier and type of the nested class.
|
||||
- `link` - Link to the nested class.
|
||||
|
||||
### Enum Constants
|
||||
|
||||
```yaml
|
||||
enums:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
type: '<string>'
|
||||
deprecated: '<string>'
|
||||
seealso:
|
||||
- name: '<string>'
|
||||
link: '<string>'
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `name` - The name to display for the Enum summary and detail. This should include any parameters the Enum has, but without any parameter name.
|
||||
- `description` - The description to display for the Enum.
|
||||
- `type` - The return type to display. Will default to `{{ page.title }}` if not set.
|
||||
- `deprecated` - Adds a notice about the deprecation of this Enum in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
|
||||
- `seealso` - List of "See also" text to display.
|
||||
- `name` - Name of the See also link.
|
||||
- `link` - Link (Relative, absolute or URL) to use for the See also text.
|
||||
|
||||
### Methods
|
||||
|
||||
```yaml
|
||||
methods:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
type:
|
||||
name: '<string>'
|
||||
type: '<string>'
|
||||
link: '<string>'
|
||||
attributes:
|
||||
- '<string>'
|
||||
parameters:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
type: '<string>'
|
||||
attributes:
|
||||
- '<string>'
|
||||
returns: '<string>'
|
||||
deprecated: '<string>'
|
||||
throws:
|
||||
- name: '<string>'
|
||||
description: '<string>'
|
||||
seealos:
|
||||
- name: '<string>'
|
||||
link: '<string>'
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `name` - The name to display for the Method summary and detail. This should include any parameters the Method has, but without any parameter name.
|
||||
- `description` - The description to display for the Method.
|
||||
- `type` - Options for object type to display.
|
||||
- `name` - Displayed name of the object.
|
||||
- `type` - Object type. Can be either `object` or `primitive` which would be used in a class name for styling.
|
||||
- `link` - Link (Relative, absolute or URL) to use for the type name.
|
||||
- `attributes` - List of attributes (i.e. nullability) to display. The provided values will be turned into `<api__{name}></api__{name}>` tags that will be prependet to the name.
|
||||
- `parameters` - List of parameters to display.
|
||||
- `name` - Name of the parameter to display.
|
||||
- `description` - Description of the parameter.
|
||||
- `type` - The type this parameter is.
|
||||
- `attributes` - List of attributes (i.e. nullability) to display. The provided values will be turned into `<api__{name}></api__{name}>` tags that will be prependet to the parameter name.
|
||||
- `returns` - Possible return values.
|
||||
- `deprecated` - Adds a notice about the deprecation of this Method in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
|
||||
- `throws` - List of possible throws to display.
|
||||
- `name` - Name of the throw to display.
|
||||
- `description` - Description of the throw.
|
||||
- `seealso` - List of "See also" text to display.
|
||||
- `name` - Name of the See also link.
|
||||
- `link` - Link (Relative, absolute or URL) to use for the See also text.
|
||||
|
||||
### Inherits
|
||||
|
||||
```yaml
|
||||
inherits:
|
||||
'<string>':
|
||||
link: '<string>'
|
||||
methods:
|
||||
- '<string>'
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `inherits.<string>` - Classpath used to display in the text `Methods inherited from <string>`
|
||||
- `link` - Link to use for the classpath text.
|
||||
- `methods` - List of strings to display. Each will be linked using `{link}#{method}`
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
template: redirect.html
|
||||
|
||||
location: https://github.com/Andre601/asl-api
|
||||
|
||||
title: Source Code
|
||||
icon: octicons/mark-github-16
|
||||
---
|
||||
|
||||
<!-- Comment to trigger proper build -->
|
||||
@@ -0,0 +1 @@
|
||||
hide: true
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user