mirror of
https://codeberg.org/Andre601/AdvancedServerList.git
synced 2026-11-05 17:02:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f6bdea168 | ||
|
|
d247d832e6 | ||
|
|
708037bb6b | ||
|
|
7da88771b6 | ||
|
|
9ccfd4674c | ||
|
|
9054ebdb0c | ||
|
|
edfd77e891 | ||
|
|
94391a8aed | ||
|
|
5a1f343cc2 | ||
|
|
e718a5c766 | ||
|
|
565644ccd5 | ||
|
|
9531af1fdd | ||
|
|
7c1d7aadbc | ||
|
|
f26f2ba269 | ||
|
|
f5d2fd1534 | ||
|
|
90537eb004 | ||
|
|
ce6a9e3b0b | ||
|
|
4d29f9e45e | ||
|
|
bf49636d6a | ||
|
|
4a6c9a55d4 | ||
|
|
a5bfc0b6e3 | ||
|
|
dff332a83a | ||
|
|
58a16baaab | ||
|
|
c8acb4d90a | ||
|
|
5575243a79 | ||
|
|
4cd4aeb12a | ||
|
|
5922b2235e | ||
|
|
2fcef08f5a | ||
|
|
30c28b07a4 | ||
|
|
08b4f1029c | ||
|
|
f5051022aa | ||
|
|
fe51e78764 | ||
|
|
5b2d9d910f | ||
|
|
6f06c47de7 | ||
|
|
ad3ba0c8b3 | ||
|
|
12d8d930dd | ||
|
|
9a30a6b679 | ||
|
|
b82cf69d43 | ||
|
|
fb6d93b455 | ||
|
|
a1276da68f | ||
|
|
25c053d495 | ||
|
|
39c1fb5452 | ||
|
|
48edebc043 | ||
|
|
3a672378ff | ||
|
|
9db9f2be7f | ||
|
|
2cf47e351b | ||
|
|
36abdb83cd | ||
|
|
ad950bf330 | ||
|
|
143753d309 | ||
|
|
0c37c21650 | ||
|
|
40a6b4f059 | ||
|
|
965e87d71b | ||
|
|
202a22f33a | ||
|
|
a4b2a6c350 | ||
|
|
ba55f5299b | ||
|
|
24fdf798cf | ||
|
|
e208d181b7 | ||
|
|
6c15c7b259 | ||
|
|
dcd76a43f5 | ||
|
|
adc2060499 | ||
|
|
4d6befc857 | ||
|
|
7cfb792471 | ||
|
|
d46245eefa | ||
|
|
d5e0fd3d7a | ||
|
|
496e246b9e | ||
|
|
e263a45f1c | ||
|
|
edfc977730 | ||
|
|
5910c26b4b | ||
|
|
5b9c506a89 | ||
|
|
913ddd7834 | ||
|
|
397c7ea59a | ||
|
|
6e7b2541e1 | ||
|
|
241c15a452 | ||
|
|
62c5d13aa2 | ||
|
|
3a73c5ce6b | ||
|
|
bf54e8eb0b | ||
|
|
aa2cabedbf | ||
|
|
66878626e1 | ||
|
|
f6f3f3d8b6 |
No files matched your search
@@ -0,0 +1,96 @@
|
||||
# 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.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/spigot_vector.svg" width="64" alt="platform-spigot" title="Tested on Spigot">
|
||||
</a>
|
||||
<a href="https://papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" width="64" alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/bungeecord_vector.svg" width="64" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
</a>
|
||||
<a href="https://www.papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/waterfall_vector.svg" width="64" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
</a>
|
||||
<a href="https://velocitypowered.com" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/velocity_vector.svg" width="64" alt="platform-velocity" title="Tested on Velocity">
|
||||
</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.
|
||||
|
||||
> [*Read More*][profiles]
|
||||
### Conditions
|
||||
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
|
||||
|
||||
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
|
||||
|
||||
> [*Read More*][conditions]
|
||||
### Placeholders
|
||||
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
|
||||
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
|
||||
|
||||
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
|
||||
|
||||
> [*Read More*][placeholders]
|
||||
### Formatting
|
||||
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
|
||||
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
|
||||
|
||||
> [*Read More*][minimessage]
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Platforms | Required? |
|
||||
| ---------------- | ------------- | --------- |
|
||||
| [ProtocolLib] | Spigot | Yes |
|
||||
| [PlaceholderAPI] | Spigot, Paper | No |
|
||||
|
||||
## Statistics
|
||||
|
||||
This plugin sends statistics to [bStats] to display.
|
||||
You can disable this in the global bStats config file located in `/plugins/bstats/`
|
||||
|
||||
- [BungeeCord][bstats-bungee]
|
||||
- [Paper/Spigot][bstats-spigot]
|
||||
- [Velocity][bstats-velocity]
|
||||
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/cozy/documentation/modrinth-gallery_vector.svg" width="208" alt="gallery" title="Check out the Gallery">
|
||||
</a>
|
||||
|
||||
## Support
|
||||
<a href="https://discord.gg/6dazXp6" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/discord-singular_vector.svg" width="64" alt="discord" title="Join my Discord Server">
|
||||
</a>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/revolt-singular_vector.svg" width="64" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/mastodon-singular_vector.svg" width="64" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
|
||||
<!-- Links -->
|
||||
[profiles]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles
|
||||
[conditions]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#conditions
|
||||
[placeholders]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#placeholders
|
||||
[minimessage]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#minimessage
|
||||
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
|
||||
[modrinth]: https://modrinth.com/plugin/advancedserverlist
|
||||
|
||||
[protocollib]: https://www.spigotmc.org/resources/1997/
|
||||
[placeholderapi]: https://www.spigotmc.org/resources/6245/
|
||||
|
||||
[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
|
||||
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# Big thank you to @Kir-Antipov for providing this workflow file.
|
||||
# Check out his mc-publish action here: https://github.com/Kir-Antipov/mc-publish
|
||||
#
|
||||
|
||||
name: Publish Assets
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- prereleased
|
||||
|
||||
jobs:
|
||||
buildJars:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 1.16
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '16'
|
||||
cache: 'maven'
|
||||
- name: Build Jar files
|
||||
run: mvn clean install
|
||||
- name: Save BungeeCord Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-bungeecord
|
||||
path: bungeecord/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Paper Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-paper
|
||||
path: paper/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Spigot Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-spigot
|
||||
path: spigot/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Save Velocity Jar file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: asl-velocity
|
||||
path: velocity/target/AdvancedServerList-*.jar
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
publish:
|
||||
needs: [buildJars]
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- platforms: BungeeCord, Waterfall
|
||||
directory: bungeecord
|
||||
loaders: |
|
||||
bungeecord
|
||||
waterfall
|
||||
- platforms: Paper
|
||||
directory: paper
|
||||
loaders: paper
|
||||
- platforms: Spigot
|
||||
directory: spigot
|
||||
loaders: spigot
|
||||
- platforms: Velocity
|
||||
directory: velocity
|
||||
loaders: velocity
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get Jar files
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: asl-${{ matrix.directory }}
|
||||
path: ${{ matrix.directory }}/target
|
||||
- name: Get Version
|
||||
id: github-release
|
||||
run: |
|
||||
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
|
||||
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
|
||||
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
|
||||
uses: Kir-Antipov/mc-publish@v3.2
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }}) BETA
|
||||
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
|
||||
version-type: beta
|
||||
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
|
||||
files-secondary: ""
|
||||
loaders: ${{ matrix.loaders }}
|
||||
version-resolver: releases
|
||||
game-versions: |
|
||||
1.19
|
||||
1.19.1
|
||||
1.19.2
|
||||
1.19.3
|
||||
java: 16
|
||||
modrinth-id: xss83sOY
|
||||
modrinth-featured: false
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -7,7 +7,9 @@ name: Publish Assets
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
types:
|
||||
- published
|
||||
- released
|
||||
|
||||
jobs:
|
||||
buildJars:
|
||||
@@ -81,12 +83,12 @@ jobs:
|
||||
id: github-release
|
||||
run: |
|
||||
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
|
||||
echo "::set-output name=version::$version"
|
||||
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
|
||||
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
|
||||
uses: Kir-Antipov/mc-publish@v3.2
|
||||
with:
|
||||
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
|
||||
version: ${{ steps.github-release.outputs.version }}
|
||||
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
|
||||
version-type: release
|
||||
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
|
||||
files-secondary: ""
|
||||
@@ -96,6 +98,7 @@ jobs:
|
||||
1.19
|
||||
1.19.1
|
||||
1.19.2
|
||||
1.19.3
|
||||
java: 16
|
||||
modrinth-id: xss83sOY
|
||||
modrinth-featured: false
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
# AdvancedServerList
|
||||
![platform] ![tested]
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/available/modrinth_vector.svg" height="64" align="right" alt="modrinth" title="Available on Modrinth">
|
||||
</a>
|
||||
|
||||
AdvancedServerList is a plugin made for SpigotMC, PaperMC, BungeeCord/Waterfall and Velocity. It allows you to create server list profiles to display based on priority and conditions.
|
||||
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.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
|
||||
</a>
|
||||
<a href="https://papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
|
||||
</a>
|
||||
<a href="https://www.spigotmc.org" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/bungeecord_vector.svg" height="64" alt="platform-bungeecord" title="Tested on BungeeCord">
|
||||
</a>
|
||||
<a href="https://www.papermc.io" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/waterfall_vector.svg" height="64" alt="platform-waterfall" title="Tested on Waterfall">
|
||||
</a>
|
||||
<a href="https://velocitypowered.com" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/velocity_vector.svg" height="64" alt="platform-velocity" title="Tested on Velocity">
|
||||
</a>
|
||||
|
||||
## What is a Server List Profile?
|
||||
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
|
||||
@@ -30,12 +50,6 @@ Only certain options are usable for each option. As an example does motd support
|
||||
|
||||
> [*Read More*][minimessage]
|
||||
|
||||
## Downloads
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/main/badges/modrinth_vector.svg" height="64" />
|
||||
</a>
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Dependency | Platforms | Required? |
|
||||
@@ -55,7 +69,18 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
## Screenshots
|
||||
|
||||
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/main/badges/modrinth-gallery_vector.svg" height="64" />
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" alt="gallery" title="Check out the Gallery">
|
||||
</a>
|
||||
|
||||
## Support
|
||||
<a href="https://discord.gg/6dazXp6" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
|
||||
</a>
|
||||
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/revolt-singular_vector.svg" height="64" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/mastodon-singular_vector.svg" height="64" alt="mastodon" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
|
||||
<!-- Links -->
|
||||
@@ -77,8 +102,3 @@ You can disable this in the global bStats config file located in `/plugins/bstat
|
||||
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
|
||||
|
||||
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
|
||||
|
||||
<!-- Badges -->
|
||||
[platform]: https://img.shields.io/badge/Platforms-Spigot%20%7C%20Paper%20%7C%20BungeeCord%20%7C%20Velocity-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMDYzIDEuNDU2YTEuNzUgMS43NSAwIDAxMS44NzQgMGw4LjM4MyA1LjMxNmExLjc1IDEuNzUgMCAwMTAgMi45NTZsLTguMzgzIDUuMzE2YTEuNzUgMS43NSAwIDAxLTEuODc0IDBMMi42OCA5LjcyOGExLjc1IDEuNzUgMCAwMTAtMi45NTZsOC4zODMtNS4zMTZ6bTEuMDcxIDEuMjY3YS4yNS4yNSAwIDAwLS4yNjggMEwzLjQ4MyA4LjAzOWEuMjUuMjUgMCAwMDAgLjQyMmw4LjM4MyA1LjMxNmEuMjUuMjUgMCAwMC4yNjggMGw4LjM4My01LjMxNmEuMjUuMjUgMCAwMDAtLjQyMmwtOC4zODMtNS4zMTZ6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTIuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTYuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PC9zdmc+
|
||||
|
||||
[tested]: https://img.shields.io/badge/Tested%20Versions-1.19%20%7C%201.19.1%20%7C%201.19.2-blue?style=for-the-badge&logo=image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTE3LjI4IDkuMjhhLjc1Ljc1IDAgMDAtMS4wNi0xLjA2bC01Ljk3IDUuOTctMi40Ny0yLjQ3YS43NS43NSAwIDAwLTEuMDYgMS4wNmwzIDNhLjc1Ljc1IDAgMDAxLjA2IDBsNi41LTYuNXoiPjwvcGF0aD48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjc1IDJBMS43NSAxLjc1IDAgMDAyIDMuNzV2MTYuNWMwIC45NjYuNzg0IDEuNzUgMS43NSAxLjc1aDE2LjVBMS43NSAxLjc1IDAgMDAyMiAyMC4yNVYzLjc1QTEuNzUgMS43NSAwIDAwMjAuMjUgMkgzLjc1ek0zLjUgMy43NWEuMjUuMjUgMCAwMS4yNS0uMjVoMTYuNWEuMjUuMjUgMCAwMS4yNS4yNXYxNi41YS4yNS4yNSAwIDAxLS4yNS4yNUgzLjc1YS4yNS4yNSAwIDAxLS4yNS0uMjVWMy43NXoiPjwvcGF0aD48L3N2Zz4=
|
||||
+5
-1
@@ -103,7 +103,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -123,6 +123,10 @@
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>okhttp3</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.okhttp3</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
|
||||
+6
-1
@@ -30,8 +30,8 @@ import ch.andre601.advancedserverlist.bungeecord.events.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.events.PingEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
|
||||
@@ -122,6 +122,11 @@ public class BungeeCordCore extends Plugin implements ProxyCore<Favicon, ServerP
|
||||
return getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoader(){
|
||||
return "bungeecord";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServerPing.PlayerInfo> createPlayers(List<String> lines, Placeholders... placeholders){
|
||||
List<ServerPing.PlayerInfo> players = new ArrayList<>(lines.size());
|
||||
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.bungeecord.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Favicon>{
|
||||
|
||||
private final BungeeCordCore plugin;
|
||||
private final ProxyPingEvent event;
|
||||
private final ServerPing.Protocol protocol;
|
||||
private final ServerPing ping;
|
||||
|
||||
public BungeeEventWrapper(BungeeCordCore plugin, ProxyPingEvent event){
|
||||
this.plugin = plugin;
|
||||
this.event = event;
|
||||
this.protocol = event.getResponse().getVersion();
|
||||
this.ping = event.getResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
ping.getPlayers().setMax(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayers(){
|
||||
ping.setPlayers(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerCount(String name){
|
||||
protocol.setName(name);
|
||||
protocol.setProtocol(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, GenericPlayer<ProxiedPlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
|
||||
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
|
||||
.toArray(new ServerPing.PlayerInfo[0]);
|
||||
|
||||
if(playerInfos.length > 0)
|
||||
ping.getPlayers().setSample(playerInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavicon(Favicon favicon){
|
||||
ping.setFavicon(favicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFavicon(){
|
||||
ping.setFavicon(ping.getFaviconObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEvent(){
|
||||
this.ping.setVersion(this.protocol);
|
||||
this.event.setResponse(this.ping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return protocol == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return this.protocol.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayers(){
|
||||
return ping.getPlayers().getOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPlayers(){
|
||||
return ping.getPlayers().getMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerIP(){
|
||||
return ((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, GenericPlayer<ProxiedPlayer> player){
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualHost(){
|
||||
return this.resolveHost(event.getConnection().getVirtualHost());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<Favicon> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericPlayer<ProxiedPlayer> createPlayer(String name, int protocol){
|
||||
return new BungeePlayer(name, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
|
||||
return Favicon.create(image);
|
||||
}
|
||||
}
|
||||
+2
-99
@@ -26,24 +26,12 @@
|
||||
package ch.andre601.advancedserverlist.bungeecord.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class PingEvent implements Listener{
|
||||
|
||||
private final BungeeCordCore plugin;
|
||||
@@ -55,91 +43,6 @@ public class PingEvent implements Listener{
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onProxyPing(ProxyPingEvent event){
|
||||
ServerPing ping = event.getResponse();
|
||||
ServerPing.Protocol protocol = ping.getVersion();
|
||||
if(protocol == null)
|
||||
return;
|
||||
|
||||
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(
|
||||
((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString()
|
||||
);
|
||||
InetSocketAddress host = event.getConnection().getVirtualHost();
|
||||
|
||||
int online = ping.getPlayers().getOnline();
|
||||
int max = ping.getPlayers().getMax();
|
||||
|
||||
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new BungeePlayer(playerName, protocol.getProtocol()));
|
||||
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(plugin.getCore())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.getProfile();
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
if(profile.isExtraPlayersEnabled()){
|
||||
max = online + profile.getExtraPlayers();
|
||||
ping.getPlayers().setMax(max);
|
||||
}
|
||||
|
||||
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
if(!profile.getMotd().isEmpty()){
|
||||
TextComponent component = new TextComponent(BungeeComponentSerializer.get().serialize(
|
||||
ComponentParser.list(profile.getMotd())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.toComponent()
|
||||
));
|
||||
|
||||
ping.setDescriptionComponent(component);
|
||||
}
|
||||
|
||||
if(profile.shouldHidePlayers()){
|
||||
ping.setPlayers(null);
|
||||
}
|
||||
|
||||
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
|
||||
protocol.setName(ComponentParser.text(profile.getPlayerCount())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.toString()
|
||||
);
|
||||
protocol.setProtocol(-1);
|
||||
}
|
||||
|
||||
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
|
||||
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
|
||||
.toArray(new ServerPing.PlayerInfo[0]);
|
||||
|
||||
if(playerInfos.length > 0)
|
||||
ping.getPlayers().setSample(playerInfos);
|
||||
}
|
||||
|
||||
if(!profile.getFavicon().isEmpty()){
|
||||
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
|
||||
|
||||
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
|
||||
try{
|
||||
return Favicon.create(image);
|
||||
}catch(Exception ex){
|
||||
plugin.getPluginLogger().warn("Unable to create Favicon. %s", ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if(favicon == null){
|
||||
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
|
||||
ping.setFavicon(ping.getFaviconObject());
|
||||
}else{
|
||||
ping.setFavicon(favicon);
|
||||
}
|
||||
}
|
||||
|
||||
ping.setVersion(protocol);
|
||||
|
||||
event.setResponse(ping);
|
||||
PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
|
||||
}
|
||||
}
|
||||
+41
-5
@@ -43,6 +43,13 @@
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>flexver-repo</id>
|
||||
<url>https://repo.sleeping.town/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
@@ -52,24 +59,47 @@
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>4.11.0</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>4.11.0</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||
<version>4.11.0</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.1.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.unascribed</groupId>
|
||||
<artifactId>flexver-java</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -89,7 +119,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
@@ -101,6 +131,12 @@
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.unascribed</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.check.UpdateChecker;
|
||||
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
|
||||
import ch.andre601.advancedserverlist.core.file.FileHandler;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
@@ -33,7 +34,7 @@ import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class AdvancedServerList{
|
||||
|
||||
@@ -42,6 +43,8 @@ public class AdvancedServerList{
|
||||
private final CommandHandler commandHandler;
|
||||
private final PlayerHandler playerHandler;
|
||||
|
||||
private UpdateChecker updateChecker;
|
||||
|
||||
private String version;
|
||||
|
||||
public AdvancedServerList(PluginCore<?> plugin){
|
||||
@@ -76,6 +79,12 @@ public class AdvancedServerList{
|
||||
public void disable(){
|
||||
getPlugin().getPluginLogger().info("Saving cache.data file...");
|
||||
getPlayerHandler().save();
|
||||
|
||||
if(updateChecker != null){
|
||||
getPlugin().getPluginLogger().info("Disabling Update Checker...");
|
||||
updateChecker.disable();
|
||||
}
|
||||
|
||||
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
|
||||
}
|
||||
|
||||
@@ -88,7 +97,6 @@ public class AdvancedServerList{
|
||||
resolveVersion();
|
||||
|
||||
getPlugin().getPluginLogger().info("Starting AdvancedServerList v%s...", version);
|
||||
|
||||
getPlugin().getPluginLogger().info("Platform: " + plugin.getPlatformName() + " " + plugin.getPlatformVersion());
|
||||
|
||||
if(getFileHandler().loadConfig()){
|
||||
@@ -125,6 +133,9 @@ public class AdvancedServerList{
|
||||
getPlugin().getPluginLogger().info("Metrics loaded!");
|
||||
|
||||
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
|
||||
|
||||
if(getFileHandler().getBoolean("check_updates"))
|
||||
this.updateChecker = new UpdateChecker(this);
|
||||
}
|
||||
|
||||
private void printBanner(){
|
||||
|
||||
+7
-34
@@ -23,42 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles;
|
||||
package ch.andre601.advancedserverlist.core.check;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
public class ProfileManager{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
|
||||
private final Map<String, Object> replacements = new HashMap<>();
|
||||
|
||||
private ProfileManager(AdvancedServerList core){
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public static ProfileManager get(AdvancedServerList core){
|
||||
return new ProfileManager(core);
|
||||
}
|
||||
|
||||
public ProfileManager replacements(Placeholders placeholders){
|
||||
this.replacements.putAll(placeholders.getReplacements());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerListProfile getProfile(){
|
||||
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
|
||||
if(profile.isInvalid())
|
||||
continue;
|
||||
|
||||
if(profile.evalConditions(replacements))
|
||||
return profile;
|
||||
}
|
||||
|
||||
return null;
|
||||
public class UpdateCheckThread implements ThreadFactory{
|
||||
@Override
|
||||
public Thread newThread(@NotNull Runnable r){
|
||||
return new Thread(r, "AdvancedServerList Update-Thread");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 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.check;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.unascribed.flexver.FlexVerComparator;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UpdateChecker{
|
||||
|
||||
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=[\"%s\"]";
|
||||
private final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
private final AdvancedServerList core;
|
||||
private final PluginLogger logger;
|
||||
private final String loader;
|
||||
|
||||
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());
|
||||
|
||||
public UpdateChecker(AdvancedServerList core){
|
||||
this.core = core;
|
||||
this.logger = core.getPlugin().getPluginLogger();
|
||||
this.loader = core.getPlugin().getLoader();
|
||||
|
||||
startUpdateChecker();
|
||||
}
|
||||
|
||||
public void startUpdateChecker(){
|
||||
executor.scheduleAtFixedRate(() -> {
|
||||
logger.info("Checking for a new update...");
|
||||
checkUpdate().whenComplete((version, throwable) -> {
|
||||
if(version == null || throwable != null){
|
||||
logger.warn("Failed to look for any updates. See previous messages for reasons.");
|
||||
return;
|
||||
}
|
||||
|
||||
int result = version.compare(core.getVersion());
|
||||
switch(result){
|
||||
case -1 -> printUpdateBanner(version.getVersionNumber(), version.getId(), version.isRelease());
|
||||
case 0 -> logger.info("No new update found. You're running the latest version!");
|
||||
case 1 -> logger.info(
|
||||
"Your version (%s) is higher than the latest release (%s). Are you running a dev build?",
|
||||
core.getVersion(), version.getVersionNumber()
|
||||
);
|
||||
}
|
||||
});
|
||||
}, 0L, 12L, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
public void disable(){
|
||||
executor.shutdown();
|
||||
try{
|
||||
if(!executor.awaitTermination(1, TimeUnit.SECONDS)){
|
||||
executor.shutdownNow();
|
||||
if(!executor.awaitTermination(1, TimeUnit.SECONDS))
|
||||
logger.warn("Scheduler didn't terminate in time!");
|
||||
}
|
||||
}catch(InterruptedException ex){
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<ModrinthVersion> checkUpdate(){
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
PluginLogger logger = core.getPlugin().getPluginLogger();
|
||||
if(core.getVersion().equals("UNKNOWN")){
|
||||
logger.warn("Cannot perform Update check! Plugin version couldn't be parsed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(String.format(url, loader))
|
||||
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
|
||||
.build();
|
||||
|
||||
try(Response response = client.newCall(request).execute()){
|
||||
if(!response.isSuccessful()){
|
||||
logger.warn("Encountered a non-successful response from Modrinth! Code: %d", response.code());
|
||||
return null;
|
||||
}
|
||||
|
||||
ResponseBody body = response.body();
|
||||
if(body == null){
|
||||
logger.warn("Received an empty Response body from Modrinth!");
|
||||
return null;
|
||||
}
|
||||
|
||||
String responseString = body.string();
|
||||
if(responseString.isEmpty()){
|
||||
logger.warn("Received an empty Response body from Modrinth!");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ModrinthVersion> list = gson.fromJson(responseString, listType);
|
||||
if(list == null || list.isEmpty()){
|
||||
logger.warn("Couldn't convert JSON Array into a valid list.");
|
||||
return null;
|
||||
}
|
||||
|
||||
ModrinthVersion version = list.get(0);
|
||||
|
||||
if(version.getVersionNumber() == null || version.getVersionNumber().isEmpty()){
|
||||
logger.warn("Cannot check latest version. Received version number was null/empty.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return version;
|
||||
}catch(JsonSyntaxException ex){
|
||||
logger.warn("Encountered invalid JSON from Response body!", ex);
|
||||
return null;
|
||||
}catch(IOException ex){
|
||||
logger.warn("Encountered Exception while checking for an update!", ex);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void printUpdateBanner(String version, String versionId, boolean isRelease){
|
||||
logger.info("==================================================================");
|
||||
logger.info("You are running an outdated version of AdvancedServerList!");
|
||||
logger.info("");
|
||||
logger.info("Your version: %s", core.getVersion());
|
||||
logger.info("Modrinth version: %s", version);
|
||||
logger.info("");
|
||||
|
||||
if(!isRelease){
|
||||
logger.info("WARNING: This release is an Alpha/Beta! It may contain");
|
||||
logger.info(" breaking changes!");
|
||||
logger.info("");
|
||||
}
|
||||
|
||||
logger.info("You can download the latest release from here:");
|
||||
logger.info("https://modrinth.com/plugin/advancedserverlist/version/%s", versionId);
|
||||
logger.info("==================================================================");
|
||||
}
|
||||
|
||||
public static class ModrinthVersion{
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
private String id;
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
private String versionNumber;
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
private String versionType;
|
||||
|
||||
public ModrinthVersion(String id, String versionNumber, String versionType){
|
||||
this.id = id;
|
||||
this.versionNumber = versionNumber;
|
||||
this.versionType = versionType;
|
||||
}
|
||||
|
||||
public String getId(){
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getVersionNumber(){
|
||||
return versionNumber;
|
||||
}
|
||||
|
||||
public boolean isRelease(){
|
||||
return versionType.equals("release");
|
||||
}
|
||||
|
||||
public int compare(String version){
|
||||
return FlexVerComparator.compare(version, versionNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 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.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
|
||||
public class PingEventHandler{
|
||||
|
||||
public static <P, F> void handleEvent(GenericEventWrapper<P, F> event){
|
||||
if(event.isInvalidProtocol())
|
||||
return;
|
||||
|
||||
PluginCore<F> plugin = event.getPlugin();
|
||||
|
||||
GenericPlayer<P> player = event.createPlayer(
|
||||
plugin.getCore().getPlayerHandler().getPlayerByIp(event.getPlayerIP()),
|
||||
event.getProtocolVersion()
|
||||
);
|
||||
String host = event.getVirtualHost();
|
||||
|
||||
int online = event.getOnlinePlayers();
|
||||
int max = event.getMaxPlayers();
|
||||
|
||||
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
|
||||
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host);
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(plugin.getCore())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.getProfile();
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
ProfileEntry entry = ProfileManager.merge(profile);
|
||||
|
||||
if(entry.isExtraPlayersEnabled() != null && entry.isExtraPlayersEnabled()){
|
||||
max = online + (entry.getExtraPlayersCount() == null ? 0 : entry.getExtraPlayersCount());
|
||||
event.setMaxPlayers(max);
|
||||
}
|
||||
|
||||
serverPlaceholders = new ServerPlaceholders(online, max, host);
|
||||
|
||||
if(!entry.getMOTD().isEmpty()){
|
||||
event.setMotd(
|
||||
ComponentParser.list(entry.getMOTD())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toComponent()
|
||||
);
|
||||
}
|
||||
|
||||
boolean hidePlayers = entry.isHidePlayersEnabled() != null && entry.isHidePlayersEnabled();
|
||||
|
||||
if(hidePlayers){
|
||||
event.hidePlayers();
|
||||
}
|
||||
|
||||
if(!entry.getPlayerCountText().isEmpty() && !hidePlayers){
|
||||
event.setPlayerCount(
|
||||
ComponentParser.text(entry.getPlayerCountText())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
|
||||
if(!entry.getPlayers().isEmpty() && !hidePlayers){
|
||||
event.setPlayers(entry.getPlayers(), player, playerPlaceholders, serverPlaceholders);
|
||||
}
|
||||
|
||||
if(!entry.getFavicon().isEmpty()){
|
||||
String favicon = StringReplacer.replace(entry.getFavicon(), playerPlaceholders.getReplacements());
|
||||
|
||||
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
|
||||
try{
|
||||
return event.createFavicon(image);
|
||||
}catch(Exception ex){
|
||||
plugin.getPluginLogger().warn("Encountered an Exception while creating Favicon!", ex);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if(fav == null){
|
||||
event.setDefaultFavicon();
|
||||
}else{
|
||||
event.setFavicon(fav);
|
||||
}
|
||||
}
|
||||
|
||||
event.updateEvent();
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,9 @@ package ch.andre601.advancedserverlist.core.file;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
@@ -106,6 +108,7 @@ public class FileHandler{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return reloadProfiles();
|
||||
}
|
||||
|
||||
@@ -127,7 +130,7 @@ public class FileHandler{
|
||||
if(tmp == null)
|
||||
continue;
|
||||
|
||||
profiles.add(new ServerListProfile(tmp, logger));
|
||||
profiles.add(ServerListProfile.Builder.resolve(tmp, logger).build());
|
||||
logger.info("Loaded " + file.getName());
|
||||
}
|
||||
|
||||
@@ -142,6 +145,7 @@ public class FileHandler{
|
||||
|
||||
public ConfigurationNode getConfigurationNode(Path path){
|
||||
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
|
||||
.defaultOptions(opts -> opts.serializers(build -> build.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
|
||||
.path(path)
|
||||
.build();
|
||||
|
||||
@@ -156,4 +160,8 @@ public class FileHandler{
|
||||
public String getString(String def, Object... path){
|
||||
return node.node(path).getString(def);
|
||||
}
|
||||
|
||||
public boolean getBoolean(Object... path){
|
||||
return node.node(path).getBoolean();
|
||||
}
|
||||
}
|
||||
@@ -52,4 +52,6 @@ public interface PluginCore<F>{
|
||||
String getPlatformName();
|
||||
|
||||
String getPlatformVersion();
|
||||
|
||||
String getLoader();
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.interfaces.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public interface GenericEventWrapper<P, F>{
|
||||
|
||||
void setMaxPlayers(int maxPlayers);
|
||||
|
||||
void setMotd(Component component);
|
||||
|
||||
void hidePlayers();
|
||||
|
||||
void setPlayerCount(String name);
|
||||
|
||||
void setPlayers(List<String> players, GenericPlayer<P> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders);
|
||||
|
||||
void setFavicon(F favicon);
|
||||
|
||||
void setDefaultFavicon();
|
||||
|
||||
void updateEvent();
|
||||
|
||||
boolean isInvalidProtocol();
|
||||
|
||||
int getProtocolVersion();
|
||||
|
||||
int getOnlinePlayers();
|
||||
|
||||
int getMaxPlayers();
|
||||
|
||||
String getPlayerIP();
|
||||
|
||||
String parsePAPIPlaceholders(String text, GenericPlayer<P> player);
|
||||
|
||||
String getVirtualHost();
|
||||
|
||||
PluginCore<F> getPlugin();
|
||||
|
||||
GenericPlayer<P> createPlayer(String name, int protocol);
|
||||
|
||||
F createFavicon(BufferedImage image) throws Exception;
|
||||
|
||||
default String resolveHost(InetSocketAddress address){
|
||||
return address == null ? null : address.getHostString();
|
||||
}
|
||||
}
|
||||
+107
-80
@@ -27,125 +27,152 @@ package ch.andre601.advancedserverlist.core.profiles;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.profiles.conditions.Expression;
|
||||
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class ServerListProfile{
|
||||
|
||||
private final int priority;
|
||||
private final List<Expression> expressions;
|
||||
private final ProfileEntry defaultProfile;
|
||||
|
||||
private final List<String> motd;
|
||||
private final List<String> players;
|
||||
private final String playerCount;
|
||||
private final String favicon;
|
||||
private final boolean hidePlayers;
|
||||
private final boolean extraPlayersEnabled;
|
||||
private final int extraPlayers;
|
||||
private final List<ProfileEntry> profiles;
|
||||
|
||||
public ServerListProfile(ConfigurationNode node, PluginLogger logger){
|
||||
this.priority = node.node("priority").getInt();
|
||||
this.expressions = createExpressions(getList(node, false, "conditions"), logger);
|
||||
|
||||
this.motd = getList(node, true, "motd");
|
||||
this.players = getList(node, false, "playerCount", "hover");
|
||||
this.playerCount = node.node("playerCount", "text").getString("");
|
||||
this.favicon = node.node("favicon").getString("");
|
||||
this.hidePlayers = node.node("playerCount", "hidePlayers").getBoolean();
|
||||
this.extraPlayersEnabled = node.node("playerCount", "extraPlayers", "enabled").getBoolean();
|
||||
this.extraPlayers = node.node("playerCount", "extraPlayers", "amount").getInt();
|
||||
private final Random random = new Random();
|
||||
|
||||
public ServerListProfile(int priority, List<Expression> expressions, List<ProfileEntry> profiles, ProfileEntry defaultProfile){
|
||||
this.priority = priority;
|
||||
this.expressions = expressions;
|
||||
this.profiles = profiles;
|
||||
this.defaultProfile = defaultProfile;
|
||||
}
|
||||
|
||||
public int getPriority(){
|
||||
return priority;
|
||||
}
|
||||
|
||||
public List<String> getMotd(){
|
||||
return motd;
|
||||
}
|
||||
|
||||
public List<String> getPlayers(){
|
||||
return players;
|
||||
}
|
||||
|
||||
public String getPlayerCount(){
|
||||
return playerCount;
|
||||
}
|
||||
|
||||
public String getFavicon(){
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public boolean shouldHidePlayers(){
|
||||
return hidePlayers;
|
||||
}
|
||||
|
||||
public boolean isExtraPlayersEnabled(){
|
||||
return extraPlayersEnabled;
|
||||
}
|
||||
|
||||
public int getExtraPlayers(){
|
||||
return extraPlayers;
|
||||
}
|
||||
|
||||
public boolean evalConditions(Map<String, Object> replacements){
|
||||
public boolean evaluateConditions(Map<String, Object> replacements){
|
||||
if(expressions.isEmpty())
|
||||
return true;
|
||||
|
||||
for(Expression expression : expressions){
|
||||
if(!expression.evaluate(replacements)){
|
||||
if(!expression.evaluate(replacements))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isInvalid(){
|
||||
return getMotd().isEmpty() &&
|
||||
getPlayers().isEmpty() &&
|
||||
(getPlayerCount().isEmpty() && !shouldHidePlayers()) &&
|
||||
getFavicon().isEmpty();
|
||||
public ProfileEntry getRandomProfile(){
|
||||
if(profiles.isEmpty()){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(profiles.size() == 1)
|
||||
return profiles.get(0); // No need to run a random for 1 profile.
|
||||
|
||||
synchronized(random){
|
||||
return profiles.get(random.nextInt(profiles.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private List<Expression> createExpressions(List<String> list, PluginLogger logger) {
|
||||
if(list.isEmpty())
|
||||
return Collections.emptyList();
|
||||
public ProfileEntry getDefaultProfile(){
|
||||
return defaultProfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the Profile...
|
||||
* ...doesn't have any valid MOTD set AND
|
||||
* ...doesn't have any player hover set AND
|
||||
* ...doesn't have a player count text set and hidePlayers is false AND
|
||||
* ...doesn't have a favicon set.
|
||||
*/
|
||||
public boolean isInvalidProfile(){
|
||||
boolean profilesValid = false;
|
||||
|
||||
List<Expression> expressions = new ArrayList<>();
|
||||
for(String str : list){
|
||||
Expression expression = new Expression(str);
|
||||
|
||||
if(expression.getResult() != Expression.ExpressionResult.VALID){
|
||||
logger.warn("Detected Invalid condition '%s'! Cause: %s", str, expression.getResult().getMessage());
|
||||
for(ProfileEntry profile : profiles){
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
|
||||
profilesValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return !profilesValid && defaultProfile.isInvalidProfile();
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
|
||||
private final ConfigurationNode node;
|
||||
private final int priority;
|
||||
private final List<Expression> expressions = new ArrayList<>();
|
||||
|
||||
private final PluginLogger logger;
|
||||
|
||||
private List<ProfileEntry> profiles = new ArrayList<>();
|
||||
private ProfileEntry defaultProfile = ProfileEntry.empty();
|
||||
|
||||
private Builder(ConfigurationNode node, PluginLogger logger){
|
||||
this.node = node;
|
||||
this.priority = node.node("priority").getInt();
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public static Builder resolve(ConfigurationNode node, PluginLogger logger){
|
||||
return new Builder(node, logger)
|
||||
.resolveExpressions()
|
||||
.resolveProfiles()
|
||||
.resolveDefaultProfile();
|
||||
}
|
||||
|
||||
private Builder resolveExpressions(){
|
||||
List<String> temp;
|
||||
try{
|
||||
temp = node.node("conditions").getList(String.class);
|
||||
}catch(SerializationException ex){
|
||||
return this;
|
||||
}
|
||||
|
||||
expressions.add(expression);
|
||||
if(temp == null || temp.isEmpty())
|
||||
return this;
|
||||
|
||||
for(String str : temp){
|
||||
Expression expr = new Expression(str);
|
||||
|
||||
if(expr.getResult() != Expression.ExpressionResult.VALID){
|
||||
logger.warn("Found invalid expression in condition '%s'! Reason: %s", str, expr.getResult().getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
this.expressions.add(expr);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
return expressions;
|
||||
}
|
||||
|
||||
private List<String> getList(ConfigurationNode node, boolean trim, Object... path){
|
||||
List<String> list;
|
||||
try{
|
||||
list = node.node(path).getList(String.class);
|
||||
}catch(SerializationException ex){
|
||||
return Collections.emptyList();
|
||||
private Builder resolveProfiles(){
|
||||
try{
|
||||
this.profiles = node.node("profiles").getList(ProfileEntry.class);
|
||||
}catch(SerializationException ignored){}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
if(list == null)
|
||||
return Collections.emptyList();
|
||||
private Builder resolveDefaultProfile(){
|
||||
try{
|
||||
this.defaultProfile = node.get(ProfileEntry.class);
|
||||
}catch(SerializationException ignored){}
|
||||
return this;
|
||||
}
|
||||
|
||||
if(trim && list.size() > 2)
|
||||
return list.subList(0, 2);
|
||||
|
||||
return list;
|
||||
public ServerListProfile build(){
|
||||
return new ServerListProfile(this.priority, this.expressions, this.profiles, this.defaultProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -192,8 +192,8 @@ public class Expression{
|
||||
public enum ExpressionResult{
|
||||
VALID(null),
|
||||
|
||||
INVALID_NO_EXPRESSION ("Received empty condition which isn't allowed!"),
|
||||
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
|
||||
INVALID_NO_EXPRESSION("Received empty condition which isn't allowed!"),
|
||||
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
|
||||
|
||||
private final String message;
|
||||
|
||||
|
||||
+16
-3
@@ -33,7 +33,6 @@ import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
@@ -54,6 +53,12 @@ public class PlayerHandler{
|
||||
core.getPlugin().getPluginLogger().info("No cache.data present. Skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().getBoolean("disable_cache")){
|
||||
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player loading...");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> lines;
|
||||
try{
|
||||
lines = Files.readAllLines(cache);
|
||||
@@ -86,6 +91,11 @@ public class PlayerHandler{
|
||||
core.getPlugin().getPluginLogger().info("No data to save. Skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
if(core.getFileHandler().getBoolean("disable_cache")){
|
||||
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player saving...");
|
||||
return;
|
||||
}
|
||||
|
||||
StringJoiner joiner = new StringJoiner("\n");
|
||||
for(Map.Entry<String, String> entry : players){
|
||||
@@ -93,7 +103,7 @@ public class PlayerHandler{
|
||||
}
|
||||
|
||||
try{
|
||||
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8, StandardOpenOption.WRITE);
|
||||
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8);
|
||||
|
||||
writer.write(joiner.toString());
|
||||
writer.close();
|
||||
@@ -105,13 +115,16 @@ public class PlayerHandler{
|
||||
}
|
||||
|
||||
public void addPlayer(String name, String ip){
|
||||
if(players.containsKey(name))
|
||||
if(players.containsKey(name) || core.getFileHandler().getBoolean("disable_cache"))
|
||||
return;
|
||||
|
||||
players.add(name, ip);
|
||||
}
|
||||
|
||||
public String getPlayerByIp(String ip){
|
||||
if(core.getFileHandler().getBoolean("disable_cache"))
|
||||
core.getFileHandler().getString("Anonymous", "unknown_player");
|
||||
|
||||
for(Map.Entry<String, String> entry : players){
|
||||
if(entry.getValue().equals(ip))
|
||||
return entry.getKey();
|
||||
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.profile;
|
||||
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileEntry{
|
||||
|
||||
private final List<String> motd;
|
||||
private final List<String> players;
|
||||
private final String playerCountText;
|
||||
private final String favicon;
|
||||
private final Boolean hidePlayersEnabled;
|
||||
private final Boolean extraPlayersEnabled;
|
||||
private final Integer extraPlayersCount;
|
||||
|
||||
public ProfileEntry(List<String> motd, List<String> players,
|
||||
String playerCountText, String favicon, Boolean hidePlayersEnabled,
|
||||
Boolean extraPlayersEnabled, Integer extraPlayersCount){
|
||||
this.motd = motd;
|
||||
this.players = players;
|
||||
this.playerCountText = playerCountText;
|
||||
this.favicon = favicon;
|
||||
this.hidePlayersEnabled = hidePlayersEnabled;
|
||||
this.extraPlayersEnabled = extraPlayersEnabled;
|
||||
this.extraPlayersCount = extraPlayersCount;
|
||||
}
|
||||
|
||||
public static ProfileEntry empty(){
|
||||
return new ProfileEntry(Collections.emptyList(), Collections.emptyList(), "", "",
|
||||
false, false, 0);
|
||||
}
|
||||
|
||||
public List<String> getMOTD(){
|
||||
return motd;
|
||||
}
|
||||
|
||||
public List<String> getPlayers(){
|
||||
return players;
|
||||
}
|
||||
|
||||
public String getPlayerCountText(){
|
||||
return playerCountText;
|
||||
}
|
||||
|
||||
public String getFavicon(){
|
||||
return favicon;
|
||||
}
|
||||
|
||||
public Boolean isHidePlayersEnabled(){
|
||||
return hidePlayersEnabled;
|
||||
}
|
||||
|
||||
public Boolean isExtraPlayersEnabled(){
|
||||
return extraPlayersEnabled;
|
||||
}
|
||||
|
||||
public Integer getExtraPlayersCount(){
|
||||
return extraPlayersCount;
|
||||
}
|
||||
|
||||
public boolean isInvalidProfile(){
|
||||
return getMOTD().isEmpty() &&
|
||||
getPlayers().isEmpty() &&
|
||||
(getPlayerCountText().isEmpty() && !isHidePlayersEnabled()) &&
|
||||
getFavicon().isEmpty();
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
|
||||
private final ConfigurationNode node;
|
||||
|
||||
private List<String> motd = new ArrayList<>();
|
||||
private List<String> players = new ArrayList<>();
|
||||
private String playerCountText = null;
|
||||
private String favicon = null;
|
||||
private Boolean hidePlayersEnabled = false;
|
||||
private Boolean extraPlayersEnabled = false;
|
||||
private Integer extraPlayersCount = 0;
|
||||
|
||||
private Builder(ConfigurationNode node){
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public static Builder resolve(ConfigurationNode node){
|
||||
return new Builder(node)
|
||||
.resolveMOTD()
|
||||
.resolvePlayers()
|
||||
.resolvePlayerCountText()
|
||||
.resolveFavicon()
|
||||
.resolveHidePlayersEnabled()
|
||||
.resolveExtraPlayersEnabled()
|
||||
.resolveExtraPlayersCount();
|
||||
}
|
||||
|
||||
public Builder resolveMOTD(){
|
||||
List<String> motd = resolveList(node, "motd");
|
||||
if(motd.size() <= 2){
|
||||
this.motd = motd;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.motd = motd.subList(0, 2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolvePlayers(){
|
||||
this.players = this.resolveList(node, "playerCount", "hover");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolvePlayerCountText(){
|
||||
this.playerCountText = node.node("playerCount", "text").getString("");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveFavicon(){
|
||||
this.favicon = node.node("favicon").getString("");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveHidePlayersEnabled(){
|
||||
if(node.node("playerCount", "hidePlayers").virtual()){
|
||||
this.hidePlayersEnabled = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.hidePlayersEnabled = node.node("playerCount", "hidePlayers").getBoolean();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveExtraPlayersEnabled(){
|
||||
if(node.node("playerCount", "extraPlayers", "enabled").virtual()){
|
||||
this.extraPlayersEnabled = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.extraPlayersEnabled = node.node("playerCount", "extraPlayers", "enabled").getBoolean();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolveExtraPlayersCount(){
|
||||
if(node.node("playerCount", "extraPlayers", "amount").virtual()){
|
||||
this.extraPlayersCount = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
this.extraPlayersCount = node.node("playerCount", "extraPlayers", "amount").getInt();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileEntry build(){
|
||||
return new ProfileEntry(this.motd, this.players, this.playerCountText,
|
||||
this.favicon, this.hidePlayersEnabled, this.extraPlayersEnabled, this.extraPlayersCount);
|
||||
}
|
||||
|
||||
private List<String> resolveList(ConfigurationNode node, Object... path){
|
||||
try{
|
||||
return node.node(path).getList(String.class);
|
||||
}catch(SerializationException ex){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.profile;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProfileManager{
|
||||
|
||||
private final AdvancedServerList core;
|
||||
|
||||
private final Map<String, Object> replacements = new HashMap<>();
|
||||
|
||||
private ProfileManager(AdvancedServerList core){
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public static ProfileManager get(AdvancedServerList core){
|
||||
return new ProfileManager(core);
|
||||
}
|
||||
|
||||
public ProfileManager replacements(Placeholders placeholders){
|
||||
this.replacements.putAll(placeholders.getReplacements());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServerListProfile getProfile(){
|
||||
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
|
||||
if(profile.isInvalidProfile())
|
||||
continue;
|
||||
|
||||
if(profile.evaluateConditions(replacements))
|
||||
return profile;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience method to get a ProfileEntry instance with values merged.
|
||||
* If the random profile's value is not null will it be used instead of the default one.
|
||||
*/
|
||||
public static ProfileEntry merge(ServerListProfile profile){
|
||||
ProfileEntry entry = profile.getRandomProfile();
|
||||
ProfileEntry defEntry = profile.getDefaultProfile();
|
||||
|
||||
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);
|
||||
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
|
||||
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon, isHidePlayersEnabled, isExtraPlayersEnabled,
|
||||
extraPlayersCount);
|
||||
}
|
||||
|
||||
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getMOTD().isEmpty())
|
||||
return defaultProfile.getMOTD();
|
||||
|
||||
return profile.getMOTD();
|
||||
}
|
||||
|
||||
private static List<String> resolvePlayers(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getPlayers().isEmpty())
|
||||
return defaultProfile.getPlayers();
|
||||
|
||||
return profile.getPlayers();
|
||||
}
|
||||
|
||||
private static String resolvePlayerCountText(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getPlayerCountText().isEmpty())
|
||||
return defaultProfile.getPlayerCountText();
|
||||
|
||||
return profile.getPlayerCountText();
|
||||
}
|
||||
|
||||
private static String resolveFavicon(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getFavicon().isEmpty())
|
||||
return defaultProfile.getFavicon();
|
||||
|
||||
return profile.getFavicon();
|
||||
}
|
||||
|
||||
private static Boolean resolveHidePlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.isHidePlayersEnabled() == null)
|
||||
return defaultProfile.isHidePlayersEnabled();
|
||||
|
||||
return profile.isHidePlayersEnabled();
|
||||
}
|
||||
|
||||
private static Boolean resolveExtraPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.isExtraPlayersEnabled() == null)
|
||||
return defaultProfile.isExtraPlayersEnabled();
|
||||
|
||||
return profile.isExtraPlayersEnabled();
|
||||
}
|
||||
|
||||
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
|
||||
if(profile == null || profile.getExtraPlayersCount() == null)
|
||||
return defaultProfile.getExtraPlayersCount();
|
||||
|
||||
return profile.getExtraPlayersCount();
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.core.profiles.profile;
|
||||
|
||||
import 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;
|
||||
|
||||
public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
public static final ProfileSerializer INSTANCE = new ProfileSerializer();
|
||||
|
||||
@Override
|
||||
public ProfileEntry deserialize(Type type, ConfigurationNode node){
|
||||
return ProfileEntry.Builder.resolve(node).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Type type, @Nullable ProfileEntry profile, ConfigurationNode node) throws SerializationException{
|
||||
if(profile == null){
|
||||
node.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
node.node("motd").set(profile.getMOTD());
|
||||
node.node("playerCount", "hover").set(profile.getPlayers());
|
||||
node.node("playerCount", "text").set(profile.getPlayerCountText());
|
||||
node.node("favicon").set(profile.getFavicon());
|
||||
node.node("playerCount", "hidePlayers").set(profile.isHidePlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.isExtraPlayersEnabled());
|
||||
node.node("playerCount", "extraPlayers", "amount").set(profile.getExtraPlayersCount());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,26 @@
|
||||
#
|
||||
# Used for when AdvancedServerList doesn't have a cached player to use for ${player name}
|
||||
#
|
||||
unknown_player: "Anonymous"
|
||||
# Defaults to 'Anonymous' when not present.
|
||||
#
|
||||
unknown_player: "Anonymous"
|
||||
|
||||
#
|
||||
# Should the Caching of players be disabled?
|
||||
#
|
||||
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
|
||||
# Placeholders that rely on the player being cached (such as ${player isWhitelisted}) will not work while this option is enabled.
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
disable_cache: false
|
||||
|
||||
#
|
||||
# Should AdvancedServerList check for new versions?
|
||||
#
|
||||
# When set to true will AdvancedServerList check for a new version on modrinth.com every 12 hours and inform you in the
|
||||
# console about whether it found any new update or not.
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
check_updates: true
|
||||
@@ -16,24 +16,54 @@ priority: 0
|
||||
# - '{playerVersion} < 759'
|
||||
|
||||
#
|
||||
# Set the MOTD that should be displayed.
|
||||
# Option that allows you to define multiple profiles to use.
|
||||
# Each entry supports the same options as the server list profile does. Whenever an option is not present, or set to
|
||||
# an empty value (If supported) would the option in the file be used (if present).
|
||||
# This allows you to f.e. randomize the MOTD while keeping other options the same, without copy-pasting the same options.
|
||||
#
|
||||
# A profile will be selected randomly.
|
||||
#
|
||||
# Remove this option or set it to profiles: [] to use the global options of this file.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#profiles
|
||||
#
|
||||
#profiles:
|
||||
# - motd:
|
||||
# - '<aqua>Line 1'
|
||||
# - '<aqua>Line 2'
|
||||
# favicon: ''
|
||||
# playerCount:
|
||||
# hidePlayers: false
|
||||
# hover:
|
||||
# - '<green>Line 1'
|
||||
# - '<green>Line 2'
|
||||
# - '<green>Line 3'
|
||||
# text: ''
|
||||
# extraPlayers:
|
||||
# enabled: false
|
||||
# amount: 0
|
||||
|
||||
#
|
||||
# Set the default (Global) MOTD used by this server list profile.
|
||||
# Supports HEX colors for 1.16+ servers including gradients using MiniMessage's <gradient:color:color> format.
|
||||
#
|
||||
# Remove this option or set it to motd: [] to not alter the MOTD.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motd
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motds
|
||||
#
|
||||
motd:
|
||||
- '<grey>Line 1'
|
||||
- '<grey>Line 2'
|
||||
|
||||
#
|
||||
# Allows you to set a favicon for this server list profile.
|
||||
# Allows you to set a global (Default) favicon for this server list profile.
|
||||
# You can use one of three possible options:
|
||||
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
|
||||
# 2. A URL pointing to a valid Image
|
||||
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
|
||||
#
|
||||
# Remove this option or set to favicon: '' to not replace the Favicon.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#favicon
|
||||
#
|
||||
favicon: ''
|
||||
@@ -50,12 +80,15 @@ playerCount:
|
||||
#
|
||||
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
|
||||
#
|
||||
# Defaults to false when not present.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
|
||||
#
|
||||
hidePlayers: false
|
||||
#
|
||||
# Sets the text displayed when hovering over the player count.
|
||||
# You can set this to 'hover: []' or remove the option to not modify the hover text.
|
||||
#
|
||||
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hover
|
||||
#
|
||||
@@ -69,7 +102,7 @@ playerCount:
|
||||
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
|
||||
# This is nothing that can be fixed or avoided and would require changes from Mojang.
|
||||
#
|
||||
# You can set this to 'count: ''' or remove the option to not modify the player count text.
|
||||
# Remove this option or set it to text: '' to not modify the player count text.
|
||||
#
|
||||
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#text
|
||||
#
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 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.test;
|
||||
|
||||
import com.unascribed.flexver.FlexVerComparator;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FlexVerTests{
|
||||
|
||||
private final String baseVersion = "1.0.0";
|
||||
private final String versionMinor = "1.0.1";
|
||||
private final String versionMajor = "1.1.0";
|
||||
private final String versionBoth = "1.1.1";
|
||||
|
||||
private final String versionBeta = "1.0.0-b1";
|
||||
private final String versionBetaMinor = "1.0.1-b1";
|
||||
private final String versionBetaMajor = "1.1.0-b1";
|
||||
private final String versionBetaBoth = "1.1.1-b1";
|
||||
|
||||
private final String versionBeta2 = "1.0.0-b2";
|
||||
private final String versionBeta2Minor = "1.0.1-b2";
|
||||
private final String versionBeta2Major = "1.1.0-b2";
|
||||
private final String versionBeta2Both = "1.1.1-b2";
|
||||
|
||||
@Test
|
||||
public void testFlexVerChecks(){
|
||||
System.out.println("START: Version comparison Tests");
|
||||
|
||||
compareBaseVersion();
|
||||
compareMinorVersion();
|
||||
compareMajorVersion();
|
||||
compareBothVersion();
|
||||
|
||||
compareBetaVersion();
|
||||
compareBetaMinorVersion();
|
||||
compareBetaMajorVersion();
|
||||
compareBetaBothVersion();
|
||||
|
||||
compareBeta2Version();
|
||||
compareBeta2MinorVersion();
|
||||
compareBeta2MajorVersion();
|
||||
compareBeta2BothVersion();
|
||||
|
||||
System.out.println("END: Version comparison Tests");
|
||||
}
|
||||
|
||||
private void compareBaseVersion(){
|
||||
System.out.println("┌────────────────────────────────┐");
|
||||
System.out.println("│ Normal Version │");
|
||||
System.out.println("│ │");
|
||||
compare(baseVersion, "=", baseVersion, 0);
|
||||
compare(baseVersion, "<", versionMinor, -1);
|
||||
compare(baseVersion, "<", versionMajor, -1);
|
||||
compare(baseVersion, "<", versionBoth, -1);
|
||||
compare(baseVersion, ">", versionBeta, 1);
|
||||
compare(baseVersion, "<", versionBetaMinor, -1);
|
||||
compare(baseVersion, "<", versionBetaMajor, -1);
|
||||
compare(baseVersion, "<", versionBetaBoth, -1);
|
||||
compare(baseVersion, ">", versionBeta2, 1);
|
||||
compare(baseVersion, "<", versionBeta2Minor, -1);
|
||||
compare(baseVersion, "<", versionBeta2Major, -1);
|
||||
compare(baseVersion, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareMinorVersion(){
|
||||
System.out.println("│ Minor Version │");
|
||||
System.out.println("│ │");
|
||||
compare(versionMinor, ">", baseVersion, 1);
|
||||
compare(versionMinor, "=", versionMinor, 0);
|
||||
compare(versionMinor, "<", versionMajor, -1);
|
||||
compare(versionMinor, "<", versionBoth, -1);
|
||||
compare(versionMinor, ">", versionBeta, 1);
|
||||
compare(versionMinor, ">", versionBetaMinor, 1);
|
||||
compare(versionMinor, "<", versionBetaMajor, -1);
|
||||
compare(versionMinor, "<", versionBetaBoth, -1);
|
||||
compare(versionMinor, ">", versionBeta2, 1);
|
||||
compare(versionMinor, ">", versionBeta2Minor, 1);
|
||||
compare(versionMinor, "<", versionBeta2Major, -1);
|
||||
compare(versionMinor, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareMajorVersion(){
|
||||
System.out.println("│ Major Version │");
|
||||
System.out.println("│ │");
|
||||
compare(versionMajor, ">", baseVersion, 1);
|
||||
compare(versionMajor, ">", versionMinor, 1);
|
||||
compare(versionMajor, "=", versionMajor, 0);
|
||||
compare(versionMajor, "<", versionBoth, -1);
|
||||
compare(versionMajor, ">", versionBeta, 1);
|
||||
compare(versionMajor, ">", versionBetaMinor, 1);
|
||||
compare(versionMajor, ">", versionBetaMajor, 1);
|
||||
compare(versionMajor, "<", versionBetaBoth, -1);
|
||||
compare(versionMajor, ">", versionBeta2, 1);
|
||||
compare(versionMajor, ">", versionBeta2Minor, 1);
|
||||
compare(versionMajor, ">", versionBeta2Major, 1);
|
||||
compare(versionMajor, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBothVersion(){
|
||||
System.out.println("│ Major + Minor Version │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBoth, ">", baseVersion, 1);
|
||||
compare(versionBoth, ">", versionMinor, 1);
|
||||
compare(versionBoth, ">", versionMajor, 1);
|
||||
compare(versionBoth, "=", versionBoth, 0);
|
||||
compare(versionBoth, ">", versionBeta, 1);
|
||||
compare(versionBoth, ">", versionBetaMinor, 1);
|
||||
compare(versionBoth, ">", versionBetaMajor, 1);
|
||||
compare(versionBoth, ">", versionBetaBoth, 1);
|
||||
compare(versionBoth, ">", versionBeta2, 1);
|
||||
compare(versionBoth, ">", versionBeta2Minor, 1);
|
||||
compare(versionBoth, ">", versionBeta2Major, 1);
|
||||
compare(versionBoth, ">", versionBeta2Both, 1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBetaVersion(){
|
||||
System.out.println("│ Beta Version │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBeta, "<", baseVersion, -1);
|
||||
compare(versionBeta, "<", versionMinor, -1);
|
||||
compare(versionBeta, "<", versionMajor, -1);
|
||||
compare(versionBeta, "<", versionBoth, -1);
|
||||
compare(versionBeta, "=", versionBeta, 0);
|
||||
compare(versionBeta, "<", versionBetaMinor, -1);
|
||||
compare(versionBeta, "<", versionBetaMajor, -1);
|
||||
compare(versionBeta, "<", versionBetaBoth, -1);
|
||||
compare(versionBeta, "<", versionBeta2, -1);
|
||||
compare(versionBeta, "<", versionBeta2Minor, -1);
|
||||
compare(versionBeta, "<", versionBeta2Major, -1);
|
||||
compare(versionBeta, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBetaMinorVersion(){
|
||||
System.out.println("│ Beta Version Minor │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBetaMinor, ">", baseVersion, 1);
|
||||
compare(versionBetaMinor, "<", versionMinor, -1);
|
||||
compare(versionBetaMinor, "<", versionMajor, -1);
|
||||
compare(versionBetaMinor, "<", versionBoth, -1);
|
||||
compare(versionBetaMinor, ">", versionBeta, 1);
|
||||
compare(versionBetaMinor, "=", versionBetaMinor, 0);
|
||||
compare(versionBetaMinor, "<", versionBetaMajor, -1);
|
||||
compare(versionBetaMinor, "<", versionBetaBoth, -1);
|
||||
compare(versionBetaMinor, ">", versionBeta2, 1);
|
||||
compare(versionBetaMinor, "<", versionBeta2Minor, -1);
|
||||
compare(versionBetaMinor, "<", versionBeta2Major, -1);
|
||||
compare(versionBetaMinor, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBetaMajorVersion(){
|
||||
System.out.println("│ Beta Version Major │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBetaMajor, ">", baseVersion, 1);
|
||||
compare(versionBetaMajor, ">", versionMinor, 1);
|
||||
compare(versionBetaMajor, "<", versionMajor, -1);
|
||||
compare(versionBetaMajor, "<", versionBoth, -1);
|
||||
compare(versionBetaMajor, ">", versionBeta, 1);
|
||||
compare(versionBetaMajor, ">", versionBetaMinor, 1);
|
||||
compare(versionBetaMajor, "=", versionBetaMajor, 0);
|
||||
compare(versionBetaMajor, "<", versionBetaBoth, -1);
|
||||
compare(versionBetaMajor, ">", versionBeta2, 1);
|
||||
compare(versionBetaMajor, ">", versionBeta2Minor, 1);
|
||||
compare(versionBetaMajor, "<", versionBeta2Major, -1);
|
||||
compare(versionBetaMajor, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBetaBothVersion(){
|
||||
System.out.println("│ Beta Version Major + Minor │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBetaBoth, ">", baseVersion, 1);
|
||||
compare(versionBetaBoth, ">", versionMinor, 1);
|
||||
compare(versionBetaBoth, ">", versionMajor, 1);
|
||||
compare(versionBetaBoth, "<", versionBoth, -1);
|
||||
compare(versionBetaBoth, ">", versionBeta, 1);
|
||||
compare(versionBetaBoth, ">", versionBetaMinor, 1);
|
||||
compare(versionBetaBoth, ">", versionBetaMajor, 1);
|
||||
compare(versionBetaBoth, "=", versionBetaBoth, 0);
|
||||
compare(versionBetaBoth, ">", versionBeta2, 1);
|
||||
compare(versionBetaBoth, ">", versionBeta2Minor, 1);
|
||||
compare(versionBetaBoth, ">", versionBeta2Major, 1);
|
||||
compare(versionBetaBoth, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBeta2Version(){
|
||||
System.out.println("│ Beta Version 2 │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBeta2, "<", baseVersion, -1);
|
||||
compare(versionBeta2, "<", versionMinor, -1);
|
||||
compare(versionBeta2, "<", versionMajor, -1);
|
||||
compare(versionBeta2, "<", versionBoth, -1);
|
||||
compare(versionBeta2, ">", versionBeta, 1);
|
||||
compare(versionBeta2, "<", versionBetaMinor, -1);
|
||||
compare(versionBeta2, "<", versionBetaMajor, -1);
|
||||
compare(versionBeta2, "<", versionBetaBoth, -1);
|
||||
compare(versionBeta2, "=", versionBeta2, 0);
|
||||
compare(versionBeta2, "<", versionBeta2Minor, -1);
|
||||
compare(versionBeta2, "<", versionBeta2Major, -1);
|
||||
compare(versionBeta2, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBeta2MinorVersion(){
|
||||
System.out.println("│ Beta Version 2 Minor │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBeta2Minor, ">", baseVersion, 1);
|
||||
compare(versionBeta2Minor, "<", versionMinor, -1);
|
||||
compare(versionBeta2Minor, "<", versionMajor, -1);
|
||||
compare(versionBeta2Minor, "<", versionBoth, -1);
|
||||
compare(versionBeta2Minor, ">", versionBeta, 1);
|
||||
compare(versionBeta2Minor, ">", versionBetaMinor, 1);
|
||||
compare(versionBeta2Minor, "<", versionBetaMajor, -1);
|
||||
compare(versionBeta2Minor, "<", versionBetaBoth, -1);
|
||||
compare(versionBeta2Minor, ">", versionBeta2, 1);
|
||||
compare(versionBeta2Minor, "=", versionBeta2Minor, 0);
|
||||
compare(versionBeta2Minor, "<", versionBeta2Major, -1);
|
||||
compare(versionBeta2Minor, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBeta2MajorVersion(){
|
||||
System.out.println("│ Beta Version 2 Major │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBeta2Major, ">", baseVersion, 1);
|
||||
compare(versionBeta2Major, ">", versionMinor, 1);
|
||||
compare(versionBeta2Major, "<", versionMajor, -1);
|
||||
compare(versionBeta2Major, "<", versionBoth, -1);
|
||||
compare(versionBeta2Major, ">", versionBeta, 1);
|
||||
compare(versionBeta2Major, ">", versionBetaMinor, 1);
|
||||
compare(versionBeta2Major, ">", versionBetaMajor, 1);
|
||||
compare(versionBeta2Major, "<", versionBetaBoth, -1);
|
||||
compare(versionBeta2Major, ">", versionBeta2, 1);
|
||||
compare(versionBeta2Major, ">", versionBeta2Minor, 1);
|
||||
compare(versionBeta2Major, "=", versionBeta2Major, 0);
|
||||
compare(versionBeta2Major, "<", versionBeta2Both, -1);
|
||||
System.out.println("├────────────────────────────────┤");
|
||||
}
|
||||
|
||||
private void compareBeta2BothVersion(){
|
||||
System.out.println("│ Beta Version 2 Major + Minor │");
|
||||
System.out.println("│ │");
|
||||
compare(versionBeta2Both, ">", baseVersion, 1);
|
||||
compare(versionBeta2Both, ">", versionMinor, 1);
|
||||
compare(versionBeta2Both, ">", versionMajor, 1);
|
||||
compare(versionBeta2Both, "<", versionBoth, -1);
|
||||
compare(versionBeta2Both, ">", versionBeta, 1);
|
||||
compare(versionBeta2Both, ">", versionBetaMinor, 1);
|
||||
compare(versionBeta2Both, ">", versionBetaMajor, 1);
|
||||
compare(versionBeta2Both, ">", versionBetaBoth, 1);
|
||||
compare(versionBeta2Both, ">", versionBeta2, 1);
|
||||
compare(versionBeta2Both, ">", versionBeta2Minor, 1);
|
||||
compare(versionBeta2Both, ">", versionBeta2Major, 1);
|
||||
compare(versionBeta2Both, "=", versionBeta2Both, 0);
|
||||
System.out.println("└────────────────────────────────┘");
|
||||
}
|
||||
|
||||
private void compare(String version1, String comparator, String version2, int expected){
|
||||
String expression = version1 + " " + comparator + " " + version2 + "?";
|
||||
|
||||
System.out.printf("│ %-24s %5b │\n", expression, FlexVerComparator.compare(version1, version2) == expected);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -101,7 +101,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
|
||||
@@ -156,8 +156,9 @@ public class PaperCore extends JavaPlugin implements ServerCore<CachedServerIcon
|
||||
return getServer().getVersion();
|
||||
}
|
||||
|
||||
private void enable(){
|
||||
this.core = new AdvancedServerList(this);
|
||||
@Override
|
||||
public String getLoader(){
|
||||
return "paper";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,4 +182,8 @@ public class PaperCore extends JavaPlugin implements ServerCore<CachedServerIcon
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
private void enable(){
|
||||
this.core = new AdvancedServerList(this);
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.paper.PaperCore;
|
||||
import ch.andre601.advancedserverlist.paper.PaperPlayer;
|
||||
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
|
||||
public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, CachedServerIcon>{
|
||||
|
||||
private final PaperCore plugin;
|
||||
private final PaperServerListPingEvent event;
|
||||
|
||||
public PaperEventWrapper(PaperCore plugin, PaperServerListPingEvent event){
|
||||
this.plugin = plugin;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
event.setMaxPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
event.motd(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayers(){
|
||||
event.setHidePlayers(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerCount(String name){
|
||||
event.setVersion(name);
|
||||
event.setProtocolVersion(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
|
||||
event.getPlayerSample().clear();
|
||||
|
||||
event.getPlayerSample().addAll(
|
||||
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavicon(CachedServerIcon favicon){
|
||||
event.setServerIcon(favicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFavicon(){
|
||||
event.setServerIcon(event.getServerIcon());
|
||||
}
|
||||
|
||||
// Not used in Paper
|
||||
@Override
|
||||
public void updateEvent(){}
|
||||
|
||||
// Not used in Paper
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return event.getClient().getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayers(){
|
||||
return event.getNumPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPlayers(){
|
||||
return event.getMaxPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerIP(){
|
||||
return event.getClient().getAddress().getHostString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualHost(){
|
||||
return this.resolveHost(event.getClient().getVirtualHost());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<CachedServerIcon> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
|
||||
OfflinePlayer player = Bukkit.getPlayerExact(name);
|
||||
|
||||
if(player == null){
|
||||
player = Bukkit.getOfflinePlayer(name);
|
||||
|
||||
return new PaperPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
|
||||
}
|
||||
|
||||
return new PaperPlayer(player, name, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedServerIcon createFavicon(BufferedImage image) throws Exception{
|
||||
return Bukkit.loadServerIcon(image);
|
||||
}
|
||||
}
|
||||
@@ -25,23 +25,11 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.paper.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.paper.PaperCore;
|
||||
import ch.andre601.advancedserverlist.paper.PaperPlayer;
|
||||
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class PingEvent implements Listener{
|
||||
|
||||
@@ -54,101 +42,6 @@ public class PingEvent implements Listener{
|
||||
|
||||
@EventHandler
|
||||
public void onServerPing(PaperServerListPingEvent event){
|
||||
InetSocketAddress address = event.getClient().getAddress();
|
||||
InetSocketAddress host = event.getClient().getVirtualHost();
|
||||
|
||||
PaperPlayer player = resolvePlayer(address, event.getClient().getProtocolVersion());
|
||||
|
||||
int online = event.getNumPlayers();
|
||||
int max = event.getMaxPlayers();
|
||||
|
||||
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
|
||||
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(plugin.getCore())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.getProfile();
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
if(profile.isExtraPlayersEnabled()){
|
||||
max = online + profile.getExtraPlayers();
|
||||
event.setMaxPlayers(max);
|
||||
}
|
||||
|
||||
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
if(!profile.getMotd().isEmpty()){
|
||||
event.motd(ComponentParser.list(profile.getMotd())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> {
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toComponent());
|
||||
}
|
||||
|
||||
if(profile.shouldHidePlayers()){
|
||||
event.setHidePlayers(true);
|
||||
}
|
||||
|
||||
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
|
||||
event.setVersion(ComponentParser.text(profile.getPlayerCount())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> {
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toString());
|
||||
event.setProtocolVersion(-1);
|
||||
}
|
||||
|
||||
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
|
||||
event.getPlayerSample().clear();
|
||||
|
||||
event.getPlayerSample().addAll(
|
||||
plugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
|
||||
);
|
||||
}
|
||||
|
||||
if(!profile.getFavicon().isEmpty()){
|
||||
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
|
||||
|
||||
CachedServerIcon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
|
||||
try{
|
||||
return Bukkit.loadServerIcon(image);
|
||||
}catch(Exception ex){
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if(favicon == null){
|
||||
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
|
||||
event.setServerIcon(event.getServerIcon());
|
||||
}else{
|
||||
event.setServerIcon(favicon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PaperPlayer resolvePlayer(InetSocketAddress address, int protocol){
|
||||
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
|
||||
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
|
||||
|
||||
if(player == null){
|
||||
player = Bukkit.getOfflinePlayer(playerName);
|
||||
|
||||
return new PaperPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
|
||||
}
|
||||
|
||||
return new PaperPlayer(player, playerName, protocol);
|
||||
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@ main: 'ch.andre601.advancedserverlist.paper.PaperCore'
|
||||
|
||||
api-version: 1.19
|
||||
|
||||
libraries:
|
||||
- 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
|
||||
softdepend:
|
||||
- 'PlaceholderAPI'
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<plugin.version>1.6.2</plugin.version>
|
||||
<plugin.version>1.10.1</plugin.version>
|
||||
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
|
||||
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>velocity</module>
|
||||
<module>bungeecord</module>
|
||||
<module>paper</module>
|
||||
<module>spigot</module>
|
||||
<module>velocity</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
+1
-1
@@ -74,7 +74,7 @@
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<version>4.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
|
||||
@@ -141,6 +141,11 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
|
||||
return getServer().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoader(){
|
||||
return "spigot";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WrappedGameProfile> createPlayers(List<String> lines, OfflinePlayer player, Placeholders... placeholders){
|
||||
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
|
||||
|
||||
@@ -25,39 +25,26 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PingEvent implements Listener{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
private final ProtocolManager protocolManager;
|
||||
|
||||
private final Map<String, String> hostAddresses = new HashMap<>();
|
||||
|
||||
public PingEvent(SpigotCore plugin, ProtocolManager protocolManager){
|
||||
this.plugin = plugin;
|
||||
this.protocolManager = protocolManager;
|
||||
|
||||
loadPacketListener(plugin);
|
||||
@@ -80,106 +67,8 @@ public class PingEvent implements Listener{
|
||||
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event){
|
||||
WrappedServerPing ping = event.getPacket().getServerPings().read(0);
|
||||
InetSocketAddress address = event.getPlayer().getAddress();
|
||||
if(address == null)
|
||||
return;
|
||||
|
||||
SpigotPlayer player = resolvePlayer(address, ping.getVersionProtocol());
|
||||
|
||||
int online = ping.getPlayersOnline();
|
||||
int max = ping.getPlayersMaximum();
|
||||
|
||||
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
|
||||
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(spigotPlugin.getCore())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.getProfile();
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
if(profile.isExtraPlayersEnabled()){
|
||||
max = online + profile.getExtraPlayers();
|
||||
ping.setPlayersMaximum(max);
|
||||
}
|
||||
|
||||
serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
|
||||
|
||||
if(!profile.getMotd().isEmpty()){
|
||||
Component component = ComponentParser.list(profile.getMotd())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> {
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toComponent();
|
||||
ping.setMotD(AdventureComponentConverter.fromComponent(component));
|
||||
}
|
||||
|
||||
if(profile.shouldHidePlayers()){
|
||||
ping.setPlayersVisible(false);
|
||||
}
|
||||
|
||||
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
|
||||
ping.setVersionName(ComponentParser.text(profile.getPlayerCount())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.modifyText(text -> {
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toString()
|
||||
);
|
||||
ping.setVersionProtocol(-1);
|
||||
}
|
||||
|
||||
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
|
||||
ping.setPlayers(
|
||||
spigotPlugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
|
||||
);
|
||||
}
|
||||
|
||||
if(!profile.getFavicon().isEmpty()){
|
||||
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
|
||||
|
||||
WrappedServerPing.CompressedImage favicon = spigotPlugin.getFaviconHandler().getFavicon(favName, image -> {
|
||||
try{
|
||||
return WrappedServerPing.CompressedImage.fromPng(image);
|
||||
}catch(Exception ex){
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if(favicon == null){
|
||||
spigotPlugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
|
||||
ping.setFavicon(ping.getFavicon());
|
||||
}else{
|
||||
ping.setFavicon(favicon);
|
||||
}
|
||||
}
|
||||
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event, hostAddresses));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private SpigotPlayer resolvePlayer(InetSocketAddress address, int protocol){
|
||||
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
|
||||
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
|
||||
|
||||
if(player == null){
|
||||
//noinspection deprecation
|
||||
player = Bukkit.getOfflinePlayer(playerName);
|
||||
|
||||
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
|
||||
}
|
||||
|
||||
return new SpigotPlayer(player, playerName, protocol);
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Andre_601
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.andre601.advancedserverlist.spigot.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotCore;
|
||||
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlayer, WrappedServerPing.CompressedImage>{
|
||||
|
||||
private final SpigotCore plugin;
|
||||
private final PacketEvent event;
|
||||
private final WrappedServerPing ping;
|
||||
|
||||
private final Map<String, String> hostAddresses;
|
||||
|
||||
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event, Map<String, String> hostAddresses){
|
||||
this.plugin = plugin;
|
||||
this.event = event;
|
||||
this.ping = event.getPacket().getServerPings().read(0);
|
||||
|
||||
this.hostAddresses = hostAddresses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
ping.setPlayersMaximum(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setMotD(AdventureComponentConverter.fromComponent(component));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayers(){
|
||||
ping.setPlayersVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerCount(String name){
|
||||
ping.setVersionName(name);
|
||||
ping.setVersionProtocol(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
|
||||
ping.setPlayers(
|
||||
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavicon(WrappedServerPing.CompressedImage favicon){
|
||||
ping.setFavicon(favicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFavicon(){
|
||||
ping.setFavicon(ping.getFavicon());
|
||||
}
|
||||
|
||||
// Not used in ProtocolLib
|
||||
@Override
|
||||
public void updateEvent(){}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return event.getPlayer().getAddress() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return ping.getVersionProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayers(){
|
||||
return ping.getPlayersOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPlayers(){
|
||||
return ping.getPlayersMaximum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerIP(){
|
||||
return event.getPlayer().getAddress() == null ? "UNKNOWN" : event.getPlayer().getAddress().getHostString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
|
||||
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualHost(){
|
||||
String host = this.resolveHost(event.getPlayer().getAddress());
|
||||
if(host == null)
|
||||
return null;
|
||||
|
||||
return hostAddresses.get(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<WrappedServerPing.CompressedImage> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
|
||||
OfflinePlayer player = Bukkit.getPlayerExact(name);
|
||||
|
||||
if(player == null){
|
||||
//noinspection deprecation
|
||||
player = Bukkit.getOfflinePlayer(name);
|
||||
|
||||
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
|
||||
}
|
||||
|
||||
return new SpigotPlayer(player, name, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedServerPing.CompressedImage createFavicon(BufferedImage image) throws Exception{
|
||||
return WrappedServerPing.CompressedImage.fromPng(image);
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,11 @@ api-version: 1.19
|
||||
|
||||
libraries:
|
||||
- 'org.spongepowered:configurate-yaml:4.1.2'
|
||||
- 'net.kyori:adventure-api:4.11.0'
|
||||
- 'net.kyori:adventure-text-minimessage:4.11.0'
|
||||
- 'net.kyori:adventure-text-serializer-legacy:4.11.0'
|
||||
- 'net.kyori:adventure-platform-bukkit:4.1.2'
|
||||
- 'net.kyori:adventure-api:4.12.0'
|
||||
- 'net.kyori:adventure-text-minimessage:4.12.0'
|
||||
- 'net.kyori:adventure-text-serializer-legacy:4.12.0'
|
||||
- 'net.kyori:adventure-platform-bukkit:4.2.0'
|
||||
- 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
|
||||
softdepend:
|
||||
- 'ProtocolLib'
|
||||
|
||||
+5
-1
@@ -88,7 +88,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<relocations>
|
||||
@@ -104,6 +104,10 @@
|
||||
<pattern>com.github.benmanes.caffeine</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.caffeine</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>okhttp3</pattern>
|
||||
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.okhttp3</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
package ch.andre601.advancedserverlist.velocity;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
|
||||
@@ -162,6 +162,11 @@ public class VelocityCore implements ProxyCore<Favicon, ServerPing.SamplePlayer>
|
||||
return getProxy().getVersion().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoader(){
|
||||
return "velocity";
|
||||
}
|
||||
|
||||
public ProxyServer getProxy(){
|
||||
return proxy;
|
||||
}
|
||||
|
||||
+2
-92
@@ -25,22 +25,11 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.velocity.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
|
||||
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityCore;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
|
||||
import com.velocitypowered.api.event.PostOrder;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public class PingEvent{
|
||||
|
||||
@@ -53,85 +42,6 @@ public class PingEvent{
|
||||
|
||||
@Subscribe(order = PostOrder.EARLY)
|
||||
public void onProxyPing(ProxyPingEvent event){
|
||||
ServerPing ping = event.getPing();
|
||||
ServerPing.Version protocol = ping.getVersion();
|
||||
if(protocol == null)
|
||||
return;
|
||||
|
||||
ServerPing.Builder builder = ping.asBuilder();
|
||||
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(event.getConnection().getRemoteAddress().getHostString());
|
||||
InetSocketAddress host = event.getConnection().getVirtualHost().orElse(null);
|
||||
|
||||
int online = builder.getOnlinePlayers();
|
||||
int max = builder.getMaximumPlayers();
|
||||
|
||||
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new VelocityPlayer(playerName, protocol.getProtocol()));
|
||||
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
ServerListProfile profile = ProfileManager.get(plugin.getCore())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.getProfile();
|
||||
|
||||
if(profile == null)
|
||||
return;
|
||||
|
||||
if(profile.isExtraPlayersEnabled()){
|
||||
max = online + profile.getExtraPlayers();
|
||||
builder.maximumPlayers(max);
|
||||
}
|
||||
|
||||
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
|
||||
|
||||
if(!profile.getMotd().isEmpty()){
|
||||
List<String> motd = profile.getMotd();
|
||||
builder.description(ComponentParser.list(motd)
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.toComponent()
|
||||
);
|
||||
}
|
||||
|
||||
if(profile.shouldHidePlayers()){
|
||||
builder.nullPlayers();
|
||||
}
|
||||
|
||||
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
|
||||
builder.version(new ServerPing.Version(
|
||||
-1,
|
||||
ComponentParser.text(profile.getPlayerCount())
|
||||
.replacements(playerPlaceholders)
|
||||
.replacements(serverPlaceholders)
|
||||
.toString()
|
||||
));
|
||||
}
|
||||
|
||||
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
|
||||
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
|
||||
.toArray(new ServerPing.SamplePlayer[0]);
|
||||
|
||||
if(playerSamples.length > 0)
|
||||
builder.clearSamplePlayers().samplePlayers(playerSamples);
|
||||
}
|
||||
|
||||
if(!profile.getFavicon().isEmpty()){
|
||||
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
|
||||
|
||||
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
|
||||
try{
|
||||
return Favicon.create(image);
|
||||
}catch(Exception ex){
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if(favicon == null){
|
||||
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
|
||||
}else{
|
||||
builder.favicon(favicon);
|
||||
}
|
||||
}
|
||||
|
||||
event.setPing(builder.build());
|
||||
PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
|
||||
}
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 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.velocity.events;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
|
||||
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityCore;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
|
||||
public class VelocityEventWrapper implements GenericEventWrapper<Player, Favicon>{
|
||||
|
||||
private final VelocityCore plugin;
|
||||
private final ProxyPingEvent event;
|
||||
private final ServerPing.Builder builder;
|
||||
private final ServerPing.Version protocol;
|
||||
|
||||
public VelocityEventWrapper(VelocityCore plugin, ProxyPingEvent event){
|
||||
this.plugin = plugin;
|
||||
this.event = event;
|
||||
this.builder = event.getPing().asBuilder();
|
||||
this.protocol = event.getPing().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxPlayers(int maxPlayers){
|
||||
builder.maximumPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
builder.description(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayers(){
|
||||
builder.nullPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerCount(String name){
|
||||
builder.version(new ServerPing.Version(-1, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(List<String> players, GenericPlayer<Player> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
|
||||
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
|
||||
.toArray(new ServerPing.SamplePlayer[0]);
|
||||
|
||||
if(playerSamples.length > 0)
|
||||
builder.clearSamplePlayers().samplePlayers(playerSamples);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFavicon(Favicon favicon){
|
||||
builder.favicon(favicon);
|
||||
}
|
||||
|
||||
// Not used in Velocity
|
||||
@Override
|
||||
public void setDefaultFavicon(){}
|
||||
|
||||
@Override
|
||||
public void updateEvent(){
|
||||
event.setPing(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidProtocol(){
|
||||
return protocol == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersion(){
|
||||
return protocol.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayers(){
|
||||
return builder.getOnlinePlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPlayers(){
|
||||
return builder.getMaximumPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerIP(){
|
||||
return event.getConnection().getRemoteAddress().getHostString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePAPIPlaceholders(String text, GenericPlayer<Player> player){
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualHost(){
|
||||
return this.resolveHost(event.getConnection().getVirtualHost().orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginCore<Favicon> getPlugin(){
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericPlayer<Player> createPlayer(String name, int protocol){
|
||||
return new VelocityPlayer(name, protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favicon createFavicon(BufferedImage image){
|
||||
return Favicon.create(image);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user