mirror of
https://codeberg.org/Andre601/AdvancedServerList.git
synced 2026-11-05 17:02:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
73d94e99e4 | ||
|
|
389ed1df53 | ||
|
|
5f4a07cb71 | ||
|
|
b16f5e193c | ||
|
|
1c423e6cfa | ||
|
|
a27dcd5248 | ||
|
|
17bd1782fb | ||
|
|
96c44dafe2 | ||
|
|
d4d9a7e3c5 | ||
|
|
9f0f7297f0 | ||
|
|
691cb14c63 | ||
|
|
8670ea026e | ||
|
|
27c019c00d | ||
|
|
d34ea9c2ad | ||
|
|
74a61f2e09 | ||
|
|
5e550d5a7f | ||
|
|
b1180c0a8e | ||
|
|
fc4253acce | ||
|
|
a4e2cc29d5 | ||
|
|
95097a581a | ||
|
|
aff3aefb72 | ||
|
|
089e56be70 | ||
|
|
e7b8f1a0dc | ||
|
|
a2252f55c4 | ||
|
|
dcd6a1e867 | ||
|
|
24bf5193ff | ||
|
|
2e0068115d | ||
|
|
1accbfb5f0 | ||
|
|
f0f520d12b | ||
|
|
3edef1c2e4 | ||
|
|
0c835da51a | ||
|
|
1dc937e7b6 | ||
|
|
8d63d92ab0 | ||
|
|
2ade1c2506 | ||
|
|
c1b699aab7 | ||
|
|
6d5fc7a697 | ||
|
|
a5acd73482 | ||
|
|
f1afcc0fd8 | ||
|
|
9922485c34 | ||
|
|
9ee543fe28 | ||
|
|
da4eccdfcc | ||
|
|
89f5a45809 | ||
|
|
29664fde70 | ||
|
|
40f362f1de | ||
|
|
07cef34a37 | ||
|
|
afa80581e5 | ||
|
|
db2366e2ce | ||
|
|
b54151813f | ||
|
|
2be041a613 | ||
|
|
86411571ef | ||
|
|
d80236fef8 | ||
|
|
fe6fae58e3 | ||
|
|
b2e2b18d33 | ||
|
|
d8e54c7ff0 | ||
|
|
f0743d691f | ||
|
|
4b68253c7d | ||
|
|
d1cee68355 | ||
|
|
07d3ea088a | ||
|
|
912fb967fb | ||
|
|
d960644cc1 | ||
|
|
34908b4123 | ||
|
|
00466f1ffb | ||
|
|
d05527634d | ||
|
|
6e017219b4 | ||
|
|
8fa66867bc | ||
|
|
1df167b66a | ||
|
|
ffee02095f | ||
|
|
0fc7c7f047 | ||
|
|
c8ae03da16 | ||
|
|
dc4165465e | ||
|
|
05c32cd721 | ||
|
|
ccd326f036 | ||
|
|
e9117c8040 | ||
|
|
116714f9a4 | ||
|
|
06f025c50e | ||
|
|
25787e8c51 | ||
|
|
741ca73c62 | ||
|
|
50944717ea | ||
|
|
89d2d04c12 | ||
|
|
2aa53c556a | ||
|
|
7eb67c1571 | ||
|
|
e6ebf0964b | ||
|
|
2f7bbe8bae | ||
|
|
cc3e75f41b | ||
|
|
7706dd245f | ||
|
|
d4018ff666 | ||
|
|
4c7a2ca94d | ||
|
|
21632711ea | ||
|
|
e82ed84c11 | ||
|
|
1f44b34dd2 | ||
|
|
b7b6d8b82b | ||
|
|
53e270b183 | ||
|
|
f633bb393e | ||
|
|
41ac71e346 | ||
|
|
e04b9b4a09 | ||
|
|
42907c7f74 | ||
|
|
69bf90c20f | ||
|
|
b2f70b605c | ||
|
|
fb5e4b57bc | ||
|
|
49c17d941a | ||
|
|
ec6b852497 | ||
|
|
9bd2c4b8d5 | ||
|
|
57bb677578 | ||
|
|
40c4726fd6 | ||
|
|
c1eefbe114 | ||
|
|
082345fb66 | ||
|
|
1bedc472b3 | ||
|
|
aa9d6ff7d2 | ||
|
|
5e4fc3d69c | ||
|
|
b429e75797 | ||
|
|
c2eacf716f | ||
|
|
aca52b528d | ||
|
|
cd1469c554 | ||
|
|
ce4347ca1e | ||
|
|
acc59e0af7 | ||
|
|
099abcda67 | ||
|
|
2ced4db199 | ||
|
|
4f7c16ae5a | ||
|
|
06739bb68e | ||
|
|
d1c9ab5b82 | ||
|
|
d06f767e51 | ||
|
|
02e0821bd0 | ||
|
|
981d4e8146 | ||
|
|
05667c0f87 | ||
|
|
54f0f59925 | ||
|
|
de2c8a7547 | ||
|
|
50c31a3348 | ||
|
|
93e94aa9d3 | ||
|
|
1f71aeb7e5 | ||
|
|
5d01adfa49 | ||
|
|
da7e3eca09 | ||
|
|
66b305bbea | ||
|
|
3c1abf4f3a | ||
|
|
856be1e32e | ||
|
|
5303bb00a0 | ||
|
|
9b43428e5d | ||
|
|
d34d926f9a | ||
|
|
844279b32d | ||
|
|
5916e9b495 | ||
|
|
72384488d8 | ||
|
|
11a8b07f32 | ||
|
|
cd7dfc9c15 | ||
|
|
c715ed6163 | ||
|
|
5a35ebbef4 | ||
|
|
830eee5da3 | ||
|
|
09b845e86e | ||
|
|
a2bdd5c4e5 | ||
|
|
a72c0d326a | ||
|
|
40ef2e35d4 | ||
|
|
8422d6d2de | ||
|
|
4683dab513 | ||
|
|
d5947b20e5 | ||
|
|
147f01dd1b | ||
|
|
a6eddb3828 | ||
|
|
41e11f79cc | ||
|
|
66597ce7fa | ||
|
|
77f17b202c |
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
-18
@@ -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@2/assets/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@2/assets/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@2/assets/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@2/assets/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@2/assets/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,35 +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://raw.githubusercontent.com/intergrav/devins-badges/v2/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://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/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://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/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://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/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://github.com/Andre601/AdvancedServerList/wiki/Profiles
|
||||
[conditions]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#conditions
|
||||
[placeholders]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#placeholders
|
||||
[minimessage]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#minimessage
|
||||
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
|
||||
[modrinth]: https://modrinth.com/plugin/advancedserverlist
|
||||
[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==
|
||||
+10
-10
@@ -17,21 +17,13 @@ updates:
|
||||
- 'Type: Update Dependency'
|
||||
- 'Target: Core'
|
||||
- package-ecosystem: maven
|
||||
directory: "/paper"
|
||||
directory: "/bukkit"
|
||||
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'
|
||||
- 'Target: Bukkit'
|
||||
- package-ecosystem: maven
|
||||
directory: "/velocity"
|
||||
schedule:
|
||||
@@ -48,3 +40,11 @@ updates:
|
||||
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/**"]
|
||||
@@ -0,0 +1,100 @@
|
||||
name: Create PR Artifacts
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- 'docs/**'
|
||||
- '.gitignore'
|
||||
- 'LICENSE'
|
||||
- 'README.md'
|
||||
- 'mkdocs.yml'
|
||||
- 'requirements.txt'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.head_ref }}'
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
buildArtifacts:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
comment_id: ${{ steps.comment.outputs.comment-id }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- 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]'
|
||||
body-includes: '<!-- pr-build comment -->'
|
||||
- name: Print Comment info
|
||||
run: |
|
||||
echo "Comment ID: ${{ steps.find-comment.outputs.comment-id }}"
|
||||
echo "Comment Author: ${{ steps.find-comment.outputs.comment-author }}"
|
||||
echo "Comment created at: ${{ steps.find-comment.outputs.comment-created-at }}"
|
||||
- name: Post/Update Comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
id: comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
body-path: .github/assets/pr-comments/building.md
|
||||
- name: Set up JDK 1.16
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '16'
|
||||
cache: 'maven'
|
||||
- name: Obtain short Commit SHA
|
||||
id: get-commit
|
||||
run: 'echo "sha_short=$(git rev-parse --short ${{ github.event.pull_request.head.sha }})" >> $GITHUB_OUTPUT'
|
||||
- name: Build Jar files
|
||||
run: mvn clean install
|
||||
env:
|
||||
COMMIT_SHA: ${{ steps.get-commit.outputs.sha_short }}
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: AdvancedServerList-Artifacts
|
||||
path: '*/target/AdvancedServerList-*.jar'
|
||||
if-no-files-found: error
|
||||
commentOnFail:
|
||||
needs: [buildArtifacts]
|
||||
if: failure()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- name: Render Markdown Template
|
||||
id: render
|
||||
uses: chuhlomin/render-template@v1.7
|
||||
with:
|
||||
template: './.github/assets/pr-comments/failed.md'
|
||||
vars: |
|
||||
commit: ${{ github.event.pull_request.head.sha }}
|
||||
logs: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
- name: Update Comment (Failure)
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ needs.buildArtifacts.outputs.comment_id }}
|
||||
edit-mode: replace
|
||||
body: ${{ steps.render.outputs.result }}
|
||||
@@ -1,30 +1,39 @@
|
||||
name: Deploy Site
|
||||
name: 'Deploy Site (Push)'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'mkdocs.yml'
|
||||
- 'mkdocs-theme/**'
|
||||
- 'requirements.txt'
|
||||
branches:
|
||||
- master
|
||||
tags-ignore:
|
||||
- '**'
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.7
|
||||
python-version: 3.x
|
||||
- name: Create/Get Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: ${{ github.ref }}
|
||||
path: .cache
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip setuptools
|
||||
python -m pip install -r requirements.txt
|
||||
- name: Deploy Files
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "actions@github.com"
|
||||
mkdocs gh-deploy --force
|
||||
- name: Deploy Files
|
||||
run: mkdocs gh-deploy --force
|
||||
@@ -0,0 +1,99 @@
|
||||
name: Comment on Pull request
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
types:
|
||||
- completed
|
||||
workflows:
|
||||
- 'Create PR Artifacts'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Get Artifact and Pull request info
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }} # Needs to be set as env variable so that 'gh api' can be used.
|
||||
WORKFLOW_RUN_EVENT_OBJ: ${{ toJSON(github.event.workflow_run) }}
|
||||
OWNER: ${{ github.repository_owner }}
|
||||
REPO: ${{ github.event.repository.name }}
|
||||
run: |
|
||||
PREVIOUS_JOB_ID=$(jq -r '.id' <<< "$WORKFLOW_RUN_EVENT_OBJ")
|
||||
echo "Previous Job ID: $PREVIOUS_JOB_ID"
|
||||
echo "PREVIOUS_JOB_ID=$PREVIOUS_JOB_ID" >> "$GITHUB_ENV"
|
||||
|
||||
SUITE_ID=$(jq -r '.check_suite_id' <<< "$WORKFLOW_RUN_EVENT_OBJ")
|
||||
echo "Previous Suite ID: $SUITE_ID"
|
||||
echo "SUITE_ID=$SUITE_ID" >> "$GITHUB_ENV"
|
||||
|
||||
ARTIFACT_ID=$(gh api "/repos/$OWNER/$REPO/actions/artifacts" \
|
||||
--jq ".artifacts.[] |
|
||||
select(.workflow_run.id==${PREVIOUS_JOB_ID}) |
|
||||
select(.expired==false) |
|
||||
.id")
|
||||
|
||||
echo "Artifact ID: $ARTIFACT_ID"
|
||||
echo "ARTIFACT_ID=$ARTIFACT_ID" >> "$GITHUB_ENV"
|
||||
|
||||
ARTIFACT_EXPIRE_DATE=$(gh api "/repos/$OWNER/$REPO/actions/artifacts" \
|
||||
--jq ".artifacts.[] |
|
||||
select(.workflow_run.id==${PREVIOUS_JOB_ID}) |
|
||||
select(.expired==false) |
|
||||
.expires_at")
|
||||
|
||||
echo "Artifact Expire Date: $ARTIFACT_EXPIRE_DATE"
|
||||
echo "ARTIFACT_EXPIRE_DATE=$ARTIFACT_EXPIRE_DATE" >> "$GITHUB_ENV"
|
||||
|
||||
PR_NUMBER=$(jq -r '.pull_requests[0].number' \
|
||||
<<< "$WORKFLOW_RUN_EVENT_OBJ")
|
||||
|
||||
echo "Pull request Number: $PR_NUMBER"
|
||||
echo "PR_NUMBER=$PR_NUMBER" >> "$GITHUB_ENV"
|
||||
|
||||
HEAD_SHA=$(jq -r '.pull_requests[0].head.sha' \
|
||||
<<< "$WORKFLOW_RUN_EVENT_OBJ")
|
||||
|
||||
echo "Head SHA: $HEAD_SHA"
|
||||
echo "HEAD_SHA=$HEAD_SHA" >> "$GITHUB_ENV"
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ env.PR_NUMBER }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: '<!-- pr-build comment -->'
|
||||
- name: Print Comment info
|
||||
run: |
|
||||
echo "Comment ID: ${{ steps.find-comment.outputs.comment-id }}"
|
||||
echo "Comment Author: ${{ steps.find-comment.outputs.comment-author }}"
|
||||
echo "Comment created at: ${{ steps.find-comment.outputs.comment-created-at }}"
|
||||
- name: Render Markdown Template
|
||||
id: render
|
||||
uses: chuhlomin/render-template@v1.7
|
||||
env:
|
||||
JOB_PATH: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ env.PREVIOUS_JOB_ID }}"
|
||||
ARTIFACT_URL: "https://nightly.link/${{ github.repository }}/suites/${{ env.SUITE_ID }}/artifacts/${{ env.ARTIFACT_ID }}"
|
||||
ARTIFACT_EXPIRE_DATE: "${{ env.ARTIFACT_EXPIRE_DATE }}"
|
||||
HEAD_SHA: "${{ env.HEAD_SHA }}"
|
||||
with:
|
||||
template: './.github/assets/pr-comments/success.md'
|
||||
timezone: Europe/Zurich
|
||||
vars: |
|
||||
commit: ${{ env.HEAD_SHA }}
|
||||
logs: ${{ env.JOB_PATH }}
|
||||
download: ${{ env.ARTIFACT_URL }}
|
||||
expire: ${{ env.ARTIFACT_EXPIRE_DATE }}
|
||||
- name: Update Comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
issue-number: ${{ env.PR_NUMBER }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
body: ${{ steps.render.outputs.result }}
|
||||
@@ -13,8 +13,16 @@ on:
|
||||
jobs:
|
||||
buildJars:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
plugin_release: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- 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:
|
||||
@@ -23,32 +31,13 @@ jobs:
|
||||
cache: 'maven'
|
||||
- name: Build Jar files
|
||||
run: mvn clean install
|
||||
- name: Save BungeeCord Jar file
|
||||
- name: Save All files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-bungeecord
|
||||
path: bungeecord/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Paper Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-paper
|
||||
path: paper/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Spigot Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-spigot
|
||||
path: spigot/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Velocity Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-velocity
|
||||
path: velocity/target/AdvancedServerList-*.jar
|
||||
name: asl-files
|
||||
path: |
|
||||
*/target/AdvancedServerList-*.jar
|
||||
hangar-uploader/target/HangarUploader.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
publish:
|
||||
@@ -61,45 +50,76 @@ jobs:
|
||||
loaders: |
|
||||
bungeecord
|
||||
waterfall
|
||||
- platforms: Paper
|
||||
directory: paper
|
||||
loaders: paper
|
||||
- platforms: Spigot
|
||||
directory: spigot
|
||||
loaders: spigot
|
||||
dependencies: 'papiproxybridge@1.3(optional)'
|
||||
- platforms: Spigot, Paper, Folia
|
||||
directory: bukkit
|
||||
loaders: |
|
||||
spigot
|
||||
paper
|
||||
folia
|
||||
dependencies: ''
|
||||
- platforms: Velocity
|
||||
directory: velocity
|
||||
loaders: velocity
|
||||
dependencies: 'papiproxybridge@1.3(optional)'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get Jar files
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: asl-${{ matrix.directory }}
|
||||
path: ${{ matrix.directory }}/target
|
||||
- name: Get Version
|
||||
id: github-release
|
||||
run: |
|
||||
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
|
||||
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
|
||||
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
|
||||
uses: Kir-Antipov/mc-publish@v3.2
|
||||
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.3
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
|
||||
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
|
||||
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
|
||||
game-version-filter: releases
|
||||
game-versions: '>=1.19'
|
||||
java: 16
|
||||
dependencies: ${{ matrix.dependencies }}
|
||||
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.3
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
|
||||
version: ${{ needs.buildJars.outputs.plugin_release }}
|
||||
version-type: beta
|
||||
files: ${{ matrix.directory }}/target/AdvancedServerList-*.jar
|
||||
loaders: ${{ matrix.loaders }}
|
||||
game-version-filter: releases
|
||||
game-versions: '>=1.19'
|
||||
java: 16
|
||||
dependencies: ${{ matrix.dependencies }}
|
||||
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 }}
|
||||
@@ -0,0 +1,58 @@
|
||||
when:
|
||||
- event: tag
|
||||
branch: master
|
||||
|
||||
steps:
|
||||
createFiles:
|
||||
image: maven:3.9.4-eclipse-temurin-17
|
||||
commands:
|
||||
# Create the jar files.
|
||||
- mvn clean install
|
||||
#uploadFiles:
|
||||
# image: badouralix/curl-jq
|
||||
# secrets:
|
||||
# - cb_token
|
||||
# commands:
|
||||
# # Get release info and setup env vars.
|
||||
# - |-
|
||||
# export JSON=`curl --location "https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases?limit=10" \
|
||||
# --header 'Authorization: token $CB_TOKEN' \
|
||||
# --header 'Accept: application/json' -s -S \
|
||||
# --fail-with-body | jq ".[] | select (.tag_name==\"$CI_COMMIT_TAG\").")`
|
||||
# - export PLUGIN_CHANGELOG=$( echo $JSON | jq -r '.body' )
|
||||
# - export PLUGIN_PRE_RELEASE=$( echo $JSON | jq -r '.prerelease' )
|
||||
# - export RELEASE_ID=$( echo $JSON | jq -r '.id' )
|
||||
# # Upload release assets to Codeberg release
|
||||
# - |-
|
||||
# curl -X POST --location "https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/$RELEASE_ID/assets" \
|
||||
# --header "Authorization: token $CB_TOKEN" \
|
||||
# --header "Content-Type: multipart/form-data" -s -S \
|
||||
# --form "attachment=@bukkit/target/AdvancedServerList-Bukkit-${CI_COMMIT_TAG##v}.jar;type=application/octet-stream" \
|
||||
# --fail-with-body
|
||||
# - |-
|
||||
# curl -X POST --location "https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/$RELEASE_ID/assets" \
|
||||
# --header "Authorization: token $CB_TOKEN" \
|
||||
# --header "Content-Type: multipart/form-data" -s -S \
|
||||
# --form "attachment=@bungeecord/target/AdvancedServerList-BungeeCord-${CI_COMMIT_TAG##v}.jar;type=application/octet-stream" \
|
||||
# --fail-with-body
|
||||
# - |-
|
||||
# curl -X POST --location "https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/$RELEASE_ID/assets" \
|
||||
# --header "Authorization: token $CB_TOKEN" \
|
||||
# --header "Content-Type: multipart/form-data" -s -S \
|
||||
# --form "attachment=@velocity/target/AdvancedServerList-Velocity-${CI_COMMIT_TAG##v}.jar;type=application/octet-stream" \
|
||||
# --fail-with-body
|
||||
uploadToModrinthAndMaven:
|
||||
image: eclipse-temurin
|
||||
secrets:
|
||||
- cb_token
|
||||
- modrinth_api_token
|
||||
- hangar_api_token
|
||||
commands:
|
||||
# Move VersionUploader.jar
|
||||
- cd version-uploader/target/
|
||||
- mv VersionUploader.jar ../../
|
||||
- cd ../../
|
||||
# Create Modrinth releases
|
||||
- java -jar VersionUploader.jar --modrinth
|
||||
# Create Hangar release
|
||||
- java -jar VersionUploader.jar --hangar
|
||||
@@ -0,0 +1,28 @@
|
||||
when:
|
||||
- branch: master
|
||||
event: push
|
||||
path:
|
||||
include: ['requirements.txt', 'mkdocs.yml', 'docs/**']
|
||||
|
||||
steps:
|
||||
buildDocs:
|
||||
image: python
|
||||
secrets:
|
||||
- cb_token
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- git config --global --add safe.directory /woodpecker/src/codeberg.org/Andre601/blog-source/website
|
||||
- git config --global user.email "github@andre601.ch"
|
||||
- git config --global user.name "CI Website Builder"
|
||||
- git fetch --unshallow
|
||||
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
|
||||
- chmod -R a+w site
|
||||
- python -m pip install --upgrade pip
|
||||
- python -m pip install -r requirements.txt
|
||||
- mkdocs build
|
||||
- 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" )) [CI SKIP]"
|
||||
- git push
|
||||
@@ -1,26 +1,32 @@
|
||||
# AdvancedServerList
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/available/modrinth_vector.svg" height="64" align="right" alt="modrinth" title="Available on Modrinth">
|
||||
</a>
|
||||
|
||||
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>
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
|
||||
<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/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
|
||||
<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>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/bungeecord_vector.svg" height="64" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/bungeecord_vector.svg" height="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@2/assets/minimal/supported/waterfall_vector.svg" height="64" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/waterfall_vector.svg" height="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@2/assets/minimal/supported/velocity_vector.svg" height="64" alt="platform-velocity" title="Tested on Velocity">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/velocity_vector.svg" height="64" alt="platform-velocity" title="Tested on Velocity">
|
||||
</a>
|
||||
|
||||
## What is a Server List Profile?
|
||||
@@ -54,10 +60,13 @@ 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 |
|
||||
| Dependency | Platforms | Required? |
|
||||
|-------------------|-------------------------------------|-----------|
|
||||
| [ProtocolLib] | Spigot | Yes |
|
||||
| [PlaceholderAPI] | Spigot, Paper | No |
|
||||
| [ViaVersion] | Spigot, Paper | No |
|
||||
| [PAPIProxyBridge] | Spigot, Paper, BungeeCord, Velocity | No |
|
||||
| [Maintenance] | Spigot, Paper, BungeeCord, Velocity | No |
|
||||
|
||||
## Statistics
|
||||
|
||||
@@ -71,30 +80,33 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" alt="gallery" title="Check out the Gallery">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" 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@2/assets/minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
|
||||
<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>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/revolt-singular_vector.svg" height="64" alt="revolt" title="Join my Revolt Server">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/revolt-singular_vector.svg" height="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@2/assets/minimal/social/mastodon-singular_vector.svg" height="64" alt="mastodon" title="Chat with me on Mastodon">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/mastodon-singular_vector.svg" height="64" alt="mastodon" title="Chat with me on Mastodon">
|
||||
</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/
|
||||
[protocollib]: https://hangar.papermc.io/dmulloy2/ProtocolLib
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
[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
|
||||
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>ch.andre601.advancedserverlist</groupId>
|
||||
<version>parent</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>${plugin.version}</version>
|
||||
<description>${plugin.description}</description>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<finalName>AdvancedServerList-API-${plugin.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,98 +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.api;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.internal.CheckUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Core class of the API for AdvancedServerList.
|
||||
* <br>Use {@link #get() get()} to retrieve the instance currently used.
|
||||
*/
|
||||
public class AdvancedServerListAPI{
|
||||
|
||||
private static AdvancedServerListAPI instance;
|
||||
private final Map<String, PlaceholderProvider> placeholderProviders = new HashMap<>();
|
||||
|
||||
private AdvancedServerListAPI(){}
|
||||
|
||||
/**
|
||||
* Retrieves the instance used of this API.
|
||||
* <br>If no instance has been made so far will a new one be created.
|
||||
*
|
||||
* @return Instance of this API.
|
||||
*/
|
||||
public static AdvancedServerListAPI get(){
|
||||
if(instance != null)
|
||||
return instance;
|
||||
|
||||
return (instance = new AdvancedServerListAPI());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided {@link PlaceholderProvider PlaceholderProvider} to the list, if it passes the following checks:
|
||||
* <ul>
|
||||
* <li>The identifier is not null or 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
|
||||
* {@link ch.andre601.advancedserverlist.api.exceptions.InvalidPlaceholderProviderException InvalidPlaceholderProviderException}
|
||||
* being thrown.
|
||||
*
|
||||
* @param placeholderProvider
|
||||
* The {@link PlaceholderProvider PlaceholderProvider} to add.
|
||||
*
|
||||
* @throws ch.andre601.advancedserverlist.api.exceptions.InvalidPlaceholderProviderException
|
||||
* When the provided {@link PlaceholderProvider PlaceholderProvider instance} has a null or empty identifier,
|
||||
* the identifier contains spaces or another provider with the same identifier is already loaded.
|
||||
*/
|
||||
public void addPlaceholderProvider(PlaceholderProvider placeholderProvider){
|
||||
CheckUtil.notEmpty(placeholderProvider.getIdentifier(), "Identifier");
|
||||
|
||||
String identifier = placeholderProvider.getIdentifier().toLowerCase(Locale.ROOT);
|
||||
CheckUtil.check(identifier.contains(" "), "Identifier may not contain spaces.");
|
||||
CheckUtil.check(placeholderProviders.containsKey(identifier), "A PlaceholderProvider with name " + identifier + " already exists.");
|
||||
|
||||
placeholderProviders.put(identifier, placeholderProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@link PlaceholderProvider PlaceholderProvider} associated with the given identifier, or {@code null}
|
||||
* should no such entry exist.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier to find a matching {@link PlaceholderProvider PlaceholderProvider} for.
|
||||
*
|
||||
* @return Possibly-null {@link PlaceholderProvider PlaceholderProvider instance}.
|
||||
*/
|
||||
public PlaceholderProvider retrievePlaceholderProvider(String identifier){
|
||||
return placeholderProviders.get(identifier.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
@@ -1,97 +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.api;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
|
||||
/**
|
||||
* Abstract class that is used to provide your own Placeholder patterns for AdvancedServerList to parse.
|
||||
*
|
||||
* <p>In order for your class to be considered a valid PlaceholderProvider will you need to set the
|
||||
* {@link #identifier identifier} to a non-null, non-empty value without having any spaces in it.
|
||||
* <br>Once set, use {@link ch.andre601.advancedserverlist.api.AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider) AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)}
|
||||
* to register your class for AdvancedServerList to use.
|
||||
*/
|
||||
public abstract class PlaceholderProvider{
|
||||
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* Constructor used to set the identifier for the class extending the PlaceholderProvider class.
|
||||
*
|
||||
* <h2>Example</h2>
|
||||
* <pre>{@code
|
||||
* public class MyPlaceholders extends PlaceholderProvider {
|
||||
*
|
||||
* public MyPlaceholders() {
|
||||
* super("myplaceholders");
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
|
||||
* if(placeholder.equals("hello")
|
||||
* return "Hi!";
|
||||
*
|
||||
* return null;
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier to use for the placeholder. Shouldn't be null nor empty.
|
||||
*/
|
||||
public PlaceholderProvider(String identifier){
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by AdvancedServerList's StringReplacer class to replace any appearances of
|
||||
* {@code ${<identifier> <placeholder>}} with whatever value a PlaceholderProvider may return.
|
||||
*
|
||||
* <p>Returning {@code null} will be treated as an invalid placeholder, returning the full placeholder as-is without
|
||||
* any changes made.
|
||||
*
|
||||
* @param placeholder
|
||||
* The part of the placeholder after the identifier ({@code ${<identifier> <placeholder>}}
|
||||
* @param player
|
||||
* The {@link GenericPlayer GenericPlayer instance} used.
|
||||
* @param server
|
||||
* The {@link GenericServer GenericServer instance} used.
|
||||
*
|
||||
* @return Parsed String based on the PlaceholderProvider or {@code null} for invalid placeholders.
|
||||
*/
|
||||
public abstract String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server);
|
||||
|
||||
/**
|
||||
* Returns the identifier used by this instance.
|
||||
*
|
||||
* @return String containing the identifier used by this instance.
|
||||
*/
|
||||
public String getIdentifier(){
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +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.api.objects;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A basic abstract class used to store generic player data with to use in placeholder resolving.
|
||||
* <br>The different variants of AdvancedServerList extend their own class with this one and may or may not use all values
|
||||
* available here.
|
||||
*
|
||||
* <p>The following values will always be present, no matter the platform this class is used on:
|
||||
* <ul>
|
||||
* <li>{@link #getName() Name of Player}</li>
|
||||
* <li>{@link #getProtocol() Protocol version of Player}</li>
|
||||
* <li>{@link #getUUID() UUID of Player}</li>
|
||||
* </ul>
|
||||
* Any other value is not guaranteed to be accurate or even be set.
|
||||
*/
|
||||
public abstract class GenericPlayer{
|
||||
protected String name = null;
|
||||
protected int protocol = -1;
|
||||
protected UUID uuid = null;
|
||||
|
||||
protected String version = null;
|
||||
protected boolean playedBefore = false;
|
||||
protected boolean banned = false;
|
||||
protected boolean whitelisted = false;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p>Name may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet
|
||||
* by AdvancedServerList.
|
||||
*
|
||||
* @return String representing the player's name.
|
||||
*/
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol ID the player is using. The protocol ID is an integer used by Minecraft to determine what
|
||||
* version a server or client is running.
|
||||
*
|
||||
* @return Integer representing the protocol version of this player.
|
||||
*/
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Unique ID associated with this player.
|
||||
*
|
||||
* <p>UUID may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet
|
||||
* by AdvancedServerList.
|
||||
*
|
||||
* @return UUID of the player.
|
||||
*/
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #getProtocol() protocol version} in a readable MC version format (i.e. 1.19.3).
|
||||
*
|
||||
* <p>This only works on Velocity and will return {@code null} for any other platform.
|
||||
*
|
||||
* @return The readable MC version the player uses.
|
||||
*/
|
||||
public String getVersion(){
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this player has played on the Server before.
|
||||
*
|
||||
* <p>The returned boolean is <b>always</b> false on BungeeCord and Velocity due to a lack of any offline player data
|
||||
* storage.
|
||||
*
|
||||
* @return Boolean indicating whether this player has played on this Server before.
|
||||
*/
|
||||
public boolean hasPlayedBefore() {
|
||||
return playedBefore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this player is banned on the server.
|
||||
*
|
||||
* <p>The returned boolean is <b>always</b> false on BungeeCord and Velocity due to a lack of any offline player data
|
||||
* storage.
|
||||
*
|
||||
* @return Boolean indicating whether this player was banned from the server.
|
||||
*/
|
||||
public boolean isBanned(){
|
||||
return banned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this player is whitelisted on the server.
|
||||
*
|
||||
* <p>The returned boolean is <b>always</b> false on BungeeCord and Velocity due to a lack of any offline player data
|
||||
* storage.
|
||||
*
|
||||
* @return Boolean indicating whether this player was banned from the server.
|
||||
*/
|
||||
public boolean isWhitelisted(){
|
||||
return whitelisted;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +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.api.objects;
|
||||
|
||||
/**
|
||||
* Simple class used to wrap around some generic server data such as online player count, amount of total players that
|
||||
* can join and the host (IP/Domain) that got pinged by the player.
|
||||
*/
|
||||
public class GenericServer{
|
||||
|
||||
private final int playersOnline;
|
||||
private final int playersMax;
|
||||
private final String host;
|
||||
|
||||
public GenericServer(int playersOnline, int playersMax, String host){
|
||||
this.playersOnline = playersOnline;
|
||||
this.playersMax = playersMax;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of players currently online on the server.
|
||||
*
|
||||
* @return Number of players online on the server.
|
||||
*/
|
||||
public int getPlayersOnline(){
|
||||
return playersOnline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of total players that can join the server.
|
||||
*
|
||||
* @return Number of total players that can join the server.
|
||||
*/
|
||||
public int getPlayersMax(){
|
||||
return playersMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP/Domain that got pinged by the player.
|
||||
*
|
||||
* @return Possibly-null String containing the IP/Domain that got pinged by the player.
|
||||
*/
|
||||
public String getHost(){
|
||||
return host;
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spigot</artifactId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>${plugin.version}</version>
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
@@ -56,6 +60,10 @@
|
||||
<id>placeholderapi-repo</id>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>viaversion</id>
|
||||
<url>https://repo.viaversion.com/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
@@ -65,39 +73,58 @@
|
||||
<version>${plugin.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bukkit</artifactId>
|
||||
<version>${api.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.11.2</version>
|
||||
<version>2.11.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion-api</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>AdvancedServerList-Spigot-${plugin.version}</finalName>
|
||||
<finalName>AdvancedServerList-Bukkit-${plugin.version}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
@@ -108,7 +135,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<release>16</release>
|
||||
</configuration>
|
||||
@@ -116,7 +143,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -124,10 +151,6 @@
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
@@ -151,4 +174,4 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/*
|
||||
* Small convenience class to "merge" the PluginCore and JavaPlugin classes.
|
||||
* Allows me to have BukkitCore<?> for whenever I also need a JavaPlugin (i.e. registering events).
|
||||
* See JoinEvent class for an example.
|
||||
*/
|
||||
public abstract class BukkitCore<F> extends JavaPlugin implements PluginCore<F>{
|
||||
public abstract WorldCache getWorldCache();
|
||||
}
|
||||
+33
-9
@@ -23,29 +23,53 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.commands;
|
||||
package ch.andre601.advancedserverlist.bukkit.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
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;
|
||||
|
||||
public class CmdAdvancedServerList implements CommandExecutor{
|
||||
import java.util.Collections;
|
||||
|
||||
public class CmdAdvancedServerList extends Command implements CommandExecutor{
|
||||
|
||||
SpigotCore plugin;
|
||||
BukkitAudiences bukkitAudiences;
|
||||
private final PluginCore<?> plugin;
|
||||
private final BukkitAudiences audiences;
|
||||
|
||||
public CmdAdvancedServerList(SpigotCore plugin){
|
||||
public CmdAdvancedServerList(PluginCore<?> plugin){
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public CmdAdvancedServerList(PluginCore<?> plugin, BukkitAudiences audiences){
|
||||
super(
|
||||
"advancedserverlist",
|
||||
"Main command of the plugin",
|
||||
"/asl [reload|help|clearCache]",
|
||||
Collections.singletonList("asl")
|
||||
);
|
||||
|
||||
this.plugin = plugin;
|
||||
bukkitAudiences = BukkitAudiences.create(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(new SpigotCmdSender(sender, bukkitAudiences), 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);
|
||||
}
|
||||
}
|
||||
+12
-7
@@ -23,9 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.events;
|
||||
package ch.andre601.advancedserverlist.bukkit.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.paper.PaperCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -33,13 +34,17 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class JoinEvent implements Listener{
|
||||
public class JoinEvent<F> implements Listener{
|
||||
|
||||
private final PaperCore plugin;
|
||||
private final BukkitCore<F> plugin;
|
||||
|
||||
public JoinEvent(PaperCore plugin){
|
||||
private JoinEvent(BukkitCore<F> plugin){
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static <F> void init(BukkitCore<F> plugin){
|
||||
new JoinEvent<>(plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -47,7 +52,7 @@ public class JoinEvent implements Listener{
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if(address == null)
|
||||
return;
|
||||
|
||||
|
||||
Player player = event.getPlayer();
|
||||
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
|
||||
}
|
||||
+26
-10
@@ -23,36 +23,52 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
package ch.andre601.advancedserverlist.bukkit.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.spigot.listeners.ProtocolLibEvents;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import org.bukkit.Bukkit;
|
||||
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;
|
||||
private final BukkitCore<?> plugin;
|
||||
|
||||
public LoadEvent(SpigotCore plugin){
|
||||
private LoadEvent(BukkitCore<?> plugin){
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static void init(BukkitCore<?> plugin){
|
||||
new LoadEvent(plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerLoad(ServerLoadEvent event){
|
||||
PluginManager manager = plugin.getServer().getPluginManager();
|
||||
JoinEvent.init(plugin);
|
||||
WorldEvents.init(plugin);
|
||||
|
||||
if(!manager.isPluginEnabled("ProtocolLib")){
|
||||
// Populate WorldCache with all loaded worlds
|
||||
Bukkit.getWorlds().forEach(world -> plugin.getWorldCache().addWorld(world.getName(), world));
|
||||
|
||||
if(!(plugin instanceof SpigotCore spigotCore))
|
||||
return;
|
||||
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")){
|
||||
plugin.getCore().getPlugin().getPluginLogger().warn("ProtocolLib not found! AdvancedServerList requires it to work on Spigot!");
|
||||
|
||||
manager.disablePlugin(plugin);
|
||||
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
manager.registerEvents(new JoinEvent(plugin), plugin);
|
||||
manager.registerEvents(new PingEvent(plugin, ProtocolLibrary.getProtocolManager()), plugin);
|
||||
ProtocolLibEvents.init(spigotCore, ProtocolLibrary.getProtocolManager());
|
||||
|
||||
if(Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
spigotCore.setPapiPlaceholders(PAPIPlaceholders.init(spigotCore));
|
||||
}
|
||||
}
|
||||
+7
-8
@@ -23,15 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.api.exceptions;
|
||||
package ch.andre601.advancedserverlist.bukkit.listeners;
|
||||
|
||||
/**
|
||||
* RuntimeException thrown whenever an invalid {@link ch.andre601.advancedserverlist.api.PlaceholderProvider PlaceholderProvider}
|
||||
* has been given.
|
||||
*/
|
||||
public class InvalidPlaceholderProviderException extends RuntimeException{
|
||||
import ch.andre601.advancedserverlist.api.bukkit.events.PreServerListSetEvent;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
|
||||
public class PreServerListSetEventImpl extends PreServerListSetEvent{
|
||||
|
||||
public InvalidPlaceholderProviderException(String msg){
|
||||
super(msg);
|
||||
public PreServerListSetEventImpl(ProfileEntry entry){
|
||||
super(entry);
|
||||
}
|
||||
}
|
||||
+19
-15
@@ -23,31 +23,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
package ch.andre601.advancedserverlist.bukkit.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import org.bukkit.entity.Player;
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class JoinEvent implements Listener{
|
||||
public class WorldEvents implements Listener{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
private final BukkitCore<?> plugin;
|
||||
|
||||
public JoinEvent(SpigotCore plugin){
|
||||
private WorldEvents(BukkitCore<?> plugin){
|
||||
this.plugin = plugin;
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static void init(BukkitCore<?> plugin){
|
||||
new WorldEvents(plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event){
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if(address == null)
|
||||
return;
|
||||
public void onWorldLoad(WorldLoadEvent event){
|
||||
plugin.getWorldCache().addWorld(event.getWorld().getName(), event.getWorld());
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
|
||||
@EventHandler
|
||||
public void onWorldUnload(WorldUnloadEvent event){
|
||||
plugin.getWorldCache().removeWorld(event.getWorld().getName());
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -23,18 +23,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.logging;
|
||||
package ch.andre601.advancedserverlist.bukkit.logging;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PaperLogger implements PluginLogger{
|
||||
public class BukkitLogger implements PluginLogger{
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
public PaperLogger(Logger logger){
|
||||
public BukkitLogger(Logger logger){
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 org.bukkit.World;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public record WorldCache(Map<String, World> worlds){
|
||||
|
||||
public WorldCache(){
|
||||
this(new HashMap<>());
|
||||
}
|
||||
|
||||
public boolean containsWorld(String key){
|
||||
return worlds().containsKey(key);
|
||||
}
|
||||
|
||||
public void addWorld(String key, World world){
|
||||
worlds().put(key, world);
|
||||
}
|
||||
|
||||
public void removeWorld(String key){
|
||||
worlds().remove(key);
|
||||
}
|
||||
}
|
||||
+24
-4
@@ -23,17 +23,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.objects;
|
||||
package ch.andre601.advancedserverlist.bukkit.objects.impl;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitPlayer;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class SpigotPlayer extends GenericPlayer{
|
||||
public class BukkitPlayerImpl extends GenericPlayerImpl implements BukkitPlayer{
|
||||
|
||||
private final OfflinePlayer player;
|
||||
private boolean playedBefore = false;
|
||||
private boolean banned = false;
|
||||
private boolean whitelisted = false;
|
||||
|
||||
public SpigotPlayer(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
|
||||
public BukkitPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
|
||||
this.player = player;
|
||||
|
||||
this.name = player == null ? cachedPlayer.getName() : player.getName();
|
||||
@@ -49,7 +53,23 @@ public class SpigotPlayer extends GenericPlayer{
|
||||
this.whitelisted = player.isWhitelisted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlayer getPlayer(){
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlayedBefore(){
|
||||
return playedBefore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned(){
|
||||
return banned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWhitelisted(){
|
||||
return whitelisted;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.impl;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitServer;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public record BukkitServerImpl(Map<String, World> worlds, int playersOnline, int playersMax, String host) implements BukkitServer{
|
||||
|
||||
@Override
|
||||
public Map<String, World> getWorlds(){
|
||||
return worlds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayersOnline(){
|
||||
return playersOnline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayersMax(){
|
||||
return playersMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost(){
|
||||
return host;
|
||||
}
|
||||
}
|
||||
+17
-11
@@ -23,34 +23,40 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.objects;
|
||||
package ch.andre601.advancedserverlist.bukkit.objects.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
|
||||
public class PlayerPlaceholders extends PlaceholderProvider{
|
||||
public class BukkitPlayerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
public PlayerPlaceholders(){
|
||||
private BukkitPlayerPlaceholders(){
|
||||
super("player");
|
||||
}
|
||||
|
||||
public static BukkitPlayerPlaceholders init(){
|
||||
return new BukkitPlayerPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
SpigotPlayer spigotPlayer = (SpigotPlayer)player;
|
||||
if(!(player instanceof BukkitPlayer bukkitPlayer))
|
||||
return null;
|
||||
|
||||
return switch(placeholder){
|
||||
case "name" -> spigotPlayer.getName();
|
||||
case "protocol" -> String.valueOf(spigotPlayer.getProtocol());
|
||||
case "uuid" -> String.valueOf(spigotPlayer.getUUID());
|
||||
case "hasPlayedBefore" -> returnValue(spigotPlayer, player.hasPlayedBefore());
|
||||
case "isBanned" -> returnValue(spigotPlayer, player.isBanned());
|
||||
case "isWhitelisted" -> returnValue(spigotPlayer, player.isWhitelisted());
|
||||
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){
|
||||
private String returnValue(BukkitPlayer player, Object value){
|
||||
return player.getPlayer() == null ? null : String.valueOf(value);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitServer;
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class BukkitServerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private BukkitServerPlaceholders(){
|
||||
super("server");
|
||||
}
|
||||
|
||||
public static BukkitServerPlaceholders init(){
|
||||
return new BukkitServerPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholders, GenericPlayer player, GenericServer server){
|
||||
if(!(server instanceof BukkitServer bukkitServer))
|
||||
return null;
|
||||
|
||||
String[] args = placeholders.split("\\s", 2);
|
||||
|
||||
return switch(args[0]){
|
||||
case "playersOnline" -> {
|
||||
if(args.length >= 2){
|
||||
int players = 0;
|
||||
for(int i = 1; i < args.length; i++){
|
||||
World world = bukkitServer.getWorlds().get(args[i]);
|
||||
if(world == null)
|
||||
continue;
|
||||
|
||||
players += world.getPlayers().size();
|
||||
}
|
||||
|
||||
yield String.valueOf(players);
|
||||
}
|
||||
|
||||
yield String.valueOf(bukkitServer.getPlayersOnline());
|
||||
}
|
||||
case "playersMax" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
|
||||
yield String.valueOf(bukkitServer.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
|
||||
yield bukkitServer.getHost();
|
||||
}
|
||||
case "whitelistEnabled" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
|
||||
yield String.valueOf(Bukkit.hasWhitelist());
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.placeholders;
|
||||
|
||||
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.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.objects.GenericServerImpl;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.spigot.listeners.ProtocolLibEvents;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
|
||||
public class PAPIPlaceholders<F> extends PlaceholderExpansion{
|
||||
|
||||
private final BukkitCore<F> plugin;
|
||||
|
||||
private PAPIPlaceholders(BukkitCore<F> plugin){
|
||||
this.plugin = plugin;
|
||||
this.register();
|
||||
}
|
||||
|
||||
public static <F> PAPIPlaceholders<F> init(BukkitCore<F> plugin){
|
||||
return new PAPIPlaceholders<>(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier(){
|
||||
return "asl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor(){
|
||||
return "Andre601";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion(){
|
||||
return plugin.getCore().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(Player pl, @NotNull String identifier){
|
||||
InetSocketAddress address = pl.getAddress();
|
||||
|
||||
String host = resolveVirtualHost(pl, address);
|
||||
CachedPlayer cached = plugin.getCore().getPlayerHandler().getCachedPlayer(pl.getUniqueId());
|
||||
|
||||
int protocol = resolveProtocol(pl);
|
||||
int online = Bukkit.getOnlinePlayers().size();
|
||||
int max = Bukkit.getMaxPlayers();
|
||||
GenericServer server = new GenericServerImpl(online, max, host);
|
||||
GenericPlayer player = new BukkitPlayerImpl(pl, cached, protocol);
|
||||
|
||||
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
|
||||
if(profile == null)
|
||||
return null;
|
||||
|
||||
ProfileEntry entry = ProfileManager.merge(profile);
|
||||
|
||||
if(ProfileManager.checkOption(entry.extraPlayersEnabled()))
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
|
||||
GenericServer finalServer = new GenericServerImpl(online, max, host);
|
||||
|
||||
return switch(identifier.toLowerCase(Locale.ROOT)){
|
||||
case "motd" -> getOption(entry.motd(), pl, player, finalServer);
|
||||
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
|
||||
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer);
|
||||
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
|
||||
case "extra_players_max" -> String.valueOf(max);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String getOption(String str, Player pl, GenericPlayer player, GenericServer server){
|
||||
return getOption(Collections.singletonList(str), pl, player, server);
|
||||
}
|
||||
|
||||
private String getOption(List<String> list, Player pl, GenericPlayer player, GenericServer server){
|
||||
return ComponentParser.list(list)
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.toString();
|
||||
}
|
||||
|
||||
private int resolveProtocol(Player player){
|
||||
if(Bukkit.getPluginManager().isPluginEnabled("ViaVersion"))
|
||||
return Via.getAPI().getPlayerVersion(player.getUniqueId());
|
||||
|
||||
// Since Spigot version requires ProtocolLib can we use it here safely if the plugin instance is SpigotCore.
|
||||
if(plugin instanceof SpigotCore)
|
||||
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
|
||||
|
||||
// getProtocolVersion is only in Paper, so this is only called when main class isn't SpigotCore.
|
||||
// Also, ViaVersion is not present, so the player protocol *should* be the same as the server.
|
||||
return Bukkit.getUnsafe().getProtocolVersion();
|
||||
}
|
||||
|
||||
private String resolveVirtualHost(Player player, InetSocketAddress address){
|
||||
try {
|
||||
// Server is a Paper Server with Player#getVirtualHost()
|
||||
Class.forName("com.destroystokyo.paper.network.NetworkClient");
|
||||
return player.getVirtualHost() == null ? null : player.getVirtualHost().getHostString();
|
||||
}catch(ClassNotFoundException ignored){}
|
||||
|
||||
if(address == null)
|
||||
return null;
|
||||
|
||||
return ProtocolLibEvents.getHostAddresses().get(address.getHostString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.paper;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
|
||||
import io.papermc.paper.plugin.loader.PluginLoader;
|
||||
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.eclipse.aether.artifact.DefaultArtifact;
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ASLLoader implements PluginLoader{
|
||||
@Override
|
||||
public void classloader(@NotNull PluginClasspathBuilder pluginClasspathBuilder){
|
||||
ComponentLogger logger = pluginClasspathBuilder.getContext().getLogger();
|
||||
|
||||
logger.info(Component.text("Loading Libraries for plugin..."));
|
||||
|
||||
MavenLibraryResolver resolver = new MavenLibraryResolver();
|
||||
|
||||
resolver.addRepository(new RemoteRepository.Builder(
|
||||
"paper-maven",
|
||||
"default",
|
||||
"https://repo.papermc.io/repository/maven-public/"
|
||||
).build());
|
||||
|
||||
logger.info(Component.text("Loading com.squareup.okhttp3:okhttp:4.10.0 from repo.papermc.io..."));
|
||||
|
||||
resolver.addDependency(new Dependency(new DefaultArtifact("com.squareup.okhttp3:okhttp:4.10.0"), null));
|
||||
pluginClasspathBuilder.addLibrary(resolver);
|
||||
|
||||
logger.info(Component.text("Loading libraries complete!"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.paper;
|
||||
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.LoadEvent;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.WorldEvents;
|
||||
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.paper.listeners.PaperPingEvent;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class PaperCore extends BukkitCore<CachedServerIcon>{
|
||||
|
||||
private final PluginLogger logger = new BukkitLogger(getLogger());
|
||||
|
||||
private AdvancedServerList<CachedServerIcon> core;
|
||||
private FaviconHandler<CachedServerIcon> faviconHandler = null;
|
||||
private PAPIPlaceholders<CachedServerIcon> papiPlaceholders = null;
|
||||
private WorldCache worldCache = null;
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init(), BukkitServerPlaceholders.init());
|
||||
|
||||
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
papiPlaceholders = PAPIPlaceholders.init(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable(){
|
||||
if(papiPlaceholders != null){
|
||||
papiPlaceholders.unregister();
|
||||
papiPlaceholders = null;
|
||||
}
|
||||
|
||||
if(worldCache != null)
|
||||
worldCache = null;
|
||||
|
||||
getCore().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCommands(){
|
||||
if(getServer().getCommandMap().register("asl", new CmdAdvancedServerList(this))){
|
||||
getPluginLogger().info("Registered /advancedserverlist:advancedserverlist");
|
||||
}else{
|
||||
getPluginLogger().info("Registered /asl:advancedserverlist");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadEvents(){
|
||||
LoadEvent.init(this);
|
||||
PaperPingEvent.init(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<CachedServerIcon> getCore(){
|
||||
return core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFolderPath(){
|
||||
return getDataFolder().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginLogger getPluginLogger(){
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaviconHandler<CachedServerIcon> 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 "paper";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldCache getWorldCache(){
|
||||
if(worldCache != null)
|
||||
return worldCache;
|
||||
|
||||
return (worldCache = new WorldCache());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
+54
-13
@@ -23,14 +23,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.events;
|
||||
package ch.andre601.advancedserverlist.paper.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.PreServerListSetEventImpl;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitServerImpl;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
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.paper.PaperCore;
|
||||
import ch.andre601.advancedserverlist.paper.objects.PaperPlayer;
|
||||
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
@@ -40,9 +47,9 @@ import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, PlayerProfile, PaperPlayer>{
|
||||
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, BukkitPlayerImpl>{
|
||||
|
||||
private final PaperCore plugin;
|
||||
private final PaperServerListPingEvent event;
|
||||
@@ -52,6 +59,14 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServerListEvent callEvent(ProfileEntry entry){
|
||||
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
event.setMaxPlayers(maxPlayers);
|
||||
@@ -74,12 +89,25 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, PaperPlayer player, GenericServer server){
|
||||
public void setPlayers(List<String> lines, BukkitPlayerImpl player, GenericServer server){
|
||||
event.getPlayerSample().clear();
|
||||
List<PlayerProfile> players = new ArrayList<>(lines.size());
|
||||
|
||||
event.getPlayerSample().addAll(
|
||||
plugin.createPlayers(players, player, server)
|
||||
);
|
||||
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(Bukkit.createProfile(UUID.randomUUID(), parsed));
|
||||
}
|
||||
|
||||
event.getPlayerSample().addAll(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,6 +130,14 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenanceModeActive(){
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("Maintenance"))
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return event.getClient().getProtocolVersion();
|
||||
@@ -123,7 +159,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, PaperPlayer player){
|
||||
public String parsePAPIPlaceholders(String text, BukkitPlayerImpl player){
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
@@ -136,15 +172,20 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<CachedServerIcon, PlayerProfile, PaperPlayer> getPlugin(){
|
||||
public BukkitCore<CachedServerIcon> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaperPlayer createPlayer(CachedPlayer player, int protocol){
|
||||
public BukkitPlayerImpl createPlayer(CachedPlayer player, int protocol){
|
||||
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
|
||||
return new PaperPlayer(pl.hasPlayedBefore() ? pl : null, player, protocol);
|
||||
return new BukkitPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
|
||||
return new BukkitServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
|
||||
}
|
||||
|
||||
@Override
|
||||
+8
-4
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.events;
|
||||
package ch.andre601.advancedserverlist.paper.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.paper.PaperCore;
|
||||
@@ -31,17 +31,21 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class PingEvent implements Listener{
|
||||
public class PaperPingEvent implements Listener{
|
||||
|
||||
private final PaperCore plugin;
|
||||
|
||||
public PingEvent(PaperCore plugin){
|
||||
private PaperPingEvent(PaperCore plugin){
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static void init(PaperCore plugin){
|
||||
new PaperPingEvent(plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerPing(PaperServerListPingEvent event){
|
||||
public void onPaperServerListPing(PaperServerListPingEvent event){
|
||||
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
|
||||
}
|
||||
}
|
||||
+37
-41
@@ -25,36 +25,33 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
|
||||
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.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.spigot.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.spigot.events.LoadEvent;
|
||||
import ch.andre601.advancedserverlist.spigot.logging.SpigotLogger;
|
||||
import ch.andre601.advancedserverlist.spigot.objects.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.spigot.objects.SpigotPlayer;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.LoadEvent;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPing.CompressedImage, WrappedGameProfile, SpigotPlayer>{
|
||||
public class SpigotCore extends BukkitCore<WrappedServerPing.CompressedImage>{
|
||||
|
||||
private final PluginLogger logger = new SpigotLogger(getLogger());
|
||||
private final PluginLogger logger = new BukkitLogger(getLogger());
|
||||
|
||||
private AdvancedServerList core;
|
||||
FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
|
||||
private AdvancedServerList<WrappedServerPing.CompressedImage> core;
|
||||
private FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
|
||||
private PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders = null;
|
||||
private WorldCache worldCache = null;
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
@@ -71,11 +68,19 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
|
||||
}catch(ClassNotFoundException ignored){}
|
||||
}
|
||||
|
||||
this.core = new AdvancedServerList(this, new PlayerPlaceholders());
|
||||
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init(), BukkitServerPlaceholders.init());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable(){
|
||||
if(papiPlaceholders != null){
|
||||
papiPlaceholders.unregister();
|
||||
papiPlaceholders = null;
|
||||
}
|
||||
|
||||
if(worldCache != null)
|
||||
worldCache = null;
|
||||
|
||||
getCore().disable();
|
||||
}
|
||||
|
||||
@@ -83,15 +88,15 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
|
||||
public void loadCommands(){
|
||||
PluginCommand cmd = getServer().getPluginCommand("advancedserverlist");
|
||||
if(cmd == null){
|
||||
getPluginLogger().warn("Could not register command /advancedserverlist");
|
||||
getPluginLogger().warn("Unable to register command /advancedserverlist");
|
||||
return;
|
||||
}
|
||||
cmd.setExecutor(new CmdAdvancedServerList(this));
|
||||
cmd.setExecutor(new CmdAdvancedServerList(this, BukkitAudiences.create(this)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadEvents(){
|
||||
new LoadEvent(this);
|
||||
LoadEvent.init(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,7 +115,7 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList getCore(){
|
||||
public AdvancedServerList<WrappedServerPing.CompressedImage> getCore(){
|
||||
return core;
|
||||
}
|
||||
|
||||
@@ -148,24 +153,15 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WrappedGameProfile> createPlayers(List<String> lines, SpigotPlayer player, GenericServer server){
|
||||
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
|
||||
public WorldCache getWorldCache(){
|
||||
if(worldCache != null)
|
||||
return worldCache;
|
||||
|
||||
for(String line : lines){
|
||||
String parsed = ComponentParser.text(line)
|
||||
.applyReplacements(player, server)
|
||||
.modifyText(text -> {
|
||||
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toString();
|
||||
|
||||
players.add(new WrappedGameProfile(UUID.randomUUID(), parsed));
|
||||
}
|
||||
|
||||
return players;
|
||||
return (worldCache = new WorldCache());
|
||||
}
|
||||
|
||||
public void setPapiPlaceholders(PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders){
|
||||
this.papiPlaceholders = papiPlaceholders;
|
||||
}
|
||||
|
||||
private void printPaperInfo(){
|
||||
@@ -173,7 +169,7 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
|
||||
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 downloading of external Libraries already provided by Paper (i.e. Adventure).");
|
||||
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!");
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.command.CommandSender;
|
||||
+62
-22
@@ -23,41 +23,52 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
package ch.andre601.advancedserverlist.spigot.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
|
||||
import ch.andre601.advancedserverlist.bukkit.listeners.PreServerListSetEventImpl;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitServerImpl;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
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.spigot.objects.SpigotPlayer;
|
||||
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServerPing.CompressedImage, WrappedGameProfile, SpigotPlayer>{
|
||||
public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServerPing.CompressedImage, BukkitPlayerImpl>{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
private final PacketEvent event;
|
||||
private final WrappedServerPing ping;
|
||||
|
||||
private final Map<String, String> hostAddresses;
|
||||
|
||||
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event, Map<String, String> hostAddresses){
|
||||
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);
|
||||
|
||||
this.hostAddresses = hostAddresses;
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +78,7 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServe
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setMotD(AdventureComponentConverter.fromComponent(component));
|
||||
ping.setMotD(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,10 +93,24 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, SpigotPlayer player, GenericServer server){
|
||||
ping.setPlayers(
|
||||
plugin.createPlayers(players, player, server)
|
||||
);
|
||||
public void setPlayers(List<String> lines, BukkitPlayerImpl 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
|
||||
@@ -100,13 +125,23 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServe
|
||||
|
||||
// Not used in ProtocolLib
|
||||
@Override
|
||||
public void updateEvent(){}
|
||||
public void updateEvent(){
|
||||
event.getPacket().getServerPings().write(0, ping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return event.getPlayer().getAddress() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenanceModeActive(){
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("Maintenance"))
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return ping.getVersionProtocol();
|
||||
@@ -128,7 +163,7 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServe
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, SpigotPlayer player){
|
||||
public String parsePAPIPlaceholders(String text, BukkitPlayerImpl player){
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
@@ -141,19 +176,24 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServe
|
||||
if(host == null)
|
||||
return null;
|
||||
|
||||
return hostAddresses.get(host);
|
||||
return ProtocolLibEvents.getHostAddresses().get(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<WrappedServerPing.CompressedImage, WrappedGameProfile, SpigotPlayer> getPlugin(){
|
||||
public BukkitCore<WrappedServerPing.CompressedImage> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpigotPlayer createPlayer(CachedPlayer player, int protocol){
|
||||
public BukkitPlayerImpl createPlayer(CachedPlayer player, int protocol){
|
||||
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
|
||||
|
||||
return new SpigotPlayer(pl.hasPlayedBefore() ? pl : null, player, protocol);
|
||||
return new BukkitPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
|
||||
return new BukkitServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
|
||||
}
|
||||
|
||||
@Override
|
||||
+16
-6
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
package ch.andre601.advancedserverlist.spigot.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
@@ -32,22 +32,32 @@ 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.Bukkit;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class PingEvent implements Listener{
|
||||
public class ProtocolLibEvents implements Listener{
|
||||
|
||||
private final ProtocolManager protocolManager;
|
||||
|
||||
private final Map<String, String> hostAddresses = new HashMap<>();
|
||||
private static final Map<String, String> hostAddresses = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
public PingEvent(SpigotCore plugin, ProtocolManager protocolManager){
|
||||
private ProtocolLibEvents(SpigotCore plugin, ProtocolManager protocolManager){
|
||||
this.protocolManager = protocolManager;
|
||||
|
||||
loadPacketListener(plugin);
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static void init(SpigotCore plugin, ProtocolManager protocolManager){
|
||||
new ProtocolLibEvents(plugin, protocolManager);
|
||||
}
|
||||
|
||||
public static Map<String, String> getHostAddresses(){
|
||||
return hostAddresses;
|
||||
}
|
||||
|
||||
private void loadPacketListener(SpigotCore spigotPlugin){
|
||||
@@ -67,7 +77,7 @@ public class PingEvent implements Listener{
|
||||
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event){
|
||||
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event, hostAddresses));
|
||||
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -4,16 +4,24 @@ version: '${plugin.version}'
|
||||
description: '${plugin.description}'
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
|
||||
loader: 'ch.andre601.advancedserverlist.paper.ASLLoader'
|
||||
|
||||
api-version: 1.19
|
||||
api-version: '1.19'
|
||||
|
||||
libraries:
|
||||
- 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
dependencies:
|
||||
server:
|
||||
PlaceholderAPI:
|
||||
load: BEFORE
|
||||
required: false
|
||||
ViaVersion:
|
||||
load: BEFORE
|
||||
required: false
|
||||
Maintenance:
|
||||
load: BEFORE
|
||||
required: false
|
||||
|
||||
softdepend:
|
||||
- 'PlaceholderAPI'
|
||||
|
||||
commands:
|
||||
# The below stuff is NOT used by Paper plugin.
|
||||
commands:
|
||||
advancedserverlist:
|
||||
description: 'Main command of AdvancedServerList'
|
||||
usage: '/<command> [help|reload]'
|
||||
@@ -21,11 +29,12 @@ commands:
|
||||
- 'asl'
|
||||
permission: 'advancedserverlist.admin'
|
||||
|
||||
permissions:
|
||||
# This is actually supported(?)
|
||||
permissions:
|
||||
advancedserverlist.*:
|
||||
description: 'Grants access to all permissions'
|
||||
default: op
|
||||
children:
|
||||
children:
|
||||
- 'advancedserverlist.admin'
|
||||
advancedserverlist.admin:
|
||||
description: 'Grants access to all permissions'
|
||||
@@ -7,6 +7,8 @@ main: 'ch.andre601.advancedserverlist.spigot.SpigotCore'
|
||||
|
||||
api-version: 1.19
|
||||
|
||||
folia-supported: true
|
||||
|
||||
libraries:
|
||||
- 'org.spongepowered:configurate-yaml:4.1.2'
|
||||
- 'net.kyori:adventure-api:4.12.0'
|
||||
@@ -18,11 +20,12 @@ libraries:
|
||||
softdepend:
|
||||
- 'ProtocolLib'
|
||||
- 'PlaceholderAPI'
|
||||
- 'Maintenance'
|
||||
|
||||
commands:
|
||||
advancedserverlist:
|
||||
description: 'Main command of AdvancedServerList'
|
||||
usage: '/<command> [help|reload]'
|
||||
usage: '/<command> [help|reload|clearCache]'
|
||||
aliases:
|
||||
- 'asl'
|
||||
permission: 'advancedserverlist.admin'
|
||||
@@ -49,4 +52,7 @@ permissions:
|
||||
default: op
|
||||
advancedserverlist.command.reload:
|
||||
description: 'Grants access to /asl reload'
|
||||
default: op
|
||||
advancedserverlist.command.clearcache:
|
||||
description: 'Clears the Player and Favicon cache'
|
||||
default: op
|
||||
+32
-6
@@ -58,6 +58,12 @@
|
||||
<version>${plugin.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bungeecord</artifactId>
|
||||
<version>${api.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
@@ -72,6 +78,18 @@
|
||||
<type>javadoc</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.13.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bungeecord</artifactId>
|
||||
@@ -84,6 +102,18 @@
|
||||
<version>3.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -98,12 +128,12 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -119,10 +149,6 @@
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>okhttp3</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.okhttp3</shadedPattern>
|
||||
|
||||
+8
-29
@@ -25,38 +25,32 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
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.BungeePlayer;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.PlayerPlaceholders;
|
||||
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;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.bstats.bungeecord.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeCordCore extends Plugin implements PluginCore<Favicon, ServerPing.PlayerInfo, BungeePlayer>{
|
||||
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 PlayerPlaceholders());
|
||||
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,7 +86,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon, Server
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList getCore(){
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
}
|
||||
|
||||
@@ -128,19 +122,4 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon, Server
|
||||
public String getLoader(){
|
||||
return "bungeecord";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServerPing.PlayerInfo> createPlayers(List<String> lines, BungeePlayer player, GenericServer server){
|
||||
List<ServerPing.PlayerInfo> players = new ArrayList<>(lines.size());
|
||||
|
||||
for(String line : lines){
|
||||
String parsed = ComponentParser.text(line)
|
||||
.applyReplacements(player, server)
|
||||
.toString();
|
||||
|
||||
players.add(new ServerPing.PlayerInfo(parsed, UUID.randomUUID()));
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
|
||||
+72
-12
@@ -23,26 +23,36 @@
|
||||
*
|
||||
*/
|
||||
|
||||
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.BungeePlayer;
|
||||
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;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
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, ServerPing.PlayerInfo, BungeePlayer>{
|
||||
public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePlayerImpl>{
|
||||
|
||||
private final BungeeCordCore plugin;
|
||||
private final ProxyPingEvent event;
|
||||
@@ -56,6 +66,14 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, ServerPi
|
||||
this.ping = event.getResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericServerListEvent callEvent(ProfileEntry entry){
|
||||
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
|
||||
plugin.getProxy().getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
ping.getPlayers().setMax(maxPlayers);
|
||||
@@ -78,11 +96,20 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, ServerPi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, BungeePlayer player, GenericServer server){
|
||||
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(players, player, server).toArray(new ServerPing.PlayerInfo[0]);
|
||||
public void setPlayers(List<String> lines, BungeePlayerImpl player, GenericServer server){
|
||||
ServerPing.PlayerInfo[] players = new ServerPing.PlayerInfo[lines.size()];
|
||||
|
||||
if(playerInfos.length > 0)
|
||||
ping.getPlayers().setSample(playerInfos);
|
||||
for(int i = 0; i < players.length; i++){
|
||||
String parsed = ComponentParser.text(lines.get(i))
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.toString();
|
||||
|
||||
ServerPing.PlayerInfo pi = new ServerPing.PlayerInfo(parsed, UUID.randomUUID());
|
||||
players[i] = pi;
|
||||
}
|
||||
|
||||
if(players.length > 0)
|
||||
ping.getPlayers().setSample(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,6 +133,14 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, ServerPi
|
||||
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();
|
||||
@@ -127,8 +162,26 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, ServerPi
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, BungeePlayer player){
|
||||
return text;
|
||||
public String parsePAPIPlaceholders(String text, BungeePlayerImpl player){
|
||||
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
|
||||
@@ -137,13 +190,20 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, ServerPi
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<Favicon, ServerPing.PlayerInfo, BungeePlayer> getPlugin(){
|
||||
public PluginCore<Favicon> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BungeePlayer createPlayer(CachedPlayer player, int protocol){
|
||||
return new BungeePlayer(player, protocol);
|
||||
public BungeePlayerImpl createPlayer(CachedPlayer player, int protocol){
|
||||
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
|
||||
+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;
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.listeners;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bungeecord.events.PreServerListSetEvent;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
|
||||
public class PreServerListSetEventImpl extends PreServerListSetEvent{
|
||||
|
||||
public PreServerListSetEventImpl(ProfileEntry entry){
|
||||
super(entry);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -25,12 +25,12 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
|
||||
|
||||
public class BungeePlayer extends GenericPlayer{
|
||||
public class BungeePlayerImpl extends GenericPlayerImpl{
|
||||
|
||||
public BungeePlayer(CachedPlayer player, int protocol){
|
||||
public BungeePlayerImpl(CachedPlayer player, int protocol){
|
||||
this.name = player.getName();
|
||||
this.protocol = protocol;
|
||||
this.uuid = player.getUuid();
|
||||
+6
-2
@@ -31,12 +31,16 @@ import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class PlayerPlaceholders extends PlaceholderProvider{
|
||||
public class BungeePlayerPlaceholders extends PlaceholderProvider{
|
||||
|
||||
public PlayerPlaceholders(){
|
||||
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;
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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){
|
||||
int players = 0;
|
||||
|
||||
for(int i = 1; i < args.length; i++){
|
||||
ServerInfo info = proxy.getServers().get(args[i]);
|
||||
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'
|
||||
+43
-15
@@ -48,54 +48,82 @@
|
||||
<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>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.advancedserverlist</groupId>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>${plugin.version}</version>
|
||||
<version>${api.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.12.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.12.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<scope>compile</scope>
|
||||
<version>4.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<version>4.11.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>32.1.2-jre</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.3</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>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
@@ -119,12 +147,12 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
||||
@@ -27,21 +27,23 @@ package ch.andre601.advancedserverlist.core;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.internal.ServerPlaceholders;
|
||||
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,18 +53,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;
|
||||
}
|
||||
|
||||
@@ -102,6 +108,10 @@ public class AdvancedServerList{
|
||||
plugin.clearFaviconCache();
|
||||
}
|
||||
|
||||
public void clearPlayerCache(){
|
||||
getPlayerHandler().clearCache();
|
||||
}
|
||||
|
||||
private void load(){
|
||||
printBanner();
|
||||
resolveVersion();
|
||||
@@ -116,6 +126,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{
|
||||
@@ -144,12 +164,11 @@ public class AdvancedServerList{
|
||||
|
||||
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
|
||||
|
||||
if(getFileHandler().getBoolean("check_updates"))
|
||||
if(getFileHandler().getBoolean("checkUpdates"))
|
||||
this.updateChecker = new UpdateChecker(this);
|
||||
}
|
||||
|
||||
private void printBanner(){
|
||||
getPlugin().getPluginLogger().info("");
|
||||
getPlugin().getPluginLogger().info(" _____ _");
|
||||
getPlugin().getPluginLogger().info(" /\\ / ____| |");
|
||||
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
|
||||
|
||||
@@ -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();
|
||||
|
||||
+98
-39
@@ -26,56 +26,115 @@
|
||||
package ch.andre601.advancedserverlist.core.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.PluginCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandHandler{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final List<PluginCommand> subCommands = new ArrayList<>();
|
||||
|
||||
public CommandHandler(AdvancedServerList core){
|
||||
this.core = core;
|
||||
public CommandHandler(AdvancedServerList<?> core){
|
||||
subCommands.add(new Help());
|
||||
subCommands.add(new Reload(core));
|
||||
subCommands.add(new ClearCache(core));
|
||||
}
|
||||
|
||||
public void handle(CmdSender sender, String[] args){
|
||||
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>]";
|
||||
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>]";
|
||||
if(args.length == 0){
|
||||
sender.sendErrorMsg("<red>Too few arguments! Use <grey>/asl help</grey> for a list of commands.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length == 0 || args[0].equalsIgnoreCase("help")){
|
||||
if(sender.hasPermission("advancedserverlist.command.help")){
|
||||
sender.sendMsg("%s - Commands", prefix);
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<gradient:aqua:white>/asl help</gradient> <grey>- Shows this Help");
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<gradient:aqua:white>/asl reload</gradient> <grey>- Reloads the plugin");
|
||||
}else{
|
||||
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
|
||||
}
|
||||
}else
|
||||
if(args[0].equalsIgnoreCase("reload")){
|
||||
if(sender.hasPermission("advancedserverlist.command.reload")){
|
||||
sender.sendMsg("%s Reloading plugin...", prefix);
|
||||
|
||||
if(core.getFileHandler().reloadConfig()){
|
||||
sender.sendMsg("%s <green>Reloaded <grey>config.yml</grey>!", prefix);
|
||||
}else{
|
||||
sender.sendMsg("%s <red>Error while reloading the <grey>config.yml</grey>!", errorPrefix);
|
||||
for(PluginCommand subCommand : subCommands){
|
||||
if(subCommand.getArgument().equalsIgnoreCase(args[0])){
|
||||
if(!sender.hasPermission(subCommand.getPermission())){
|
||||
sender.sendErrorMsg(
|
||||
"<red>You do not have the permission <grey>%s</grey> to execute this command.",
|
||||
subCommand.getPermission()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().reloadProfiles()){
|
||||
sender.sendMsg("%s <green>Loaded <grey>%d Profile(s)</grey>!", prefix, core.getFileHandler().getProfiles().size());
|
||||
}else{
|
||||
sender.sendMsg("%s <red>Cannot load Profiles!", errorPrefix);
|
||||
}
|
||||
|
||||
core.clearFaviconCache();
|
||||
sender.sendMsg("%s <green>Successfully cleared Favicon cache!", prefix);
|
||||
|
||||
sender.sendMsg("%s <green>Reload complete!", prefix);
|
||||
}else{
|
||||
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
|
||||
subCommand.handle(sender);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
sender.sendMsg("%s <red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", prefix, args[0]);
|
||||
}
|
||||
|
||||
sender.sendErrorMsg("<red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", args[0]);
|
||||
}
|
||||
|
||||
private static class Help extends PluginCommand{
|
||||
|
||||
public Help(){
|
||||
super("help");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CmdSender sender){
|
||||
sender.sendPrefixedMsg("- Commands");
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<aqua>/asl <white>help <grey>- Shows this help");
|
||||
sender.sendMsg();
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
private static class Reload extends PluginCommand{
|
||||
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public Reload(AdvancedServerList<?> core){
|
||||
super("reload");
|
||||
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CmdSender sender){
|
||||
sender.sendPrefixedMsg("Reloading plugin...");
|
||||
|
||||
if(core.getFileHandler().reloadConfig()){
|
||||
sender.sendPrefixedMsg("<green>Reloaded <grey>config.yml</grey>!");
|
||||
}else{
|
||||
sender.sendErrorMsg("<red>Error while reloading <grey>config.yml</grey>!");
|
||||
}
|
||||
|
||||
if(core.getFileHandler().reloadProfiles()){
|
||||
sender.sendPrefixedMsg("<green>Loaded <grey>%d profile(s)</grey>!", core.getFileHandler().getProfiles().size());
|
||||
}else{
|
||||
sender.sendErrorMsg("<red>Error while loading profile(s)!");
|
||||
}
|
||||
|
||||
sender.sendPrefixedMsg("<green>Reload complete!");
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClearCache extends PluginCommand{
|
||||
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public ClearCache(AdvancedServerList<?> core){
|
||||
super("clearCache");
|
||||
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CmdSender sender){
|
||||
sender.sendPrefixedMsg("Clearing caches...");
|
||||
|
||||
core.clearFaviconCache();
|
||||
sender.sendPrefixedMsg("<green>Successfully cleared Favicon Cache!");
|
||||
|
||||
core.clearPlayerCache();
|
||||
sender.sendPrefixedMsg("<green>Successfully cleared Player Cache!");
|
||||
|
||||
sender.sendPrefixedMsg("<green>Cache clearing complete!");
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-8
@@ -23,18 +23,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.api.internal;
|
||||
package ch.andre601.advancedserverlist.core.compat.maintenance;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.exceptions.InvalidPlaceholderProviderException;
|
||||
import eu.kennytv.maintenance.api.Maintenance;
|
||||
import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
|
||||
public class CheckUtil{
|
||||
public class MaintenanceUtil{
|
||||
|
||||
public static void notEmpty(String text, String name){
|
||||
check(text == null || text.isEmpty(), name + " may not be null or empty.");
|
||||
private final Maintenance api;
|
||||
|
||||
public MaintenanceUtil(){
|
||||
this.api = MaintenanceProvider.get();
|
||||
}
|
||||
|
||||
public static void check(boolean condition, String msg){
|
||||
if(condition)
|
||||
throw new InvalidPlaceholderProviderException(msg);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-25
@@ -25,23 +25,29 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.events;
|
||||
|
||||
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.compat.papi.PAPIUtil;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
|
||||
public class PingEventHandler{
|
||||
|
||||
public static <F, PL, P extends GenericPlayer> void handleEvent(GenericEventWrapper<F, PL, P> event){
|
||||
if(event.isInvalidProtocol())
|
||||
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() || event.isMaintenanceModeActive())
|
||||
return;
|
||||
|
||||
PluginCore<F, PL, P> plugin = event.getPlugin();
|
||||
PluginCore<F> plugin = event.getPlugin();
|
||||
String host = event.getVirtualHost();
|
||||
|
||||
int online = event.getOnlinePlayers();
|
||||
@@ -51,54 +57,58 @@ public class PingEventHandler{
|
||||
plugin.getCore().getPlayerHandler().getCachedPlayer(event.getPlayerIP()),
|
||||
event.getProtocolVersion()
|
||||
);
|
||||
GenericServer server = new GenericServer(online, max, host);
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(plugin.getCore())
|
||||
.applyReplacements(player, server)
|
||||
.getProfile();
|
||||
GenericServer server = event.createGenericServer(online, max, host);
|
||||
|
||||
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
ProfileEntry entry = ProfileManager.merge(profile);
|
||||
|
||||
if(entry.isExtraPlayersEnabled().getValue(false)){
|
||||
max = online + (entry.getExtraPlayersCount() == null ? 0 : entry.getExtraPlayersCount());
|
||||
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
|
||||
if(e == null || e.isCancelled())
|
||||
return;
|
||||
|
||||
ProfileEntry entry = e.getEntry();
|
||||
if(entry.isInvalid())
|
||||
return;
|
||||
|
||||
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
event.setMaxPlayers(max);
|
||||
}
|
||||
|
||||
server = new GenericServer(online, max, host);
|
||||
GenericServer finalServer = event.createGenericServer(online, max, host);
|
||||
|
||||
if(!entry.getMOTD().isEmpty()){
|
||||
if(ProfileManager.checkOption(entry.motd())){
|
||||
event.setMotd(
|
||||
ComponentParser.list(entry.getMOTD())
|
||||
.applyReplacements(player, server)
|
||||
ComponentParser.list(entry.motd())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toComponent()
|
||||
);
|
||||
}
|
||||
|
||||
boolean hidePlayers = entry.isHidePlayersEnabled().getValue(false);
|
||||
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
|
||||
|
||||
if(hidePlayers){
|
||||
event.hidePlayers();
|
||||
}
|
||||
|
||||
if(!entry.getPlayerCountText().isEmpty() && !hidePlayers){
|
||||
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers){
|
||||
event.setPlayerCount(
|
||||
ComponentParser.text(entry.getPlayerCountText())
|
||||
.applyReplacements(player, server)
|
||||
ComponentParser.text(entry.playerCountText())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
|
||||
if(!entry.getPlayers().isEmpty() && !hidePlayers){
|
||||
event.setPlayers(entry.getPlayers(), player, server);
|
||||
if(ProfileManager.checkOption(entry.players()) && !hidePlayers){
|
||||
event.setPlayers(entry.players(), player, server);
|
||||
}
|
||||
|
||||
if(!entry.getFavicon().isEmpty()){
|
||||
String favicon = StringReplacer.replace(entry.getFavicon(), player, server);
|
||||
if(ProfileManager.checkOption(entry.favicon())){
|
||||
String favicon = StringReplacer.replace(entry.favicon(), player, server);
|
||||
|
||||
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
|
||||
try{
|
||||
@@ -118,4 +128,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;
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,11 @@ package ch.andre601.advancedserverlist.core.file;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.interfaces.commands;
|
||||
|
||||
public interface CmdSender{
|
||||
|
||||
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>] ";
|
||||
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>] ";
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
void sendMsg(String msg, Object... args);
|
||||
|
||||
default void sendMsg(){
|
||||
sendMsg("");
|
||||
}
|
||||
|
||||
default void sendPrefixedMsg(String msg, Object... args){
|
||||
sendMsg(prefix + msg, args);
|
||||
}
|
||||
|
||||
default void sendErrorMsg(String msg, Object... args){
|
||||
sendMsg(errorPrefix + msg, args);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.interfaces.commands;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class PluginCommand{
|
||||
|
||||
private final String argument;
|
||||
|
||||
public PluginCommand(String argument){
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
public String getArgument(){
|
||||
return argument;
|
||||
}
|
||||
|
||||
public String getPermission(){
|
||||
return "advancedserverlist.command." + getArgument().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public abstract void handle(CmdSender sender);
|
||||
}
|
||||
+2
-7
@@ -25,16 +25,13 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.interfaces.core;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public interface PluginCore<F, PL, P extends GenericPlayer>{
|
||||
public interface PluginCore<F>{
|
||||
|
||||
void loadCommands();
|
||||
|
||||
@@ -44,7 +41,7 @@ public interface PluginCore<F, PL, P extends GenericPlayer>{
|
||||
|
||||
void clearFaviconCache();
|
||||
|
||||
AdvancedServerList getCore();
|
||||
AdvancedServerList<F> getCore();
|
||||
|
||||
Path getFolderPath();
|
||||
|
||||
@@ -57,6 +54,4 @@ public interface PluginCore<F, PL, P extends GenericPlayer>{
|
||||
String getPlatformVersion();
|
||||
|
||||
String getLoader();
|
||||
|
||||
List<PL> createPlayers(List<String> lines, P player, GenericServer server);
|
||||
}
|
||||
+10
-2
@@ -27,6 +27,8 @@ package ch.andre601.advancedserverlist.core.interfaces.events;
|
||||
|
||||
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.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -35,7 +37,9 @@ import java.awt.image.BufferedImage;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public interface GenericEventWrapper<F, PL, P extends GenericPlayer>{
|
||||
public interface GenericEventWrapper<F, P extends GenericPlayer>{
|
||||
|
||||
GenericServerListEvent callEvent(ProfileEntry entry);
|
||||
|
||||
void setMaxPlayers(int maxPlayers);
|
||||
|
||||
@@ -55,6 +59,8 @@ public interface GenericEventWrapper<F, PL, P extends GenericPlayer>{
|
||||
|
||||
boolean isInvalidProtocol();
|
||||
|
||||
boolean isMaintenanceModeActive();
|
||||
|
||||
int getProtocolVersion();
|
||||
|
||||
int getOnlinePlayers();
|
||||
@@ -67,10 +73,12 @@ public interface GenericEventWrapper<F, PL, P extends GenericPlayer>{
|
||||
|
||||
String getVirtualHost();
|
||||
|
||||
PluginCore<F, PL, P> getPlugin();
|
||||
PluginCore<F> getPlugin();
|
||||
|
||||
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){
|
||||
|
||||
+21
-18
@@ -25,29 +25,32 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.objects;
|
||||
|
||||
/*
|
||||
* A simple class to allow having a nullable boolean without having to deal with possible NPEs
|
||||
* when trying to get Boolean.getValue() while it is null...
|
||||
*
|
||||
* Here, it simply checks if the value is null and if it is, returns a default. Otherwise, it gives
|
||||
* the value.
|
||||
*/
|
||||
public class NullBool{
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
|
||||
public class GenericServerImpl implements GenericServer{
|
||||
|
||||
public static final NullBool FALSE = new NullBool(false);
|
||||
public static final NullBool NULL = new NullBool(null);
|
||||
private final int online;
|
||||
private final int max;
|
||||
private final String host;
|
||||
|
||||
private final Boolean value;
|
||||
|
||||
public NullBool(Boolean value){
|
||||
this.value = value;
|
||||
public GenericServerImpl(int online, int max, String host){
|
||||
this.online = online;
|
||||
this.max = max;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public boolean isNull(){
|
||||
return value == null;
|
||||
@Override
|
||||
public int getPlayersOnline(){
|
||||
return online;
|
||||
}
|
||||
|
||||
public boolean getValue(boolean def){
|
||||
return isNull() ? def : value;
|
||||
@Override
|
||||
public int getPlayersMax(){
|
||||
return max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost(){
|
||||
return host;
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.api.internal;
|
||||
package ch.andre601.advancedserverlist.core.objects;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
@@ -36,11 +36,11 @@ public class ServerPlaceholders extends PlaceholderProvider{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer genericPlayer, GenericServer genericServer){
|
||||
return switch(placeholder){
|
||||
case "playersOnline" -> String.valueOf(server.getPlayersOnline());
|
||||
case "playersMax" -> String.valueOf(server.getPlayersMax());
|
||||
case "host" -> server.getHost();
|
||||
case "playersOnline" -> String.valueOf(genericServer.getPlayersOnline());
|
||||
case "playersMax" -> String.valueOf(genericServer.getPlayersMax());
|
||||
case "host" -> genericServer.getHost();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
@@ -25,9 +25,6 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.parsing;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
@@ -59,11 +56,6 @@ public class ComponentParser{
|
||||
return new ComponentParser(String.join("\n", lines));
|
||||
}
|
||||
|
||||
public ComponentParser applyReplacements(GenericPlayer player, GenericServer server){
|
||||
text = StringReplacer.replace(text, player, server);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ComponentParser modifyText(Function<String, String> function){
|
||||
this.text = function.apply(text);
|
||||
return this;
|
||||
|
||||
+9
-8
@@ -27,9 +27,9 @@ package ch.andre601.advancedserverlist.core.profiles;
|
||||
|
||||
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.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.conditions.Expression;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
@@ -47,11 +47,12 @@ public class ServerListProfile{
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
public ServerListProfile(int priority, List<Expression> expressions, List<ProfileEntry> profiles, ProfileEntry defaultProfile){
|
||||
public ServerListProfile(int priority, List<Expression> expressions, ProfileEntry defaultProfile, List<ProfileEntry> profiles){
|
||||
this.priority = priority;
|
||||
this.expressions = expressions;
|
||||
this.profiles = profiles;
|
||||
this.defaultProfile = defaultProfile;
|
||||
|
||||
this.profiles = profiles;
|
||||
}
|
||||
|
||||
public int getPriority(){
|
||||
@@ -96,19 +97,19 @@ public class ServerListProfile{
|
||||
*/
|
||||
public boolean isInvalidProfile(){
|
||||
if(profiles.isEmpty())
|
||||
return defaultProfile.isInvalidProfile();
|
||||
return defaultProfile.isInvalid();
|
||||
|
||||
boolean profilesValid = false;
|
||||
|
||||
for(ProfileEntry profile : profiles){
|
||||
if(profile.isInvalidProfile())
|
||||
if(profile.isInvalid())
|
||||
continue;
|
||||
|
||||
profilesValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return !profilesValid && defaultProfile.isInvalidProfile();
|
||||
return !profilesValid && defaultProfile.isInvalid();
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
@@ -150,7 +151,7 @@ public class ServerListProfile{
|
||||
return this;
|
||||
|
||||
for(String str : temp){
|
||||
Expression expr = new Expression(str);
|
||||
Expression expr = Expression.resolve(str);
|
||||
|
||||
if(expr.getResult() != Expression.ExpressionResult.VALID){
|
||||
logger.warn("Found invalid expression in condition '%s'! Reason: %s", str, expr.getResult().getMessage());
|
||||
@@ -183,7 +184,7 @@ public class ServerListProfile{
|
||||
}
|
||||
|
||||
public ServerListProfile build(){
|
||||
return new ServerListProfile(this.priority, this.expressions, this.profiles, this.defaultProfile);
|
||||
return new ServerListProfile(this.priority, this.expressions, this.defaultProfile, this.profiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
-29
@@ -31,37 +31,34 @@ import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
|
||||
public class Expression{
|
||||
|
||||
private ExpressionResult result = ExpressionResult.VALID;
|
||||
private final ExpressionResult result;
|
||||
|
||||
private String left;
|
||||
private Operator operator = Operator.UNKNOWN;
|
||||
private String right;
|
||||
private final String left;
|
||||
private final Operator operator;
|
||||
private final String right;
|
||||
|
||||
public Expression(String expression){
|
||||
resolveExpression(expression);
|
||||
private Expression(ExpressionResult result, String left, Operator operator, String right){
|
||||
this.result = result;
|
||||
this.left = left;
|
||||
this.operator = operator;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public boolean evaluate(GenericPlayer player, GenericServer server){
|
||||
String newLeft = StringReplacer.replace(left, player, server);
|
||||
String newRight = StringReplacer.replace(right, player, server);
|
||||
public static Expression createInvalid(ExpressionResult result){
|
||||
return new Expression(result, null, Operator.UNKNOWN, null);
|
||||
}
|
||||
|
||||
public static Expression resolve(String expression){
|
||||
Operator operator = Operator.UNKNOWN;
|
||||
|
||||
return operator.evaluate(newLeft, newRight);
|
||||
}
|
||||
|
||||
public ExpressionResult getResult(){
|
||||
return result;
|
||||
}
|
||||
|
||||
private void resolveExpression(String expression){
|
||||
if(expression == null || expression.isEmpty()){
|
||||
result = ExpressionResult.INVALID_NO_EXPRESSION;
|
||||
return;
|
||||
return Expression.createInvalid(ExpressionResult.INVALID_NO_EXPRESSION);
|
||||
}
|
||||
|
||||
char[] chars = expression.toCharArray();
|
||||
|
||||
StringBuilder left = new StringBuilder();
|
||||
StringBuilder right = new StringBuilder();
|
||||
StringBuilder leftBuilder = new StringBuilder();
|
||||
StringBuilder rightBuilder = new StringBuilder();
|
||||
|
||||
boolean foundOperator = false;
|
||||
|
||||
@@ -81,19 +78,28 @@ public class Expression{
|
||||
}
|
||||
|
||||
if(foundOperator){
|
||||
right.append(c);
|
||||
rightBuilder.append(c);
|
||||
}else{
|
||||
left.append(c);
|
||||
leftBuilder.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if(left.isEmpty() || right.isEmpty()){
|
||||
result = ExpressionResult.INVALID_EMPTY_PARTS;
|
||||
return;
|
||||
if(leftBuilder.isEmpty() || rightBuilder.isEmpty()){
|
||||
return Expression.createInvalid(ExpressionResult.INVALID_EMPTY_PARTS);
|
||||
}
|
||||
|
||||
this.left = left.toString();
|
||||
this.right = right.toString();
|
||||
return new Expression(ExpressionResult.VALID, leftBuilder.toString().trim(), operator, rightBuilder.toString().trim());
|
||||
}
|
||||
|
||||
public boolean evaluate(GenericPlayer player, GenericServer server){
|
||||
String newLeft = StringReplacer.replace(left, player, server);
|
||||
String newRight = StringReplacer.replace(right, player, server);
|
||||
|
||||
return operator.evaluate(newLeft, newRight);
|
||||
}
|
||||
|
||||
public ExpressionResult getResult(){
|
||||
return result;
|
||||
}
|
||||
|
||||
public enum Operator{
|
||||
@@ -121,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){
|
||||
@@ -166,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;
|
||||
}
|
||||
}
|
||||
|
||||
+33
-15
@@ -26,8 +26,8 @@
|
||||
package ch.andre601.advancedserverlist.core.profiles.favicon;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
@@ -39,36 +39,46 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FaviconHandler<F>{
|
||||
|
||||
private final Cache<String, F> favicons = Caffeine.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){
|
||||
return favicons.get(input, k -> {
|
||||
BufferedImage image = resolveImage(core, input);
|
||||
if(image == null)
|
||||
return null;
|
||||
|
||||
return function.apply(image);
|
||||
});
|
||||
try{
|
||||
return favicons.get(input, () -> convert(input, function)).getNow(null);
|
||||
}catch(ExecutionException e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCache(){
|
||||
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://")){
|
||||
@@ -121,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();
|
||||
@@ -135,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;
|
||||
});
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.profiles.players;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class GenericPlayerImpl implements GenericPlayer{
|
||||
|
||||
protected String name = null;
|
||||
protected int protocol = 0;
|
||||
protected UUID uuid = null;
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
+36
-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){
|
||||
@@ -128,6 +134,20 @@ public class PlayerHandler{
|
||||
return getDefaultPlayer();
|
||||
}
|
||||
|
||||
public CachedPlayer getCachedPlayer(UUID uuid){
|
||||
for(CachedPlayer player : cachedPlayers){
|
||||
if(player.getUuid().equals(uuid))
|
||||
return player;
|
||||
}
|
||||
|
||||
return getDefaultPlayer();
|
||||
}
|
||||
|
||||
public void clearCache(){
|
||||
cachedPlayers.clear();
|
||||
defaultPlayer = null;
|
||||
}
|
||||
|
||||
private boolean contains(String ip){
|
||||
for(CachedPlayer player : cachedPlayers){
|
||||
if(player.getIp().equals(ip))
|
||||
@@ -143,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"))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -153,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-194
@@ -1,194 +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.core.profiles.profile;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.objects.NullBool;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileEntry{
|
||||
|
||||
private final List<String> motd;
|
||||
private final List<String> players;
|
||||
private final String playerCountText;
|
||||
private final String favicon;
|
||||
private final NullBool hidePlayersEnabled;
|
||||
private final NullBool extraPlayersEnabled;
|
||||
private final Integer extraPlayersCount;
|
||||
|
||||
public ProfileEntry(List<String> motd, List<String> players,
|
||||
String playerCountText, String favicon, NullBool hidePlayersEnabled,
|
||||
NullBool extraPlayersEnabled, Integer extraPlayersCount){
|
||||
this.motd = motd;
|
||||
this.players = players;
|
||||
this.playerCountText = playerCountText;
|
||||
this.favicon = favicon;
|
||||
this.hidePlayersEnabled = hidePlayersEnabled;
|
||||
this.extraPlayersEnabled = extraPlayersEnabled;
|
||||
this.extraPlayersCount = extraPlayersCount;
|
||||
}
|
||||
|
||||
public static ProfileEntry empty(){
|
||||
return new ProfileEntry(Collections.emptyList(), Collections.emptyList(), "", "",
|
||||
NullBool.FALSE, NullBool.FALSE, 0);
|
||||
}
|
||||
|
||||
public List<String> getMOTD(){
|
||||
return motd;
|
||||
}
|
||||
|
||||
public List<String> getPlayers(){
|
||||
return players;
|
||||
}
|
||||
|
||||
public String getPlayerCountText(){
|
||||
return playerCountText;
|
||||
}
|
||||
|
||||
public String getFavicon(){
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public NullBool isHidePlayersEnabled(){
|
||||
return hidePlayersEnabled;
|
||||
}
|
||||
|
||||
public NullBool isExtraPlayersEnabled(){
|
||||
return extraPlayersEnabled;
|
||||
}
|
||||
|
||||
public Integer getExtraPlayersCount(){
|
||||
return extraPlayersCount;
|
||||
}
|
||||
|
||||
public boolean isInvalidProfile(){
|
||||
return getMOTD().isEmpty() &&
|
||||
getPlayers().isEmpty() &&
|
||||
(getPlayerCountText().isEmpty() && !isHidePlayersEnabled().getValue(false)) &&
|
||||
getFavicon().isEmpty();
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
|
||||
private final ConfigurationNode node;
|
||||
|
||||
private List<String> motd = new ArrayList<>();
|
||||
private List<String> players = new ArrayList<>();
|
||||
private String playerCountText = null;
|
||||
private String favicon = null;
|
||||
private NullBool hidePlayersEnabled = NullBool.FALSE;
|
||||
private NullBool extraPlayersEnabled = NullBool.FALSE;
|
||||
private Integer extraPlayersCount = 0;
|
||||
|
||||
private Builder(ConfigurationNode node){
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public static Builder resolve(ConfigurationNode node){
|
||||
return new Builder(node)
|
||||
.resolveMOTD()
|
||||
.resolvePlayers()
|
||||
.resolvePlayerCountText()
|
||||
.resolveFavicon()
|
||||
.resolveHidePlayersEnabled()
|
||||
.resolveExtraPlayersEnabled()
|
||||
.resolveExtraPlayersCount();
|
||||
}
|
||||
|
||||
public Builder resolveMOTD(){
|
||||
List<String> motd = resolveList(node, "motd");
|
||||
if(motd.size() <= 2){
|
||||
this.motd = motd;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.motd = motd.subList(0, 2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolvePlayers(){
|
||||
this.players = this.resolveList(node, "playerCount", "hover");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolvePlayerCountText(){
|
||||
this.playerCountText = node.node("playerCount", "text").getString("");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveFavicon(){
|
||||
this.favicon = node.node("favicon").getString("");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveHidePlayersEnabled(){
|
||||
if(node.node("playerCount", "hidePlayers").virtual()){
|
||||
this.hidePlayersEnabled = NullBool.NULL;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.hidePlayersEnabled = new NullBool(node.node("playerCount", "hidePlayers").getBoolean());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveExtraPlayersEnabled(){
|
||||
if(node.node("playerCount", "extraPlayers", "enabled").virtual()){
|
||||
this.extraPlayersEnabled = NullBool.NULL;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.extraPlayersEnabled = new NullBool(node.node("playerCount", "extraPlayers", "enabled").getBoolean());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveExtraPlayersCount(){
|
||||
if(node.node("playerCount", "extraPlayers", "amount").virtual()){
|
||||
this.extraPlayersCount = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.extraPlayersCount = node.node("playerCount", "extraPlayers", "amount").getInt();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileEntry build(){
|
||||
return new ProfileEntry(this.motd, this.players, this.playerCountText,
|
||||
this.favicon, this.hidePlayersEnabled, this.extraPlayersEnabled, this.extraPlayersCount);
|
||||
}
|
||||
|
||||
private List<String> resolveList(ConfigurationNode node, Object... path){
|
||||
try{
|
||||
return node.node(path).getList(String.class);
|
||||
}catch(SerializationException ex){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+97
-55
@@ -27,46 +27,18 @@ package ch.andre601.advancedserverlist.core.profiles.profile;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.objects.NullBool;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.objects.NullBool;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileManager{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
|
||||
private GenericPlayer player;
|
||||
private GenericServer server;
|
||||
|
||||
private ProfileManager(AdvancedServerList core){
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public static ProfileManager get(AdvancedServerList core){
|
||||
return new ProfileManager(core);
|
||||
}
|
||||
|
||||
public ProfileManager applyReplacements(GenericPlayer player, GenericServer server){
|
||||
this.player = player;
|
||||
this.server = server;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerListProfile getProfile(){
|
||||
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
|
||||
if(profile.evalConditions(player, server))
|
||||
return profile;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience method to get a ProfileEntry instance with values merged.
|
||||
* If the random profile's value is not null will it be used instead of the default one.
|
||||
@@ -84,56 +56,126 @@ public class ProfileManager{
|
||||
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
|
||||
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon,
|
||||
new NullBool(isHidePlayersEnabled), new NullBool(isExtraPlayersEnabled), extraPlayersCount);
|
||||
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), extraPlayersCount);
|
||||
}
|
||||
|
||||
public static ServerListProfile resolveProfile(AdvancedServerList core, GenericPlayer player, GenericServer server){
|
||||
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
|
||||
if(profile.evalConditions(player, server))
|
||||
return profile;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ProfileEntry retrieveProfileEntry(ConfigurationNode node){
|
||||
List<String> motd = resolveList(node, "motd");
|
||||
List<String> players = resolveList(node, "playerCount", "hover");
|
||||
String playerCountText = node.node("playerCount", "text").getString("");
|
||||
String favicon = node.node("favicon").getString("");
|
||||
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
|
||||
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
|
||||
Integer extraPlayers = resolveNullableInt(node);
|
||||
|
||||
return new ProfileEntry.Builder()
|
||||
.setMotd(motd)
|
||||
.setPlayers(players)
|
||||
.setPlayerCountText(playerCountText)
|
||||
.setFavicon(favicon)
|
||||
.setHidePlayersEnabled(hidePlayers)
|
||||
.setExtraPlayersEnabled(extraPlayersEnabled)
|
||||
.setExtraPlayerCount(extraPlayers)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static boolean checkOption(Object obj){
|
||||
if(obj == null)
|
||||
return false;
|
||||
|
||||
if(obj instanceof List<?> list){
|
||||
return !list.isEmpty(); // Check if list isn't empty
|
||||
}else
|
||||
if(obj instanceof String str){
|
||||
return !str.isEmpty(); // Check if String is not empty
|
||||
}else
|
||||
if(obj instanceof NullBool nb){
|
||||
return nb.getOrDefault(false); // Return NullBool's value
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getMOTD().isEmpty())
|
||||
return defaultProfile.getMOTD();
|
||||
if(profile == null || !checkOption(profile.motd()))
|
||||
return defaultProfile.motd();
|
||||
|
||||
return profile.getMOTD();
|
||||
return profile.motd();
|
||||
}
|
||||
|
||||
private static List<String> resolvePlayers(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getPlayers().isEmpty())
|
||||
return defaultProfile.getPlayers();
|
||||
if(profile == null || !checkOption(profile.players()))
|
||||
return defaultProfile.players();
|
||||
|
||||
return profile.getPlayers();
|
||||
return profile.players();
|
||||
}
|
||||
|
||||
private static String resolvePlayerCountText(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getPlayerCountText().isEmpty())
|
||||
return defaultProfile.getPlayerCountText();
|
||||
if(profile == null || !checkOption(profile.playerCountText()))
|
||||
return defaultProfile.playerCountText();
|
||||
|
||||
return profile.getPlayerCountText();
|
||||
return profile.playerCountText();
|
||||
}
|
||||
|
||||
private static String resolveFavicon(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getFavicon().isEmpty())
|
||||
return defaultProfile.getFavicon();
|
||||
if(profile == null || !checkOption(profile.favicon()))
|
||||
return defaultProfile.favicon();
|
||||
|
||||
return profile.getFavicon();
|
||||
return profile.favicon();
|
||||
}
|
||||
|
||||
private static boolean resolveHidePlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.isHidePlayersEnabled().isNull())
|
||||
return defaultProfile.isHidePlayersEnabled().getValue(false);
|
||||
if(profile == null || !checkOption(profile.hidePlayersEnabled()))
|
||||
return defaultProfile.hidePlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.isHidePlayersEnabled().getValue(false);
|
||||
return profile.hidePlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static boolean resolveExtraPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.isExtraPlayersEnabled().isNull())
|
||||
return defaultProfile.isExtraPlayersEnabled().getValue(false);
|
||||
if(profile == null || !checkOption(profile.extraPlayersEnabled()))
|
||||
return defaultProfile.extraPlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.isExtraPlayersEnabled().getValue(false);
|
||||
return profile.extraPlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getExtraPlayersCount() == null)
|
||||
return defaultProfile.getExtraPlayersCount() == null ? 0 : defaultProfile.getExtraPlayersCount();
|
||||
if(profile == null || profile.extraPlayersCount() == null)
|
||||
return defaultProfile.extraPlayersCount() == null ? 0 : defaultProfile.extraPlayersCount();
|
||||
|
||||
return profile.getExtraPlayersCount();
|
||||
return profile.extraPlayersCount();
|
||||
}
|
||||
|
||||
private static List<String> resolveList(ConfigurationNode node, Object... path){
|
||||
try{
|
||||
return node.node(path).getList(String.class);
|
||||
}catch(SerializationException ex){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private static NullBool resolveNullBool(ConfigurationNode node, Object... path){
|
||||
if(node.node(path).virtual())
|
||||
return NullBool.NOT_SET;
|
||||
|
||||
return NullBool.resolve(node.node(path).getBoolean());
|
||||
}
|
||||
|
||||
private static Integer resolveNullableInt(ConfigurationNode node){
|
||||
if(node.node("playerCount", "extraPlayers", "amount").virtual())
|
||||
return null;
|
||||
|
||||
return node.node("playerCount", "extraPlayers", "amount").getInt();
|
||||
}
|
||||
}
|
||||
+9
-8
@@ -29,6 +29,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@@ -37,7 +38,7 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
|
||||
@Override
|
||||
public ProfileEntry deserialize(Type type, ConfigurationNode node){
|
||||
return ProfileEntry.Builder.resolve(node).build();
|
||||
return ProfileManager.retrieveProfileEntry(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,12 +48,12 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
return;
|
||||
}
|
||||
|
||||
node.node("motd").set(profile.getMOTD());
|
||||
node.node("playerCount", "hover").set(profile.getPlayers());
|
||||
node.node("playerCount", "text").set(profile.getPlayerCountText());
|
||||
node.node("favicon").set(profile.getFavicon());
|
||||
node.node("playerCount", "hidePlayers").set(profile.isHidePlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.isExtraPlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "amount").set(profile.getExtraPlayersCount());
|
||||
node.node("motd").set(profile.motd());
|
||||
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());
|
||||
}
|
||||
}
|
||||
+3
@@ -33,6 +33,9 @@ import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
public class StringReplacer{
|
||||
|
||||
public static String replace(String input, GenericPlayer player, GenericServer server){
|
||||
if(input == null)
|
||||
return null;
|
||||
|
||||
char[] chars = input.toCharArray();
|
||||
StringBuilder builder = new StringBuilder(input.length());
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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,203 @@
|
||||
{% 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.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 }}">
|
||||
{% 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.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,17 @@
|
||||
<a
|
||||
href="{{ config.repo_url}}"
|
||||
title="{{ lang.t('source') }}"
|
||||
class="md-source"
|
||||
target="_blank"
|
||||
rel="nofollow noreferral noopener"
|
||||
>
|
||||
<div class="md-source__icon md-icon">
|
||||
{% set icon = config.theme.icon.repo or "fontawesome/brands/git-alt" %}
|
||||
{% include ".icons/" ~ icon ~ ".svg" %}
|
||||
</div>
|
||||
<div class="md-source__repository">
|
||||
{{ config.repo_name }}
|
||||
<ul class="md-source__facts" data-md-component="codeberg-stats">
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
@@ -0,0 +1,9 @@
|
||||
nav:
|
||||
- Home:
|
||||
- index.md
|
||||
- commands.md
|
||||
- profiles
|
||||
- examples
|
||||
- migration
|
||||
- api
|
||||
- placeholderapi
|
||||
@@ -0,0 +1,2 @@
|
||||
nav:
|
||||
- ...
|
||||
@@ -0,0 +1,82 @@
|
||||
---
|
||||
icon: octicons/log-24
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
This page lists the recent changes made towards the AdvancedServerListAPI.
|
||||
They are ordered newest to oldest.
|
||||
|
||||
## 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
|
||||
|
||||
### :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 record's own `x()` methods (i.e. `getMotd()` -> `motd()`)
|
||||
|
||||
## v2.0.0
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v2-breaking }
|
||||
|
||||
- `platform-paper` has been removed. It used the same code as `platform-spigot` and was therefore considered duplicate code and useless.
|
||||
- `core` has been removed. The `CachedPlayer` is no longer needed in the platform-specific APIs.
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v2-added }
|
||||
|
||||
- `PreServerListSetEvent` to the different platform-specific APIs.
|
||||
- Called before AdvancedServerList alters the server list.
|
||||
- Allows to override the `ProfileEntry` used or even cancel the event.
|
||||
- `ProfileEntry`
|
||||
- Used for setting the different values of the server list.
|
||||
- Own instances can be made using the nested `Builder` class.
|
||||
- Has methods to create a Builder instance from itself, or make a copy from another ProfileEntry-instance.
|
||||
|
||||
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v2-changed }
|
||||
|
||||
- Converted `GenericPlayer`, `GenericServer`, `BungeePlayer`, `SpigotPlayer` and `VelocityPlayer` into interfaces.
|
||||
- `GenericPlayer` no longer has `getVersion()`, `hasPlayedBefore()`, `isBanned()` and `isWhitelisted()`. They have been moved to `VelocityPlayer` (Only `getVersion()`) and `SpigotPlayer` respectively.
|
||||
- Converted `NullBool` from a class to an enum.
|
||||
- Contains `TRUE`, `FALSE` and `NOT_SET`.
|
||||
- `isNull()` is now `isNotSet()`.
|
||||
|
||||
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v2-removed }
|
||||
|
||||
- `UnsupportedAPIAccessException` as it is no longer used in the API itself.
|
||||
|
||||
## v1.0.0
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v1-added }
|
||||
|
||||
- `AdvancedServerListAPI`
|
||||
- Main class used to add your own `PlaceholderProvider` instances.
|
||||
- `PlaceholderProvider`
|
||||
- Abstract class used to add your own placeholders to parse in AdvancedServerList.
|
||||
|
||||
<!--
|
||||
|
||||
Templates for changelog
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v-breaking }
|
||||
### :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 }
|
||||
|
||||
-->
|
||||
@@ -1,7 +1,11 @@
|
||||
---
|
||||
icon: octicons/command-palette-24
|
||||
---
|
||||
|
||||
# API
|
||||
|
||||
AdvancedServerList v2 introduced a new API that plugins can hook into to use.
|
||||
As of right now is it only providing a way to add your own placeholders for it to use.
|
||||
It provides a way for your plugin to provide its own placeholders that should be parsed by AdvancedServerList and also an event to modify the server list.
|
||||
|
||||
## Add dependency
|
||||
|
||||
@@ -9,29 +13,32 @@ Add the following to your `build.gradle` or `pom.xml` file to use the API:
|
||||
|
||||
=== ":simple-gradle: Gradle"
|
||||
|
||||
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
|
||||
[![latest_release][release]][api-repo]
|
||||
|
||||
```groovy
|
||||
Make sure to replace `{version}` with the version displayed above.
|
||||
|
||||
```groovy title="build.gradle"
|
||||
repositorories {
|
||||
maven { url = 'https://jitpack.io/" }
|
||||
maven { url = 'https://jitpack.io/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'ch.andre601.asl-api:api:{version}'
|
||||
|
||||
// Optional platform dependencies
|
||||
implementation 'ch.andre601.asl-api:platform-bukkit:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-bungeecord:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-paper:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-spigot:{version}'
|
||||
implementation 'ch.andre601.asl-api:platform-velocity:{version}'
|
||||
}
|
||||
```
|
||||
|
||||
=== ":simple-apachemaven: Maven"
|
||||
|
||||
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
|
||||
[![latest_release][release]][api-repo]
|
||||
|
||||
```xml
|
||||
Make sure to replace `{version}` with the version displayed above.
|
||||
|
||||
```xml title="pom.xml"
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack</id>
|
||||
@@ -47,21 +54,16 @@ Add the following to your `build.gradle` or `pom.xml` file to use the API:
|
||||
</dependency>
|
||||
|
||||
<!-- Optional platform dependencies -->
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bukkit</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-bungeecord</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.andre601.asl-api</groupId>
|
||||
<artifactId>platform-paper</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>
|
||||
@@ -70,6 +72,7 @@ Add the following to your `build.gradle` or `pom.xml` file to use the API:
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
[release]: https://img.shields.io/github/v/tag/Andre601/asl-api?labelColor=252631&color=292a36&style=for-the-badge&label=Latest%20Release:
|
||||
[api-repo]: https://github.com/Andre601/asl-api
|
||||
|
||||
## Add own placeholders
|
||||
@@ -84,8 +87,9 @@ It will be needed at a later point.
|
||||
### 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
|
||||
Your IDE should now tell you to implement/override some methods. Confirm this action and your class should look something alongside this:
|
||||
|
||||
```java title="PlaceholderProvider example"
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
public MyPlaceholders(String identifier) {
|
||||
@@ -100,7 +104,8 @@ 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:
|
||||
For example:
|
||||
|
||||
```java
|
||||
public MyPlaceholders() {
|
||||
super("myplaceholders");
|
||||
@@ -112,8 +117,9 @@ The `placeholder` String is whatever value was provided after the identifier in
|
||||
|
||||
Something to note is, that when returning `null` will AdvancedServerList understand it as an invalid placeholder and return it unchanged.
|
||||
|
||||
Here is a small example of the final class:
|
||||
```java
|
||||
Here is a small example of the final class:
|
||||
|
||||
```java title="PlaceholderProvider example"
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
public MyPlaceholders() {
|
||||
@@ -134,9 +140,23 @@ public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
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.
|
||||
|
||||
Example:
|
||||
```java
|
||||
```java title="Registering PlaceholderProvider class"
|
||||
AdvancedServerListAPI api = AdvancedServerListAPI.get();
|
||||
|
||||
api.addPlaceholderProvider(new MyPlaceholders());
|
||||
```
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
!!! 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.
|
||||
|
||||
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.
|
||||
|
||||
### ProfileEntry
|
||||
|
||||
The ProfileEntry class has been moved to the API in v2 allowing you to create your own versions using the available Builder class.
|
||||
|
||||
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`.
|
||||
@@ -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())
|
||||
Loaded 100 of 178 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user