mirror of
https://codeberg.org/Andre601/AdvancedServerList.git
synced 2026-11-05 09:00:15 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d5d4fcab2 | ||
|
|
0763a9b3b4 | ||
|
|
2d67a89fc2 | ||
|
|
4207d875f9 | ||
|
|
5da420c6c6 | ||
|
|
1ffa4842c3 | ||
|
|
819e194f27 | ||
|
|
269e55b93f | ||
|
|
04412f7138 | ||
|
|
0fce9d01e1 | ||
|
|
1c29301635 | ||
|
|
8bd7bbb5d7 | ||
|
|
1a99663b59 | ||
|
|
36e31279b2 | ||
|
|
4aa7eba675 | ||
|
|
3bbe2d26b8 | ||
|
|
782ad838be | ||
|
|
ceddb26137 | ||
|
|
ff044d75c7 | ||
|
|
8955df695d | ||
|
|
8ddcb208f5 | ||
|
|
95834df89f | ||
|
|
2f67f26cbe | ||
|
|
00957f9458 | ||
|
|
2e9e886c48 | ||
|
|
d2d4e48b73 | ||
|
|
fe16df27f2 | ||
|
|
cc29f70dff | ||
|
|
e136f7cfaf | ||
|
|
fd52f124fb | ||
|
|
5a656cee39 | ||
|
|
21a89f9b14 | ||
|
|
9ded4d2d57 | ||
|
|
fb64d92879 | ||
|
|
1a4bcae4d1 | ||
|
|
25ee4da4f4 | ||
|
|
35cb39c35e | ||
|
|
3a5f232f92 | ||
|
|
4ed201fba9 | ||
|
|
03835f71d9 | ||
|
|
480e50e71e | ||
|
|
39110b2898 | ||
|
|
e8db70e319 | ||
|
|
eb907988fb | ||
|
|
95935022b8 | ||
|
|
1e70cb0651 | ||
|
|
1594d062e5 | ||
|
|
04b266f558 | ||
|
|
9989fec809 | ||
|
|
ab8eabc348 | ||
|
|
931b8b5c36 | ||
|
|
64957ba13c | ||
|
|
a03be990ab | ||
|
|
44729495f5 | ||
|
|
9e7500f0cd | ||
|
|
d10ff8bdbc | ||
|
|
f91fc36365 | ||
|
|
84ddff07a2 | ||
|
|
4a89658cf4 | ||
|
|
5daef41031 | ||
|
|
07cc1e8160 | ||
|
|
8b2d763207 | ||
|
|
fb8c556e24 | ||
|
|
397fa12f12 | ||
|
|
d86ecf8d8b | ||
|
|
2882e9ecdf | ||
|
|
69a4a05069 | ||
|
|
361a340ef1 | ||
|
|
ee7c0451af | ||
|
|
200c7cbfea | ||
|
|
9a665ddf26 | ||
|
|
c4327ac238 | ||
|
|
9f4b798848 | ||
|
|
3cc18f4dc0 | ||
|
|
9637308045 | ||
|
|
772603e785 | ||
|
|
f9417ee2f7 | ||
|
|
2db85bff60 | ||
|
|
527b5aa25c | ||
|
|
5d9bb0dc4a | ||
|
|
cc51756f0d | ||
|
|
5ff66adb0c | ||
|
|
8e9cc98ded | ||
|
|
4387e78007 | ||
|
|
4fff1e24cc | ||
|
|
9791ed0cee | ||
|
|
e8e6f3a8fd | ||
|
|
5e6da9b24e | ||
|
|
59bd9239b2 | ||
|
|
08436a278c | ||
|
|
5d512e5e89 | ||
|
|
ec1a367691 | ||
|
|
457450683b | ||
|
|
a8d76d6b0f | ||
|
|
5036d62824 | ||
|
|
4f5f6e724f | ||
|
|
71f7532fe3 | ||
|
|
9ea37af603 | ||
|
|
1964a6b4e3 | ||
|
|
94a9ea31a0 | ||
|
|
2855d268da | ||
|
|
d6d576da20 | ||
|
|
34ed832d79 | ||
|
|
42ef8c0c39 | ||
|
|
1ce0c2db4e | ||
|
|
028aaa1cf7 | ||
|
|
66937916c4 | ||
|
|
82a053095e | ||
|
|
f24e62687d | ||
|
|
184cf8443c | ||
|
|
2b06bcc497 | ||
|
|
743f4cc5eb | ||
|
|
45ccb18133 | ||
|
|
3812e11702 | ||
|
|
c731cd3c87 | ||
|
|
466a24eea3 | ||
|
|
d747a0c19a | ||
|
|
59a64620bf | ||
|
|
f36b4b4078 | ||
|
|
9298b0270b | ||
|
|
d8dc50ceec | ||
|
|
60be698c61 | ||
|
|
0b37e92260 | ||
|
|
b7b1b63c4e | ||
|
|
98b923aa54 | ||
|
|
b24d7cb849 | ||
|
|
7df7157d5f | ||
|
|
47263746db | ||
|
|
ff06b06966 | ||
|
|
fe42d282d1 | ||
|
|
12df4e49c6 | ||
|
|
06812b2725 | ||
|
|
93e4ae7ca7 | ||
|
|
d57f3f20e3 | ||
|
|
f418fb961b | ||
|
|
267af92ceb | ||
|
|
57448ddaf6 | ||
|
|
9f40af4553 | ||
|
|
e25da2c6c5 | ||
|
|
897cccaa86 | ||
|
|
512efd0efe | ||
|
|
b67fa683c6 | ||
|
|
34387925b8 | ||
|
|
303dbc5ae9 | ||
|
|
ee565ff6f7 | ||
|
|
98baaab36a | ||
|
|
92e9d790a4 | ||
|
|
b8f2e2932b | ||
|
|
45f9202bdd | ||
|
|
ffeffc70c3 | ||
|
|
60080a5af6 |
No files matched your search
+53
-58
@@ -1,108 +1,103 @@
|
||||
# AdvancedServerList
|
||||
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.
|
||||
<center><strong><u><font size="6">AdvancedServerList</font ></u></strong></center>
|
||||
|
||||
AdvancedServerList is a plugin designed to allow the largest possible customization for your server's appearance in a Player's multiplayer screen.
|
||||
The plugin offers extensive customization including changing the MOTD, player count text, player count hover and favicon of your server. All while also allowing you to create multiple profiles with priorities and conditions to set when a specific profile should be displayed.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<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://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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg&h=48" alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/bungeecord_vector.svg&h=48" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://www.papermc.io" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/waterfall_vector.svg&h=48" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://velocitypowered.com" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/velocity_vector.svg&h=48" alt="platform-velocity" title="Tested on Velocity">
|
||||
</a>
|
||||
|
||||
## What is a Server List Profile?
|
||||
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
|
||||
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.
|
||||
## Server List Profiles
|
||||
|
||||
> [*Read More*][profiles]
|
||||
A Server List Profile is a single YAML file located in the plugin's `profiles` folder. It contains settings that allow you to modify the server's appearance within a Player's multiplayer screen.
|
||||
|
||||
### 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).
|
||||
### Priority and Conditions
|
||||
|
||||
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.
|
||||
Each file has a priority and optional condition. The priority is used to determine what file AdvancedServerList should use first - starting from highest number to lowest - with conditions being used to set when the profile should be used.
|
||||
Once a profile has been found with a condition returning true - which is the default should there be no condition - will AdvancedServerList use said profile.
|
||||
|
||||
> [*Read More*][conditions]
|
||||
> *Read more about [Priority](https://asl.andre601.ch/profiles/#priority) and [Conditions](https://asl.andre601.ch/profiles/#condition)*
|
||||
|
||||
### 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.
|
||||
|
||||
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.
|
||||
AdvancedServerList supports two sets of placeholders. The first one being its own placeholders using the `${<type> <values>}` format adobted from BungeeTabListPlus and the second one being placeholders from PlaceholderAPI using its `%<identifier>_<values>%` placeholder format.
|
||||
|
||||
> [*Read More*][placeholders]
|
||||
Note that internal placeholders can be used in all text-based options of a profile, while PlaceholderAPI placeholders can be used in all text-based options except the `condition` one.
|
||||
As a final note can plugins provide their own placeholders to use within AdvancedServerList by using its API.
|
||||
|
||||
> *Read more about [Placeholders](https://asl.andre601.ch/profiles/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]
|
||||
AdvancedServerList utilizes the MiniMessage formatting to handle colors and formatting of text. This option was chosen over legacy formatting - using `&` character - for being more clear and readable in its design, not to mention having an easier way for more complex features such as RGB gradients.
|
||||
|
||||
> *Read more about [Formatting](https://asl.andre601.ch/profiles/formatting/)*
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Platforms | Required? |
|
||||
|------------------|---------------|-----------|
|
||||
| [ProtocolLib] | Spigot | Yes |
|
||||
| [PlaceholderAPI] | Spigot, Paper | No |
|
||||
| [ViaVersion] | Spigot, Paper | No |
|
||||
AdvancedServerList soft-depends on the following plugins, meaning their inclusion is not required.
|
||||
|
||||
| Plugin | Supported Platforms |
|
||||
|-------------------------------------------------------------------------|----------------------------------------|
|
||||
| [PlaceholderAPI](https://hangar.papermc.io/HelpChat/PlaceholderAPI) | Paper |
|
||||
| [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) | Paper |
|
||||
| [PAPIProxyBridge](https://hangar.papermc.io/William278/PAPIProxyBridge) | BungeeCord, Waterfall, Velocity |
|
||||
| [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) | Paper, BungeeCord, Waterfall, Velocity |
|
||||
|
||||
## Statistics
|
||||
|
||||
This plugin sends statistics to [bStats] to display.
|
||||
You can disable this in the global bStats config file located in `/plugins/bstats/`
|
||||
The plugin sends statistics to [bStats](https://bstats.org) to show.
|
||||
You can disable the sending of statistics in the global bStats config located inside `/plugins/bstats/`.
|
||||
|
||||
- [BungeeCord][bstats-bungee]
|
||||
- [Paper/Spigot][bstats-spigot]
|
||||
- [Velocity][bstats-velocity]
|
||||
You can find the bStats pages of the plugin for the following platforms:
|
||||
|
||||
- [Paper](https://bstats.org/plugin/bungeecord/AdvancedServerList/15584)
|
||||
- [BungeeCord, Waterfall](https://bstats.org/plugin/bungeecord/AdvancedServerList/15585)
|
||||
- [Velocity](https://bstats.org/plugin/velocity/AdvancedServerList/15587)
|
||||
|
||||
## 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>
|
||||
Below can you find a collection of videos made for my plugin. If you made a video and it isn't shown here, let me know and I'll add it.
|
||||
|
||||
<details><summary>Click to show/hide Videos</summary>
|
||||
<p>
|
||||
|
||||
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>
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/modrinth-gallery_vector.svg&h=48" alt="gallery" title="Check out the Gallery">
|
||||
</a>
|
||||
|
||||
## Support
|
||||
|
||||
<a href="https://discord.gg/MyPTjpsgGH" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg&h=48" alt="discord" title="Join the M.O.S.S. Discord Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<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">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg&h=48" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<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://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
|
||||
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
|
||||
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
|
||||
|
||||
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg&h=48" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 876 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 877 KiB |
@@ -11,7 +11,7 @@ variables:
|
||||
|
||||
steps:
|
||||
- name: "Clone Preview Repository"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- <<: *setup_git
|
||||
@@ -24,7 +24,7 @@ steps:
|
||||
settings:
|
||||
pip_install_file: requirements.txt
|
||||
- name: "Commit and Push"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
secrets:
|
||||
- bot_token
|
||||
commands:
|
||||
|
||||
@@ -4,7 +4,7 @@ when:
|
||||
|
||||
steps:
|
||||
- name: "Build Jar and Upload"
|
||||
image: maven:3.9.6-eclipse-temurin-17
|
||||
image: maven:3.9.9-eclipse-temurin-21
|
||||
secrets:
|
||||
- modrinth_api_token
|
||||
- hangar_api_token
|
||||
@@ -34,7 +34,7 @@ steps:
|
||||
when:
|
||||
- status: ["success"]
|
||||
settings:
|
||||
server_url: https://blobfox.coffee
|
||||
server_url: https://swiss.social
|
||||
access_token:
|
||||
from_secret: mastodon_token
|
||||
status: |-
|
||||
|
||||
@@ -12,7 +12,7 @@ variables:
|
||||
|
||||
steps:
|
||||
- name: "Clone target Repository"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- <<: *setup_git
|
||||
@@ -23,7 +23,7 @@ steps:
|
||||
settings:
|
||||
pip_install_file: requirements.txt
|
||||
- name: "Commit and Push"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
secrets:
|
||||
- bot_token
|
||||
commands:
|
||||
|
||||
@@ -1,119 +1,113 @@
|
||||
# AdvancedServerList
|
||||
|
||||
AdvancedServerList is a plugin that allows 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.
|
||||
AdvancedServerList is a plugin designed to allow the largest possible customization for your server's appearance in a Player's multiplayer screen.
|
||||
The plugin offers extensive customization including changing the MOTD, player count text, player count hover and favicon of your server. All while also allowing you to create multiple profiles with priorities and conditions to set when a specific profile should be displayed.
|
||||
|
||||
## 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">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg" height="48" 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">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg" height="48" alt="hangar" title="Available on Hangar">
|
||||
</a>
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg" height="48" alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<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">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/bungeecord_vector.svg" height="48" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://www.papermc.io" target="_blank">
|
||||
<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">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/waterfall_vector.svg" height="48" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://velocitypowered.com" target="_blank">
|
||||
<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">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/velocity_vector.svg" height="48" alt="platform-velocity" title="Tested on Velocity">
|
||||
</a>
|
||||
|
||||
## What is a Server List Profile?
|
||||
## Server List Profiles
|
||||
|
||||
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
|
||||
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.
|
||||
A Server List Profile is a single YAML file located in the plugin's `profiles` folder. It contains settings that allow you to modify the server's appearance within a Player's multiplayer screen.
|
||||
|
||||
> [*Read More*][profiles]
|
||||
### Priority and Conditions
|
||||
|
||||
### Conditions
|
||||
Each file has a priority and optional condition. The priority is used to determine what file AdvancedServerList should use first - starting from highest number to lowest - with conditions being used to set when the profile should be used.
|
||||
Once a profile has been found with a condition returning true - which is the default should there be no condition - will AdvancedServerList use said profile.
|
||||
|
||||
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 it automatically true.
|
||||
|
||||
> [*Read More*][conditions]
|
||||
> *Read more about [Priority](https://asl.andre601.ch/profiles/#priority) and [Conditions](https://asl.andre601.ch/profiles/#condition)*
|
||||
|
||||
### Placeholders
|
||||
|
||||
Placeholders can be used within conditions to further customize them. They can also be used in any other text option to display their respective values.
|
||||
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
|
||||
AdvancedServerList supports two sets of placeholders. The first one being its own placeholders using the `${<type> <values>}` format adobted from BungeeTabListPlus and the second one being placeholders from PlaceholderAPI using its `%<identifier>_<values>%` placeholder format.
|
||||
|
||||
When using the SpigotMC/PaperMC version, or while [PAPIProxyBridge][papiproxybridge] is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed on the server (not proxy) for that.
|
||||
Note that internal placeholders can be used in all text-based options of a profile, while PlaceholderAPI placeholders can be used in all text-based options except the `condition` one.
|
||||
As a final note can plugins provide their own placeholders to use within AdvancedServerList by using its API.
|
||||
|
||||
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
|
||||
|
||||
> [*Read More*][placeholders]
|
||||
> *Read more about [Placeholders](https://asl.andre601.ch/profiles/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.
|
||||
AdvancedServerList utilizes the MiniMessage formatting to handle colors and formatting of text. This option was chosen over legacy formatting - using `&` character - for being more clear and readable in its design, not to mention having an easier way for more complex features such as RGB gradients.
|
||||
|
||||
> [*Read More*][minimessage]
|
||||
> *Read more about [Formatting](https://asl.andre601.ch/profiles/formatting/)*
|
||||
|
||||
## Dependencies
|
||||
|
||||
All listed dependencies are optional.
|
||||
AdvancedServerList soft-depends on the following plugins, meaning their inclusion is not required.
|
||||
|
||||
| Dependency | Platforms |
|
||||
|-------------------|----------------------|
|
||||
| [PlaceholderAPI] | Paper |
|
||||
| [ViaVersion] | Paper |
|
||||
| [PAPIProxyBridge] | BungeeCord, Velocity |
|
||||
| [Maintenance] | All |
|
||||
| Plugin | Supported Platforms |
|
||||
|-------------------------------------------------------------------------|----------------------------------------|
|
||||
| [PlaceholderAPI](https://hangar.papermc.io/HelpChat/PlaceholderAPI) | Paper |
|
||||
| [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) | Paper |
|
||||
| [PAPIProxyBridge](https://hangar.papermc.io/William278/PAPIProxyBridge) | BungeeCord, Waterfall, Velocity |
|
||||
| [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) | Paper, BungeeCord, Waterfall, Velocity |
|
||||
|
||||
## Statistics
|
||||
|
||||
This plugin sends statistics to [bStats] to display.
|
||||
You can disable this in the global bStats config file located in `/plugins/bstats/`
|
||||
The plugin sends statistics to [bStats](https://bstats.org) to show.
|
||||
You can disable the sending of statistics in the global bStats config located inside `/plugins/bstats/`.
|
||||
|
||||
- [BungeeCord][bstats-bungee]
|
||||
- [Paper/Spigot][bstats-spigot]
|
||||
- [Velocity][bstats-velocity]
|
||||
You can find the bStats pages of the plugin for the following platforms:
|
||||
|
||||
- [Paper](https://bstats.org/plugin/bungeecord/AdvancedServerList/15584)
|
||||
- [BungeeCord, Waterfall](https://bstats.org/plugin/bungeecord/AdvancedServerList/15585)
|
||||
- [Velocity](https://bstats.org/plugin/velocity/AdvancedServerList/15587)
|
||||
|
||||
## Videos
|
||||
|
||||
Below can you find a collection of videos made for my plugin. If you made a video and it isn't shown here, let me know and I'll add it.
|
||||
|
||||
<details><summary>Click to show/hide Videos</summary>
|
||||
<p>
|
||||
|
||||
Spanish Video by Ajneb97
|
||||
[](https://youtube.com/watch?v=rIbljm_4HVI)
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" alt="gallery" title="Check out the Gallery">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/modrinth-gallery_vector.svg" height="48" alt="gallery" title="Check out the Gallery">
|
||||
</a>
|
||||
|
||||
## Support
|
||||
|
||||
<a href="https://discord.gg/MyPTjpsgGH" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join the M.O.S.S. Discord Server">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg" height="48" alt="discord" title="Join the M.O.S.S. Discord Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<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">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg" height="48" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<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://asl.andre601.ch/profiles/
|
||||
[conditions]: https://asl.andre601.ch/profiles/#condition
|
||||
[placeholders]: https://asl.andre601.ch/profiles/placeholders/
|
||||
[minimessage]: https://asl.andre601.ch/profiles/formatting/
|
||||
|
||||
[modrinth]: https://modrinth.com/plugin/advancedserverlist
|
||||
|
||||
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
|
||||
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
|
||||
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
|
||||
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
|
||||
|
||||
[bstats]: https://bstats.org
|
||||
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
|
||||
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
|
||||
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
|
||||
|
||||
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg" height="48" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
@@ -52,7 +52,7 @@
|
||||
</repository>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>libertybans</id>
|
||||
@@ -79,7 +79,7 @@
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -2,7 +2,7 @@ name: 'ASLBanPluginsAddon'
|
||||
author: 'Andre_601'
|
||||
version: '${plugin.version}'
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.banplugins.paper.AdvancedBanPlaceholders'
|
||||
main: 'ch.andre601.advancedserverlist.banplugins.paper.PaperBanPluginsAddon'
|
||||
|
||||
api-version: '1.19'
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
AdvancedServerList:
|
||||
required: false
|
||||
load: BEFORE
|
||||
AdvancedBans:
|
||||
AdvancedBan:
|
||||
required: false
|
||||
load: BEFORE
|
||||
LibertyBans:
|
||||
|
||||
+3
-7
@@ -49,10 +49,6 @@
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-snapshots</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
@@ -85,7 +81,7 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Adventure Library. Needs to be shaded in -->
|
||||
<!-- Adventure Library -->
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
@@ -109,7 +105,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bungeecord</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -155,7 +151,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
|
||||
+33
-11
@@ -30,12 +30,14 @@ 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.placeholders.BungeePlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeProxyPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.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.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
|
||||
import com.alessiodp.libby.BungeeLibraryManager;
|
||||
import com.alessiodp.libby.Library;
|
||||
import de.myzelyam.api.vanish.BungeeVanishAPI;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
@@ -52,12 +54,15 @@ import java.util.List;
|
||||
|
||||
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
|
||||
private final PluginLogger logger = new BungeeLogger(this);
|
||||
|
||||
private boolean successfulLoad = false;
|
||||
|
||||
private AdvancedServerList<Favicon> core;
|
||||
private FaviconHandler<Favicon> faviconHandler = null;
|
||||
private BungeeAudiences audiences = null;
|
||||
private final PluginLogger logger = new BungeeLogger(this);
|
||||
|
||||
private BungeeLibraryManager libraryManager = null;
|
||||
|
||||
@Override
|
||||
public void onLoad(){
|
||||
@@ -79,7 +84,8 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
}
|
||||
|
||||
this.audiences = BungeeAudiences.create(this);
|
||||
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
|
||||
this.core = AdvancedServerList.init(this,
|
||||
BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this), BungeeProxyPlaceholders.init(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,6 +125,23 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
faviconHandler.cleanCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadLibrary(String groupId, String artifactId, String version){
|
||||
if(libraryManager == null){
|
||||
libraryManager = new BungeeLibraryManager(this);
|
||||
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
|
||||
}
|
||||
|
||||
Library lib = Library.builder()
|
||||
.groupId(groupId)
|
||||
.artifactId(artifactId)
|
||||
.version(version)
|
||||
.resolveTransitiveDependencies(true)
|
||||
.build();
|
||||
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
@@ -143,13 +166,8 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName(){
|
||||
return getProxy().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion(){
|
||||
return getProxy().getVersion();
|
||||
public String getPlatformInfo(){
|
||||
return getProxy().getName() + " " + getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,7 +202,11 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
|
||||
private boolean loadLibs(){
|
||||
try{
|
||||
BungeeLibraryManager libraryManager = new BungeeLibraryManager(this);
|
||||
if(libraryManager == null){
|
||||
libraryManager = new BungeeLibraryManager(this);
|
||||
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
|
||||
}
|
||||
|
||||
libraryManager.configureFromJSON("dependencies.json");
|
||||
|
||||
return true;
|
||||
|
||||
+12
-6
@@ -31,7 +31,8 @@ import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeePlayerImpl;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeeProxyImpl;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
|
||||
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
@@ -78,6 +79,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
ping.getPlayers().setMax(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
ping.getPlayers().setOnline(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
|
||||
@@ -137,7 +143,7 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
if(plugin.getProxy().getPluginManager().getPlugin("Maintenance") == null)
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
return MaintenanceUtil.get().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,10 +171,10 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
if(plugin.getProxy().getPluginManager().getPlugin("PAPIProxyBridge") == null)
|
||||
return text;
|
||||
|
||||
if(!PingEventHandler.getPAPIUtil().isCompatible())
|
||||
if(!PAPIUtil.get().isCompatible())
|
||||
return text;
|
||||
|
||||
String server = PingEventHandler.getPAPIUtil().getServer();
|
||||
String server = PAPIUtil.get().getServer();
|
||||
if(server == null || server.isEmpty())
|
||||
return text;
|
||||
|
||||
@@ -176,11 +182,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
if(serverInfo == null || serverInfo.getPlayers().isEmpty())
|
||||
return text;
|
||||
|
||||
ProxiedPlayer carrier = PingEventHandler.getPAPIUtil().getPlayer(serverInfo.getPlayers());
|
||||
ProxiedPlayer carrier = PAPIUtil.get().getPlayer(serverInfo.getPlayers());
|
||||
if(carrier == null)
|
||||
return text;
|
||||
|
||||
return PingEventHandler.getPAPIUtil().parse(text, carrier.getUniqueId(), player.getUUID());
|
||||
return PAPIUtil.get().parse(text, carrier.getUniqueId(), player.getUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+23
-2
@@ -25,14 +25,35 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeePlayer;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
|
||||
|
||||
public class BungeePlayerImpl extends GenericPlayerImpl{
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeePlayerImpl implements BungeePlayer{
|
||||
|
||||
private final String name;
|
||||
private final int protocol;
|
||||
private final UUID uuid;
|
||||
|
||||
public BungeePlayerImpl(CachedPlayer player, int protocol){
|
||||
this.name = player.name();
|
||||
this.protocol = protocol;
|
||||
this.uuid = player.uuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeeProxyPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private final Map<String, ServerPing> serverStates = new ConcurrentHashMap<>();
|
||||
private final BungeeCordCore plugin;
|
||||
|
||||
private BungeeProxyPlaceholders(BungeeCordCore plugin){
|
||||
super("proxy");
|
||||
|
||||
this.plugin = plugin;
|
||||
plugin.getProxy().getScheduler().schedule(plugin, this::fetchServerStates, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static BungeeProxyPlaceholders init(BungeeCordCore plugin){
|
||||
return new BungeeProxyPlaceholders(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
String[] args = placeholder.split("\\s", 2);
|
||||
if(args.length < 2)
|
||||
return null;
|
||||
|
||||
ServerPing ping = serverStates.get(args[1]);
|
||||
|
||||
return switch(args[0]){
|
||||
case "status" -> ping == null ? "offline" : "online";
|
||||
case "motd" -> {
|
||||
if(ping == null)
|
||||
yield "none";
|
||||
|
||||
BaseComponent[] components = new BaseComponent[]{ping.getDescriptionComponent()};
|
||||
Component component = BungeeComponentSerializer.get().deserialize(components);
|
||||
|
||||
yield ComponentParser.toMMString(component);
|
||||
}
|
||||
case "players" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(ping.getPlayers().getOnline());
|
||||
}
|
||||
case "maxPlayers" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(ping.getPlayers().getMax());
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private void fetchServerStates(){
|
||||
serverStates.clear();
|
||||
plugin.getProxy().getServers().forEach((name, server) -> server.ping((ping, throwable) -> {
|
||||
if(throwable != null){
|
||||
plugin.getPluginLogger().warn("Encountered an exception while fetching status of Server %s", throwable, name);
|
||||
return;
|
||||
}
|
||||
|
||||
serverStates.put(name, ping);
|
||||
}));
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -79,18 +79,18 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
|
||||
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 "";
|
||||
|
||||
yield String.valueOf(proxy.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length > 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
if(args.length == 2){
|
||||
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
|
||||
ServerInfo info = proxy.getServers().get(args[1]);
|
||||
if(info == null)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{
|
||||
"repositories": [
|
||||
"https://repo.papermc.io/repository/maven-public"
|
||||
],
|
||||
"libraries": [
|
||||
{
|
||||
"groupId": "net{}kyori",
|
||||
|
||||
+14
-8
@@ -41,7 +41,7 @@
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
<plugin.config.version>5</plugin.config.version>
|
||||
<plugin.config.version>6</plugin.config.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@@ -77,7 +77,7 @@
|
||||
<dependency>
|
||||
<groupId>ch.andre601</groupId>
|
||||
<artifactId>expressionparser</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -86,6 +86,12 @@
|
||||
<version>${dependency.configurate-yaml}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-hocon</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- MiniMessage -->
|
||||
<dependency>
|
||||
@@ -111,7 +117,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
<version>2.11.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -123,7 +129,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.2.0-jre</version>
|
||||
<version>33.3.1-jre</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -131,13 +137,13 @@
|
||||
<dependency>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<version>1.6.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>eu.kennytv.maintenance</groupId>
|
||||
<artifactId>maintenance-api</artifactId>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<version>4.2.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -151,7 +157,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<version>5.11.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -173,7 +179,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
||||
@@ -29,10 +29,11 @@ import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.core.check.UpdateChecker;
|
||||
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenancePlaceholder;
|
||||
import ch.andre601.advancedserverlist.core.file.FileHandler;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -59,7 +60,16 @@ public class AdvancedServerList<F>{
|
||||
this.commandHandler = new CommandHandler(this);
|
||||
this.playerHandler = new PlayerHandler(this);
|
||||
|
||||
placeholders.forEach(AdvancedServerList.getApi()::addPlaceholderProvider);
|
||||
plugin.getPluginLogger().info("Registering internal Placeholders...");
|
||||
|
||||
placeholders.forEach(this::addPlaceholder);
|
||||
|
||||
if(plugin.isPluginEnabled("Maintenance")){
|
||||
plugin.getPluginLogger().info("Found Maintenance Plugin. Registering extra Placeholder...");
|
||||
addPlaceholder(new MaintenancePlaceholder(this));
|
||||
}
|
||||
|
||||
plugin.getPluginLogger().info("Completed internal Placeholder registration!");
|
||||
|
||||
load();
|
||||
}
|
||||
@@ -68,6 +78,10 @@ public class AdvancedServerList<F>{
|
||||
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
|
||||
}
|
||||
|
||||
public static AdvancedServerListAPI getApi(){
|
||||
return api;
|
||||
}
|
||||
|
||||
public PluginCore<F> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
@@ -88,10 +102,6 @@ public class AdvancedServerList<F>{
|
||||
return version;
|
||||
}
|
||||
|
||||
public static AdvancedServerListAPI getApi(){
|
||||
return api;
|
||||
}
|
||||
|
||||
public ProfileConditionParser getParser(){
|
||||
return parser;
|
||||
}
|
||||
@@ -125,7 +135,7 @@ public class AdvancedServerList<F>{
|
||||
resolveVersion();
|
||||
|
||||
getPlugin().getPluginLogger().info("Starting AdvancedServerList v%s...", version);
|
||||
getPlugin().getPluginLogger().info("Platform: " + plugin.getPlatformName() + " " + plugin.getPlatformVersion());
|
||||
getPlugin().getPluginLogger().info("Platform: %s", plugin.getPlatformInfo());
|
||||
|
||||
if(getFileHandler().loadConfig()){
|
||||
getPlugin().getPluginLogger().info("Successfully loaded config.yml!");
|
||||
@@ -195,4 +205,9 @@ public class AdvancedServerList<F>{
|
||||
version = "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
private void addPlaceholder(PlaceholderProvider placeholderProvider){
|
||||
getPlugin().getPluginLogger().info("Registering %s Placeholders...", placeholderProvider.getIdentifier());
|
||||
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
|
||||
}
|
||||
}
|
||||
@@ -51,57 +51,60 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UpdateChecker{
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
// 'https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=["%s"]' URL encoded.
|
||||
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=%%5B%%22%s%%22%%5D";
|
||||
private final HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
private final Type listType = new TypeToken<ArrayList<ModrinthVersion>>(){}.getType();
|
||||
private final Gson gson = new GsonBuilder()
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.setPrettyPrinting()
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
|
||||
|
||||
private final CacheUtil<ModrinthVersion> cache = new CacheUtil<>(Duration.ofMinutes(5));
|
||||
private final CacheUtil<CompletableFuture<ModrinthVersion>> cache = new CacheUtil<>(Duration.ofMinutes(5));
|
||||
|
||||
private final AdvancedServerList<?> core;
|
||||
private final PluginLogger logger;
|
||||
private final String loader;
|
||||
private final HttpClient client;
|
||||
|
||||
public UpdateChecker(AdvancedServerList<?> core){
|
||||
this.core = core;
|
||||
this.logger = core.getPlugin().getPluginLogger();
|
||||
this.loader = core.getPlugin().getLoader();
|
||||
this.client = HttpClient.newBuilder().executor(Executors.newSingleThreadExecutor(new UpdateCheckThread())).build();
|
||||
|
||||
startUpdateChecker();
|
||||
}
|
||||
|
||||
public void performCachedUpdateCheck(CmdSender sender){
|
||||
ModrinthVersion version = cache.get(() -> {
|
||||
try{
|
||||
return performUpdateCheck().join();
|
||||
}catch(Exception ex){
|
||||
return null;
|
||||
CompletableFuture<ModrinthVersion> modrinthVersion = cache.get(this::performUpdateCheck);
|
||||
|
||||
modrinthVersion.whenComplete((version, throwable) -> {
|
||||
if(throwable != null){
|
||||
logger.warn("Encountered an Exception while checking for an update!", throwable);
|
||||
sender.sendErrorMsg("There was an exception while checking for an update. Please check the console for details.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(version == null)
|
||||
return;
|
||||
|
||||
int result = version.compare(core.getVersion());
|
||||
if(result == -1){
|
||||
sender.sendPrefixedMsg("<green>A new Version of AdvancedServerList is available!");
|
||||
sender.sendPrefixedMsg("<green>Your version: <white>%s", core.getVersion());
|
||||
sender.sendPrefixedMsg("<green>Version on Modrinth: <white>%s", version.versionNumber());
|
||||
sender.sendPrefixedMsg(
|
||||
"<click:open_url:'https://modrinth.com/plugin/advancedserverlist/version/%s'>" +
|
||||
"<green>[<white>Download Page</white>]" +
|
||||
"</click>",
|
||||
version.id()
|
||||
);
|
||||
}else
|
||||
if(result == 1){
|
||||
sender.sendPrefixedMsg("You seem to run a newer Version (<white>%</white>) than what is available on Modrinth (<white>%s</white>).", core.getVersion(), version.versionNumber());
|
||||
sender.sendPrefixedMsg("Are you running a development build?");
|
||||
}
|
||||
});
|
||||
|
||||
if(version == null)
|
||||
return;
|
||||
|
||||
int result = version.compare(core.getVersion());
|
||||
if(result == -1){
|
||||
sender.sendPrefixedMsg("<green>A new version of AdvancedServerList is available!");
|
||||
sender.sendPrefixedMsg("<green>Your version: <white>%s", core.getVersion());
|
||||
sender.sendPrefixedMsg("<green>Modrinth: <white>%s", version.versionNumber());
|
||||
sender.sendPrefixedMsg("<click:open_url:'https://modrinth.com/plugin/advancedserverlist/version/%s'><green>[<white>Download Page</white>]</click>", version.id());
|
||||
}else
|
||||
if(result == 1){
|
||||
sender.sendPrefixedMsg("Your version (<white>%s</white>) seems newer than the latest release on Modrinth (<white>%s</white>)", core.getVersion(), version.versionNumber);
|
||||
sender.sendPrefixedMsg("Are you running a dev-build?");
|
||||
}
|
||||
}
|
||||
|
||||
public void disable(){
|
||||
@@ -144,7 +147,11 @@ public class UpdateChecker{
|
||||
}
|
||||
|
||||
private CompletableFuture<ModrinthVersion> performUpdateCheck(){
|
||||
String finalUrl = String.format(url, loader);
|
||||
String finalUrl = String.format(
|
||||
// 'https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=["%s"]' URL encoded.
|
||||
"https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=%%5B%%22%s%%22%%5D",
|
||||
loader
|
||||
);
|
||||
|
||||
logger.debug(UpdateChecker.class, "Checking '%s' for updates...", finalUrl);
|
||||
|
||||
@@ -157,6 +164,7 @@ public class UpdateChecker{
|
||||
try{
|
||||
request = HttpRequest.newBuilder()
|
||||
.uri(new URI(finalUrl))
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
|
||||
.build();
|
||||
}catch(URISyntaxException ex){
|
||||
|
||||
+286
-16
@@ -25,13 +25,26 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.commands;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.PluginCommand;
|
||||
import ch.andre601.advancedserverlist.core.migration.minimotd.MiniMOTDConfigMigrator;
|
||||
import ch.andre601.advancedserverlist.core.migration.serverlistplus.SLPConfigMigrator;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.yaml.NodeStyle;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class CommandHandler{
|
||||
|
||||
@@ -39,13 +52,18 @@ public class CommandHandler{
|
||||
|
||||
public CommandHandler(AdvancedServerList<?> core){
|
||||
subCommands = List.of(
|
||||
new Help(),
|
||||
new Help(core),
|
||||
new Reload(core),
|
||||
new ClearCache(core),
|
||||
new Migrate(core)
|
||||
new Migrate(core),
|
||||
new Profiles(core)
|
||||
);
|
||||
}
|
||||
|
||||
public List<PluginCommand> getSubCommands(){
|
||||
return subCommands;
|
||||
}
|
||||
|
||||
public void handle(CmdSender sender, String[] args){
|
||||
if(args.length == 0){
|
||||
sender.sendErrorMsg("<red>Too few arguments! Use <grey>/asl help</grey> for a list of commands.");
|
||||
@@ -53,11 +71,11 @@ public class CommandHandler{
|
||||
}
|
||||
|
||||
for(PluginCommand subCommand : subCommands){
|
||||
if(subCommand.getArgument().equalsIgnoreCase(args[0])){
|
||||
if(!sender.hasPermission(subCommand.getPermission())){
|
||||
if(subCommand.name().equalsIgnoreCase(args[0])){
|
||||
if(!sender.hasPermission(subCommand.permission())){
|
||||
sender.sendErrorMsg(
|
||||
"<red>You do not have the permission <grey>%s</grey> to execute this command.",
|
||||
subCommand.getPermission()
|
||||
subCommand.permission()
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -72,21 +90,54 @@ public class CommandHandler{
|
||||
|
||||
private static class Help extends PluginCommand{
|
||||
|
||||
public Help(){
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public Help(AdvancedServerList<?> core){
|
||||
super("help");
|
||||
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CmdSender sender, String[] args){
|
||||
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");
|
||||
sender.sendMsg();
|
||||
sender.sendMsg("<aqua>/asl <white>migrate <grey><</grey>plugin<grey>> - Migrates configuration of another plugin");
|
||||
sender.sendPrefixedMsg("- Commands. Hover for details.");
|
||||
for(PluginCommand command : core.getCommandHandler().getSubCommands()){
|
||||
sender.sendPrefixedMsg("");
|
||||
sender.sendPrefixedMsg(
|
||||
"<aqua><hover:show_text:\"%s\">" +
|
||||
"<click:suggest_command:/asl %s>" +
|
||||
"/asl <white>%s</white>" +
|
||||
"</click>" +
|
||||
"</hover></aqua>",
|
||||
getCommandHover(command),
|
||||
command.name(),
|
||||
command.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage(){
|
||||
return "<aqua>/asl <white>help</white></aqua>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(){
|
||||
return "Shows all available commands.";
|
||||
}
|
||||
|
||||
private String getCommandHover(PluginCommand command){
|
||||
return String.format(
|
||||
"""
|
||||
<grey>Usage: %s
|
||||
Permission: <white>%s</white>
|
||||
|
||||
<white>%s</white>
|
||||
""",
|
||||
command.usage(),
|
||||
command.permission(),
|
||||
command.description()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +169,16 @@ public class CommandHandler{
|
||||
|
||||
sender.sendPrefixedMsg("<green>Reload complete!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage(){
|
||||
return "<aqua>/asl <white>reload</white></aqua>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(){
|
||||
return "Reloads the main config and all profiles.";
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClearCache extends PluginCommand{
|
||||
@@ -125,7 +186,7 @@ public class CommandHandler{
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public ClearCache(AdvancedServerList<?> core){
|
||||
super("clearCache");
|
||||
super("clearcache");
|
||||
|
||||
this.core = core;
|
||||
}
|
||||
@@ -142,6 +203,16 @@ public class CommandHandler{
|
||||
|
||||
sender.sendPrefixedMsg("<green>Cache clearing complete!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage(){
|
||||
return "<aqua>/asl <white>clearcache</white></aqua>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(){
|
||||
return "Clears the Favicon and Player Cache.";
|
||||
}
|
||||
}
|
||||
|
||||
private static class Migrate extends PluginCommand{
|
||||
@@ -160,6 +231,7 @@ public class CommandHandler{
|
||||
sender.sendErrorMsg("<red>Insufficient arguments! Please provide a plugin to migrate from.");
|
||||
sender.sendErrorMsg("<red>Available options:");
|
||||
sender.sendErrorMsg(" - ServerListPlus");
|
||||
sender.sendErrorMsg(" - MiniMOTD");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,10 +250,208 @@ public class CommandHandler{
|
||||
}else{
|
||||
sender.sendPrefixedMsg("<green>Migration complete!");
|
||||
}
|
||||
}else
|
||||
if(args[0].equalsIgnoreCase("minimotd")){
|
||||
sender.sendPrefixedMsg("Migrating MiniMOTD configuration file...");
|
||||
|
||||
if(MiniMOTDConfigMigrator.migrate(core, sender)){
|
||||
sender.sendPrefixedMsg("<green>Migration complete!");
|
||||
}else{
|
||||
sender.sendErrorMsg("<red>Unable to migrate MiniMOTD configuration. Check console for details!");
|
||||
}
|
||||
}else{
|
||||
sender.sendErrorMsg("<red>Unknown plugin <grey>%s</grey>. Available Options:", args[0]);
|
||||
sender.sendErrorMsg(" - ServerListPlus");
|
||||
sender.sendErrorMsg(" - MiniMOTD");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage(){
|
||||
return "<aqua>/asl <white>migrate <grey>\\<</grey>Plugin<grey>></grey></white></aqua>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(){
|
||||
return "Migrates the configuration from supported Plugins to AdvancedServerList.";
|
||||
}
|
||||
}
|
||||
|
||||
private static class Profiles extends PluginCommand{
|
||||
|
||||
private final AdvancedServerList<?> core;
|
||||
|
||||
public Profiles(AdvancedServerList<?> core){
|
||||
super("profiles");
|
||||
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(CmdSender sender, String[] args){
|
||||
if(args.length == 0){
|
||||
sender.sendErrorMsg("<red>Invalid command usage.");
|
||||
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
|
||||
return;
|
||||
}
|
||||
|
||||
switch(args[0].toLowerCase(Locale.ROOT)){
|
||||
case "list" -> {
|
||||
sender.sendPrefixedMsg("Available Profiles:");
|
||||
core.getFileHandler().getProfiles().stream()
|
||||
.sorted(Comparator.comparingInt(ServerListProfile::priority).reversed())
|
||||
.forEach(
|
||||
profile -> sender.sendPrefixedMsg("- <white><hover:show_text:\"%s\">%s</hover></white>", getHover(profile), profile.file())
|
||||
);
|
||||
}
|
||||
case "add" -> {
|
||||
if(args.length == 1){
|
||||
sender.sendErrorMsg("<red>Insufficient arguments.");
|
||||
sender.sendErrorMsg("<red>Usage:</red> /asl profiles add <name>");
|
||||
return;
|
||||
}
|
||||
|
||||
String name = getProfileName(args[1]);
|
||||
|
||||
if(core.getFileHandler().getProfiles().stream().anyMatch(profile -> profile.file().equalsIgnoreCase(name))){
|
||||
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().createFile(name)){
|
||||
sender.sendPrefixedMsg("<green>Successfully created</green> %s<green>!", name);
|
||||
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
|
||||
}else{
|
||||
sender.sendErrorMsg("<red>Error while trying to create</red> %s<red>!", name);
|
||||
sender.sendErrorMsg("<red>Check console for further details.");
|
||||
}
|
||||
}
|
||||
case "copy" -> {
|
||||
if(args.length < 3){
|
||||
sender.sendErrorMsg("<red>Insufficient arguments.");
|
||||
sender.sendErrorMsg("<red>Usage:</red> /asl profiles copy <profile> <name>");
|
||||
return;
|
||||
}
|
||||
|
||||
String name = getProfileName(args[1]);
|
||||
String copy = getProfileName(args[2]);
|
||||
|
||||
ServerListProfile targetProfile = core.getFileHandler().getProfiles().stream()
|
||||
.filter(file -> file.file().equalsIgnoreCase(name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
boolean copyExists = core.getFileHandler().getProfiles().stream()
|
||||
.anyMatch(profile -> profile.file().equals(copy));
|
||||
|
||||
if(targetProfile == null){
|
||||
sender.sendErrorMsg("<red>There is no file with name</red> %s<red>!", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if(copyExists){
|
||||
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", copy);
|
||||
return;
|
||||
}
|
||||
|
||||
Path profilePath = core.getPlugin().getFolderPath().resolve("profiles").resolve(copy);
|
||||
try{
|
||||
Files.createFile(profilePath);
|
||||
}catch(IOException ex){
|
||||
sender.sendErrorMsg("<red>There was an error while creating the file</red> %s<red>!", copy);
|
||||
sender.sendErrorMsg("<red>Check console for further details.");
|
||||
|
||||
core.getPlugin().getPluginLogger().warn("Encountered IOException while creating file %s", ex, copy);
|
||||
return;
|
||||
}
|
||||
|
||||
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
|
||||
.path(profilePath)
|
||||
.indent(2)
|
||||
.nodeStyle(NodeStyle.BLOCK)
|
||||
.defaultOptions(options -> options.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
|
||||
.build();
|
||||
|
||||
ConfigurationNode node;
|
||||
try{
|
||||
node = loader.load();
|
||||
}catch(IOException ex){
|
||||
sender.sendErrorMsg("<red>There was an error while loading the file</red> %s<red>!", copy);
|
||||
sender.sendErrorMsg("<red>Check console for further details.");
|
||||
|
||||
core.getPlugin().getPluginLogger().warn("Encountered IOException while loading file %s", ex, copy);
|
||||
return;
|
||||
}
|
||||
|
||||
if(node == null){
|
||||
sender.sendErrorMsg("Cannot copy</red> %s <red>to</red> %s<red>. ConfigurationNode was null.", name, copy);
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
node.node("priority").set(targetProfile.priority());
|
||||
node.node("condition").set(targetProfile.condition());
|
||||
|
||||
node.node("profiles").setList(ProfileEntry.class, targetProfile.profiles());
|
||||
|
||||
node.set(ProfileEntry.class, targetProfile.defaultProfile());
|
||||
}catch(SerializationException ex){
|
||||
sender.sendErrorMsg("<red>There was an Error while copying values from</red> %s <red>to</red> %s<red>.", name, copy);
|
||||
sender.sendErrorMsg("<red>Check console for details.");
|
||||
|
||||
core.getPlugin().getPluginLogger().warn("Encountered SerializationException while set values for %s!", ex, copy);
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
loader.save(node);
|
||||
sender.sendPrefixedMsg("<green>Successfully created copy of</green> %s <green>as</green> %s<green>!", name, copy);
|
||||
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
|
||||
}catch(IOException ex){
|
||||
sender.sendErrorMsg("<red>There was an Error while trying to save</red> %s<red>!", copy);
|
||||
sender.sendErrorMsg("<red>Check console for details.");
|
||||
|
||||
core.getPlugin().getPluginLogger().warn("Encountered IOException while saving ConfigurationNode for %s!", ex, copy);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
sender.sendErrorMsg("<red>Unknown argument</red> %s<red>!", args[0]);
|
||||
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage(){
|
||||
return "<aqua>/asl <white>profiles</white> <grey>\\<" +
|
||||
"<white>add</white> \\<<white>name</white>> | " +
|
||||
"<white>copy</white> \\<<white>profile</white>> \\<<white>name</white>> | " +
|
||||
"<white>list</white>" +
|
||||
"></grey></aqua>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(){
|
||||
return "Creates a new profile, copies one from an existing file, or lists all available profiles.";
|
||||
}
|
||||
|
||||
private String getHover(ServerListProfile profile){
|
||||
return String.format(
|
||||
"""
|
||||
<grey>Priority: <white>%s</white>
|
||||
Condition: <white>%s</white>
|
||||
|
||||
Valid profile: %s
|
||||
""",
|
||||
profile.priority(),
|
||||
profile.condition() == null || profile.condition().isEmpty() ? "<i>None</i>" : profile.condition(),
|
||||
profile.isInvalidProfile() ? "<red>No</red>" : "<green>Yes</green>"
|
||||
);
|
||||
}
|
||||
|
||||
private String getProfileName(String name){
|
||||
String fileName = name.toLowerCase(Locale.ROOT);
|
||||
|
||||
return fileName.endsWith(".yml") ? fileName : fileName + ".yml";
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package ch.andre601.advancedserverlist.core.compat.maintenance;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
|
||||
public class MaintenancePlaceholder extends PlaceholderProvider{
|
||||
|
||||
private final AdvancedServerList<?> plugin;
|
||||
|
||||
public MaintenancePlaceholder(AdvancedServerList<?> plugin){
|
||||
super("maintenance");
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
if(!placeholder.equals("maintenanceEnabled") || !plugin.getPlugin().isPluginEnabled("Maintenance"))
|
||||
return null;
|
||||
|
||||
return String.valueOf(MaintenanceUtil.get().isMaintenanceEnabled());
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -30,12 +30,21 @@ import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
|
||||
public class MaintenanceUtil{
|
||||
|
||||
private static MaintenanceUtil instance;
|
||||
|
||||
private final Maintenance api;
|
||||
|
||||
public MaintenanceUtil(){
|
||||
private MaintenanceUtil(){
|
||||
this.api = MaintenanceProvider.get();
|
||||
}
|
||||
|
||||
public static MaintenanceUtil get(){
|
||||
if(instance != null)
|
||||
return instance;
|
||||
|
||||
return (instance = new MaintenanceUtil());
|
||||
}
|
||||
|
||||
public boolean isMaintenanceEnabled(){
|
||||
return api.isMaintenance();
|
||||
}
|
||||
|
||||
@@ -34,19 +34,26 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
public class PAPIUtil{
|
||||
|
||||
private final PlaceholderAPI papi;
|
||||
private static PAPIUtil instance;
|
||||
|
||||
private final CacheUtil<String> cache = new CacheUtil<>(Duration.ofSeconds(5));
|
||||
private final PlaceholderAPI papi;
|
||||
|
||||
public PAPIUtil(){
|
||||
private PAPIUtil(){
|
||||
this.papi = PlaceholderAPI.createInstance();
|
||||
}
|
||||
|
||||
public static PAPIUtil get(){
|
||||
if(instance != null)
|
||||
return instance;
|
||||
|
||||
return (instance = new PAPIUtil());
|
||||
}
|
||||
|
||||
// Make sure the version of PAPIProxyBridge we get has the required methods we need...
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isCompatible(){
|
||||
@@ -88,8 +95,7 @@ public class PAPIUtil{
|
||||
|
||||
public String parse(String text, UUID carrier, UUID player){
|
||||
try{
|
||||
CompletableFuture<String> future = papi.formatPlaceholders(text, carrier, player);
|
||||
return future.getNow(text);
|
||||
return papi.formatPlaceholders(text, carrier, player).getNow(text);
|
||||
}catch(IllegalArgumentException | CancellationException | CompletionException ex){
|
||||
return text;
|
||||
}
|
||||
|
||||
+52
-38
@@ -29,8 +29,6 @@ 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.compat.papi.PAPIUtil;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
@@ -41,9 +39,6 @@ import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
|
||||
public class PingEventHandler{
|
||||
|
||||
private static PAPIUtil papiUtil = null;
|
||||
private static MaintenanceUtil maintenanceUtil = null;
|
||||
|
||||
public static <F, P extends GenericPlayer> ProfileEntry handleEvent(GenericEventWrapper<F, P> event){
|
||||
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
|
||||
if(event.isInvalidProtocol()){
|
||||
@@ -75,42 +70,75 @@ public class PingEventHandler{
|
||||
|
||||
logger.debug(PingEventHandler.class, "Received valid Server List Profile. Calling PreServerListSetEvent...");
|
||||
|
||||
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
|
||||
if(e == null || e.isCancelled()){
|
||||
GenericServerListEvent slEvent = event.callEvent(ProfileManager.merge(profile));
|
||||
if(slEvent == null || slEvent.isCancelled()){
|
||||
logger.debug(PingEventHandler.class, "PreServerListSetEvent was cancelled. Stopping ping handling...");
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug(PingEventHandler.class, "PreServerListSetEvent completed. Proceeding with ping handling...");
|
||||
|
||||
ProfileEntry entry = e.getEntry();
|
||||
ProfileEntry entry = slEvent.getEntry();
|
||||
if(entry.isInvalid()){
|
||||
logger.debugWarn(PingEventHandler.class, "No valid ProfileEntry retrieved. Cancelling ping handling...");
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
|
||||
|
||||
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
if(ProfileManager.checkOption(entry.onlinePlayersEnabled()) && ignoreMaintenance(event, "onlinePlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> onlinePlayers -> enabled' option is true. Trying to apply '%s'...", entry.onlinePlayersCount());
|
||||
String onlinePlayers = ComponentParser.text(entry.onlinePlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
|
||||
|
||||
event.setMaxPlayers(max);
|
||||
try{
|
||||
online = onlinePlayers == null ? online : Integer.parseInt(onlinePlayers);
|
||||
event.setOnlinePlayers(online);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> onlinePlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
|
||||
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
|
||||
boolean extraPlayersEnabled = ProfileManager.checkOption(entry.extraPlayersEnabled());
|
||||
|
||||
if(extraPlayersEnabled && ignoreMaintenance(event, "extraPlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> enabled' option is true. Trying to apply '%s'...", entry.extraPlayersCount());
|
||||
String extraPlayers = ComponentParser.text(entry.extraPlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
|
||||
try{
|
||||
max = online + (extraPlayers == null ? 0 : Integer.parseInt(extraPlayers));
|
||||
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> amount' is a valid number. Applying it...");
|
||||
event.setMaxPlayers(max);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> extraPlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayersEnabled && ignoreMaintenance(event, "maxPlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> enabled' option is true. Trying to apply '%s'...", entry.maxPlayersCount());
|
||||
String maxPlayers = ComponentParser.text(entry.maxPlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
event.setMaxPlayers(max);
|
||||
try{
|
||||
max = maxPlayers == null ? 0 : Integer.parseInt(maxPlayers);
|
||||
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> amount' is a valid number. Applying it...");
|
||||
event.setMaxPlayers(max);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> maxPlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
GenericServer finalServer = event.createGenericServer(online, max, host);
|
||||
|
||||
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
|
||||
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
|
||||
logger.debug(PingEventHandler.class, "'motd' option present. Applying '%s'...", String.join("\\n", entry.motd()));
|
||||
|
||||
event.setMotd(
|
||||
ComponentParser.list(entry.motd())
|
||||
@@ -123,13 +151,13 @@ public class PingEventHandler{
|
||||
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
|
||||
|
||||
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
|
||||
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayers' enabled. Hiding player count...");
|
||||
|
||||
event.hidePlayers();
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
|
||||
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> text' option set. Applying '%s'...", entry.playerCountText());
|
||||
|
||||
event.setPlayerCount(
|
||||
ComponentParser.text(entry.playerCountText())
|
||||
@@ -140,13 +168,13 @@ public class PingEventHandler{
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
|
||||
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying '%s'...", String.join("\\n", entry.players()));
|
||||
|
||||
event.setPlayers(entry.players(), player, server);
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
|
||||
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
|
||||
logger.debug(PingEventHandler.class, "'favicon' option set. Resolving '%s'...", entry.favicon());
|
||||
|
||||
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
|
||||
|
||||
@@ -169,20 +197,6 @@ public class PingEventHandler{
|
||||
return entry;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
private static <F, P extends GenericPlayer> boolean ignoreMaintenance(GenericEventWrapper<F, P> event, String option){
|
||||
if(!event.isMaintenanceModeActive())
|
||||
return true;
|
||||
|
||||
@@ -46,13 +46,24 @@ public class ConfigMigrator{
|
||||
public static ConfigurationTransformation.Versioned create(){
|
||||
return ConfigurationTransformation.versionedBuilder()
|
||||
.versionKey("configVersion")
|
||||
.addVersion(LATEST, fourToFive())
|
||||
.addVersion(LATEST, fiveToSix())
|
||||
.addVersion(5, fourToFive())
|
||||
.addVersion(4, threeToFour())
|
||||
.addVersion(3, twoToThree())
|
||||
.addVersion(2, oneToTwo())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfigurationTransformation fiveToSix(){
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
|
||||
value.node("onlinePlayers").set(true);
|
||||
|
||||
return null;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfigurationTransformation fourToFive(){
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(NodePath.path(), (path, value) -> {
|
||||
|
||||
@@ -99,23 +99,36 @@ public class FileHandler{
|
||||
|
||||
public boolean loadProfiles(){
|
||||
logger.info("Loading profiles...");
|
||||
if(!profilesFolder.toFile().exists() && profilesFolder.toFile().mkdirs()){
|
||||
|
||||
if(createFile("default.yml")){
|
||||
return reloadProfiles();
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean createFile(String name){
|
||||
if(Files.notExists(profilesFolder) && profilesFolder.toFile().mkdirs()){
|
||||
logger.info("Successfully created profiles folder.");
|
||||
|
||||
try(InputStream stream = plugin.getClass().getResourceAsStream("/profiles/default.yml")){
|
||||
if(stream == null){
|
||||
logger.warn("Cannot retrieve default.yml from Plugin.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Files.copy(stream, profilesFolder.resolve("default.yml"));
|
||||
}catch(IOException ex){
|
||||
logger.warn("Cannot create default.yml for plugin.", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return reloadProfiles();
|
||||
File file = new File(profilesFolder.toFile(), name);
|
||||
if(file.exists()){
|
||||
return true;
|
||||
}
|
||||
|
||||
try(InputStream stream = plugin.getClass().getResourceAsStream("/profiles/default.yml")){
|
||||
if(stream == null){
|
||||
logger.warn("Cannot retrieve content of internal default.yml file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Files.copy(stream, profilesFolder.resolve(name));
|
||||
return true;
|
||||
}catch(IOException ex){
|
||||
logger.warn("Encountered IOException while trying to create file %s", ex, name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean migrateConfig(){
|
||||
|
||||
+7
-3
@@ -35,13 +35,17 @@ public abstract class PluginCommand{
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
public String getArgument(){
|
||||
public String name(){
|
||||
return argument;
|
||||
}
|
||||
|
||||
public String getPermission(){
|
||||
return "advancedserverlist.command." + getArgument().toLowerCase(Locale.ROOT);
|
||||
public String permission(){
|
||||
return "advancedserverlist.command." + name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public abstract void handle(CmdSender sender, String[] args);
|
||||
|
||||
public abstract String usage();
|
||||
|
||||
public abstract String description();
|
||||
}
|
||||
+4
-4
@@ -27,7 +27,7 @@ package ch.andre601.advancedserverlist.core.interfaces.core;
|
||||
|
||||
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.core.profiles.handlers.FaviconHandler;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.file.Path;
|
||||
@@ -44,6 +44,8 @@ public interface PluginCore<F>{
|
||||
|
||||
void clearFaviconCache();
|
||||
|
||||
void downloadLibrary(String groupId, String artifactId, String version);
|
||||
|
||||
AdvancedServerList<F> getCore();
|
||||
|
||||
Path getFolderPath();
|
||||
@@ -52,9 +54,7 @@ public interface PluginCore<F>{
|
||||
|
||||
FaviconHandler<F> getFaviconHandler();
|
||||
|
||||
String getPlatformName();
|
||||
|
||||
String getPlatformVersion();
|
||||
String getPlatformInfo();
|
||||
|
||||
String getLoader();
|
||||
|
||||
|
||||
+2
@@ -42,6 +42,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
|
||||
|
||||
void setMaxPlayers(int maxPlayers);
|
||||
|
||||
void setOnlinePlayers(int onlinePlayers);
|
||||
|
||||
void setMotd(Component component);
|
||||
|
||||
void hidePlayers();
|
||||
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2024 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.migration.minimotd;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.NullBool;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.migration.minimotd.serializing.MiniMOTDConfig;
|
||||
import ch.andre601.advancedserverlist.core.migration.minimotd.serializing.MiniMOTDSerializer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.yaml.NodeStyle;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class MiniMOTDConfigMigrator{
|
||||
|
||||
public static boolean migrate(AdvancedServerList<?> core, CmdSender sender){
|
||||
core.getPlugin().downloadLibrary("org.spongepowered", "configurate-hocon", "4.1.2");
|
||||
|
||||
PluginLogger logger = core.getPlugin().getPluginLogger();
|
||||
String folder = core.getPlugin().getLoader().equals("velocity") ? "minimotd-velocity" : "MiniMOTD";
|
||||
|
||||
Path mainConf = core.getPlugin().getFolderPath().getParent().resolve(folder).resolve("main.conf");
|
||||
if(!Files.exists(mainConf)){
|
||||
logger.warn("[Migrator - MiniMOTD] Cannot find a main.conf file in /plugins/%s/ folder.", folder);
|
||||
sender.sendErrorMsg(" -> <red>No main.conf file found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
|
||||
.path(mainConf)
|
||||
.defaultOptions(options -> options.serializers(builder ->
|
||||
builder.register(MiniMOTDConfig.class, MiniMOTDSerializer.MINI_MOTD_SERIALIZER)
|
||||
.register(MiniMOTDConfig.Motd.class, MiniMOTDSerializer.MOTD_SERIALIZER)
|
||||
.register(MiniMOTDConfig.PlayerCount.class, MiniMOTDSerializer.PLAYER_COUNT_SERIALIZER)
|
||||
))
|
||||
.build();
|
||||
|
||||
MiniMOTDConfig config;
|
||||
try{
|
||||
ConfigurationNode node = loader.load();
|
||||
|
||||
config = node.get(MiniMOTDConfig.class);
|
||||
}catch(IOException ex){
|
||||
logger.warn("[Migrator - MiniMOTD] Encountered IOException while loading main.conf file.", ex);
|
||||
sender.sendErrorMsg(" -> <red>IOException while loading</red> main.conf <red>file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(config == null){
|
||||
logger.warn("[Migrator - MiniMOTD] Retrieved main.conf file returned null.");
|
||||
sender.sendErrorMsg(" -> <red>Received invalid</red> main.conf <red>file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ProfileEntry.Builder profileBuilder = ProfileEntry.empty().builder();
|
||||
List<ProfileEntry.Builder> profilesBuilders = new ArrayList<>();
|
||||
|
||||
if(config.motdEnabled() && config.motds().size() > 1){
|
||||
for(int i = 0; i < config.motds().size(); i++){
|
||||
profilesBuilders.add(ProfileEntry.empty().builder());
|
||||
}
|
||||
}
|
||||
|
||||
if(config.motdEnabled()){
|
||||
if(config.motds().size() == 1){
|
||||
applyMotd(profileBuilder, config.motds().get(0));
|
||||
}else
|
||||
if(config.motds().size() > 1){
|
||||
for(int i = 0; i < config.motds().size(); i++){
|
||||
applyMotd(profilesBuilders.get(i), config.motds().get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.iconEnabled()){
|
||||
if(config.motds().size() == 1){
|
||||
MiniMOTDConfig.Motd motd = config.motds().get(0);
|
||||
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
|
||||
profileBuilder.favicon(motd.icon());
|
||||
}
|
||||
}else
|
||||
if(config.motds().size() > 1){
|
||||
for(int i = 0; i < config.motds().size(); i++){
|
||||
MiniMOTDConfig.Motd motd = config.motds().get(i);
|
||||
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
|
||||
profilesBuilders.get(i).favicon(motd.icon());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.playerCount() != null){
|
||||
MiniMOTDConfig.PlayerCount playerCount = config.playerCount();
|
||||
|
||||
NullBool hidePlayers = NullBool.resolve(playerCount.hidePlayers());
|
||||
NullBool xMoreEnabled = NullBool.resolve(playerCount.xMoreEnabled());
|
||||
int xMore = playerCount.xMore();
|
||||
NullBool maxPlayersEnabled = NullBool.resolve(playerCount.maxPlayersEnabled());
|
||||
int maxPlayers = playerCount.maxPlayers();
|
||||
|
||||
profileBuilder.hidePlayersEnabled(hidePlayers)
|
||||
.extraPlayersEnabled(xMoreEnabled)
|
||||
.extraPlayersCount(String.valueOf(xMore))
|
||||
.maxPlayersEnabled(maxPlayersEnabled)
|
||||
.maxPlayersCount(String.valueOf(maxPlayers));
|
||||
}
|
||||
|
||||
ProfileEntry entry = profileBuilder.build();
|
||||
List<ProfileEntry> profiles = profilesBuilders.stream()
|
||||
.map(ProfileEntry.Builder::build)
|
||||
.toList();
|
||||
|
||||
boolean profilesInvalid = profiles.isEmpty() || profiles.stream().allMatch(ProfileEntry::isInvalid);
|
||||
if(entry.isInvalid() && profilesInvalid){
|
||||
logger.warn("[Migrator - MiniMOTD] Main ProfileEntry was invalid and profiles were empty.");
|
||||
sender.sendErrorMsg(" -> <red>Received invalid configuration.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Path profile = core.getPlugin().getFolderPath().resolve("profiles").resolve("minimotd_migrated.yml");
|
||||
if(Files.exists(profile)){
|
||||
logger.warn("[Migrator - MiniMOTD] Cannot create new file minimotd_migrated.yml. One with the same name is already present.");
|
||||
sender.sendErrorMsg(" -> <red>File</red> minimotd_migrated.yml <red>already present.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try{
|
||||
Files.createFile(profile);
|
||||
}catch(IOException ex){
|
||||
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to create file minimotd_migrated.yml.", ex);
|
||||
sender.sendErrorMsg(" -> <red>File creation error.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
YamlConfigurationLoader yamlLoader = YamlConfigurationLoader.builder()
|
||||
.path(profile)
|
||||
.indent(2)
|
||||
.nodeStyle(NodeStyle.BLOCK)
|
||||
.defaultOptions(option -> option.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
|
||||
.build();
|
||||
|
||||
ConfigurationNode migrated;
|
||||
try{
|
||||
migrated = yamlLoader.load();
|
||||
}catch(IOException ex){
|
||||
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to load file minimotd_migrated.yml.", ex);
|
||||
sender.sendErrorMsg(" -> <red>File loading error.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(migrated == null){
|
||||
logger.warn("[Migrator - MiniMOTD] Cannot migrate Configuration. ConfigurationNode was null.");
|
||||
sender.sendErrorMsg(" -> <red>File loading error.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try{
|
||||
migrated.node("priority").set(0);
|
||||
|
||||
if(!profiles.isEmpty()){
|
||||
migrated.node("profiles").setList(ProfileEntry.class, profiles);
|
||||
}
|
||||
|
||||
migrated.set(entry);
|
||||
}catch(SerializationException ex){
|
||||
logger.warn("[Migrator - MiniMOTD] Encountered a SerializationException while setting values.", ex);
|
||||
sender.sendErrorMsg(" -> <red>Error while updating file</red> minimotd_migrated.yml<red>.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try{
|
||||
yamlLoader.save(migrated);
|
||||
sender.sendPrefixedMsg(" -> <green>Completed!");
|
||||
|
||||
return true;
|
||||
}catch(IOException ex){
|
||||
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to save new file minimotd_migrated.yml.", ex);
|
||||
sender.sendErrorMsg(" -> <red>File saving error.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyMotd(ProfileEntry.Builder builder, MiniMOTDConfig.Motd motd){
|
||||
if(motd.line1().isEmpty() && !motd.line2().isEmpty()){
|
||||
builder.motd(List.of("<grey>", motd.line2()));
|
||||
}else
|
||||
if(!motd.line1().isEmpty() && motd.line2().isEmpty()){
|
||||
builder.motd(Collections.singletonList(motd.line1()));
|
||||
}else
|
||||
if(!motd.line1().isEmpty()){ // Line2 is by logic not empty here. So this check is not required.
|
||||
builder.motd(List.of(motd.line1(), motd.line2()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-23
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
* Copyright (c) 2022-2024 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
|
||||
@@ -23,30 +23,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.players;
|
||||
package ch.andre601.advancedserverlist.core.migration.minimotd.serializing;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class GenericPlayerImpl implements GenericPlayer{
|
||||
public record MiniMOTDConfig(boolean iconEnabled, boolean motdEnabled, List<Motd> motds, PlayerCount playerCount){
|
||||
|
||||
protected String name = null;
|
||||
protected int protocol = 0;
|
||||
protected UUID uuid = null;
|
||||
public record Motd(String icon, String line1, String line2){}
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
public record PlayerCount(boolean hidePlayers, boolean xMoreEnabled, int xMore, boolean maxPlayersEnabled, int maxPlayers){}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2024 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.migration.minimotd.serializing;
|
||||
|
||||
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 java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class MiniMOTDSerializer implements TypeSerializer<MiniMOTDConfig>{
|
||||
|
||||
public static final MiniMOTDSerializer MINI_MOTD_SERIALIZER = new MiniMOTDSerializer();
|
||||
public static final MotdSerializer MOTD_SERIALIZER = new MotdSerializer();
|
||||
public static final PlayerCountSerializer PLAYER_COUNT_SERIALIZER = new PlayerCountSerializer();
|
||||
|
||||
@Override
|
||||
public MiniMOTDConfig deserialize(Type type, ConfigurationNode node) throws SerializationException{
|
||||
boolean iconsEnabled = node.node("icon-enabled").getBoolean();
|
||||
boolean motdEnabled = node.node("motd-enabled").getBoolean();
|
||||
|
||||
List<MiniMOTDConfig.Motd> motds = node.node("motds").getList(MiniMOTDConfig.Motd.class);
|
||||
MiniMOTDConfig.PlayerCount playerCount = node.node("player-count-settings").get(MiniMOTDConfig.PlayerCount.class);
|
||||
|
||||
return new MiniMOTDConfig(iconsEnabled, motdEnabled, motds, playerCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Type type, @Nullable MiniMOTDConfig obj, ConfigurationNode node) throws SerializationException{
|
||||
if(obj == null){
|
||||
node.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
node.node("icon-enabled").set(obj.iconEnabled());
|
||||
node.node("motd-enable").set(obj.motdEnabled());
|
||||
node.node("motds").setList(MiniMOTDConfig.Motd.class, obj.motds());
|
||||
node.node("player-count-settings").set(MiniMOTDConfig.PlayerCount.class, obj.playerCount());
|
||||
}
|
||||
|
||||
public static class MotdSerializer implements TypeSerializer<MiniMOTDConfig.Motd>{
|
||||
|
||||
@Override
|
||||
public MiniMOTDConfig.Motd deserialize(Type type, ConfigurationNode node) throws SerializationException{
|
||||
String icon = node.node("icon").getString("");
|
||||
String line1 = node.node("line1").getString("");
|
||||
String line2 = node.node("line2").getString("");
|
||||
|
||||
return new MiniMOTDConfig.Motd(icon, line1, line2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Type type, MiniMOTDConfig.@Nullable Motd obj, ConfigurationNode node) throws SerializationException{
|
||||
if(obj == null){
|
||||
node.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
node.node("icon").set(obj.icon());
|
||||
node.node("line1").set(obj.line1());
|
||||
node.node("line2").set(obj.line2());
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlayerCountSerializer implements TypeSerializer<MiniMOTDConfig.PlayerCount>{
|
||||
|
||||
@Override
|
||||
public MiniMOTDConfig.PlayerCount deserialize(Type type, ConfigurationNode node) throws SerializationException{
|
||||
boolean hidePlayerCount = node.node("hide-player-count").getBoolean();
|
||||
boolean xMoreEnabled = node.node("just-x-more-settings", "just-x-more-enabled").getBoolean();
|
||||
int xMore = node.node("just-x-more-settings", "x-value").getInt();
|
||||
boolean maxPlayersEnabled = node.node("max-players-enabled").getBoolean();
|
||||
int maxPlayers = node.node("max-players").getInt();
|
||||
|
||||
|
||||
return new MiniMOTDConfig.PlayerCount(hidePlayerCount, xMoreEnabled, xMore, maxPlayersEnabled, maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Type type, MiniMOTDConfig.@Nullable PlayerCount obj, ConfigurationNode node) throws SerializationException{
|
||||
if(obj == null){
|
||||
node.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
node.node("allow-exceeding-maximum").set(false);
|
||||
node.node("disable-player-list-hover").set(false);
|
||||
|
||||
node.node("fake-players", "fake-players").set("25%");
|
||||
node.node("fake-players", "fake-players-enabled").set(false);
|
||||
|
||||
node.node("hide-player-count").set(obj.hidePlayers());
|
||||
|
||||
node.node("just-x-more-settings", "just-x-more-enabled").set(obj.xMoreEnabled());
|
||||
node.node("just-x-more-settings", "x-value").set(obj.xMore());
|
||||
|
||||
node.node("max-players").set(obj.maxPlayers());
|
||||
node.node("max-players-enabled").set(obj.maxPlayersEnabled());
|
||||
|
||||
node.node("servers").setList(String.class, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -129,7 +129,7 @@ public class SLPConfigMigrator{
|
||||
apply(motds, builder, profiles, ProfileEntry.Builder::motd);
|
||||
apply(favicons, builder, profiles, ProfileEntry.Builder::favicon);
|
||||
apply(hovers, builder, profiles, ProfileEntry.Builder::players);
|
||||
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(count));
|
||||
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(String.valueOf(count)));
|
||||
apply(playerCount, builder, profiles, ProfileEntry.Builder::playerCountText);
|
||||
|
||||
builder.hidePlayersEnabled(hidePlayers);
|
||||
@@ -139,7 +139,8 @@ public class SLPConfigMigrator{
|
||||
.map(ProfileEntry.Builder::build)
|
||||
.toList();
|
||||
|
||||
if(entry.isInvalid() && profileEntries.isEmpty()){
|
||||
boolean profilesInvalid = profileEntries.isEmpty() || profileEntries.stream().anyMatch(ProfileEntry::isInvalid);
|
||||
if(entry.isInvalid() && profilesInvalid){
|
||||
logger.warn("[Migrator - ServerListPlus] Unable to parse ServerListPlus configuration of type %s. Generated ProfileEntry was invalid.", type.getName());
|
||||
sender.sendErrorMsg(" -> <red>Received invalid Configuration.");
|
||||
|
||||
@@ -208,7 +209,7 @@ public class SLPConfigMigrator{
|
||||
|
||||
node.set(entry);
|
||||
}catch(SerializationException ex){
|
||||
logger.warn("Encountered a SerializationException while setting values.", ex);
|
||||
logger.warn("[Migrator - ServerListPlus] Encountered a SerializationException while setting values.", ex);
|
||||
sender.sendErrorMsg(" -> <red>Error while updating file</red> %s<red>.", type.getFile());
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -65,6 +65,10 @@ public class ComponentParser{
|
||||
return mm.deserialize(text);
|
||||
}
|
||||
|
||||
public static String toMMString(Component component){
|
||||
return mm.serialize(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return legacy.serialize(toComponent());
|
||||
|
||||
+5
-12
@@ -28,8 +28,8 @@ 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.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
|
||||
import ch.andre601.expressionparser.ParseWarnCollector;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
@@ -41,13 +41,14 @@ import java.util.Random;
|
||||
public record ServerListProfile(int priority, String condition, ProfileEntry defaultProfile, List<ProfileEntry> profiles, String file){
|
||||
private static final Random random = new Random();
|
||||
|
||||
public boolean evalConditions(ProfileConditionParser parser, PluginLogger logger, GenericPlayer player, GenericServer server){
|
||||
public boolean evalConditions(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
|
||||
if(condition == null || condition.isEmpty())
|
||||
return true;
|
||||
|
||||
ParseWarnCollector collector = new ParseWarnCollector(condition);
|
||||
PluginLogger logger = core.getPlugin().getPluginLogger();
|
||||
|
||||
boolean result = parser.evaluate(condition, player, server, collector);
|
||||
boolean result = core.getParser().evaluate(condition, player, server, collector);
|
||||
|
||||
if(collector.hasWarnings()){
|
||||
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
|
||||
@@ -55,9 +56,8 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
|
||||
for(ParseWarnCollector.Context context : collector.getWarnings()){
|
||||
logger.warn(" - At position %s:", context.position() == -1 ? "Unknown" : context.position());
|
||||
logger.warn(" %s", condition);
|
||||
logger.warn(" ".repeat(context.position() + 5) + "^");
|
||||
logger.warn(" ".repeat(context.position() + 4) + "^");
|
||||
logger.warn(" -> %s", context.message());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,13 +120,6 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public Builder(String filename, int priority, PluginLogger logger){
|
||||
this.fileName = filename;
|
||||
this.node = null;
|
||||
this.priority = priority;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public static Builder resolve(String fileName, ConfigurationNode node, PluginLogger logger){
|
||||
return new Builder(fileName, node, logger)
|
||||
.resolveCondition()
|
||||
|
||||
+15
-6
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
* Copyright (c) 2022-2024 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
|
||||
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.favicon;
|
||||
package ch.andre601.advancedserverlist.core.profiles.handlers;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
@@ -70,11 +70,20 @@ public class FaviconHandler<F>{
|
||||
}
|
||||
|
||||
public F getFavicon(String input){
|
||||
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT).split("\\.")[0])){
|
||||
return localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]);
|
||||
if(localFavicons.size() > 0){
|
||||
logger.debug(FaviconHandler.class, "Current Local Favicons:");
|
||||
for(String key : localFavicons.keySet()){
|
||||
logger.debug(FaviconHandler.class, " - %s", key);
|
||||
}
|
||||
}
|
||||
|
||||
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT))){
|
||||
logger.debug(FaviconHandler.class, "Input matches local favicon Image. Returning it...");
|
||||
return localFavicons.get(input.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
try{
|
||||
logger.debug(FaviconHandler.class, "Getting Favicon image from cache...");
|
||||
return faviconCache.get(input, () -> getFuture(input)).getNow(null);
|
||||
}catch(ExecutionException ex){
|
||||
logger.warn("Received ExecutionException while retrieving Favicon for '%s'.", ex, input);
|
||||
@@ -94,7 +103,7 @@ public class FaviconHandler<F>{
|
||||
}else
|
||||
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
|
||||
logger.debug(FaviconHandler.class, "Resolving image file '%s'...", input);
|
||||
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]));
|
||||
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT)));
|
||||
}else{
|
||||
logger.debug(FaviconHandler.class, "Resolving Name/UUID as https://mc-heads.net/avatar/%s/64...", input);
|
||||
return CompletableFuture.supplyAsync(() -> fromURL(core, "https://mc-heads.net/avatar/" + input + "/64"), this.faviconThreadPool);
|
||||
@@ -134,7 +143,7 @@ public class FaviconHandler<F>{
|
||||
return;
|
||||
}
|
||||
|
||||
localFavicons.put(path.getFileName().toString().split("\\.")[0], favicon);
|
||||
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), favicon);
|
||||
logger.info("Loaded file '%s' as Favicon.", path.getFileName().toString());
|
||||
}catch(IOException ex){
|
||||
logger.warn("Cannot create Favicon from file '%s'. Encountered IOException.", ex);
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022-2023 Andre_601
|
||||
* Copyright (c) 2022-2024 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
|
||||
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.players;
|
||||
package ch.andre601.advancedserverlist.core.profiles.handlers;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
@@ -66,7 +66,7 @@ public class PlayerHandler{
|
||||
}
|
||||
|
||||
public void load(){
|
||||
if(!cache.toFile().exists()){
|
||||
if(!Files.exists(cache)){
|
||||
logger.info("No playercache.json file present. Skipping...");
|
||||
return;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public class PlayerHandler{
|
||||
logger.warn("Encountered IOException while reading the playercache.json file!", ex);
|
||||
return;
|
||||
}catch(JsonIOException | JsonSyntaxException ex){
|
||||
logger.warn("Encountered Json exception while parsing playercache.json file!", ex);
|
||||
logger.warn("Encountered JsonSyntaxException while parsing playercache.json file!", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
+28
-78
@@ -36,6 +36,7 @@ import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ProfileManager{
|
||||
|
||||
@@ -44,22 +45,23 @@ public class ProfileManager{
|
||||
* If the random profile's value is not null will it be used instead of the default one.
|
||||
*/
|
||||
public static ProfileEntry merge(ServerListProfile profile){
|
||||
ProfileEntry entry = profile.getRandomProfile();
|
||||
ProfileEntry defEntry = profile.defaultProfile();
|
||||
ProfileEntry entry = profile.getRandomProfile();
|
||||
|
||||
List<String> motd = resolveMOTD(entry, defEntry);
|
||||
List<String> players = resolvePlayers(entry, defEntry);
|
||||
String playerCountText = resolvePlayerCountText(entry, defEntry);
|
||||
String favicon = resolveFavicon(entry, defEntry);
|
||||
boolean isHidePlayersEnabled = resolveHidePlayersEnabled(entry, defEntry);
|
||||
boolean isExtraPlayersEnabled = resolveExtraPlayersEnabled(entry, defEntry);
|
||||
boolean isMaxPlayersEnabled = resolveMaxPlayersEnabled(entry, defEntry);
|
||||
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
|
||||
Integer maxPlayersCount = resolveMaxPlayersCount(entry, defEntry);
|
||||
List<String> motd = resolve(defEntry, entry, ProfileEntry::motd);
|
||||
List<String> players = resolve(defEntry, entry, ProfileEntry::players);
|
||||
String playerCountText = resolve(defEntry, entry, ProfileEntry::playerCountText);
|
||||
String favicon = resolve(defEntry, entry, ProfileEntry::favicon);
|
||||
NullBool hidePlayersEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersEnabled);
|
||||
NullBool extraPlayersEnabled = resolve(defEntry, entry, ProfileEntry::extraPlayersEnabled);
|
||||
NullBool maxPlayersEnabled = resolve(defEntry, entry, ProfileEntry::maxPlayersEnabled);
|
||||
NullBool onlinePlayersEnabled = resolve(defEntry, entry, ProfileEntry::onlinePlayersEnabled);
|
||||
String extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
|
||||
String maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
|
||||
String onlinePlayersCount = resolve(defEntry, entry, ProfileEntry::onlinePlayersCount);
|
||||
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon,
|
||||
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), NullBool.resolve(isMaxPlayersEnabled),
|
||||
extraPlayersCount, maxPlayersCount);
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon, hidePlayersEnabled, extraPlayersEnabled,
|
||||
maxPlayersEnabled, onlinePlayersEnabled, extraPlayersCount, maxPlayersCount, onlinePlayersCount);
|
||||
}
|
||||
|
||||
public static ServerListProfile resolveProfile(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
|
||||
@@ -67,7 +69,7 @@ public class ProfileManager{
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
|
||||
if(profile.evalConditions(core.getParser(), core.getPlugin().getPluginLogger(), player, server))
|
||||
if(profile.evalConditions(core, player, server))
|
||||
return profile;
|
||||
}
|
||||
|
||||
@@ -82,8 +84,10 @@ public class ProfileManager{
|
||||
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
|
||||
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
|
||||
NullBool maxPlayersEnabled = resolveNullBool(node, "playerCount", "maxPlayers", "enabled");
|
||||
Integer extraPlayers = resolveNullableInt(node, "playerCount", "extraPlayers", "amount");
|
||||
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
|
||||
NullBool onlinePlayersEnabled = resolveNullBool(node, "playerCount", "onlinePlayers", "enabled");
|
||||
String extraPlayers = resolveNullableString(node, "playerCount", "extraPlayers", "amount");
|
||||
String maxPlayers = resolveNullableString(node, "playerCount", "maxPlayers", "amount");
|
||||
String onlinePlayers = resolveNullableString(node, "playerCount", "onlinePlayers", "amount");
|
||||
|
||||
return new ProfileEntry.Builder()
|
||||
.motd(motd)
|
||||
@@ -93,8 +97,10 @@ public class ProfileManager{
|
||||
.hidePlayersEnabled(hidePlayers)
|
||||
.extraPlayersEnabled(extraPlayersEnabled)
|
||||
.maxPlayersEnabled(maxPlayersEnabled)
|
||||
.onlinePlayersEnabled(onlinePlayersEnabled)
|
||||
.extraPlayersCount(extraPlayers)
|
||||
.maxPlayersCount(maxPlayers)
|
||||
.onlinePlayersCount(onlinePlayers)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -115,67 +121,11 @@ public class ProfileManager{
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.motd()))
|
||||
return defaultProfile.motd();
|
||||
private static <T> T resolve(ProfileEntry defProfile, ProfileEntry profile, Function<ProfileEntry, T> function){
|
||||
if(profile == null || !checkOption(function.apply(profile)))
|
||||
return function.apply(defProfile);
|
||||
|
||||
return profile.motd();
|
||||
}
|
||||
|
||||
private static List<String> resolvePlayers(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.players()))
|
||||
return defaultProfile.players();
|
||||
|
||||
return profile.players();
|
||||
}
|
||||
|
||||
private static String resolvePlayerCountText(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.playerCountText()))
|
||||
return defaultProfile.playerCountText();
|
||||
|
||||
return profile.playerCountText();
|
||||
}
|
||||
|
||||
private static String resolveFavicon(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.favicon()))
|
||||
return defaultProfile.favicon();
|
||||
|
||||
return profile.favicon();
|
||||
}
|
||||
|
||||
private static boolean resolveHidePlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.hidePlayersEnabled()))
|
||||
return defaultProfile.hidePlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.hidePlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static boolean resolveExtraPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.extraPlayersEnabled()))
|
||||
return defaultProfile.extraPlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.extraPlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static boolean resolveMaxPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || !checkOption(profile.maxPlayersEnabled()))
|
||||
return defaultProfile.maxPlayersEnabled().getOrDefault(false);
|
||||
|
||||
return profile.maxPlayersEnabled().getOrDefault(false);
|
||||
}
|
||||
|
||||
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.extraPlayersCount() == null)
|
||||
return defaultProfile.extraPlayersCount() == null ? 0 : defaultProfile.extraPlayersCount();
|
||||
|
||||
return profile.extraPlayersCount();
|
||||
}
|
||||
|
||||
private static Integer resolveMaxPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.maxPlayersCount() == null)
|
||||
return defaultProfile.maxPlayersCount() == null ? 0 : defaultProfile.maxPlayersCount();
|
||||
|
||||
return profile.maxPlayersCount();
|
||||
return function.apply(profile);
|
||||
}
|
||||
|
||||
private static List<String> resolveList(ConfigurationNode node, Object... path){
|
||||
@@ -193,10 +143,10 @@ public class ProfileManager{
|
||||
return NullBool.resolve(node.node(path).getBoolean());
|
||||
}
|
||||
|
||||
private static Integer resolveNullableInt(ConfigurationNode node, Object... path){
|
||||
private static String resolveNullableString(ConfigurationNode node, Object... path){
|
||||
if(node.node(path).virtual())
|
||||
return null;
|
||||
|
||||
return node.node(path).getInt();
|
||||
return node.node(path).getString();
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -54,8 +54,10 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
node.node("favicon").set(profile.favicon());
|
||||
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? 0 : profile.extraPlayersCount());
|
||||
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? "0" : profile.extraPlayersCount());
|
||||
node.node("playerCount", "maxPlayers", "enabled").set(profile.maxPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? 0 : profile.maxPlayersCount());
|
||||
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? "0" : profile.maxPlayersCount());
|
||||
node.node("playerCount", "onlinePlayers", "enabled").set(profile.onlinePlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "onlinePlayers", "amount").set(profile.onlinePlayersCount() == null ? "0" : profile.onlinePlayersCount());
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -64,8 +64,6 @@ public class StringReplacer{
|
||||
|
||||
private static String parsePlaceholder0(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
|
||||
AdvancedServerListAPI api = AdvancedServerList.getApi();
|
||||
|
||||
int placeholderStart = position.getIndex() - 2;
|
||||
int index = position.getIndex();
|
||||
|
||||
StringBuilder identifier = new StringBuilder();
|
||||
@@ -113,7 +111,7 @@ public class StringReplacer{
|
||||
raw.append(' ').append(valuesStr);
|
||||
|
||||
if(collector != null)
|
||||
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
|
||||
collector.appendWarningFormatted(index, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
|
||||
|
||||
return raw.toString();
|
||||
}
|
||||
@@ -128,7 +126,7 @@ public class StringReplacer{
|
||||
raw.append('}');
|
||||
|
||||
if(collector != null)
|
||||
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
|
||||
collector.appendWarningFormatted(index, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
|
||||
|
||||
return raw.toString();
|
||||
}
|
||||
@@ -143,7 +141,7 @@ public class StringReplacer{
|
||||
raw.append('}');
|
||||
|
||||
if(collector != null)
|
||||
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
|
||||
collector.appendWarningFormatted(index, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
|
||||
|
||||
return raw.toString();
|
||||
}
|
||||
|
||||
@@ -107,6 +107,12 @@ disableDuringMaintenance:
|
||||
# Default: true
|
||||
#
|
||||
maxPlayers: true
|
||||
#
|
||||
# Whether the online players feature should be disabled while Maintenance mode is active.
|
||||
#
|
||||
# Default: true
|
||||
#
|
||||
onlinePlayers: true
|
||||
|
||||
#
|
||||
# DO NOT EDIT!
|
||||
@@ -114,4 +120,4 @@ disableDuringMaintenance:
|
||||
# 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: ${plugin.config.version}
|
||||
configVersion: ${plugin.config.version}
|
||||
@@ -134,6 +134,7 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be added to the online player count to then use as the new max player count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
|
||||
# 9 when 8 are online and so on.
|
||||
@@ -162,9 +163,34 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new max players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to 0.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
#
|
||||
# The onlinePlayers feature allows to set a number to use as the online player count to display.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers
|
||||
#
|
||||
onlinePlayers:
|
||||
#
|
||||
# Set whether the onlinePlayers feature should be enabled or not.
|
||||
# When set to true, the max player count will be set to the 'amount' value.
|
||||
#
|
||||
# If not present, defaults to false.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-enabled
|
||||
#
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new online players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to current online player count.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
@@ -7,6 +7,23 @@ icon: octicons/log-24
|
||||
This page lists the recent changes made towards the AdvancedServerListAPI.
|
||||
They are ordered newest to oldest.
|
||||
|
||||
## v4.0.0 { #v4.0.0 }
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v4.0.0-breaking }
|
||||
|
||||
- Changed `extraPlayersCount()` and `maxPlayersCount()` from using an Integer to using a String instead.
|
||||
- This also affects their corresponding `ProfileEntry.Builder` methods.
|
||||
- Removed all previously deprecated methods.
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v4.0.0-added }
|
||||
|
||||
- New setter methods added to [`ProfileEntry.Builder`][profilentry.builder] class:
|
||||
- [`onlinePlayersCount(String)`][onlinePlayersCount]
|
||||
- [`onlinePlayersEnabled(NullBool)`][onlinePlayersEnabled]
|
||||
|
||||
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount(integer)
|
||||
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled(nullbool)
|
||||
|
||||
## v3.3.0 { #v3.3.0 }
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.3.0-added }
|
||||
|
||||
+28
-186
@@ -119,6 +119,34 @@ methods:
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
- name: 'onlinePlayersCount'
|
||||
description: |
|
||||
Sets the value to resolve into a number by AdvancedServerList.<br>
|
||||
Strings not resolving into valid numbers will be treated as this option not being set.
|
||||
parameters:
|
||||
- name: 'onlinePlayersCount'
|
||||
description: 'The number of online players to set.'
|
||||
type: 'String'
|
||||
attribute:
|
||||
- 'nullable'
|
||||
returns: 'This Builder after the max player count has been set. Useful for chaining.'
|
||||
- name: 'onlinePlayersEnabled'
|
||||
description: |
|
||||
Sets whether the online players feature should be enabled.<br>
|
||||
<br>
|
||||
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
|
||||
<br>
|
||||
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should onlinePlayersEnabled be null.
|
||||
parameters:
|
||||
- name: 'onlinePlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: 'NullBool'
|
||||
attribute:
|
||||
- 'notnull'
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
- name: 'playerCountText'
|
||||
description: |
|
||||
Sets the text to override the player count with.<br>
|
||||
@@ -155,192 +183,6 @@ methods:
|
||||
name: 'ProfileEntry'
|
||||
type: 'object'
|
||||
link: './..'
|
||||
#
|
||||
# Deprecated stuff
|
||||
#
|
||||
- name: 'setExtraPlayerCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayerscount(integer)">extraPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the extra players feature should be enabled or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayersenabled(nullbool)">extraPlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setFavicon'
|
||||
description: |
|
||||
Sets the value to use for the favicon.<br>
|
||||
The following values are supported:
|
||||
<ul>
|
||||
<li>URL to a valid PNG file.</li>
|
||||
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
|
||||
<li><code>${player uuid}</code> to display the avatar of the player.</li>
|
||||
</ul>
|
||||
returns: 'This Builder after the favicon has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'favicon'
|
||||
description: 'The favicon to set'
|
||||
type: String
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#favicon(string)">favicon(String)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setHidePlayersEnabled'
|
||||
description: |
|
||||
Sets whether the player count should be hidden or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'hidePlayersEnabled'
|
||||
description: 'Whether the player count should be hidden or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#hideplayersenabled(nullbool)">hidePlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersCount'
|
||||
description: |
|
||||
Sets the number of max players allowed to join this server.<br>
|
||||
This option has no effect when <a href="../#maxplayersenabled()"><code>maxPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setmaxplayersenabled(nullbool)"><code>setMaxPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersCount'
|
||||
description: 'The number of max players to set.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayerscount(integer)">maxPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the max players feature should be enabled.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMotd'
|
||||
description: |
|
||||
Sets a new MOTD to use.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the MOTD.<br>
|
||||
Only the first two entries of the list will be considered and any additional ones discarded.
|
||||
returns: 'This Builder after the motd has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'motd'
|
||||
description: 'The MOTD to use.'
|
||||
type: 'List<String>'
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#motd(string)">motd(String)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayerCountText'
|
||||
description: |
|
||||
Sets the text to override the player count with.<br>
|
||||
<br>
|
||||
Set to an empty String or <code>null</code> to not alter the player count text.
|
||||
returns: 'This Builder after the player count text has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'playerCountText'
|
||||
description: 'The text to show in the player count.'
|
||||
type: String
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#playercounttext(string)">playerCountText(String)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayers'
|
||||
description: |
|
||||
Sets the players (lines) to use for the hover.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the hover text.
|
||||
returns: 'This Builder after the players have been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'players'
|
||||
description: 'The lines to set for the hover.'
|
||||
type: 'List<String>'
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#players(list<string>)">players(List<String>)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
---
|
||||
|
||||
# <api__class></api__class> Builder
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,5 +1,7 @@
|
||||
document$.subscribe(async () => {
|
||||
const url = 'https://codeberg-stats-proxy.vercel.app'
|
||||
const url = 'https://api.allorigins.win/raw?url='
|
||||
const apiUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/asl-api/releases/latest')}`
|
||||
|
||||
const repo_stats = document.querySelector('[data-md-component="source"] .md-source__repository');
|
||||
|
||||
function loadCodebergInfo(data) {
|
||||
@@ -45,10 +47,11 @@ document$.subscribe(async () => {
|
||||
}
|
||||
|
||||
async function fetchApiInfo() {
|
||||
const tag = await fetch(`${url}/api/latest-release`).then(_ => _.json());
|
||||
const tag = await fetch(`${apiUrl}`)
|
||||
.then(_ => _.json());
|
||||
|
||||
const data = {
|
||||
"version": tag.name
|
||||
"version": tag.tag_name
|
||||
};
|
||||
|
||||
__md_set("__api_tag", data, sessionStorage);
|
||||
@@ -57,14 +60,14 @@ document$.subscribe(async () => {
|
||||
|
||||
async function fetchInfo() {
|
||||
const [release, repo] = await Promise.all([
|
||||
fetch(`${url}/repo/latest-release`).then(_ => _.json()),
|
||||
fetch(`${url}/repo/stats`).then(_ => _.json()),
|
||||
fetch(`${url}${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/latest')}`).then(_ => _.json()),
|
||||
fetch(`${url}${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList')}`).then(_ => _.json()),
|
||||
]);
|
||||
|
||||
const data = {
|
||||
"version": release.name,
|
||||
"stars": repo.stars,
|
||||
"forks": repo.forks
|
||||
"version": release.tag_name,
|
||||
"stars": repo.stars_count,
|
||||
"forks": repo.forks_count
|
||||
};
|
||||
|
||||
__md_set("__git_repo", data, sessionStorage);
|
||||
|
||||
+26
-13
@@ -19,40 +19,53 @@ The following subcommands are available (Subcommands are case-insensitive):
|
||||
- [`reload`](#reload)
|
||||
- [`clearCache`](#clearcache)
|
||||
- [`migrate <plugin>`](#migrate)
|
||||
- [`profiles <add <profile> | copy <profile> <name> | list>`](#profiles)
|
||||
|
||||
### help
|
||||
### `help`
|
||||
|
||||
/// info |
|
||||
**Permission:** `advancedserverlist.command.help`
|
||||
|
||||
Shows a list of all available [subcommands](#subcommands) for AdvancedServerList.
|
||||
///
|
||||
|
||||
### reload
|
||||
----
|
||||
|
||||
### `reload`
|
||||
|
||||
/// info |
|
||||
**Permission:** `advancedserverlist.command.reload`
|
||||
|
||||
Reloads the plugin's `config.yml` and all available YAML files in the `profiles` folder.
|
||||
///
|
||||
|
||||
### clearCache
|
||||
----
|
||||
|
||||
### `clearcache`
|
||||
|
||||
/// info |
|
||||
**Permission:** `advancedserverlist.command.clearcache`
|
||||
|
||||
Clears the currently cached favicons and players.
|
||||
///
|
||||
|
||||
### migrate <plugin> { #migrate }
|
||||
----
|
||||
|
||||
### `migrate <plugin>` { #migrate }
|
||||
|
||||
/// info |
|
||||
**Permission:** `advancedserverlist.command.migrate`
|
||||
|
||||
**Arguments:
|
||||
**Arguments:**
|
||||
|
||||
- `<plugin>` - The plugin to migrate from.
|
||||
|
||||
Migrates files from one plugin over to AdvancedServerList.
|
||||
Check the [Migration Page](../migration/index.md) for a list of supported plugins.
|
||||
///
|
||||
|
||||
----
|
||||
|
||||
### `profiles <add <profile> | copy <profile> <name> | list>` { #profiles }
|
||||
|
||||
**Permission:** `advancedserverlist.command.profiles`
|
||||
|
||||
**Arguments:**
|
||||
|
||||
- `add <profile>` - Creates a new profile with name `<profile>` using the default profile values.
|
||||
- `copy <profile> <name>` - Creates a copy of `<profile>` and saves it as `<name>`.
|
||||
- `list` - Lists all loaded profiles. The entries have hover text for extra info.
|
||||
|
||||
Creates, copies or shows profiles in AdvancedServerList.
|
||||
@@ -502,16 +502,14 @@ motd:
|
||||
|
||||
### Additional profiles
|
||||
|
||||
To add additional profiles, create a new YAML file inside the `profiles` folder. The name can be whatever you like, but it is recommended to keep it simple and only use alphanumeric characters (`a-z` and `0-9`), underlines and hyphens.
|
||||
Additional profiles can be created to display different content under specific situations. To create a new file, either manually create a YAML file in the `profiles` folder, or use [`/asl profiles add <name>`](../commands/index.md#profiles) to have one created for you. In either case is it recommended to only use alphanummeric (`a-z` abd `0-9`) characters, dashes and underscores for the file name. You should also choose a name that fits the purpose of the file (i.e. for a profile that displays stuff when someone is banned, name it `banned.yml`).
|
||||
|
||||
Inside the file, add a priority and at least one setting, similar to the above shown example.
|
||||
This would already be enough to have a valid profile, but depending on the priority and file name may the file not be used, or used over other profiles.
|
||||
In case you manually created a YAML file, make sure it contains the [`priority`](../profiles/index.md#priority) setting and one of the other settings, to have a valid profile.
|
||||
You should also add a [`condition`](../profiles/index.md#condition) to ensure that the profile is only loaded when needed. The [Expressions page](../profiles/expressions.md) covers what counts as valid expressions and conditions.
|
||||
Do note that the plugin goes through the profiles in order of priority, starting with the highest number first, picking the first one that returns a `condition` returning true.
|
||||
|
||||
If you want to only show this file under specific situations can you use the [`condition`](../profiles/index.md#condition) option to apply conditions that need to be met to show the profile.
|
||||
The condition option would have a single String containing one or multiple [Expressions](../profiles/expressions.md). Only if the condition would return true, would the profile be displayed, granted that it has a higher priority than any other valid file with a true condition output.
|
||||
|
||||
/// info | Note
|
||||
Files without a condition or an empty condition will be treated as always having a true condition.
|
||||
/// info | Note about Condition
|
||||
The Condition option, if not set or empty, will always return true.
|
||||
///
|
||||
|
||||
Here is another example profile using conditions to show it when the player was banned on the server:
|
||||
|
||||
@@ -11,11 +11,17 @@ These pages may include important information about the migration process and wh
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [**MiniMOTD**](minimotd.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from the Plugin [MiniMOTD](https://github.com/jpenilla/MiniMOTD){ target="_blank" rel="nofollow" }
|
||||
|
||||
- [**ServerListPlus**](serverlistplus.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from the Plugin [ServerListPlus](https://github.com/Minecrell/ServerListPlus).
|
||||
Migrate from the Plugin [ServerListPlus](https://github.com/Minecrell/ServerListPlus){ target="_blank" rel="nofollow" }.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
icon: octicons/arrow-right-24
|
||||
---
|
||||
|
||||
Version `4.10.0` added support for migrating your existing `main.conf` configuration from MiniMOTD to AdvancedServerList.
|
||||
|
||||
## Important Notes
|
||||
|
||||
- MiniMOTD does not need to be present on the server/proxy to migrate its files. Only the `main.conf` file needs to be available.
|
||||
- The plugin will **only** migrate the `main.conf` file. No other files will be migrated.
|
||||
|
||||
## How to Migrate
|
||||
|
||||
Execute the command [`/asl migrate minimotd`](../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
|
||||
|
||||
## Example
|
||||
|
||||
Below can you find a full example of a `main.conf` file and the corresponding migrated files from AdvancedServerList:
|
||||
|
||||
/// tab | :octicons-file-code-24: main.conf
|
||||
```conf
|
||||
icon-enabled=true
|
||||
motd-enabled=true
|
||||
motds=[
|
||||
{
|
||||
icon=random
|
||||
line1="<rainbow>MiniMOTD Default"
|
||||
line2="MiniMessage <gradient:blue:red>Gradients"
|
||||
},
|
||||
{
|
||||
icon=random
|
||||
line1="<blue>Another <bold><red>MOTD"
|
||||
line2="<italic><underlined><gradient:red:green>much wow"
|
||||
}
|
||||
]
|
||||
player-count-settings {
|
||||
allow-exceeding-maximum=false
|
||||
disable-player-list-hover=false
|
||||
fake-players {
|
||||
fake-players="25%"
|
||||
fake-players-enabled=false
|
||||
}
|
||||
hide-player-count=false
|
||||
just-x-more-settings {
|
||||
just-x-more-enabled=false
|
||||
x-value=3
|
||||
}
|
||||
max-players=69
|
||||
max-players-enabled=true
|
||||
servers=[]
|
||||
}
|
||||
```
|
||||
///
|
||||
|
||||
/// tab | :octicons-file-code-24: minimotd_migrated.yml
|
||||
```yaml
|
||||
priority: 0
|
||||
profiles:
|
||||
- motd:
|
||||
- <rainbow>MiniMOTD Default
|
||||
- MiniMessage <gradient:blue:red>Gradients
|
||||
playerCount:
|
||||
hover: []
|
||||
text: ''
|
||||
hidePlayers: false
|
||||
extraPlayers:
|
||||
enabled: false
|
||||
amount: 0
|
||||
maxPlayers:
|
||||
enabled: false
|
||||
amount: 0
|
||||
favicon: ''
|
||||
- motd:
|
||||
- <blue>Another <bold><red>MOTD
|
||||
- <italic><underlined><gradient:red:green>much wow
|
||||
playerCount:
|
||||
hover: []
|
||||
text: ''
|
||||
hidePlayers: false
|
||||
extraPlayers:
|
||||
enabled: false
|
||||
amount: 0
|
||||
maxPlayers:
|
||||
enabled: false
|
||||
amount: 0
|
||||
favicon: ''
|
||||
motd: []
|
||||
playerCount:
|
||||
hover: []
|
||||
text: ''
|
||||
hidePlayers: false
|
||||
extraPlayers:
|
||||
enabled: false
|
||||
amount: 3
|
||||
maxPlayers:
|
||||
enabled: true
|
||||
amount: 69
|
||||
favicon: ''
|
||||
```
|
||||
///
|
||||
+48
-5
@@ -127,7 +127,7 @@ The Value can be one of three possible options, each being checked for in order:
|
||||
|
||||
Note that for the name/UUID, the site https://mc-heads.net is being used.
|
||||
Use the URL option with the `${player uuid}` placeholder if you want to use another service.
|
||||
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -161,7 +161,7 @@ When set to true will the player count be replaced with `???`.
|
||||
In addition are the [`playerCount -> text`](#text) and [`playerCount -> hover`](#hover) options ignored.
|
||||
|
||||
If you want to not show any text at all, set this option to `false` (or remove it) and instead use the [`playerCount -> text`](#text) option.
|
||||
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -227,7 +227,7 @@ Please take note of the following caveats:
|
||||
If you want to not show any text, just use a single color (i.e. `text: '<grey>'`) to do so.
|
||||
|
||||
This option only supports basic colors and no HEX colors.
|
||||
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -267,7 +267,9 @@ Use the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option t
|
||||
The `playerCount -> extraPlayers -> amount` option defines how much should be added to the current online player count to then use as max player count.
|
||||
|
||||
Example: Setting this option to `1` while currently 10 players are online will result in `10/11` being displayed on the player count (Assuming it is not being overriden by the [`playerCount -> text`](#text) option).
|
||||
|
||||
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -309,7 +311,9 @@ Use the [`playerCount -> maxPlayers -> amount`](#maxplayers-amount) option to se
|
||||
|
||||
The `playerCount -> maxPlayers -> amount` option defines the number to use as the server's max players count.
|
||||
Unlike the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option does this one not first add the current online player count to the number to then set.
|
||||
|
||||
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -330,5 +334,44 @@ playerCount:
|
||||
|
||||
{ loading="lazy" }
|
||||
|
||||
</div>
|
||||
///
|
||||
|
||||
### OnlinePlayers
|
||||
|
||||
<!-- admo:warning Using this option alters the output of <code>playerCount -> extraPlayers</code> -->
|
||||
|
||||
The `playerCount -> onlinePlayers` option contains settings to enable and set the number of players online on the server.
|
||||
|
||||
#### Enabled { #onlineplayers-enabled }
|
||||
|
||||
Enables the online players feature.
|
||||
Use the [`playerCount -> onlinePlayers -> amount`](#onlineplayers-amount) option to set the online players value itself.
|
||||
|
||||
#### Amount { #onlineplayers-amount }
|
||||
|
||||
Sets the number to display as the server's only player count.
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
```yaml title="YAML file
|
||||
priority: 0
|
||||
|
||||
# Hides the MOTD for demonstration purposes
|
||||
motd:
|
||||
- '<grey>'
|
||||
- '<grey>'
|
||||
|
||||
playerCount:
|
||||
onlinePlayers:
|
||||
enabled: true
|
||||
amount: 10
|
||||
```
|
||||
<div class="result" markdown>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
///
|
||||
@@ -11,7 +11,7 @@ It also has built-in [PlaceholderAPI support](#placeholderapi) for Spigot and Pa
|
||||
|
||||
The following placeholders are available in AdvancedServerList itself. Please note that not all placeholders are available on all platforms.
|
||||
|
||||
### Player Placeholders
|
||||
### Player
|
||||
|
||||
These placeholders use the player who pinged the server, to return values. They may require the player to be cached in order to work.
|
||||
|
||||
@@ -44,7 +44,8 @@ These placeholders use values given by the server/proxy AdvancedServerList runs
|
||||
|
||||
[^4]:
|
||||
A comma-separated list of world (On Paper) or Server (On BungeeCord/Velocity) names can be provided to display the added numbers of players in these worlds/servers.
|
||||
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
|
||||
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
|
||||
Using the [onlinePlayers' `amount`](index.md#onlineplayers-amount) option will modify the output of this placeholder, except when used in [`condition`](index.md#condition).
|
||||
[^5]:
|
||||
Using either the [extraPlayers' `amount`](index.md#extraplayers-amount) or [maxPlayers' `amount`](index.md#maxplayers-amount) option will make this placeholder return the modified max players count.
|
||||
Only exception to this rule is when the placeholder is used in the [`condition`](index.md#condition) option in which case it returns the actual max player count of the proxy/server.
|
||||
@@ -52,6 +53,31 @@ These placeholders use values given by the server/proxy AdvancedServerList runs
|
||||
An optional server name can be provided to display the IP/Domain associated with that server. This only works on BungeeCord or Velocity.
|
||||
**Example:** `${server host survival}` would display the IP/Domain associated with the `survival` server.
|
||||
|
||||
### Proxy
|
||||
|
||||
These placeholders are only available on the BungeeCord and Velocity versions of AdvancedServerList.
|
||||
|
||||
/// note
|
||||
Servers are pinged every 10 seconds by the plugin and cached for that time period.
|
||||
///
|
||||
|
||||
| Placeholders | Description | Default[^7] |
|
||||
|------------------------------|-------------------------------------------------------------------|-------------|
|
||||
| `${proxy status <name>}` | Returns `online` or `offline` based on the Server's availability. | `offline` |
|
||||
| `${proxy motd <name>}` | Returns the Server's MOTD as MiniMessage String. | `none` |
|
||||
| `${proxy players <name>}` | Returns the number of online Players on the Server. | `0` |
|
||||
| `${proxy maxPlayers <name>}` | Returns the max number of Players allowed to join the Server. | `0` |
|
||||
|
||||
[^7]: The default value returned, should the Server or parts of it not be available.
|
||||
|
||||
### Maintenance
|
||||
|
||||
These placeholders require the [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) plugin to work.
|
||||
|
||||
| Placeholder | Description |
|
||||
|-------------------------------------|----------------------------------------------------------------|
|
||||
| `${maintenance maintenanceEnabled}` | Returns whether the Global maintenance mode is enabled or not. |
|
||||
|
||||
## PlaceholderAPI
|
||||
|
||||
Please visit the [PlaceholderAPI page](../placeholderapi/index.md) for how AdvancedServerList works with PlaceholderAPI.
|
||||
|
||||
+2
-1
@@ -119,6 +119,7 @@ nav:
|
||||
- Migration:
|
||||
- migration/index.md
|
||||
- Other Plugins:
|
||||
- MiniMOTD: migration/minimotd.md
|
||||
- ServerListPlus: migration/serverlistplus.md
|
||||
- AdvancedServerList:
|
||||
- v3.8.0 to v3.9.0: migration/v3_8_0-to-v3_9_0.md
|
||||
@@ -147,7 +148,7 @@ nav:
|
||||
- api/reference/api/ch.andre601.advancedserverlist.api/objects/genericserver.md
|
||||
- api/reference/api/ch.andre601.advancedserverlist.api/objects/nullbool.md
|
||||
- profiles:
|
||||
- '<api__record></api__record> ProfileEntry':
|
||||
- ProfileEntry:
|
||||
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
|
||||
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
|
||||
- platform-bukkit:
|
||||
|
||||
+26
-7
@@ -46,7 +46,7 @@
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>placeholderapi-repo</id>
|
||||
@@ -59,6 +59,7 @@
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- AdvancedServerList -->
|
||||
<dependency>
|
||||
<groupId>ch.andre601.advancedserverlist</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
@@ -71,30 +72,44 @@
|
||||
<version>${api.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Paper API -->
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.20-R0.1-SNAPSHOT</version>
|
||||
<version>1.21-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- bStats -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Plugins -->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.11.5</version>
|
||||
<version>2.11.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion-api</artifactId>
|
||||
<version>4.10.2</version>
|
||||
<version>5.0.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Other -->
|
||||
<dependency>
|
||||
<groupId>com.alessiodp.libby</groupId>
|
||||
<artifactId>libby-paper</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -117,13 +132,17 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.bstats</shadedPattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.alessiodp.libby</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.libby</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
|
||||
@@ -28,7 +28,7 @@ package ch.andre601.advancedserverlist.paper;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.paper.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.paper.listeners.LoadEvent;
|
||||
import ch.andre601.advancedserverlist.paper.logging.PaperLogger;
|
||||
@@ -36,6 +36,9 @@ import ch.andre601.advancedserverlist.paper.objects.WorldCache;
|
||||
import ch.andre601.advancedserverlist.paper.objects.placeholders.PAPIPlaceholders;
|
||||
import ch.andre601.advancedserverlist.paper.objects.placeholders.PaperPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.paper.objects.placeholders.PaperServerPlaceholders;
|
||||
import com.alessiodp.libby.Library;
|
||||
import com.alessiodp.libby.PaperLibraryManager;
|
||||
import io.papermc.paper.ServerBuildInfo;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -49,6 +52,7 @@ import java.awt.image.BufferedImage;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon>{
|
||||
|
||||
@@ -59,6 +63,8 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
private PAPIPlaceholders papiPlaceholders = null;
|
||||
private WorldCache worldCache = null;
|
||||
|
||||
private PaperLibraryManager libraryManager = null;
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
try{
|
||||
@@ -126,6 +132,23 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
faviconHandler.cleanCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadLibrary(String groupId, String artifactId, String version){
|
||||
if(libraryManager == null){
|
||||
libraryManager = new PaperLibraryManager(this);
|
||||
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
|
||||
}
|
||||
|
||||
Library lib = Library.builder()
|
||||
.groupId(groupId)
|
||||
.artifactId(artifactId)
|
||||
.version(version)
|
||||
.resolveTransitiveDependencies(true)
|
||||
.build();
|
||||
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<CachedServerIcon> getCore(){
|
||||
return core;
|
||||
@@ -150,13 +173,14 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName(){
|
||||
return getServer().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion(){
|
||||
return getServer().getVersion();
|
||||
public String getPlatformInfo(){
|
||||
try{
|
||||
Class.forName("io.papermc.paper.ServerBuildInfo");
|
||||
return getNewVersion();
|
||||
}catch(ClassNotFoundException ignored){
|
||||
// Old Paper versions (Before 16th of May 2024)
|
||||
return getOldVersion();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -216,4 +240,22 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
private String getNewVersion(){
|
||||
ServerBuildInfo info = ServerBuildInfo.buildInfo();
|
||||
|
||||
String name = info.brandName();
|
||||
String id = info.brandId().asString();
|
||||
String version = info.minecraftVersionName();
|
||||
|
||||
OptionalInt build = info.buildNumber();
|
||||
if(build.isEmpty())
|
||||
return String.format("%s (%s, Version: %s)", name, id, version);
|
||||
|
||||
return String.format("%s (ID: %s, Version: %s, Build: %d)", name, id, version, build.getAsInt());
|
||||
}
|
||||
|
||||
private String getOldVersion(){
|
||||
return getServer().getName() + " " + getServer().getVersion();
|
||||
}
|
||||
}
|
||||
+50
-19
@@ -28,7 +28,7 @@ package ch.andre601.advancedserverlist.paper.listeners;
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
@@ -48,6 +48,8 @@ import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, PaperPlayerImpl>{
|
||||
|
||||
@@ -72,6 +74,11 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
event.setMaxPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
event.setNumPlayers(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
event.motd(component);
|
||||
@@ -90,24 +97,13 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> lines, PaperPlayerImpl player, GenericServer server){
|
||||
event.getPlayerSample().clear();
|
||||
List<PlayerProfile> 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(FakePlayerProfile.create(parsed));
|
||||
try{
|
||||
event.getListedPlayers();
|
||||
setListedPlayers(lines, player, server);
|
||||
}catch(NoSuchMethodError ex){
|
||||
// Version before latest 1.20.6 builds(?)
|
||||
setPlayerSample(lines, player, server);
|
||||
}
|
||||
|
||||
event.getPlayerSample().addAll(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,7 +131,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
if(!Bukkit.getPluginManager().isPluginEnabled("Maintenance"))
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
return MaintenanceUtil.get().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,4 +183,39 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
|
||||
return new PaperServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
|
||||
}
|
||||
|
||||
private void setListedPlayers(List<String> lines, PaperPlayerImpl player, GenericServer server){
|
||||
event.getListedPlayers().clear();
|
||||
List<PaperServerListPingEvent.ListedPlayerInfo> playerList = getPlayerList(lines, player, server,
|
||||
text -> new PaperServerListPingEvent.ListedPlayerInfo(text, UUID.randomUUID()));
|
||||
|
||||
event.getListedPlayers().addAll(playerList);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"Deprecation", "removal"})
|
||||
private void setPlayerSample(List<String> lines, PaperPlayerImpl player, GenericServer server){
|
||||
event.getPlayerSample().clear();
|
||||
List<PlayerProfile> playerProfiles = getPlayerList(lines, player, server, FakePlayerProfile::create);
|
||||
|
||||
event.getPlayerSample().addAll(playerProfiles);
|
||||
}
|
||||
|
||||
private <T> List<T> getPlayerList(List<String> lines, PaperPlayerImpl player, GenericServer server, Function<String, T> function){
|
||||
List<T> playerList = 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();
|
||||
|
||||
playerList.add(function.apply(parsed));
|
||||
}
|
||||
|
||||
return playerList;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -70,7 +70,7 @@ public record FakePlayerProfile(String name, UUID uuid) implements PlayerProfile
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerTextures getTextures(){
|
||||
return new FakePlayeerTextures();
|
||||
return new FakePlayerTextures();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,7 +153,7 @@ public record FakePlayerProfile(String name, UUID uuid) implements PlayerProfile
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private static record FakePlayeerTextures() implements PlayerTextures{
|
||||
private record FakePlayerTextures() implements PlayerTextures{
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(){
|
||||
|
||||
+23
-2
@@ -27,12 +27,18 @@ package ch.andre601.advancedserverlist.paper.objects.impl;
|
||||
|
||||
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 PaperPlayerImpl extends GenericPlayerImpl implements BukkitPlayer{
|
||||
import java.util.UUID;
|
||||
|
||||
public class PaperPlayerImpl implements BukkitPlayer{
|
||||
|
||||
private final OfflinePlayer player;
|
||||
|
||||
private final String name;
|
||||
private int protocol;
|
||||
private final UUID uuid;
|
||||
|
||||
private boolean playedBefore = false;
|
||||
private boolean banned = false;
|
||||
private boolean whitelisted = false;
|
||||
@@ -52,6 +58,21 @@ public class PaperPlayerImpl extends GenericPlayerImpl implements BukkitPlayer{
|
||||
this.whitelisted = player.isWhitelisted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlayer getPlayer(){
|
||||
return player;
|
||||
|
||||
+25
-5
@@ -94,16 +94,22 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
|
||||
ProfileEntry entry = ProfileManager.merge(profile);
|
||||
|
||||
Integer onlinePlayers = null;
|
||||
if(ProfileManager.checkOption(entry.onlinePlayersEnabled())){
|
||||
onlinePlayers = parseNumberOption(entry.onlinePlayersCount(), pl, player, server);
|
||||
online = onlinePlayers == null ? online : onlinePlayers;
|
||||
}
|
||||
|
||||
Integer maxPlayers = null;
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled())){
|
||||
max = entry.maxPlayersCount() == null ? 0 : entry.maxPlayersCount();
|
||||
maxPlayers = entry.maxPlayersCount();
|
||||
maxPlayers = parseNumberOption(entry.maxPlayersCount(), pl, player, server);
|
||||
max = maxPlayers == null ? 0 : maxPlayers;
|
||||
}
|
||||
|
||||
Integer extraPlayers = null;
|
||||
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
extraPlayers = entry.extraPlayersCount();
|
||||
extraPlayers = parseNumberOption(entry.extraPlayersCount(), pl, player, server);
|
||||
max = online + (extraPlayers == null ? 0 : extraPlayers);
|
||||
}
|
||||
|
||||
BukkitServer finalServer = new PaperServerImpl(plugin.getWorldCache().worlds(), online, max, host);
|
||||
@@ -114,6 +120,7 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
|
||||
case "playercount_extraplayers" -> extraPlayers == null ? "null" : String.valueOf(extraPlayers);
|
||||
case "playercount_maxplayers" -> maxPlayers == null ? "null" : String.valueOf(maxPlayers);
|
||||
case "playercount_onlineplayers" -> onlinePlayers == null ? "null" : String.valueOf(onlinePlayers);
|
||||
case "server_playersmax" -> String.valueOf(max);
|
||||
default -> null;
|
||||
};
|
||||
@@ -134,8 +141,21 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
|
||||
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server){
|
||||
return ComponentParser.list(list)
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.toString();
|
||||
}
|
||||
|
||||
private Integer parseNumberOption(String option, Player pl, BukkitPlayer player, BukkitServer server){
|
||||
String parsed = ComponentParser.text(option)
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.toString();
|
||||
|
||||
try{
|
||||
return Integer.parseInt(parsed);
|
||||
}catch(NumberFormatException ex){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -73,19 +73,19 @@ public class PaperServerPlaceholders extends PlaceholderProvider{
|
||||
}
|
||||
case "playersMax" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(paperServer.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield paperServer.getHost();
|
||||
}
|
||||
case "whitelistEnabled" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(Bukkit.hasWhitelist());
|
||||
}
|
||||
|
||||
@@ -37,15 +37,15 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<plugin.version>4.9.1</plugin.version>
|
||||
<plugin.version>5.0.2</plugin.version>
|
||||
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
|
||||
|
||||
<api.version>3.3.0</api.version>
|
||||
<api.version>4.0.0</api.version>
|
||||
|
||||
<dependency.adventure-api>4.17.0</dependency.adventure-api>
|
||||
<dependency.adventure-text-minimessage>4.17.0</dependency.adventure-text-minimessage>
|
||||
<dependency.adventure-text-serializer-legacy>4.17.0</dependency.adventure-text-serializer-legacy>
|
||||
<dependency.adventure-platform-bungeecord>4.3.2</dependency.adventure-platform-bungeecord>
|
||||
<dependency.adventure-platform-bungeecord>4.3.4</dependency.adventure-platform-bungeecord>
|
||||
<dependency.configurate-yaml>4.1.2</dependency.configurate-yaml>
|
||||
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
@@ -61,6 +61,10 @@
|
||||
<id>codeberg</id>
|
||||
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-snapshots</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<modules>
|
||||
|
||||
+42
-8
@@ -7,17 +7,18 @@
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Use Jitpack registry for AdvancedBan",
|
||||
"description": "Use Jitpack registry for various Libs",
|
||||
"matchPackageNames": [
|
||||
"com.github.DevLeoko:AdvancedBan",
|
||||
"com.github.LeonMangler:PremiumVanishAPI"
|
||||
"com.github.LeonMangler:PremiumVanishAPI",
|
||||
"com.gitlab.ruany:LiteBansAPI"
|
||||
],
|
||||
"registryUrls": [
|
||||
"https://jitpack.io"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use Codeberg packages for asl-api",
|
||||
"description": "Use Codeberg packages for Own API stuff",
|
||||
"matchPackageNames": [
|
||||
"ch.andre601.asl-api:api",
|
||||
"ch.andre601.asl-api:parent",
|
||||
@@ -30,6 +31,44 @@
|
||||
"https://codeberg.org/api/packages/Andre601/maven"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use Paper Repo for Paper API",
|
||||
"matchPackageNames": [
|
||||
"io.papermc.paper:paper-api"
|
||||
],
|
||||
"registryUrls": [
|
||||
"https://papermc.io/repo/repository/maven-public"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use PlaceholderAPI Repo for PlaceholderAPI",
|
||||
"matchPackageNames": [
|
||||
"me.clip:placeholderapi"
|
||||
],
|
||||
"registryUrls": [
|
||||
"https://repo.extendedclip.com/content/repositories/placeholderapi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use ViaVersion Repo for ViaVersion",
|
||||
"matchPackageNames": [
|
||||
"com.viaversion:viaversion-api"
|
||||
],
|
||||
"registryUrls": [
|
||||
"https://repo.viaversion.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use Sonatype for Libby",
|
||||
"matchPackageNames": [
|
||||
"com.alessiodp.libby:libby-bungee",
|
||||
"com.alessiodp.libby:libby-paper",
|
||||
"com.alessiodp.libby:libby-velocity"
|
||||
],
|
||||
"registryUrls": [
|
||||
"https://s01.oss.sonatype.org/content/repositories/snapshots/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Apply label for Bukkit platform",
|
||||
"matchFileNames": ["bukkit/pom.xml"],
|
||||
@@ -50,11 +89,6 @@
|
||||
"matchFileNames": ["velocity/pom.xml"],
|
||||
"addLabels": ["PR Target/Velocity"]
|
||||
},
|
||||
{
|
||||
"description": "Apply label for GitHub Actions",
|
||||
"matchFileNames": [".github/workflows/*.yml"],
|
||||
"addLabels": ["PR Target/GitHub Action"]
|
||||
},
|
||||
{
|
||||
"description": "Apply label for MkDocs",
|
||||
"matchFileNames": ["requirements.txt"],
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
mkdocs-material==9.5.22
|
||||
mkdocs-material==9.5.39
|
||||
mkdocs-glightbox==0.4.0
|
||||
git+https://github.com/Andre601/mkdocs-pagenav-generator
|
||||
+15
-3
@@ -46,7 +46,7 @@
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>velocity-repo</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-velocity</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -95,6 +95,14 @@
|
||||
<version>2.9.0-4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Other -->
|
||||
<dependency>
|
||||
<groupId>com.alessiodp.libby</groupId>
|
||||
<artifactId>libby-velocity</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -114,7 +122,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -122,6 +130,10 @@
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.bstats</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.alessiodp.libby</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.libby</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
|
||||
@@ -28,13 +28,16 @@ package ch.andre601.advancedserverlist.velocity;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.velocity.commands.CmdAdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.velocity.listeners.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.velocity.listeners.PingEvent;
|
||||
import ch.andre601.advancedserverlist.velocity.logging.VelocityLogger;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityProxyPlaceholders;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityServerPlaceholders;
|
||||
import com.alessiodp.libby.Library;
|
||||
import com.alessiodp.libby.VelocityLibraryManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.command.CommandMeta;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
@@ -48,6 +51,7 @@ import com.velocitypowered.api.util.Favicon;
|
||||
import de.myzelyam.api.vanish.VelocityVanishAPI;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.velocity.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -58,7 +62,9 @@ import java.util.Locale;
|
||||
|
||||
public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
private final PluginLogger logger;
|
||||
private final Logger logger = LoggerFactory.getLogger("AdvancedServerList");
|
||||
|
||||
private final PluginLogger pluginLogger;
|
||||
private final ProxyServer proxy;
|
||||
private final Path path;
|
||||
private final Metrics.Factory metrics;
|
||||
@@ -66,9 +72,11 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
private AdvancedServerList<Favicon> core;
|
||||
private FaviconHandler<Favicon> faviconHandler = null;
|
||||
|
||||
private VelocityLibraryManager<VelocityCore> libraryManager = null;
|
||||
|
||||
@Inject
|
||||
public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
|
||||
this.logger = new VelocityLogger(this, LoggerFactory.getLogger("AdvancedServerList"));
|
||||
this.pluginLogger = new VelocityLogger(this, this.logger);
|
||||
|
||||
this.proxy = proxy;
|
||||
this.path = path;
|
||||
@@ -77,7 +85,8 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
@Subscribe
|
||||
public void init(ProxyInitializeEvent event){
|
||||
this.core = AdvancedServerList.init(this, VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init(this));
|
||||
this.core = AdvancedServerList.init(this,
|
||||
VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init(this), VelocityProxyPlaceholders.init(this));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -121,6 +130,23 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
faviconHandler.cleanCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadLibrary(String groupId, String artifactId, String version){
|
||||
if(libraryManager == null){
|
||||
libraryManager = new VelocityLibraryManager<>(this, this.logger, getFolderPath(), getProxy().getPluginManager());
|
||||
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
|
||||
}
|
||||
|
||||
Library lib = Library.builder()
|
||||
.groupId(groupId)
|
||||
.artifactId(artifactId)
|
||||
.version(version)
|
||||
.resolveTransitiveDependencies(true)
|
||||
.build();
|
||||
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
@@ -133,7 +159,7 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
@Override
|
||||
public PluginLogger getPluginLogger(){
|
||||
return logger;
|
||||
return pluginLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,13 +171,8 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName(){
|
||||
return getProxy().getVersion().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion(){
|
||||
return getProxy().getVersion().getVersion();
|
||||
public String getPlatformInfo(){
|
||||
return getProxy().getVersion().getName() + " " + getProxy().getVersion().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-7
@@ -28,7 +28,8 @@ package ch.andre601.advancedserverlist.velocity.listeners;
|
||||
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
|
||||
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
@@ -44,7 +45,10 @@ import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class VelocityEventWrapper implements GenericEventWrapper<Favicon, VelocityPlayerImpl>{
|
||||
@@ -78,6 +82,11 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
builder.maximumPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
builder.onlinePlayers(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
builder.description(component);
|
||||
@@ -133,7 +142,7 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
if(!plugin.getProxy().getPluginManager().isLoaded("maintenance"))
|
||||
return false;
|
||||
|
||||
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
|
||||
return MaintenanceUtil.get().isMaintenanceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,10 +174,10 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
if(!plugin.getProxy().getPluginManager().isLoaded("papiproxybridge"))
|
||||
return text;
|
||||
|
||||
if(!PingEventHandler.getPAPIUtil().isCompatible())
|
||||
if(!PAPIUtil.get().isCompatible())
|
||||
return text;
|
||||
|
||||
String server = PingEventHandler.getPAPIUtil().getServer();
|
||||
String server = PAPIUtil.get().getServer();
|
||||
if(server == null || server.isEmpty())
|
||||
return text;
|
||||
|
||||
@@ -176,11 +185,11 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
if(registeredServer == null || registeredServer.getPlayersConnected().isEmpty())
|
||||
return text;
|
||||
|
||||
Player carrier = PingEventHandler.getPAPIUtil().getPlayer(registeredServer.getPlayersConnected());
|
||||
Player carrier = PAPIUtil.get().getPlayer(registeredServer.getPlayersConnected());
|
||||
if(carrier == null)
|
||||
return text;
|
||||
|
||||
return PingEventHandler.getPAPIUtil().parse(text, carrier.getUniqueId(), player.getUUID());
|
||||
return PAPIUtil.get().parse(text, carrier.getUniqueId(), player.getUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
-2
@@ -27,10 +27,15 @@ package ch.andre601.advancedserverlist.velocity.objects.impl;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.velocity.objects.VelocityPlayer;
|
||||
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
|
||||
public class VelocityPlayerImpl extends GenericPlayerImpl implements VelocityPlayer{
|
||||
import java.util.UUID;
|
||||
|
||||
public class VelocityPlayerImpl implements VelocityPlayer{
|
||||
|
||||
private final String name;
|
||||
private final int protocol;
|
||||
private final UUID uuid;
|
||||
|
||||
private final String version;
|
||||
|
||||
@@ -41,6 +46,21 @@ public class VelocityPlayerImpl extends GenericPlayerImpl implements VelocityPla
|
||||
this.version = ProtocolVersion.getProtocolVersion(protocol).getVersionIntroducedIn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocol(){
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(){
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion(){
|
||||
return version;
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package ch.andre601.advancedserverlist.velocity.objects.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityCore;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class VelocityProxyPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private final Map<String, ServerPing> serverStates = new ConcurrentHashMap<>();
|
||||
private final VelocityCore plugin;
|
||||
|
||||
private VelocityProxyPlaceholders(VelocityCore plugin){
|
||||
super("proxy");
|
||||
|
||||
this.plugin = plugin;
|
||||
plugin.getProxy().getScheduler().buildTask(plugin, this::fetchServerStates)
|
||||
.repeat(Duration.ofSeconds(10))
|
||||
.schedule();
|
||||
}
|
||||
|
||||
public static VelocityProxyPlaceholders init(VelocityCore plugin){
|
||||
return new VelocityProxyPlaceholders(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
String[] args = placeholder.split("\\s", 2);
|
||||
if(args.length < 2)
|
||||
return null;
|
||||
|
||||
ServerPing ping = serverStates.get(args[1]);
|
||||
return switch(args[0]){
|
||||
case "status" -> ping == null ? "offline" : "online";
|
||||
case "motd" -> {
|
||||
if(ping == null)
|
||||
yield "none";
|
||||
|
||||
yield ComponentParser.toMMString(ping.getDescriptionComponent());
|
||||
}
|
||||
case "players" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
ServerPing.Players players = ping.getPlayers().orElse(null);
|
||||
if(players == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(players.getOnline());
|
||||
}
|
||||
case "maxPlayers" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
ServerPing.Players players = ping.getPlayers().orElse(null);
|
||||
if(players == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(players.getMax());
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private void fetchServerStates(){
|
||||
serverStates.clear();
|
||||
plugin.getProxy().getAllServers().forEach(server -> server.ping().whenComplete((ping, throwable) -> {
|
||||
if(throwable != null){
|
||||
plugin.getPluginLogger().warn("Encountered an exception while fetching status of Server %s", throwable, server.getServerInfo().getName());
|
||||
return;
|
||||
}
|
||||
|
||||
serverStates.put(server.getServerInfo().getName(), ping);
|
||||
}));
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -80,18 +80,18 @@ public class VelocityServerPlaceholders extends PlaceholderProvider{
|
||||
}
|
||||
case "playersMax" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(proxy.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length > 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
if(args.length == 2){
|
||||
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
|
||||
RegisteredServer info = proxy.getServers().get(args[1]);
|
||||
if(info == null)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield info.getServerInfo().getAddress().getHostString();
|
||||
}
|
||||
|
||||
@@ -46,19 +46,19 @@
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
<version>2.11.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.5.6</version>
|
||||
<version>1.5.8</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<version>5.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -70,7 +70,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.masecla</groupId>
|
||||
<artifactId>Modrinth4J</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.2.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -101,7 +101,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>3.4.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
@@ -115,7 +115,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
|
||||
+2
-2
@@ -130,8 +130,8 @@ public class HangarVersionUploader{
|
||||
Platform.VELOCITY, velocityDependencies
|
||||
),
|
||||
Map.of(
|
||||
Platform.PAPER, List.of("1.20.x"),
|
||||
Platform.WATERFALL, List.of("1.19.x", "1.20.x"),
|
||||
Platform.PAPER, List.of("1.20.x", "1.21"),
|
||||
Platform.WATERFALL, List.of("1.19.x", "1.20.x", "1.21"),
|
||||
Platform.VELOCITY, Collections.singletonList("3.2")
|
||||
),
|
||||
changelog.replaceAll("\r\n", "\n"),
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class ModrinthVersionUploader{
|
||||
PlatformInfo.VELOCITY
|
||||
);
|
||||
private final List<String> versions = List.of(
|
||||
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6"
|
||||
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6", "1.21"
|
||||
);
|
||||
|
||||
private final ModrinthAPI api;
|
||||
|
||||
Reference in new issue
Block a user