Compare commits

...
101 Commits
Author SHA1 Message Date
Andre601 5df2e05a14 Fix wrong file paths for paper 2023-12-02 14:27:45 +01:00
Andre601 d4e4173cc3 Improve placeholders with world/server args 2023-12-02 13:59:56 +01:00
Andre601 562ad481c5 Bump version to 3.6.0 2023-12-02 12:43:11 +00:00
Andre601 a0ee2a4322 Merge pull request 'Remove Spigot support' (#183) from feature/remove-spigot-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/183
2023-12-02 12:42:30 +00:00
Andre601 2c92efdb43 Merge branch 'master' into feature/remove-spigot-support 2023-12-02 12:39:37 +00:00
Andre601 555dc9d6a5 Merge pull request 'Improve docs workflow setup' (#179) from feature/improve-docs-workflow into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/179
2023-12-02 12:39:28 +00:00
Andre601 27742c5e1b .woodpecker/publish_docs.yml aktualisiert 2023-12-02 12:39:16 +00:00
Andre601 280aeb8d2e Merge branch 'master' into feature/improve-docs-workflow 2023-12-02 12:38:49 +00:00
Andre601 92a868f0fa Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.2.3' (#185) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/185
2023-12-02 12:03:33 +00:00
Andre601 189ac5e09b Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.4.14' (#184) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/184
2023-12-02 12:03:13 +00:00
Andre601's Renovate Bot 833cb81d65 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.2.3 2023-12-02 12:01:18 +00:00
Andre601's Renovate Bot ab09422da5 Update dependency ch.qos.logback:logback-classic to v1.4.14 2023-12-02 12:01:14 +00:00
Andre601 64cad6dc26 Remove Spigot from readme and docs 2023-12-01 17:00:14 +01:00
Andre601 ce78b493f4 Remove spigot from supported platforms in PlatformInfo 2023-12-01 16:58:43 +01:00
Andre601 c43048ea3f Remove Spigot support 2023-12-01 16:51:33 +01:00
Andre601 6d4d1600ab Add Getting Started page 2023-11-29 15:09:32 +01:00
Andre601 f114e99b9b Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.4.13' (#182) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/182
2023-11-29 12:06:26 +00:00
Andre601's Renovate Bot 3d587bc86d Update dependency ch.qos.logback:logback-classic to v1.4.13 2023-11-29 12:01:18 +00:00
Andre601 bd8c6be7c6 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.4.12' (#181) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/181
2023-11-28 12:02:35 +00:00
Andre601's Renovate Bot b5d5d508e2 Update dependency ch.qos.logback:logback-classic to v1.4.12 2023-11-28 12:01:02 +00:00
Andre601 3001b65fe8 Merge pull request 'Update dependency mkdocs-material to v9.4.14' (#180) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/180
2023-11-27 12:08:29 +00:00
Andre601's Renovate Bot c82771db59 Update dependency mkdocs-material to v9.4.14 2023-11-27 12:01:59 +00:00
Andre601 9880836c25 Improve docs workflow setup 2023-11-25 00:32:57 +00:00
Andre601 f12ae28722 Add Source redirect for API 2023-11-25 00:19:59 +00:00
Andre601 42b0f0e94f Merge pull request 'Update dependency mkdocs-material to v9.4.12' (#178) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/178
2023-11-24 12:04:02 +00:00
Andre601's Renovate Bot 0a4b872051 Update dependency mkdocs-material to v9.4.12 2023-11-24 12:00:59 +00:00
Andre601 b1322105ed Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.2.2' (#177) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/177
2023-11-23 12:02:45 +00:00
Andre601 831ca57fbb Merge branch 'master' into renovate/org.apache.httpcomponents.client5-httpclient5-5.x 2023-11-23 12:02:17 +00:00
Andre601 6502639cd3 Merge pull request 'Update dependency mkdocs-material to v9.4.11' (#176) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/176
2023-11-23 12:01:54 +00:00
Andre601's Renovate Bot 5059b80db2 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.2.2 2023-11-23 12:01:07 +00:00
Andre601's Renovate Bot ecdaf72963 Update dependency mkdocs-material to v9.4.11 2023-11-23 12:00:58 +00:00
Andre601 28e2ca69ed Merge pull request 'Update dependency mkdocs-material to v9.4.10' (#175) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/175
2023-11-19 20:40:20 +00:00
Andre601 9cad78b6e4 Merge branch 'master' into renovate/mkdocs-material-9.x 2023-11-19 21:39:40 +01:00
Andre601 af8654666b Merge pull request 'Update dependency mkdocs-glightbox to v0.3.5' (#174) from renovate/mkdocs-glightbox-0.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/174
2023-11-19 12:20:05 +00:00
Andre601's Renovate Bot 6cd474b35d Update dependency mkdocs-material to v9.4.10 2023-11-19 12:01:07 +00:00
Andre601's Renovate Bot 3802ab556c Update dependency mkdocs-glightbox to v0.3.5 2023-11-19 12:01:02 +00:00
Andre601 3a520eeaf0 Merge pull request 'Update dependency mkdocs-material to v9.4.9' (#173) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/173
2023-11-17 12:15:02 +00:00
Andre601's Renovate Bot 204f43c112 Update dependency mkdocs-material to v9.4.9 2023-11-17 12:00:45 +00:00
Andre601 fc8ed8e49e Merge pull request 'Update dependency mkdocs-material to v9.4.8' (#172) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/172
2023-11-06 12:02:13 +00:00
Andre601's Renovate Bot 56082c308b Update dependency mkdocs-material to v9.4.8 2023-11-06 12:01:06 +00:00
Andre601 205e563095 Fix wrong placeholder names. 2023-11-05 13:59:46 +00:00
Andre601 5b01940c60 Merge pull request 'Update dependency me.clip:placeholderapi to v2.11.5' (#171) from renovate/me.clip-placeholderapi-2.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/171
2023-10-29 12:05:36 +00:00
Andre601's Renovate Bot cbb087e3d1 Update dependency me.clip:placeholderapi to v2.11.5 2023-10-29 12:01:15 +00:00
Andre601 524b926244 Merge pull request 'Update dependency mkdocs-material to v9.4.7' (#170) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/170
2023-10-28 12:01:09 +00:00
Andre601's Renovate Bot 4059bbfe93 Update dependency mkdocs-material to v9.4.7 2023-10-28 12:00:43 +00:00
Andre601 9b0b69a4f4 Merge pull request 'Update maven Docker tag to v3.9.5' (#169) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/169
2023-10-20 12:02:12 +00:00
Andre601's Renovate Bot 10a82eb951 Update maven Docker tag to v3.9.5 2023-10-20 12:01:07 +00:00
Andre601 690f7dfaf0 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp to v4.12.0' (#168) from renovate/com.squareup.okhttp3-okhttp-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/168
2023-10-17 12:03:39 +00:00
Andre601's Renovate Bot 6a22d20b3a Update dependency com.squareup.okhttp3:okhttp to v4.12.0 2023-10-17 12:00:59 +00:00
Andre601 b1072bb1fa Update HangarVersionUploader for latest API changes 2023-10-16 12:01:12 +02:00
Andre601 d20da91bab Remove Hangar for now 2023-10-16 11:43:54 +02:00
Andre601 17e9692028 Remove unused import 2023-10-16 11:22:37 +02:00
Andre601 45dc8a5fe6 Don't use closeable http client 2023-10-16 11:22:09 +02:00
Andre601 a237ac1ce4 Merge pull request 'Update dependency mkdocs-material to v9.4.6' (#167) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/167
2023-10-15 17:27:18 +00:00
Andre601's Renovate Bot 27e66a16b9 Update dependency mkdocs-material to v9.4.6 2023-10-15 17:01:04 +00:00
Andre601 8f98846bc3 Ignore deprecation state of getUnsafe() 2023-10-15 00:00:57 +02:00
Andre601 bbcab59845 Final change I hope 2023-10-14 23:59:49 +02:00
Andre601 3130e07070 More consistent names 2023-10-14 23:57:05 +02:00
Andre601 7bc61ddf4d Use more matching placeholder names 2023-10-14 23:54:32 +02:00
Andre601 53d15a9011 Bump version 2023-10-14 23:42:16 +02:00
Andre601 8718e4a0ae update PAPI placeholders info 2023-10-11 12:10:04 +00:00
Andre601 06a49956af Merge pull request 'Update dependency com.google.guava:guava to v32.1.3-jre' (#166) from renovate/com.google.guava-guava-32.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/166
2023-10-11 12:04:37 +00:00
Andre601's Renovate Bot 38ec131b69 Update dependency com.google.guava:guava to v32.1.3-jre 2023-10-11 12:00:57 +00:00
Andre601 1bdaa61dd9 Merge pull request 'Update dependency mkdocs-material to v9.4.5' (#165) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/165
2023-10-10 12:02:55 +00:00
Andre601's Renovate Bot 080d5055c4 Update dependency mkdocs-material to v9.4.5 2023-10-10 12:01:23 +00:00
Andre601 423b363964 Use maxPlayers value 2023-10-09 01:33:40 +02:00
Andre601 6b9abfccfc Update PlaceholderAPI placeholders 2023-10-07 12:53:46 +02:00
Andre601 f589a8da35 Update Docs 2023-10-06 23:54:51 +02:00
Andre601 465581306f docs/api/javadocs.md aktualisiert 2023-10-06 20:54:27 +00:00
Andre601 6b2919961b Merge pull request 'Add Javadoc redirect' (#164) from docs/javadoc-link into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/164
2023-10-06 20:52:04 +00:00
Andre601 adb6e797b2 Add Javadoc redirect 2023-10-06 20:51:35 +00:00
Andre601 b410b9438f Merge pull request 'Update dependency mkdocs-material to v9.4.4' (#163) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/163
2023-10-06 12:22:17 +00:00
Andre601's Renovate Bot c1d5b4efa9 Update dependency mkdocs-material to v9.4.4 2023-10-06 12:01:00 +00:00
Andre601 4785dd127e Only allow workflow_dispatch from now on 2023-10-04 14:19:16 +00:00
Andre601 9e8e2f7e74 Add missing id property 2023-10-03 21:49:01 +00:00
Andre601 c14dfe0f3a Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.8.1' (#162) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/162
2023-10-03 12:40:03 +00:00
Andre601's Renovate Bot ed92e7002c Update dependency com.viaversion:viaversion-api to v4.8.1 2023-10-03 12:01:05 +00:00
Andre601 8f93d9732c Merge pull request 'Update dependency mkdocs-material to v9.4.3' (#161) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/161
2023-10-02 12:03:50 +00:00
Andre601's Renovate Bot 96f8fa5860 Update dependency mkdocs-material to v9.4.3 2023-10-02 12:00:57 +00:00
Andre601 bfb857bd5c Merge pull request 'Update dependency net.william278:papiproxybridge to v1.4.2' (#160) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/160
2023-09-30 12:04:14 +00:00
Andre601 5fe3b5811c Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.3.1' (#159) from renovate/net.kyori-adventure-platform-bungeecord-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/159
2023-09-30 12:03:54 +00:00
Andre601's Renovate Bot 2a7eff0092 Update dependency net.william278:papiproxybridge to v1.4.2 2023-09-30 12:01:23 +00:00
Andre601 1907f5d47e Merge pull request 'Update dependency net.kyori:adventure-platform-bukkit to v4.3.1' (#158) from renovate/net.kyori-adventure-platform-bukkit-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/158
2023-09-29 12:03:12 +00:00
Andre601's Renovate Bot aa92350b52 Update dependency net.kyori:adventure-platform-bungeecord to v4.3.1 2023-09-29 12:01:05 +00:00
Andre601's Renovate Bot 869b9bd3b7 Update dependency net.kyori:adventure-platform-bukkit to v4.3.1 2023-09-29 12:00:56 +00:00
Andre601 fe31dcf0a4 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.4.1' (#156) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/156
2023-09-26 18:39:12 +00:00
Andre601 6b44438f52 Use custom compact admonition boxes 2023-09-26 20:38:22 +02:00
Andre601's Renovate Bot 6b0c654f41 Update dependency net.william278:papiproxybridge to v1.4.1 2023-09-26 12:00:57 +00:00
Andre601 c28ff3a891 Use some JS to insert API version 2023-09-26 13:56:48 +02:00
Andre601 f424b41c3b Header consistency 2023-09-25 15:14:10 +02:00
Andre601 b5f901d8f5 Use Hangar version of PAPI as dependency 2023-09-25 15:04:10 +02:00
Andre601 29d52492fc Merge pull request 'Update dependency mkdocs-material to v9.4.2' (#155) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/155
2023-09-25 12:03:05 +00:00
Andre601's Renovate Bot 2d6af20bdc Update dependency mkdocs-material to v9.4.2 2023-09-25 12:01:00 +00:00
Andre601 59c913ecf8 Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1' (#154) from renovate/org.apache.maven.plugins-maven-shade-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/154
2023-09-24 22:18:35 +00:00
Andre601's Renovate Bot 4a50beb4e0 Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1 2023-09-24 22:16:36 +00:00
Andre601 c099127272 delete renovate.yml 2023-09-24 21:48:23 +00:00
Andre601 15974b5c54 Merge pull request 'Update dependency me.clip:placeholderapi to v2.11.4' (#153) from renovate/me.clip-placeholderapi-2.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/153
2023-09-24 13:03:36 +00:00
Andre601's Renovate Bot 483afe63c4 Update dependency me.clip:placeholderapi to v2.11.4 2023-09-24 12:00:56 +00:00
Andre601 f0cb458a34 Use snippets for API version display 2023-09-24 03:19:41 +02:00
Andre601 2c547cd6d0 Add changelog newline sanitization to HangarVersionUploader too 2023-09-23 22:35:45 +02:00
Andre601 e7282b4a97 Support all MC 1.19 versions. 2023-09-23 22:27:48 +02:00
72 changed files with 1897 additions and 1630 deletions

No files matched your search

+1 -10
View File
@@ -2,16 +2,6 @@ name: 'Deploy Site (Push)'
on:
workflow_dispatch:
push:
paths:
- 'docs/**'
- 'mkdocs.yml'
- 'requirements.txt'
- '.github/workflows/docs-deploy.yml'
branches:
- master
tags-ignore:
- '**'
permissions:
contents: read
@@ -55,4 +45,5 @@ jobs:
with:
path: 'site/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
+1
View File
@@ -2,3 +2,4 @@
/.idea/
/**/dependency-reduced-pom.xml
/**/target/
/**/__pycache__/
+3 -5
View File
@@ -4,12 +4,10 @@ when:
steps:
createFiles:
image: maven:3.9.4-eclipse-temurin-17
image: maven:3.9.5-eclipse-temurin-17
secrets:
- source: cb_token
target: codeberg_api_token
- source: gh_token
target: github_api_token
- source: modrinth_api_token
target: modrinth_api_token
- source: hangar_api_token
@@ -22,14 +20,14 @@ steps:
- mv VersionUploader.jar ../../
- cd ../../
# Execute Jar file
- java -jar VersionUploader.jar --all
- java -jar VersionUploader.jar --modrinth
uploadToCodeberg:
image: woodpeckerci/plugin-gitea-release
settings:
base_url: https://codeberg.org
files:
- "bukkit/target/AdvancedServerList-*.jar"
- "bungeecord/target/AdvancedServerList-*.jar"
- "paper/target/AdvancedServerList-*.jar"
- "velocity/target/AdvancedServerList-*.jar"
api_key:
from_secret: CB_TOKEN
+20 -12
View File
@@ -4,25 +4,33 @@ when:
path:
include: ['requirements.txt', 'mkdocs.yml', 'docs/**']
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "github@andre601.ch"
- git config --global user.name "ASL Docs Builder"
steps:
cloneTargetRepo:
image: alpine:3.18.4
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
- chmod -R a+w site
buildDocs:
image: python
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
commitAndPush:
image: alpine:3.18.4
secrets:
- cb_token
commands:
- chmod -R a+w .
- git config --global --add safe.directory /woodpecker/src/codeberg.org/Andre601/blog-source/website
- git config --global user.email "github@andre601.ch"
- git config --global user.name "CI Website Builder"
- git fetch --unshallow
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
- chmod -R a+w site
- python -m pip install --upgrade pip
- python -m pip install -r requirements.txt
- mkdocs build
- <<: *setup_git
- mv domains site/.domains
- cd site
- git remote set-url origin https://$CB_TOKEN@codeberg.org/Andre601/AdvancedServerList.git
- git add --all
- git commit -m "Update AdvancedServerList Docs ($( env TZ=Europe/Zurich date +"%d.%m.%Y" )) [CI SKIP]"
- git commit -m "Update AdvancedServerList Docs ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
-45
View File
@@ -1,45 +0,0 @@
platform: linux/amd64
when:
event:
- cron
- manual
branch:
- master
steps:
#renovateDryRun:
# image: renovate/renovate
# pull: true
# commands:
# - renovate $${CI_REPO}
# environment:
# RENOVATE_PLATFORM: gitea
# RENOVATE_ENDPOINT: https://codeberg.org
# LOG_LEVEL: debug
# RENOVATE_DRY_RUN: full
# secrets:
# - source: rb_token
# target: renovate_token
# - source: git_author
# target: renovate_git_author
# when:
# - event: push
renovate:
image: renovate/renovate
pull: true
commands:
- renovate $${CI_REPO}
environment:
RENOVATE_PLATFORM: gitea
RENOVATE_ENDPOINT: https://codeberg.org
LOG_LEVEL: debug
secrets:
- source: rb_token
target: renovate_token
- source: gh_renovate_token
target: github_com_token
when:
- event: cron
cron: renovate
- event: manual
+15 -14
View File
@@ -3,19 +3,19 @@
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Downloads
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg" height="46" alt="modrinth" title="Available on Modrinth">
</a>
<br>
<!--
<a href="https://hangar.papermc.io/Andre_601/AdvancedServerList" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg" height="46" alt="hangar" title="Available on Hangar">
</a>
-->
## Supported Platforms
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
</a>
<a href="https://papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
</a>
@@ -43,10 +43,10 @@ When multiple profiles exist that have valid conditions will the one with the hi
> [*Read More*][conditions]
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
Placeholders can be used within conditions to further customize them. They can also be used in any other text option to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
When using the SpigotMC/PaperMC version, or while PAPIProxyBridge is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
@@ -60,13 +60,14 @@ Only certain options are usable for each option. As an example does motd support
## Dependencies
| Dependency | Platforms | Required? |
|-------------------|----------------------|-----------|
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
| [ViaVersion] | Spigot, Paper | No |
| [PAPIProxyBridge] | BungeeCord, Velocity | No |
| [Maintenance] | All | No |
All listed dependencies are optional.
| Dependency | Platforms |
|-------------------|----------------------|
| [PlaceholderAPI] | Paper |
| [ViaVersion] | Paper |
| [PAPIProxyBridge] | BungeeCord, Velocity |
| [Maintenance] | All |
## Statistics
@@ -84,6 +85,7 @@ You can disable this in the global bStats config file located in `/plugins/bstat
</a>
## Support
<a href="https://discord.gg/6dazXp6" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
</a>
@@ -102,8 +104,7 @@ You can disable this in the global bStats config file located in `/plugins/bstat
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[protocollib]: https://hangar.papermc.io/dmulloy2/ProtocolLib
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
@@ -1,39 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit;
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import org.bukkit.plugin.java.JavaPlugin;
/*
* Small convenience class to "merge" the PluginCore and JavaPlugin classes.
* Allows me to have BukkitCore<?> for whenever I also need a JavaPlugin (i.e. registering events).
* See JoinEvent class for an example.
*/
public abstract class BukkitCore<F> extends JavaPlugin implements PluginCore<F>{
public abstract WorldCache getWorldCache();
}
@@ -1,75 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.paper.commands.PaperCmdSender;
import ch.andre601.advancedserverlist.spigot.commands.SpigotCmdSender;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class CmdAdvancedServerList extends Command implements CommandExecutor{
private final PluginCore<?> plugin;
private final BukkitAudiences audiences;
public CmdAdvancedServerList(PluginCore<?> plugin){
this(plugin, null);
}
public CmdAdvancedServerList(PluginCore<?> plugin, BukkitAudiences audiences){
super(
"advancedserverlist",
"Main command of the plugin",
"/asl [reload|help|clearCache]",
Collections.singletonList("asl")
);
this.plugin = plugin;
this.audiences = audiences;
}
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
return true;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
return true;
}
private CmdSender getSender(CommandSender sender){
return audiences == null ? new PaperCmdSender(sender) : new SpigotCmdSender(sender, audiences);
}
}
@@ -1,74 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit.listeners;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.listeners.ProtocolLibEvents;
import com.comphenix.protocol.ProtocolLibrary;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerLoadEvent;
public class LoadEvent implements Listener{
private final BukkitCore<?> plugin;
private LoadEvent(BukkitCore<?> plugin){
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public static void init(BukkitCore<?> plugin){
new LoadEvent(plugin);
}
@EventHandler
public void onServerLoad(ServerLoadEvent event){
JoinEvent.init(plugin);
WorldEvents.init(plugin);
// Populate WorldCache with all loaded worlds
Bukkit.getWorlds().forEach(world -> plugin.getWorldCache().addWorld(world.getName(), world));
if(!(plugin instanceof SpigotCore spigotCore))
return;
if(!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")){
plugin.getCore().getPlugin().getPluginLogger().warn("ProtocolLib not found! AdvancedServerList requires it to work on Spigot!");
Bukkit.getPluginManager().disablePlugin(plugin);
return;
}
ProtocolLibEvents.init(spigotCore, ProtocolLibrary.getProtocolManager());
if(Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"))
spigotCore.setPapiPlaceholders(PAPIPlaceholders.init(spigotCore));
}
}
@@ -1,62 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
public class BukkitPlayerPlaceholders extends PlaceholderProvider{
private BukkitPlayerPlaceholders(){
super("player");
}
public static BukkitPlayerPlaceholders init(){
return new BukkitPlayerPlaceholders();
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!(player instanceof BukkitPlayer bukkitPlayer))
return null;
return switch(placeholder){
case "name" -> bukkitPlayer.getName();
case "protocol" -> String.valueOf(bukkitPlayer.getProtocol());
case "uuid" -> bukkitPlayer.getUUID().toString();
case "hasPlayedBefore" -> returnValue(bukkitPlayer, bukkitPlayer.hasPlayedBefore());
case "isBanned" -> returnValue(bukkitPlayer, bukkitPlayer.isBanned());
case "isWhitelisted" -> returnValue(bukkitPlayer, bukkitPlayer.isWhitelisted());
default -> null;
};
}
private String returnValue(BukkitPlayer player, Object value){
return player.getPlayer() == null ? null : String.valueOf(value);
}
}
@@ -1,178 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitPlayerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitServerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.bukkit.listeners.LoadEvent;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.command.PluginCommand;
import java.nio.file.Path;
public class SpigotCore extends BukkitCore<WrappedServerPing.CompressedImage>{
private final PluginLogger logger = new BukkitLogger(getLogger());
private AdvancedServerList<WrappedServerPing.CompressedImage> core;
private FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
private PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders = null;
private WorldCache worldCache = null;
@Override
public void onEnable(){
try{
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
printPaperInfo();
}catch(ClassNotFoundException ex){
try{
// Above class only exists since 1.19+, so this is a fallback for older versions.
Class.forName("com.destroystokyo.paper.PaperConfig");
printPaperInfo();
}catch(ClassNotFoundException ignored){}
}
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init(), BukkitServerPlaceholders.init());
}
@Override
public void onDisable(){
if(papiPlaceholders != null){
papiPlaceholders.unregister();
papiPlaceholders = null;
}
if(worldCache != null)
worldCache = null;
getCore().disable();
}
@Override
public void loadCommands(){
PluginCommand cmd = getServer().getPluginCommand("advancedserverlist");
if(cmd == null){
getPluginLogger().warn("Unable to register command /advancedserverlist");
return;
}
cmd.setExecutor(new CmdAdvancedServerList(this, BukkitAudiences.create(this)));
}
@Override
public void loadEvents(){
LoadEvent.init(this);
}
@Override
public void loadMetrics(){
new Metrics(this, 15584).addCustomChart(new SimplePie("profiles",
() -> String.valueOf(core.getFileHandler().getProfiles().size())
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList<WrappedServerPing.CompressedImage> getCore(){
return core;
}
@Override
public Path getFolderPath(){
return getDataFolder().toPath();
}
@Override
public PluginLogger getPluginLogger(){
return logger;
}
@Override
public FaviconHandler<WrappedServerPing.CompressedImage> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getServer().getName();
}
@Override
public String getPlatformVersion(){
return getServer().getVersion();
}
@Override
public String getLoader(){
return "spigot";
}
@Override
public WorldCache getWorldCache(){
if(worldCache != null)
return worldCache;
return (worldCache = new WorldCache());
}
public void setPapiPlaceholders(PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders){
this.papiPlaceholders = papiPlaceholders;
}
private void printPaperInfo(){
getPluginLogger().warn("======================================================================================");
getPluginLogger().warn("You are using the Spigot version of AdvancedServerList on a Paper server.");
getPluginLogger().warn("It is recommended to use the dedicated Paper version, to benefit from the");
getPluginLogger().warn("following improvements:");
getPluginLogger().warn(" - No downloading of external Libraries already provided by Paper (i.e. Adventure).");
getPluginLogger().warn(" - No dependency on ProtocolLib thanks to provided Events.");
getPluginLogger().warn("");
getPluginLogger().warn("AdvancedServerList may work as normal, but consider using the PaperMC version instead!");
getPluginLogger().warn("======================================================================================");
}
}
@@ -1,52 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender;
public class SpigotCmdSender implements CmdSender{
private final CommandSender sender;
private final BukkitAudiences bukkitAudiences;
public SpigotCmdSender(CommandSender sender, BukkitAudiences bukkitAudiences){
this.sender = sender;
this.bukkitAudiences = bukkitAudiences;
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
}
@Override
public void sendMsg(String msg, Object... args){
bukkitAudiences.sender(sender).sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
}
@@ -1,203 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot.listeners;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.listeners.PreServerListSetEventImpl;
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitServerImpl;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.awt.image.BufferedImage;
import java.util.*;
public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServerPing.CompressedImage, BukkitPlayerImpl>{
private final SpigotCore plugin;
private final PacketEvent event;
private final WrappedServerPing ping;
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event){
this.plugin = plugin;
this.event = event;
this.ping = event.getPacket().getServerPings().read(0);
}
@Override
public GenericServerListEvent callEvent(ProfileEntry entry){
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
plugin.getServer().getPluginManager().callEvent(event);
return event;
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.setPlayersMaximum(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setMotD(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)));
}
@Override
public void hidePlayers(){
ping.setPlayersVisible(false);
}
@Override
public void setPlayerCount(String name){
ping.setVersionName(name);
ping.setVersionProtocol(-1);
}
@Override
public void setPlayers(List<String> lines, BukkitPlayerImpl player, GenericServer server){
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString();
players.add(new WrappedGameProfile(UUID.randomUUID(), parsed));
}
ping.setPlayers(players);
}
@Override
public void setFavicon(WrappedServerPing.CompressedImage favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFavicon());
}
// Not used in ProtocolLib
@Override
public void updateEvent(){
event.getPacket().getServerPings().write(0, ping);
}
@Override
public boolean isInvalidProtocol(){
return event.getPlayer().getAddress() == null;
}
@Override
public boolean isMaintenanceModeActive(){
if(!Bukkit.getPluginManager().isPluginEnabled("Maintenance"))
return false;
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
}
@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, BukkitPlayerImpl player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
}
@Override
public String getVirtualHost(){
String host = this.resolveHost(event.getPlayer().getAddress());
if(host == null)
return null;
return ProtocolLibEvents.getHostAddresses().get(host);
}
@Override
public BukkitCore<WrappedServerPing.CompressedImage> getPlugin(){
return plugin;
}
@Override
public BukkitPlayerImpl createPlayer(CachedPlayer player, int protocol){
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
return new BukkitPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
}
@Override
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
return new BukkitServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
}
@Override
public WrappedServerPing.CompressedImage createFavicon(BufferedImage image) throws Exception{
return WrappedServerPing.CompressedImage.fromPng(image);
}
}
@@ -1,84 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot.listeners;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.TreeMap;
public class ProtocolLibEvents implements Listener{
private final ProtocolManager protocolManager;
private static final Map<String, String> hostAddresses = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private ProtocolLibEvents(SpigotCore plugin, ProtocolManager protocolManager){
this.protocolManager = protocolManager;
loadPacketListener(plugin);
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public static void init(SpigotCore plugin, ProtocolManager protocolManager){
new ProtocolLibEvents(plugin, protocolManager);
}
public static Map<String, String> getHostAddresses(){
return hostAddresses;
}
private void loadPacketListener(SpigotCore spigotPlugin){
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Handshake.Client.SET_PROTOCOL){
@Override
public void onPacketReceiving(PacketEvent event){
InetSocketAddress address = event.getPlayer().getAddress();
if(address == null)
return;
String host = event.getPacket().getStrings().read(0);
hostAddresses.put(address.getHostString(), host);
}
});
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
@Override
public void onPacketSending(PacketEvent event){
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event));
}
});
}
}
+3 -3
View File
@@ -93,7 +93,7 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.3.0</version>
<version>4.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -111,7 +111,7 @@
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -133,7 +133,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -53,10 +53,14 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
return switch(args[0]){
case "playersOnline" -> {
if(args.length >= 2){
int players = 0;
String[] servers = args[1].split(",");
for(int i = 1; i < args.length; i++){
ServerInfo info = proxy.getServers().get(args[i]);
int players = 0;
for(String serverName : servers){
if(serverName.isEmpty())
continue;
ServerInfo info = proxy.getServers().get(serverName);
if(info == null)
continue;
+4 -4
View File
@@ -98,7 +98,7 @@
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -110,13 +110,13 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.2-jre</version>
<version>32.1.3-jre</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.william278</groupId>
<artifactId>papiproxybridge</artifactId>
<version>1.3</version>
<version>1.4.2</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -152,7 +152,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
@@ -31,7 +31,6 @@ import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.objects.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
import java.io.IOException;
+57
View File
@@ -0,0 +1,57 @@
#
# Modified version of Squidfunk's shortcodes.py file for Material for MkDocs.
#
# It was altered to create compact admonition-like boxes to display in the documentation.
#
# Original shortcodes.py file:
# https://github.com/squidfunk/mkdocs-material/blob/56b96b4d799174d48d36613d70ffac9b964171cc/material/overrides/hooks/shortcodes.py
#
from __future__ import annotations
import posixpath
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.pages import Page
from re import Match
def on_page_markdown(
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
):
# Replace callback
def replace(match: Match):
type, args = match.groups()
args = args.strip()
if type == "abstract": return _admo(text = args, type = "abstract")
elif type == "info": return _admo(text = args, type = "info")
elif type == "tip": return _admo(text = args, type = "tip")
elif type == "success": return _admo(text = args, type = "success")
elif type == "question": return _admo(text = args, type = "question")
elif type == "warning": return _admo(text = args, type = "warning")
elif type == "failure": return _admo(text = args, type = "failure")
elif type == "danger": return _admo(text = args, type = "danger")
elif type == "bug": return _admo(text = args, type = "bug")
elif type == "example": return _admo(text = args, type = "example")
elif type == "quote": return _admo(text = args, type = "quote")
else: return _admo(text = args)
# Otherwise, raise an error
raise RuntimeError(f"Unknown shortcode: {type}")
# Find and replace all external asset URLs in current page
return re.sub(
r"<!-- admo:(\w+)(.*?) -->",
replace, markdown, flags = re.I | re.M
)
def _admo(text: str = "", type: str = ""):
classes = f"mdx-grid-wrapper mdx-admo--{type}" if type else "mdx-grid-wrapper"
return "".join([
f"<div class=\"{classes}\">",
f"<div class=\"mdx-grid-child mdx-grid-child--icon\"></div>",
f"<div class=\"mdx-grid-child\">{text}</div>"
"</div>",
])
@@ -149,7 +149,7 @@
</h3>
{% if detail.deprecated %}
<div class="admonition danger">
<div class="admonition deprecated">
<div class="admonition-title">Deprecation Warning</div>
<p>
{{ detail.deprecated }}
+1
View File
@@ -1,5 +1,6 @@
nav:
- Home: index.md
- getting-started
- commands
- profiles
- examples
+1
View File
@@ -0,0 +1 @@
<div class="mdx-badge"><span class="mdx-badge__icon">[:octicons-tag-24:](changelog.md#v3.1.0 'View latest Release Changelog')</span><span class="mdx-badge__text">[v3.1.0](changelog.md#v3.1.0 'View latest Release Changelog')</span></div>
+1
View File
@@ -0,0 +1 @@
<div class="mdx-badge"><span class="mdx-badge__icon" >[:octicons-alert-24:](changelog.md)</span><span class="mdx-badge__text">[v3.1.0](changelog.md#v3.1.0 'View latest Release Changelog')</span></div>
+21 -12
View File
@@ -7,25 +7,34 @@ icon: octicons/log-24
This page lists the recent changes made towards the AdvancedServerListAPI.
They are ordered newest to oldest.
## v3.1.0
## v3.1.0 { #v3.1.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.1.0-added }
- New getters in `ProfileEntry`:
- `maxPlayersEnabled()` - Returns the value for `playerCount -> maxPlayers -> enabled` as `NullBool`
- `maxPlayersCount()` - Returns the value of `playerCount -> maxPlayers -> amount` as nullable `Integer`
- New setters in `ProfileEntry.Builder`:
- `setMaxPlayersEnabled(NullBool)` - Sets whether the max players feature is enabled or not.
- `setMaxPlayersCount(Integer)` - Sets the number to use for the max players count.
- `setExtraPlayersCount(Integer)` - Replacement for [deprecated `setExtraPlayerCount(Integer)` method](#v3.1.0-deprecated).
- New getters in [`ProfileEntry`][profileentry]:
- [`maxPlayersEnabled()`][maxplayersenabled] - Returns the value for `playerCount -> maxPlayers -> enabled` as `NullBool`
- [`maxPlayersCount()`][maxplayerscount] - Returns the value of `playerCount -> maxPlayers -> amount` as nullable `Integer`
- New setters in [`ProfileEntry.Builder`][profileentry.builder]:
- [`setMaxPlayersEnabled(NullBool)`][setmaxplayersenabled] - Sets whether the max players feature is enabled or not.
- [`setMaxPlayersCount(Integer)`][setmaxplayerscount] - Sets the number to use for the max players count.
- [`setExtraPlayersCount(Integer)`][setextraplayersecount] - Replacement for [deprecated `setExtraPlayerCount(Integer)` method](#v3.1.0-deprecated).
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v3.1.0-deprecated }
- `setExtraPlayerEnabled(Integer)` in `ProfileEntry.Builder` - Typo in method name.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled()
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount()
[profileentry.builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
[setmaxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayersenabled(nullbool)
[setmaxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayerscount(integer)
[setextraplayersecount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setextraplayerscount(integer)
----
## v3.0.0
## v3.0.0 { #v3.0.0 }
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v3-breaking }
@@ -45,7 +54,7 @@ They are ordered newest to oldest.
----
## v2.1.0
## v2.1.0 { #v2.1.0 }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v2.1.0-changed }
@@ -54,7 +63,7 @@ They are ordered newest to oldest.
----
## v2.0.0
## v2.0.0 { #v2.0.0 }
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v2-breaking }
@@ -85,7 +94,7 @@ They are ordered newest to oldest.
----
## v1.0.0
## v1.0.0 { #v1.0.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v1-added }
+327 -94
View File
@@ -9,87 +9,95 @@ It provides a way for your plugin to provide its own placeholders that should be
## Add dependency
Add the following to your `build.gradle` or `pom.xml` file to use the API:
Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depending on what you use:
=== ":simple-gradle: Gradle"
/// tab | :simple-apachemaven: Maven
```xml title="pom.xml"
<repositories>
<repository>
<id>jitpack</id>
<url>https://jitpack.io/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
<!-- Optional platform dependencies -->
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bukkit</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bungeecord</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-velocity</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
</dependencies>
```
///
/// tab | :simple-gradle: Gradle
```groovy title="build.gradle"
repositorories {
maven { url = 'https://jitpack.io/' }
}
dependencies {
compileOnly 'ch.andre601.asl-api:api:{apiVersion}'
[![latest_release][release]][api-repo]
// Optional platform dependencies
compileOnly 'ch.andre601.asl-api:platform-bukkit:{apiVersion}'
compileOnly 'ch.andre601.asl-api:platform-bungeecord:{apiVersion}'
compileOnly 'ch.andre601.asl-api:platform-velocity:{apiVersion}'
}
```
///
/// tab | :simple-gradle: Gradle (KTS)
```kotlin title="build.gradle.kts"
repositories {
maven("https://jitpack.io")
}
dependencies {
compileOnly("ch.andre601.asl-api:api:{apiVersion}")
Make sure to replace `{version}` with the version displayed above.
```groovy title="build.gradle"
repositorories {
maven { url = 'https://jitpack.io/' }
}
dependencies {
implementation 'ch.andre601.asl-api:api:{version}'
// Optional platform dependencies
implementation 'ch.andre601.asl-api:platform-bukkit:{version}'
implementation 'ch.andre601.asl-api:platform-bungeecord:{version}'
implementation 'ch.andre601.asl-api:platform-velocity:{version}'
}
```
// Optional platform dependencies
compileOnly("ch.andre601.asl-api:platform-bukkit:{apiVersion}")
compileOnly("ch.andre601.asl-api:platform-bungeecord:{apiVersion}")
compileOnly("ch.andre601.asl-api:platform-velocity:{apiVersion}")
}
```
///
=== ":simple-apachemaven: Maven"
[![latest_release][release]][api-repo]
Make sure to replace `{version}` with the version displayed above.
```xml title="pom.xml"
<repositories>
<repository>
<id>jitpack</id>
<url>https://jitpack.io/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>{version}</version>
</dependency>
<!-- Optional platform dependencies -->
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bukkit</artifactId>
<version>{version}</version>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bungeecord</artifactId>
<version>{version}</version>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-velocity</artifactId>
<version>{version}</version>
</dependency>
</dependencies>
```
## Adding your own Placeholders
[release]: https://img.shields.io/github/v/tag/Andre601/asl-api?labelColor=252631&color=292a36&style=for-the-badge&label=Latest%20Release:
[api-repo]: https://github.com/Andre601/asl-api
<!-- admo:info This requires the main api module -->
## Add own placeholders
The API allows you to add your own placeholders which would be available through the `${<identifier> <values>}` placeholder Pattern in a Server List profile.
To add your own placeholders will you need to do a few steps.
To add your own placeholders, follow these steps:
### 1) Get API instance
### 1. Create a Placeholder class
Use `AdvancedServerListAPI.get()` to retrieve an instance of the currently used AdvancedServerList API.
It will be needed at a later point.
You should first create a new class and make it extend the abstract [`PlaceholderProvider`][placeholderprovider]. This class includes a constructor and a method you need to add, so do that:
### 2) Create a Placeholder class
Make a new class that you want to use for the placeholders and let it extend the `PlaceholderProvider` class of AdvancedServerList.
Your IDE should now tell you to implement/override some methods. Confirm this action and your class should look something alongside this:
```java title="PlaceholderProvider example"
```java
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders(String identifier) {
@@ -103,23 +111,25 @@ public class MyPlaceholders extends PlaceholderProvider {
}
```
It's recommended to replace your generated constructor with a no-args one and set the identifier directly in the `super()`.
For example:
/// tip
You can replace the Constructor with a String argument with a no-args constructor and set the identifier directly in the `super`:
```java
public MyPlaceholders() {
super("myplaceholders");
}
```
///
The next step now would be to handle the different placeholders. These are handled in the `parsePlaceholder` method you had to override.
The `placeholder` String is whatever value was provided after the identifier in `${<identifier> <placeholder>}`. It can contain spaces.
The [`parsePlaceholder(String, GenericPlayer, GenericServer)`][parseplaceholder] method is used by AdvancedServerList to replace a matching placeholder with a value.
What you return is completely up to you. Just keep in mind that returning `null` will be treated as an invalid placeholder by AdvancedServerList, resulting in the placeholder being returned as-is without any changes.
Something to note is, that when returning `null` will AdvancedServerList understand it as an invalid placeholder and return it unchanged.
[placeholderprovider]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
[parseplaceholder]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md#parseplaceholder(string,-genericplayer,-genericserver)
Here is a small example of the final class:
/// details | Example of final class
type: example
```java title="PlaceholderProvider example"
```java
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders() {
@@ -128,35 +138,258 @@ public class MyPlaceholders extends PlaceholderProvider {
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if(placeholder.equals("hello"))
return "Hi!";
if(placeholder.equalsIgnoreCase("hello"))
return "Hello " + player.getName();
return null;
}
}
```
///
### 3) Register the placeholder class
### 2. Register the Placeholders
All that is left to do now is to register your class as a new PlaceholderProvider instance. To do this, get the API instance you retrieved earlier and use `addPlaceholderProvider` with a new instance of your class.
Next step should be to register the placeholder. To achieve this, first obtain an instance of the [`AdvancedServerListAPI`][advancedserverlistapi] by using the static [`get()`][get] method. After that call [`addPlaceholderProvider(PlaceholderProvider placeholderProvider)`][addplaceholderprovider].
Your code may look similar to this:
```java title="Registering PlaceholderProvider class"
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholders());
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholders());
}
}
```
## Events
[advancedserverlistapi]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
[get]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#get()
[addplaceholderprovider]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)
!!! info "Note"
The mentioned event is only accessible through one of the platform dependencies, as those are used in the platform's respective event handler system.
This should register your PlaceholderExpansion as long as it is valid, meaning that the identifier...
v2 of the API adds the `PreServerListSetEvent` to the different platform dependencies to use.
It allows you to modify the ProfileEntry used for the player pinging the server/proxy or even cancelling the event altogether.
- ...is not `null`
- ...is not containing spaces
- ...is not using a name already registered in the API
### 3. Declare AdvancedServerList as (soft)depend
The final thing you should make sure is to define AdvancedServerList as a depend or soft-depend for your plugin, to make sure it loads after AdvancedServerList.
Below are example setups for Spigot, Paper, BungeeCord and Velocity:
/// tab | :simple-spigotmc: Spigot
//// tab | Softdepend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
softdepend:
- AdvancedServerList
```
////
//// tab | Depend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
depend:
- AdvancedServerList
```
////
///
/// tab | :fontawesome-solid-paper-plane: Paper
//// tab | Softdepend
```yaml title="paper-plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
dependencies:
server:
AdvancedServerList:
load: BEFORE
required: false # Default, not required
```
////
//// tab | Depend
```yaml title="paper-plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
dependencies:
server:
AdvancedServerList:
load: BEFORE
required: true
```
////
///
/// tab | :octicons-git-merge-24: BungeeCord
//// tab | Softdepend
```yaml title="bungee.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
softDepends:
- AdvancedServerList
```
////
//// tab | Depend
```yaml title="bungee.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
depends:
- AdvancedServerList
```
////
///
/// tab | :octicons-git-merge-24: Velocity
//// tab | Softdepend (File)
```json title="velocity-plugin.json"
{
"id": "myplugin",
"name": "MyPlugin",
"version": "1.0.0",
"authors": [
"author"
],
"main": "com.example.plugin.ExamplePlugin",
"dependencies": [
{
"id": "advancedserverlist",
"optional": true
}
]
}
```
////
//// tab | Depend (File)
```json title="velocity-plugin.json"
{
"id": "myplugin",
"name": "MyPlugin",
"version": "1.0.0",
"authors": [
"author"
],
"main": "com.example.plugin.ExamplePlugin",
"dependencies": [
{
"id": "advancedserverlist",
"optional": false // Default, not required
}
]
}
```
////
//// tab | Softdepend (Annotation)
```java title="MyPlugin.java"
@Plugin(
id = "myplugin",
name = "MyPlugin",
version = "1.0.0",
authors = {"author"},
dependencies = {
@Dependency(
id = "advancedserverlist",
optional = true
)
}
)
public class MyPlugin {
// ...
}
```
////
//// tab | Depend (Annotation)
```java title="MyPlugin.java"
@Plugin(
id = "myplugin",
name = "MyPlugin",
version = "1.0.0",
authors = {"author"},
dependencies = {
@Dependency(
id = "advancedserverlist",
optional = false // Default, not required
)
}
)
public class MyPlugin {
// ...
}
```
////
///
### 4. You're done!
Your plugin should now hook into AdvancedServerList and register its own custom placeholders to use.
## Listening for events
<!-- admo:info This requires the platform specific dependencies -->
AdvancedServerList provides an Event that your plugin can listen for.
The event is called `PreServerListSetEvent` and provides the following methods to use:
- [`getEntry()`][getentry] - Gets the currently set [`ProfileEntry`][profileentry].
- [`setEntry(ProfileEntry)`][setentry] - Sets a new [`ProfileEntry`][profileentry] to use.
- [`isCancelled()`][iscancelled] - Gets the current cancelled state of the event.
- [`setCancelled(boolean)`][setcancelled] - Sets the current cancelled state.
Setting the event's cancelled state to true will result in AdvancedServerList not altering the Server list.
Please check the server/proxy's documentation on how to listen for events with your plugin.
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry(profileentry)
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled()
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled(boolean)
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
### ProfileEntry
The ProfileEntry class has been moved to the API in v2 allowing you to create your own versions using the available Builder class.
The ProfileEntry record is the core class used within the `PreServerListSetEvent`. It sets what values (MOTD, Favicon, Players, etc.) should be displayed.
Note that the record is - by nature - immutable and that the [`Builder`][builder] class should be used to create a new ProfileEntry instance to use.
This class contains values from a Server List Profile file. The values can either be from a `profiles` list entry, one of the global options in the file, or a mix of both, depending on what options are present.
You can create a new entry or copy an existing one (i.e. from the [`PreServerListSetEvent`](#events)) to modify and use in the server list by setting it in the aforementioned `PreServerListSetEvent`.
A convenience method exists to create a `Builder` instance from an existing `ProfileEntry` in case you only want to alter certain options while everything else unchanged.
This allows you to customize the Server list using your plugin. Just keep in mind that other plugins may also do the same, overriding your changes.
[builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
+10
View File
@@ -0,0 +1,10 @@
---
template: redirect.html
location: https://docs.andre601.ch/asl-api
title: Javadocs
icon: octicons/link-external-24
---
<!-- Comment to trigger proper build -->
+11 -11
View File
@@ -27,7 +27,7 @@ An example class to show how the page structure may look like.
## custom HTML tags
There is a collection of custom HTML tags that are used to render specific text in certain styles.
Below is a list of all custom tags. Note that these tags only render on the actual site and not within the repository.
Below is a list of all custom tags. Note that these tags only render on the actual site and not within the repository when viewing the source.
- `<api__class></api__class>`: <api__class></api__class>
- `<api__interface></api__interface>`: <api__interface></api__interface>
@@ -43,12 +43,12 @@ Below is a list of all custom tags. Note that these tags only render on the actu
In addition are there two classes used within `span` tags to colour the text, to indicate their type:
- `<span class="api-type__object">Object</span>`: <span class="api-type__object">Object</span>
- `<span class="api-type__primitive">Object</span>`: <span class="api-type__primitive">Primitive</span>
- `<span class="api-type__primitive">primitive</span>`: <span class="api-type__primitive">primitive</span>
## Auto-generated content
The page template used checks for specific YAML frontmatter in the page to include other templates.
These templates pull the data from the YAML frontmatter to generate the page content which is then appendet to the already existing page content.
A page template is used to auto-generate the page content based on available YAML frontmatter.
Depending on the frontmatter available will the template call a jinja2 Macro to generate a Summary and Detailed info on the page for the respective frontmatter data.
There are 5 frontmatter options, each following a specific structure:
@@ -88,7 +88,7 @@ constructors:
- `description` - Description of the parameter.
- `type` - The type this parameter is.
- `attributes` - List of attributes (i.e. nullability) to display. The provided values will be turned into `<api__{name}></api__{name}>` tags that will be prependet to the parameter name.
- `deprecated` - Adds a notice about the deprecation of this Constructor in the form of a deprecation label and a `deprecated` section with the provided explanation.
- `deprecated` - Adds a notice about the deprecation of this Constructor in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
- `throws` - List of possible throws to display.
- `name` - Name of the throw to display.
- `description` - Description of the throw.
@@ -128,10 +128,10 @@ enums:
**Options:**
- `name` - The name to display for the Constructor summary and detail. This should include any parameters the Constructor has, but without any parameter name.
- `description` - The description to display for the Constructor.
- `name` - The name to display for the Enum summary and detail. This should include any parameters the Enum has, but without any parameter name.
- `description` - The description to display for the Enum.
- `type` - The return type to display. Will default to `{{ page.title }}` if not set.
- `deprecated` - Adds a notice about the deprecation of this Enum in the form of a deprecation label and a `deprecated` section with the provided explanation.
- `deprecated` - Adds a notice about the deprecation of this Enum in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
- `seealso` - List of "See also" text to display.
- `name` - Name of the See also link.
- `link` - Link (Relative, absolute or URL) to use for the See also text.
@@ -166,8 +166,8 @@ methods:
**Options:**
- `name` - The name to display for the Constructor summary and detail. This should include any parameters the Constructor has, but without any parameter name.
- `description` - The description to display for the Constructor.
- `name` - The name to display for the Method summary and detail. This should include any parameters the Method has, but without any parameter name.
- `description` - The description to display for the Method.
- `type` - Options for object type to display.
- `name` - Displayed name of the object.
- `type` - Object type. Can be either `object` or `primitive` which would be used in a class name for styling.
@@ -179,7 +179,7 @@ methods:
- `type` - The type this parameter is.
- `attributes` - List of attributes (i.e. nullability) to display. The provided values will be turned into `<api__{name}></api__{name}>` tags that will be prependet to the parameter name.
- `returns` - Possible return values.
- `deprecated` - Adds a notice about the deprecation of this Method in the form of a deprecation label and a `deprecated` section with the provided explanation.
- `deprecated` - Adds a notice about the deprecation of this Method in the form of a deprecation label and a `deprecated` section with the provided `<string>` as explanation.
- `throws` - List of possible throws to display.
- `name` - Name of the throw to display.
- `description` - Description of the throw.
+10
View File
@@ -0,0 +1,10 @@
---
template: redirect.html
location: https://github.com/Andre601/asl-api
title: Source Code
icon: octicons/mark-github-16
---
<!-- Comment to trigger proper build -->
+44 -4
View File
@@ -2,7 +2,7 @@ document$.subscribe(async () => {
const url = 'https://codeberg-stats-proxy.vercel.app/repo'
const repo_stats = document.querySelector('[data-md-component="source"] .md-source__repository');
function loadInfo(data) {
function loadCodebergInfo(data) {
const facts = document.createElement("ul");
facts.className = "md-source__facts";
@@ -26,6 +26,35 @@ document$.subscribe(async () => {
repo_stats.appendChild(facts);
}
function loadApiInfo(data) {
const version = data["version"];
const versionToken = '{apiVersion}';
const codeBlocks = document.querySelectorAll('.md-content pre code');
for(const codeBlock of codeBlocks) {
codeBlock.innerHTML = codeBlock.innerHTML.replace(new RegExp(versionToken, 'g'), version);
}
}
function loadPluginVersion(data) {
const version = data["version"];
const versionToken = '{version}'
const entries = document.querySelectorAll('.md-content code');
for(const entry of entries) {
entry.innerHTML = entry.innerHTML.replace(new RegExp(versionToken, 'g'), version);
}
}
async function fetchApiInfo() {
const tag = await fetch("https://api.github.com/repos/Andre601/asl-api/releases/latest").then(_ => _.json());
const data = {
"version": tag.tag_name
};
__md_set("__api_tag", data, sessionStorage);
loadApiInfo(data);
}
async function fetchInfo() {
const [release, repo] = await Promise.all([
fetch(`${url}/latest-release`).then(_ => _.json()),
@@ -39,15 +68,26 @@ document$.subscribe(async () => {
};
__md_set("__git_repo", data, sessionStorage);
loadInfo(data);
loadCodebergInfo(data);
loadPluginVersion(data);
}
if(!document.querySelector('[data-md-component="source"] .md-source__facts')){
if(!document.querySelector('[data-md-component="source"] .md-source__facts')) {
const cached = __md_get("__git_repo", sessionStorage);
if((cached != null) && (cached["version"])) {
loadInfo(cached);
loadCodebergInfo(cached);
loadPluginVersion(cached);
} else {
fetchInfo();
}
}
if(location.href.includes('/api/')) {
const cachedApi = __md_get("__api_tag", sessionStorage);
if((cachedApi != null) && (cachedApi["version"])) {
loadApiInfo(cachedApi);
} else {
fetchApiInfo();
}
}
})
+260
View File
@@ -0,0 +1,260 @@
:root {
--md-badge-fg--note: #448aff;
--md-badge-bg--note: #448aff1a;
--md-badge-fg--abstract: #00b0ff;
--md-badge-bg--abstract: #00b0ff1a;
--md-badge-fg--info: #00b8d4;
--md-badge-bg--info: #00b8d41a;
--md-badge-fg--tip: #00bfa5;
--md-badge-bg--tip: #00bfa51a;
--md-badge-fg--success: #00c853;
--md-badge-bg--success: #00c8531a;
--md-badge-fg--question: #64dd17;
--md-badge-bg--question: #64dd171a;
--md-badge-fg--warning: #ff9100;
--md-badge-bg--warning: #ff91001a;
--md-badge-fg--failure: #ff5252;
--md-badge-bg--failure: #ff52521a;
--md-badge-fg--danger: #ff1744;
--md-badge-bg--danger: #ff17441a;
--md-badge-fg--bug: #f50057;
--md-badge-bg--bug: #f500571a;
--md-badge-fg--example: #7c4dff;
--md-badge-bg--example: #7c4dff1a;
--md-badge-fg--quote: #9e9e9e;
--md-badge-bg--quote: #9e9e9e1a;
--badge-icon--note: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M17.263 2.177a1.75 1.75 0 0 1 2.474 0l2.586 2.586a1.75 1.75 0 0 1 0 2.474L19.53 10.03l-.012.013L8.69 20.378a1.753 1.753 0 0 1-.699.409l-5.523 1.68a.748.748 0 0 1-.747-.188.748.748 0 0 1-.188-.747l1.673-5.5a1.75 1.75 0 0 1 .466-.756L14.476 4.963ZM4.708 16.361a.26.26 0 0 0-.067.108l-1.264 4.154 4.177-1.271a.253.253 0 0 0 .1-.059l10.273-9.806-2.94-2.939-10.279 9.813ZM19 8.44l2.263-2.262a.25.25 0 0 0 0-.354l-2.586-2.586a.25.25 0 0 0-.354 0L16.061 5.5Z"></path></svg>');
--badge-icon--abstract: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M5.962 2.513a.75.75 0 0 1-.475.949l-.816.272a.25.25 0 0 0-.171.237V21.25c0 .138.112.25.25.25h14.5a.25.25 0 0 0 .25-.25V3.97a.25.25 0 0 0-.17-.236l-.817-.272a.75.75 0 0 1 .474-1.424l.816.273A1.751 1.751 0 0 1 21 3.97v17.28A1.75 1.75 0 0 1 19.25 23H4.75A1.75 1.75 0 0 1 3 21.25V3.97a1.75 1.75 0 0 1 1.197-1.66l.816-.272a.75.75 0 0 1 .949.475Z"></path><path d="M7 1.75C7 .784 7.784 0 8.75 0h6.5C16.216 0 17 .784 17 1.75v1.5A1.75 1.75 0 0 1 15.25 5h-6.5A1.75 1.75 0 0 1 7 3.25Zm1.75-.25a.25.25 0 0 0-.25.25v1.5c0 .138.112.25.25.25h6.5a.25.25 0 0 0 .25-.25v-1.5a.25.25 0 0 0-.25-.25Z"></path></svg>');
--badge-icon--info: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M13 7.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-3 3.75a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 .75.75v4.25h.75a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1 0-1.5h.75V12h-.75a.75.75 0 0 1-.75-.75Z"></path><path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Z"></path></svg>');
--badge-icon--tip: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M14.265 1.627c0 3.545 1.869 5.327 3.479 7.021 1.54 1.62 3.006 3.163 3.006 6.102 0 4.812-3.753 8.25-8.565 8.25-4.813 0-8.935-3.421-8.935-8.25 0-2.039.962-4.011 2.509-4.899.305-.175.672.007.803.334C7.563 12.684 8.797 12.64 9.437 12c.388-.387.47-1.116-.004-2.062-2.405-4.812 1.863-8.279 4.2-8.854.336-.082.615.198.632.543ZM12.185 21.5c4.059 0 7.065-2.84 7.065-6.75 0-2.337-1.093-3.489-2.678-5.158l-.021-.023c-1.44-1.517-3.139-3.351-3.649-6.557a6.148 6.148 0 0 0-1.911 1.76c-.787 1.144-1.147 2.633-.216 4.495.603 1.205.777 2.74-.277 3.794-.657.657-1.762 1.1-2.956.586-.752-.324-1.353-.955-1.838-1.79-.567.706-.954 1.74-.954 2.893 0 3.847 3.288 6.75 7.435 6.75Z"></path></svg>');
--badge-icon--success: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M21.03 5.72a.75.75 0 0 1 0 1.06l-11.5 11.5a.747.747 0 0 1-1.072-.012l-5.5-5.75a.75.75 0 1 1 1.084-1.036l4.97 5.195L19.97 5.72a.75.75 0 0 1 1.06 0Z"></path></svg>');
--badge-icon--question: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M10.97 8.265a1.45 1.45 0 0 0-.487.57.75.75 0 0 1-1.341-.67c.2-.402.513-.826.997-1.148C10.627 6.69 11.244 6.5 12 6.5c.658 0 1.369.195 1.934.619a2.45 2.45 0 0 1 1.004 2.006c0 1.033-.513 1.72-1.027 2.215-.19.183-.399.358-.579.508l-.147.123a4.329 4.329 0 0 0-.435.409v1.37a.75.75 0 1 1-1.5 0v-1.473c0-.237.067-.504.247-.736.22-.28.486-.517.718-.714l.183-.153.001-.001c.172-.143.324-.27.47-.412.368-.355.569-.676.569-1.136a.953.953 0 0 0-.404-.806C12.766 8.118 12.384 8 12 8c-.494 0-.814.121-1.03.265ZM13 17a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path><path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Z"></path></svg>');
--badge-icon--warning: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M13 17.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-8.25a.75.75 0 0 0-1.5 0v4.5a.75.75 0 0 0 1.5 0v-4.5Z"></path><path d="M9.836 3.244c.963-1.665 3.365-1.665 4.328 0l8.967 15.504c.963 1.667-.24 3.752-2.165 3.752H3.034c-1.926 0-3.128-2.085-2.165-3.752Zm3.03.751a1.002 1.002 0 0 0-1.732 0L2.168 19.499A1.002 1.002 0 0 0 3.034 21h17.932a1.002 1.002 0 0 0 .866-1.5L12.866 3.994Z"></path></svg>');
--badge-icon--failure: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M5.72 5.72a.75.75 0 0 1 1.06 0L12 10.94l5.22-5.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L13.06 12l5.22 5.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L12 13.06l-5.22 5.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L10.94 12 5.72 6.78a.75.75 0 0 1 0-1.06Z"></path></svg>');
--badge-icon--danger: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M15.716 1.329a1.341 1.341 0 0 1 2.109 1.55L15.147 9h4.161c1.623 0 2.372 2.016 1.143 3.075L8.102 22.721a1.148 1.148 0 0 1-1.81-1.317L8.996 15H4.674c-1.619 0-2.37-2.008-1.148-3.07l12.19-10.6Zm.452 1.595L4.51 13.061a.25.25 0 0 0 .164.439h5.45a.749.749 0 0 1 .692 1.041l-2.559 6.066 11.215-9.668a.25.25 0 0 0-.164-.439H14a.75.75 0 0 1-.687-1.05Z"></path></svg>');
--badge-icon--bug: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M7.72.22a.75.75 0 0 1 1.06 0l1.204 1.203A4.98 4.98 0 0 1 12 1c.717 0 1.4.151 2.016.423L15.22.22a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-.971.972A4.991 4.991 0 0 1 17 6v1.104a2.755 2.755 0 0 1 1.917 1.974l1.998-.999a.75.75 0 0 1 .67 1.342L19 10.714V13.5l3.25.003a.75.75 0 0 1 0 1.5L19 15.001V16c0 .568-.068 1.134-.204 1.686l.04.018 2.75 1.375a.75.75 0 1 1-.671 1.342l-2.638-1.319A6.998 6.998 0 0 1 12 23a6.998 6.998 0 0 1-6.197-3.742l-2.758 1.181a.752.752 0 0 1-1.064-.776.752.752 0 0 1 .474-.602l2.795-1.199A6.976 6.976 0 0 1 5 16v-.996H1.75a.75.75 0 0 1 0-1.5H5v-2.79L2.415 9.42a.75.75 0 0 1 .67-1.342l1.998.999A2.756 2.756 0 0 1 7 7.104V6a4.99 4.99 0 0 1 1.69-3.748l-.97-.972a.75.75 0 0 1 0-1.06ZM6.5 9.75V16a5.5 5.5 0 1 0 11 0V9.75c0-.69-.56-1.25-1.25-1.25h-8.5c-.69 0-1.25.56-1.25 1.25ZM8.5 7h7V6a3.5 3.5 0 1 0-7 0Z"></path></svg>');
--badge-icon--example: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M8 8.807V3.5h-.563a.75.75 0 0 1 0-1.5h9.125a.75.75 0 0 1 0 1.5H16v5.307l5.125 9.301c.964 1.75-.302 3.892-2.299 3.892H5.174c-1.998 0-3.263-2.142-2.3-3.892ZM4.189 18.832a1.123 1.123 0 0 0 .985 1.668h13.652a1.123 1.123 0 0 0 .985-1.668L17.7 15H6.3ZM14.5 3.5h-5V9a.75.75 0 0 1-.093.362L7.127 13.5h9.746l-2.28-4.138A.75.75 0 0 1 14.5 9Z"></path></svg>');
--badge-icon--quote: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M3 6.25a.75.75 0 0 1 .75-.75h13.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.25Zm5 6.063a.75.75 0 0 1 .75-.75h11.5a.75.75 0 0 1 0 1.5H8.75a.75.75 0 0 1-.75-.75Zm0 5.937a.75.75 0 0 1 .75-.75h11.5a.75.75 0 0 1 0 1.5H8.75a.75.75 0 0 1-.75-.75ZM3.75 11a.75.75 0 0 1 .75.75v7a.75.75 0 0 1-1.5 0v-7a.75.75 0 0 1 .75-.75Z"></path></svg>');
}
/*
* Grid stuff
*/
.mdx-grid-wrapper {
display: grid;
grid-template-columns: .5fr 9fr;
gap: 1rem;
border: .075rem solid var(--md-badge-fg--note);
border-radius: .2rem;
}
.mdx-grid-child {
align-self: center;
font-size: .64rem;
}
.mdx-grid-child.mdx-grid-child--icon {
background-color: var(--md-badge-bg--note);
}
.mdx-grid-child.mdx-grid-child--icon::before {
content: "";
background-color: var(--md-badge-fg--note);
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
height: 1rem;
width: 1rem;
margin: .4rem;
display: block;
-webkit-mask-image: var(--badge-icon--note);
mask-image: var(--badge-icon--note);
}
/*
* Types
*/
/* Abstract */
.mdx-admo--abstract {
border-color: var(--md-badge-fg--abstract);
}
.mdx-admo--abstract .mdx-grid-child--icon {
background-color: var(--md-badge-bg--abstract);
}
.mdx-admo--abstract .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--abstract);
-webkit-mask-image: var(--badge-icon--abstract);
mask-image: var(--badge-icon--abstract);
}
/* Info */
.mdx-admo--info {
border-color: var(--md-badge-fg--info);
}
.mdx-admo--info .mdx-grid-child--icon {
background-color: var(--md-badge-bg--info);
}
.mdx-admo--info .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--info);
-webkit-mask-image: var(--badge-icon--info);
mask-image: var(--badge-icon--info);
}
/* Tip */
.mdx-admo--tip {
border-color: var(--md-badge-fg--tip);
}
.mdx-admo--tip .mdx-grid-child--icon {
background-color: var(--md-badge-bg--tip);
}
.mdx-admo--tip .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--tip);
-webkit-mask-image: var(--badge-icon--tip);
mask-image: var(--badge-icon--tip);
}
/* Success */
.mdx-admo--success {
border-color: var(--md-badge-fg--success);
}
.mdx-admo--success .mdx-grid-child--icon {
background-color: var(--md-badge-bg--success);
}
.mdx-admo--success .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--success);
-webkit-mask-image: var(--badge-icon--success);
mask-image: var(--badge-icon--success);
}
/* Question */
.mdx-admo--question {
border-color: var(--md-badge-fg--question);
}
.mdx-admo--question .mdx-grid-child--icon {
background-color: var(--md-badge-bg--question);
}
.mdx-admo--question .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--question);
-webkit-mask-image: var(--badge-icon--question);
mask-image: var(--badge-icon--question);
}
/* Warning */
.mdx-admo--warning {
border-color: var(--md-badge-fg--warning);
}
.mdx-admo--warning .mdx-grid-child--icon {
background-color: var(--md-badge-bg--warning);
}
.mdx-admo--warning .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--warning);
-webkit-mask-image: var(--badge-icon--warning);
mask-image: var(--badge-icon--warning);
}
/* Failure */
.mdx-admo--failure {
border-color: var(--md-badge-fg--failure);
}
.mdx-admo--failure .mdx-grid-child--icon {
background-color: var(--md-badge-bg--failure);
}
.mdx-admo--failure .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--failure);
-webkit-mask-image: var(--badge-icon--failure);
mask-image: var(--badge-icon--failure);
}
/* Danger */
.mdx-admo--danger {
border-color: var(--md-badge-fg--danger);
}
.mdx-admo--danger .mdx-grid-child--icon {
background-color: var(--md-badge-bg--danger);
}
.mdx-admo--danger .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--danger);
-webkit-mask-image: var(--badge-icon--danger);
mask-image: var(--badge-icon--danger);
}
/* Bug */
.mdx-admo--bug {
border-color: var(--md-badge-fg--bug);
}
.mdx-admo--bug .mdx-grid-child--icon {
background-color: var(--md-badge-bg--bug);
}
.mdx-admo--bug .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--bug);
-webkit-mask-image: var(--badge-icon--bug);
mask-image: var(--badge-icon--bug);
}
/* Example */
.mdx-admo--example {
border-color: var(--md-badge-fg--example);
}
.mdx-admo--example .mdx-grid-child--icon {
background-color: var(--md-badge-bg--example);
}
.mdx-admo--example .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--example);
-webkit-mask-image: var(--badge-icon--example);
mask-image: var(--badge-icon--example);
}
/* Quote */
.mdx-admo--quote {
border-color: var(--md-badge-fg--quote);
}
.mdx-admo--quote .mdx-grid-child--icon {
background-color: var(--md-badge-bg--quote);
}
.mdx-admo--quote .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--quote);
-webkit-mask-image: var(--badge-icon--quote);
mask-image: var(--badge-icon--quote);
}
+19
View File
@@ -20,6 +20,8 @@
--color-api-bg__static: #00c8531a;
--color-api-bg__final: #ff91001a;
--color-api-bg__abstract: #00bfa51a;
--md-admonition-icon--deprecated: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M16 1.75V3h5.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H8V1.75C8 .784 8.784 0 9.75 0h4.5C15.216 0 16 .784 16 1.75Zm-6.5 0V3h5V1.75a.25.25 0 0 0-.25-.25h-4.5a.25.25 0 0 0-.25.25ZM4.997 6.178a.75.75 0 1 0-1.493.144L4.916 20.92a1.75 1.75 0 0 0 1.742 1.58h10.684a1.75 1.75 0 0 0 1.742-1.581l1.413-14.597a.75.75 0 0 0-1.494-.144l-1.412 14.596a.25.25 0 0 1-.249.226H6.658a.25.25 0 0 1-.249-.226L4.997 6.178Z"></path><path d="M9.206 7.501a.75.75 0 0 1 .793.705l.5 8.5A.75.75 0 1 1 9 16.794l-.5-8.5a.75.75 0 0 1 .705-.793Zm6.293.793A.75.75 0 1 0 14 8.206l-.5 8.5a.75.75 0 0 0 1.498.088l.5-8.5Z"></path></svg>');
}
/* Page design */
@@ -148,4 +150,21 @@ api__record::before {
.api-type__primitive {
color: var(--color-api-fg-type__primitive);
font-weight: bold;
}
.md-typeset .admonition.deprecated,
.md-typeset details.deprecated {
border-color: var(--color-api-fg__deprecated);
}
.md-typeset .deprecated > .admonition-title,
.md-typeset .deprecated > summary {
background-color: var(--color-api-bg__deprecated);
}
.md-typeset .deprecated > .admonition-title::before,
.md-typeset .deprecated > summary::before {
background-color: var(--color-api-fg__deprecated);
-webkit-mask-image: var(--md-admonition-icon--deprecated);
mask-image: var(--md-admonition-icon--deprecated);
}
+2 -2
View File
@@ -6,7 +6,7 @@ icon: octicons/list-unordered-24
## About
!!! warning "The below examples may only work in v1.10.0 or newer!"
<!-- admo:info The below examples may only work in v1.10.0 or newer! -->
This page lists some examples you may want to use for your proxy or server.
@@ -72,7 +72,7 @@ Examples that can be used with the Spigot or PaperMC version.
### Different profile for banned Player
!!! warning "Requires a cached player to work reliably."
<!-- admo:info Requires a cached player -->
Displays a separate profile for when the player has been banned from the server.
+368
View File
@@ -0,0 +1,368 @@
---
icon: octicons/milestone-24
---
# Getting Started
This page will explain how to set up AdvancedServerList and make it work for your server.
It tries to be an easy to understand as possible. But if you still have problems, consider joining the [Discord Server](https://discord.gg/6dazXp6) for help.
## 1. Download the plugin { #download-the-plugin }
The first step would be to download the plugin from a download page of your choice. As of writing this is AdvancedServerList updated and available on these sites:
- [Modrinth]
- [Codeberg]
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[codeberg]: https://codeberg.org/Andre601/AdvancedServerList
The plugin is also available on these platforms, but not actively updated there anymore:
- [Spigot] (Latest version: `3.3.0-b1`)
- [Hangar] (Latest version: `3.5.0`)
[spigot]: https://www.spigotmc.org/resources/102910/
[hangar]: https://hangar.papermc.io/Andre_601/AdvancedServerList
The plugin is available for Spigot, Paper, BungeeCord, Waterfall and Velocity, and has been tested on these platforms. It may support additional forks, but this is not guaranteed.
The plugin also supports these additional plugins. Depending on the platform they are used in is the plugin required.
- [PlaceholderAPI] - Used on the Spigot and Paper server for additional Placeholder parsing.
- - [ViaVersion] - Used on the Spigot and Paper server for additional protocol version handling.
- [PAPIProxyBridge] - Used on BungeeCord, Waterfall and Velocity for PlaceholderAPI support.
- [Maintenance] - Used to disable server list handling while maintenance is active.
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
## 2. Installation { #installation }
Installing the plugin is as simple as moving the jar file into the plugins folder. Just make sure to download the right version of AdvancedServerList for the right platform.
Here is a quick table showing the jar file name with the platforms it is made for:
| Jar file name | Platforms |
|-----------------------------------------------|-----------------------|
| `AdvancedServerList-Paper-{version}.jar` | Spigot, Paper |
| `AdvancedServerList-BungeeCord-{version}.jar` | BungeeCord, Waterfall |
| `AdvancedServerList-Velocity-{version}.jar` | Velocity |
After you added it to your plugins folder - alongside any other dependency you may want or need - (re)start your server or proxy to enable the plugin.
If everything goes well should AdvancedServerList create a folder named `AdvancedServerList` (`advancedserverlist` on Velocity) with additional files and folders inside of it.
### Folder structure
When you install AdvancedServerList for the first time should it have created the following file structure inside the plugins folder of your Server or Proxy:
```
AdvancedServerList/
├── favicons/
├── profiles/
│ └── default.yml
└── config.yml
```
Let's cover the files and folders...
#### Favicons folder
This folder allows you to store PNG images that should be used as favicons by the plugin. A favicon from this folder can be used by referencing the name (Including the `.png` file extension) in the [`favicon` option of the server list profile](../profiles/index.md#favicon).
#### Profiles folder and default.yml { #profiles-folder-and-default-yml }
The profiles folder is home of the server list profile files which allow you to modify the server list entry of your server in a player's multiplayer screen.
On first creation will the folder have a `default.yml` file. This file contains all the options available to use alongside comments to try and help you in using it properly.
/// details | default.yml content
```yaml
#
# Set the priority of this profile.
# Higher number = Higher priority.
#
# Read more: https://asl.andre601.ch/profiles/#priority
#
priority: 0
#
# Set conditions that needs to be met.
# Only when all conditions return true will the profile be shown (Given no profile with higher priority is used).
#
# Read more: https://asl.andre601.ch/profiles/#conditions
#
#conditions:
# - '{playerVersion} < 759'
#
# 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://asl.andre601.ch/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://asl.andre601.ch/profiles/#motd
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
#
# 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://asl.andre601.ch/profiles/#favicon
#
favicon: ''
#
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
#
# Read more: https://asl.andre601.ch/profiles/#playercount
#
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
#
# Read more: https://asl.andre601.ch/profiles/#hover
#
hover:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
#
# Modifies the text that usually displays '<online>/<max>'
#
# 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.
#
# Remove this option or set it to text: '' to not modify the player count text.
#
# Read more: https://asl.andre601.ch/profiles/#text
#
text: ''
#
# Allows you to modify the max player count displayed.
# Note that this will affect ${server playersMax} (Except for when used in conditions).
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers
#
extraPlayers:
#
# Enables/Disables the extraPlayers option.
# When enabled will the total amount of players allowed to join be modified to the current
# number of online players + 'amount'
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
#
enabled: false
#
# Sets how much should be added/subtracted from the current number of online players
# to then use for the max player count.
#
# Example:
# When set to 1 while 10 players are online would the player count - if unmodified -
# display '10/11'. When -1 is used will it display '10/9'
#
# Defaults to 0 when not present.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
#
amount: 0
#
# Allows you to set the max players that could join your server.
# Note that this option influences the '${server playersMax}' placeholder.
#
# The settings of this option have no effect should 'extraPlayers' be enabled
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers
#
maxPlayers:
#
# Enables/Disables the maxPlayers option.
# When enabled will the total amount of players allowed to join be changed to what 'amount' is set to.
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
#
enabled: false
#
# Sets the number to display for the max number of players allowed to join your server.
#
# Example:
# Setting this option to 0 (Default) while 1 player is online would display '1/0'
#
# Defaults to 0 if not set.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
#
amount: 0
```
///
#### Config.yml
The config.yml file contains settings related to the plugin itself and some of its functionality.
These functions include, but aren't limited to:
- Setting the default name and UUID used for an unknown (Not cached) player.
- Disabling/Enabling caching of players.
- Disabling/Enabling checking for updates
- The config version used for migration. Don't touch this, or it may reset your config.
Similar to the default.yml is this file containing comments to try and explain the settings in questions.
Do note that if the config gets migrated from an older version, that the comments will be discarded in the process, unfortunately.
/// details | default config.yml content
```yaml
#
# Used for when AdvancedServerList doesn't have a cached player to use for player placeholders.
#
unknownPlayer:
#
# The name to use. Defaults to Anonymous.
#
name: "Anonymous"
#
# The UUID to use. Defaults to 606e2ff0-ed77-4842-9d6c-e1d3321c7838 (UUID of MHF_Question).
#
uuid: "606e2ff0-ed77-4842-9d6c-e1d3321c7838"
#
# Should the Caching of players be disabled?
#
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
# Placeholders that rely on the player being cached (such as ${player name}) will not work while this option is enabled.
#
# Defaults to false when not present.
#
disableCache: 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.
#
checkUpdates: true
#
# DO NOT EDIT!
#
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
config-version: 2
```
///
#### Additionally created files and folders
There are certain files and folders that get created when certain events happen:
- A `playercache.json` file will be created on plugin shutdown containing a list of IPs, UUIDs and Player names for every player that joined the server while AdvancedServerList was running.
This file allows to replace `${player name}` and `${player uuid}` with their name or UUID respectively, while they are not on the server, by using the IP they used to join with.
This file is not created nor updated when `disableCache` is set to `true` in the config.yml
- A `backups` folder containing old config.yml files.
This folder is created when AdvancedServerList migrates your old config to a new version. This allows you to transfer settings over in case the migration didn't work properly.
## 3. Creating your first profile { #creating-your-first-profile }
Creating your first profile is relatively simple.
To start, open the `default.yml` file located inside the `profiles` folder using a file editor of your choice (VSCode or Notepad++ are recommended). It should contain all the available options for a server list profile.
Next can you edit the options available to whatever you like. All text options (Except [conditions](../profiles/index.md#conditions)) support [MiniMessage formatting](../profiles/formatting.md).
If you're unsure how a specific option should look like, head over to the [Profiles page](../profiles/index.md) for more information about the general structure.
All you need to know is, that a bare-bones server list profile requires a valid [priority](../profiles/index.md#priority) and at least one of the settings to be present.
To give an example is here a basic profile that only modifies the MOTD and nothing else:
```yaml title="default.yml"
priority: 0
motd:
- 'Hello'
- 'World!'
```
### Additional profiles
To add additional profiles, create a new YAML file inside the `profiles` folder. The name doesn't matter, but it is recommended to keep it lowercase, use alphanumeric characters (`a-z, 0-9`), hyphens (`-`), underscores (`_`) and avoid spaces.
Inside the file, add a priority and at least one setting, similar to the above shown example.
This would already be enough and AdvancedServerList would use it. If you however want to only show it when certain conditions are met, should you set the priority to a higher value and add conditions.
Conditions can be multiple strings containing [operands](../profiles/index.md#operands) to evaluate them. As an example `${server playersOnline} >= 10` would return true if the current number of online players is larger or equal to 10.
Here is another example profile using conditions:
```yaml title="other_profile.yml"
priority: 1
conditions:
- '${player isBanned} = true'
motd:
- '<red>You got <bold>banned</bold> from this server.'
```
### Further examples
The [Examples page](../examples/index.md) contains more examples of different server list profiles for all kinds of situations.
## 4. Loading profiles { #loading-profiles }
Once you've set up your server list profile(s) is it time to load it/them.
To do this, simply run `/asl reload` as player (Requires permission `advancedserverlist.admin` or `advancedserverlist.command.reload`) or through the Server/Proxy console.
The plugin should then load any valid YAML file inside the `profiles` folder to then use.
And that's already it! You now have a working server list profile for your server.
+19 -15
View File
@@ -24,13 +24,11 @@ If you're new to the plugin is it recommended to check out the [Profiles page](p
AdvancedServerList supports the following platforms:
[![spigot-img]{ width="64" loading="lazy" }][spigot]
[![paper-img]{ width="64" loading="lazy" }][paper]
[![bungeecord-img]{ width="64" loading="lazy" }][spigot]
[![waterfall-img]{ width="64" loading="lazy" }][paper]
[![velocity-img]{ width="64" loading="lazy" }][velocity]
[spigot-img]: https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/spigot_vector.svg "Tested on Spigot"
[paper-img]: https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/paper_vector.svg "Tested on Paper"
[bungeecord-img]: https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/bungeecord_vector.svg "Tested on BungeeCord"
[waterfall-img]: https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/waterfall_vector.svg "Tested on Waterfall"
@@ -42,30 +40,36 @@ AdvancedServerList supports the following platforms:
## Dependencies
| Dependency | Platforms | Required? |
|-------------------------------------------------------------------------|----------------------|-----------|
| [ProtocolLib]{ target="_blank" rel="noreferrer nofollow noopener" } | Spigot | Yes |
| [PlaceholderAPI]{ target="_blank" rel="noreferrer nofollow noopener" } | Spigot, Paper | No |
| [ViaVersion]{ target="_blank" rel="noreferrer nofollow noopener" } | Spigot, Paper | No |
| [PAPIProxyBridge]{ target="_blank" rel="noreferrer nofollow noopener" } | BungeeCord, Velocity | No |
| [Maintenance]{ target="_blank" rel="noreferrer nofollow noopener" } | All | No |
/// info
All listed dependencies are optional.
///
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[viaversion]: https://www.spigotmc.org/resources/19254/
| Dependency | Platforms |
|-------------------------------------------------------------------------|----------------------|
| [PlaceholderAPI]{ target="_blank" rel="noreferrer nofollow noopener" } | Paper |
| [ViaVersion]{ target="_blank" rel="noreferrer nofollow noopener" } | Paper |
| [PAPIProxyBridge]{ target="_blank" rel="noreferrer nofollow noopener" } | BungeeCord, Velocity |
| [Maintenance]{ target="_blank" rel="noreferrer nofollow noopener" } | All |
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
## Pages
- [Getting started](getting-started/index.md)
- [Commands](commands/index.md)
- [Profiles](profiles/index.md)
- [Formatting](profiles/formatting.md)
- [Placeholders](profiles/placeholders.md)
- [API](api/index.md)
- [Changelog](api/changelog.md)
- [Reference](api/reference/index.md)
- [Examples](examples/index.md)
- [Migration](migration/index.md)
- [v1.5.3 to v1.6.0](migration/v1_5_3-to-v1_6_0.md)
- [v1.9.0 to v1.10.0](migration/v1_9_0-to-v1_10_0.md)
- [API](api/index.md)
- [Changelog](api/changelog.md)
- [Javadocs](api/javadocs.md) (External site)
- [Source Code](api/source.md) (External site)
- [Reference](api/reference/index.md)
- [PlaceholderAPI](placeholderapi/index.md)
+84 -79
View File
@@ -22,82 +22,87 @@ The migration should be fairly simple. [An example](#example) is available to lo
Here is a before and after example to help visualize the change:
=== "Before"
```yaml
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
playerCount: '<grey>Hover Me!'
xMore: 1
```
=== "After"
```yaml
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
playerCount:
hidePlayers: false
hover:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: true
amount: 1
```
=== "Diff view"
```diff
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
-hidePlayers: false
-
-players:
- - 'Line 1'
- - 'Line 2'
- - 'Line 3'
-
-playerCount: '<grey>Hover Me!'
-
-xMore: 1
+playerCount:
+ hidePlayers: false
+
+ hover:
+ - 'Line 1'
+ - 'Line 2'
+ - 'Line 3'
+
+ text: '<grey>Hover Me!'
+
+ extraPlayers:
+ enabled: true
+ amount: 1
```
/// tab | Before
```yaml
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
playerCount: '<grey>Hover Me!'
xMore: 1
```
///
/// tab | After
```yaml
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
playerCount:
hidePlayers: false
hover:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: true
amount: 1
```
///
/// tab | Diff View
```diff
priority: 0
motd:
- 'Line 1'
- 'Line 2'
favicon: '${player name}'
-hidePlayers: false
-
-players:
- - 'Line 1'
- - 'Line 2'
- - 'Line 3'
-
-playerCount: '<grey>Hover Me!'
-
-xMore: 1
+playerCount:
+ hidePlayers: false
+
+ hover:
+ - 'Line 1'
+ - 'Line 2'
+ - 'Line 3'
+
+ text: '<grey>Hover Me!'
+
+ extraPlayers:
+ enabled: true
+ amount: 1
```
///
+88 -83
View File
@@ -15,89 +15,94 @@ To migrate all you have to do is use the new `profiles` option and add separate
Here is a before and after example to help visualize the change:
=== "Before"
```yaml
priority: 0
/// tab | Before
```yaml
priority: 0
motds:
- |-
Line 1
Line 2
- |-
Line A
Line B
favicon: '${player name}'
motds:
- |-
Line 1
Line 2
- |-
Line A
Line B
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
=== "After"
```yaml
priority: 0
profiles:
# You can also use motd: ['Line 1', 'Line 2']
- motd:
- 'Line 1'
- 'Line 2'
# You can also use motd: ['Line A', 'Line B']
- motd:
- 'Line A'
- 'Line B'
favicon: '${player name}'
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
=== "Diff view"
```diff
priority: 0
favicon: '${player name}'
-motds:
- - |-
- Line 1
- Line 2
- - |-
- Line A
- Line B
+profiles:
+ # You can also use motd: ['Line 1', 'Line 2']
+ - motd:
+ - 'Line 1'
+ - 'Line 2'
+ # You can also use motd: ['Line A', 'Line B']
+ - motd:
+ - 'Line A'
+ - 'Line B'
favicon: '${player name}'
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
///
/// tab | After
```yaml
priority: 0
profiles:
# You can also use motd: ['Line 1', 'Line 2']
- motd:
- 'Line 1'
- 'Line 2'
# You can also use motd: ['Line A', 'Line B']
- motd:
- 'Line A'
- 'Line B'
favicon: '${player name}'
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
///
/// tab | Diff View
```diff
priority: 0
-motds:
- - |-
- Line 1
- Line 2
- - |-
- Line A
- Line B
+profiles:
+ # You can also use motd: ['Line 1', 'Line 2']
+ - motd:
+ - 'Line 1'
+ - 'Line 2'
+ # You can also use motd: ['Line A', 'Line B']
+ - motd:
+ - 'Line A'
+ - 'Line B'
favicon: '${player name}'
playerCount:
hidePlayers: false
players:
- 'Line 1'
- 'Line 2'
- 'Line 3'
text: '<grey>Hover Me!'
extraPlayers:
enabled: false
amount: 0
```
///
+13 -13
View File
@@ -6,23 +6,23 @@ icon: material/percent
AdvancedServerList provides support for [PlaceholderAPI] placeholders to be used, while also providing its own set of placeholders.
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
## Own placeholders
The following list of placeholders is available for use through PlaceholderAPI.
Please note that they are only available through the Bukkit version of AdvancedServerList.
The below listed placeholders can be used through PlaceholderAPI in other plugins.
Note that the values depend on the player it is used for, as AdvancedServerList will try and get a matching [Server List Profile](../profiles/index.md) to display values from.
Also note, that AdvancedServerList will try to find and use a [Server List profile](../profiles/index.md) that has maching conditions for the player, before returning any placeholder values.
This means that the output of a placeholder depends on what profile (if any) matches for the player.
| Placeholder | Description |
|---------------------------|-------------------------------------------------------------------------------|
| `%asl_favicon%` | Gives the value of `favicon` from a matching Profile. |
| `%asl_extra_players_max%` | Gives the value of `playerCount.extraPlayers.amount` from a matching Profile. |
| `%asl_motd%` | Gives the value of `motd` in the matching Profile. |
| `%asl_playercount_hover%` | Gives the value of `playerCount.hover` from a matching Profile. |
| `%asl_playercount_text%` | Gives the value of `playerCount.text` from a matching Profile. |
| Placeholder | Description |
|----------------------------------|--------------------------------------------------------------------------------------------------------|
| `%asl_favicon%` | Gives the value of `favicon` from a matching Profile. |
| `%asl_extra_players_max%` | Gives the value of `playerCount -> extraPlayers -> amount` from a matching Profile. Can return `null`. |
| `%asl_motd%` | Gives the value of `motd` in the matching Profile as a single String. |
| `%asl_playercount_extraplayers%` | Gives the value of `playerCount -> extraPlayers -> amount` from a matching Profile. Can return `null`. |
| `%asl_playercount_hover%` | Gives the value of `playerCount -> hover` from a matching Profile as a single String. |
| `%asl_playercount_maxplayers%` | Gives the value of `playerCount -> maxPlayers -> amount` from a matching profile. Can return `null`. |
| `%asl_playercount_text%` | Gives the value of `playerCount -> text` from a matching Profile. |
| `%asl_server_playersmax%` | Gives the output of `${server playersMax}` |
## Using Placeholders in Server List profiles
+6 -5
View File
@@ -6,14 +6,15 @@ icon: octicons/pencil-24
All text options, with exception of [`Conditions`](../index.md#conditions), allow the usage of formatting options using [MiniMessage].
!!! info "Online Tool"
The devs of the Adventure library provide a handy online tool to create the right formatting codes to display the text properly.
You can find the tool at https://webui.advntr.dev/
/// info | Online Tool
The devs of the Adventure library provide a handy online tool to create the right formatting codes to display the text properly.
You can find the tool at https://webui.advntr.dev/
///
## Before starting
Please make sure to surround your text with either single quotes (`'`) or double quotes (`"`) should they start with a color or formatting code.
Not surrounding these lines with (double) quotes will make the YAML parser Configurate treat them as something other than a String.
Please make sure to surround your text with either single quotes (`'`) or double quotes (`"`).
This avoids possible issues where the YAML parser would treat lines starting with specific characters as special options (i.e. `<` would be treated as a scolar value).
```yaml title="Wrong formatting"
motd:
+173 -148
View File
@@ -7,17 +7,18 @@ icon: octicons/note-24
AdvancedServerList allows the creation of multiple profiles.
A profile is a single YAML file located in the plugin's `profiles` directory containing multiple settings including [Conditions](#conditions) and [Priority](#priority).
!!! info "Important"
In order for a profile to be considered "valid" by AdvancedServerList will it need to meet the following conditions:
- Have a [`Priority`](#priority) set to a valid, whole number (i.e. `1`)
- Have **at least one** of the following options set:
- [`Profiles`](#profiles) with at least one entry containing one of the below option
- [`Motd`](#motd) set with at least one line of text
- [`Favicon`](#favicon) set with a non-empty String
- [`HidePlayers`](#hideplayers) set to `true`
- [`Hover`](#hover) set with at least one line of text
- [`Text`](#text) set with a non-empty String
/// info | Important
In order for a profile to be considered "valid" by AdvancedServerList will it need to meet the following conditions:
- Have a [`Priority`](#priority) set to a valid, whole number (i.e. `1`)
- Have **at least one** of the following options set:
- [`Profiles`](#profiles) with at least one entry containing one of the below option
- [`Motd`](#motd) set with at least one line of text
- [`Favicon`](#favicon) set with a non-empty String
- [`HidePlayers`](#hideplayers) set to `true`
- [`Hover`](#hover) set with at least one line of text
- [`Text`](#text) set with a non-empty String
///
## Priority
@@ -39,7 +40,7 @@ You can remove this option, or set it to an empty list (`conditions: []`) to alw
The following operants are available and can be used in the conditions.
!!! warning "Only one operant can be used per condition!"
<!-- admo:warning Only one operant can be used per condition! -->
| Operand | Description |
|---------|------------------------------------------------------------------------|
@@ -58,34 +59,37 @@ The following operants are available and can be used in the conditions.
## Profiles
!!! warning "Priority and Conditions are NOT supported!"
<!-- admo:warning Priority and Conditions can NOT be used within profiles -->
The `profiles` option allows you to set multiple MOTDs, player counts, etc. which the plugin would randomly choose from.
If an option such as motd is not present in an entry will it check the file for the option and use that if present.
??? example "Example"
```yaml title="YAML file"
priority: 0
profiles:
- motd:
- '<rainbow>Line 1</rainbow>'
- '<rainbow:!>Line 2</rainbow>'
playerCount:
text: '<green><bold>Awesome!'
- playerCount:
text: '<yellow><bold>Also Awesome!'
motd:
- '<rainbow:2>Line A</rainbow>'
- '<rainbow:!2>Line B</rainbow>'
```
<div class="result">
![profiles-example-1](../assets/images/examples/profiles-example-1.jpg){ loading="lazy" }
![profiles-example-2](../assets/images/examples/profiles-example-2.jpg){ loading="lazy" }
/// details | Example
type: example
</div>
```yaml title="YAML file"
priority: 0
profiles:
- motd:
- '<rainbow>Line 1</rainbow>'
- '<rainbow:!>Line 2</rainbow>'
playerCount:
text: '<green><bold>Awesome!'
- playerCount:
text: '<yellow><bold>Also Awesome!'
motd:
- '<rainbow:2>Line A</rainbow>'
- '<rainbow:!2>Line B</rainbow>'
```
<div class="result" markdown>
![profiles-example-1](../assets/images/examples/profiles-example-1.jpg){ loading="lazy" }
![profiles-example-2](../assets/images/examples/profiles-example-2.jpg){ loading="lazy" }
</div>
///
## Motd
@@ -94,20 +98,22 @@ Normal colour and formatting codes such as `<aqua>` or `<bold>` are supported. O
If you want to display multiple MOTDs will you need to use the [`Profiles` option](#profiles)
??? example "Example"
```yaml title="YAML file"
priority: 0
motd:
- '<rainbow:2>Rainbow Gradients</rainbow>'
- '<rainbow:!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
<div class="result">
/// details | Example
type: example
![motd-example](../assets/images/examples/motd-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
motd:
- '<rainbow:2>Rainbow Gradients</rainbow>'
- '<rainbow:!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
<div class="result" markdown>
![motd-example](../assets/images/examples/motd-example.jpg){ loading="lazy" }
</div>
///
## Favicon
@@ -121,23 +127,26 @@ This option currently supports the following values:
Please note that AdvancedServerList will rescale the image to be 64x64 pixels, so be sure to provide images at that particular scale.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
# Player is Andre_601
favicon: ${player uuid}
```
<div class="result">
/// details | Example
type: example
![hideplayers-example](../assets/images/examples/favicon-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
# Player is Andre_601
favicon: ${player uuid}
```
<div class="result" markdown>
![hideplayers-example](../assets/images/examples/favicon-example.jpg){ loading="lazy" }
</div>
///
## PlayerCount
@@ -148,23 +157,26 @@ The `playerCount` option contains multiple different options all about the Playe
Boolean option to set whether AdvancedServerList should hide the player count or not. When set to `true` will the player count be replaced with `???`.
Additionally will the [`Text`](#text) and [`Hover`](#hover) option be ignored.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayers: true
```
<div class="result">
/// details | Example
type: example
![hideplayers-example](../assets/images/examples/hideplayers-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayers: true
```
<div class="result" markdown>
![hideplayers-example](../assets/images/examples/hideplayers-example.jpg){ loading="lazy" }
</div>
///
### Hover
@@ -172,61 +184,68 @@ This option allows to override the hover text usually displaying the players on
You can either remove this option or set to an empty list (`hover: []`) to not override the hover.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hover:
- '<grey>Line 1'
- '<aqua>Line 2'
- '<gold>Line 3'
```
<div class="result">
/// details | Example
type: example
![hover-example](../assets/images/examples/hover-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hover:
- '<grey>Line 1'
- '<aqua>Line 2'
- '<gold>Line 3'
```
<div class="result" markdown>
![hover-example](../assets/images/examples/hover-example.jpg){ loading="lazy" }
</div>
///
### Text
This option allows to override the text usually displaying the online players and total players that can join.
Note that AdvancedServerList will not add the `<online>/<max>` text to the player count. Instead will you need to use [`${server playersOnline}`](placeholders.md#server) and [`${server playersMax}`](placeholders.md#server)
!!! info "Note"
This feature works by changing the "outdated server" message followed by altering the protocol version of the server.
Due to this will your server appear as "outdated" to the client (Have the ping icon crossed out). This is nothing that can be changed unfortunately.
/// info | Note
This feature works by changing the "outdated server" message followed by altering the protocol version of the server.
Due to this will your server appear as "outdated" to the client (Have the ping icon crossed out). This is nothing that can be changed unfortunately.
///
To not override the player count, remove this option or set it to an empty String (`text: ''`).
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
text: '<yellow><bold>Cool text!'
```
<div class="result">
/// details | Example
type: example
![hover-example](../assets/images/examples/text-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
text: '<yellow><bold>Cool text!'
```
<div class="result" markdown>
![hover-example](../assets/images/examples/text-example.jpg){ loading="lazy" }
</div>
///
### ExtraPlayers
Contains options to modify how the `<max>` number in the player count should look like.
!!! warning "Using this option will modify the `${server playersMax}` placeholder (Except in conditions)"
<!-- admo:warning Using this option will modify the <code>${server playersMax}</code> placeholder (Except when used in conditions) -->
#### Enabled { #extraplayers-enabled }
@@ -239,25 +258,28 @@ Sets the number to add to the current online players to then use as the new max
As an example, setting this to `1` while `10` players are online will display `11`, while `-1` would display `9`.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
extraPlayers:
enabled: true
amount: 1
```
<div class="result">
/// details | Example
type: example
![extraplayers-example](../assets/images/examples/extraplayers-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
extraPlayers:
enabled: true
amount: 1
```
<div class="result" markdown>
![extraplayers-example](../assets/images/examples/extraplayers-example.jpg){ loading="lazy" }
</div>
///
### MaxPlayers
@@ -268,7 +290,7 @@ Note that this feature is ignored should [`extraPlayers`](#extraplayers) be enab
In case [`hidePlayers`](#hideplayers) is enabled will the max player count not be displayed, but still changed by this option.
Should [`text`](#text) be set to a non-empty String will the max player count only be displayed when `${server playersMax}` is used.
!!! warning "Using this option will modify the `${server playersMax}` placeholder (Except in conditions)"
<!-- admo:warning Using this option will modify the <code>${server playersMax}</code> placeholder (Except when used in conditions) -->
#### Enabled { #maxplayers-enabled }
@@ -280,22 +302,25 @@ When set to `true` will the value usually displaying how many players can join b
Sets the number to display as the max number of players allowed to join your server.
Note that this will also affect the `${server playersMax}` placeholder, except when it is used inside conditions.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
maxPlayers:
enabled: true
amount: -1
```
<div class="result">
/// details | Example
type: example
![maxplayes-example](../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
```yaml title="YAML file"
priority: 0
</div>
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
maxPlayers:
enabled: true
amount: -1
```
<div class="result" markdown>
![maxplayes-example](../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
</div>
///
+3 -3
View File
@@ -43,14 +43,14 @@ These placeholders use values given by the server/proxy AdvancedServerList runs
| `${server whitelistEnabled}` | Whether the whitelist is enabled or not. Only available on Spigot/Paper |
[^4]:
An space-separated list of worlds (Spigot/Paper) or Servers (BungeeCord/Velocity) can be provided to display the number of players in these worlds/servers.
Example: `${server playersOnline lobby1 lobby2}` will display the numbers of players online on the servers `lobby1` and `lobby2`.
A comma-separated list of world (On Paper) or Server (On BungeeCord/Velocity) names can be provided to display the added numbers of players in these worlds/servers.
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
[^5]:
When the [`amount` option](../index.md#amount) is used will this placeholder display the modified max players count.
The only exception is [`conditions`](../index.md#conditions) where it uses the actual max players of the server/proxy.
[^6]:
An optional server name can be provided to display the IP/Domain associated with that server. Only works on BungeeCord/Velocity.
Example: `${server host survival}` would display the IP/Domain associated with the `survival` server.
**Example:** `${server host survival}` would display the IP/Domain associated with the `survival` server.
## PlaceholderAPI
+24 -5
View File
@@ -33,10 +33,10 @@ theme:
icon:
repo: 'simple/codeberg'
admonition:
note: 'octicons/tag-24'
note: 'octicons/pencil-24'
abstract: 'octicons/checklist-24'
info: 'octicons/info-24'
tip: 'octicons/squirrel-24'
tip: 'octicons/light-bulb-24'
success: 'octicons/check-24'
question: 'octicons/question-24'
warning: 'octicons/alert-24'
@@ -49,6 +49,7 @@ theme:
extra_css:
- assets/stylesheets/custom.css
- assets/stylesheets/api-docs.css
- assets/stylesheets/admo.css
extra_javascript:
- assets/js/repo-stats.js
@@ -71,7 +72,6 @@ plugins:
- pagenav-generator
markdown_extensions:
- markdown.extensions.admonition:
- markdown.extensions.toc:
permalink: true
- markdown.extensions.attr_list:
@@ -83,6 +83,25 @@ markdown_extensions:
- pymdownx.highlight:
- pymdownx.magiclink:
- pymdownx.superfences:
- pymdownx.tabbed:
- pymdownx.snippets:
base_path: docs/.snippets
- pymdownx.blocks.admonition:
types:
- note
- abstract
- info
- tip
- success
- question
- warning
- failure
- danger
- bug
- example
- quote
- pymdownx.blocks.tab:
alternate_style: true
- pymdownx.details:
- pymdownx.blocks.details:
hooks:
- docs/.hooks/badges.py
+5 -23
View File
@@ -34,7 +34,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bukkit</artifactId>
<artifactId>paper</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
@@ -85,24 +85,6 @@
<version>1.20-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
@@ -112,19 +94,19 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.3</version>
<version>2.11.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.8.0</version>
<version>4.8.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Bukkit-${plugin.version}</finalName>
<finalName>AdvancedServerList-Paper-${plugin.version}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -143,7 +125,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -25,7 +25,6 @@
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
@@ -25,41 +25,52 @@
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bukkit.listeners.JoinEvent;
import ch.andre601.advancedserverlist.bukkit.listeners.LoadEvent;
import ch.andre601.advancedserverlist.bukkit.listeners.WorldEvents;
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitPlayerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.BukkitServerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.placeholders.PAPIPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.WorldCache;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.paper.listeners.PaperPingEvent;
import ch.andre601.advancedserverlist.paper.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.paper.listeners.LoadEvent;
import ch.andre601.advancedserverlist.paper.logging.PaperLogger;
import ch.andre601.advancedserverlist.paper.objects.WorldCache;
import ch.andre601.advancedserverlist.paper.objects.placeholders.PAPIPlaceholders;
import ch.andre601.advancedserverlist.paper.objects.placeholders.PaperPlayerPlaceholders;
import ch.andre601.advancedserverlist.paper.objects.placeholders.PaperServerPlaceholders;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.CachedServerIcon;
import java.nio.file.Path;
public class PaperCore extends BukkitCore<CachedServerIcon>{
public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon>{
private final PluginLogger logger = new BukkitLogger(getLogger());
private final PluginLogger logger = new PaperLogger(this.getLogger());
private AdvancedServerList<CachedServerIcon> core;
private FaviconHandler<CachedServerIcon> faviconHandler = null;
private PAPIPlaceholders<CachedServerIcon> papiPlaceholders = null;
private PAPIPlaceholders papiPlaceholders = null;
private WorldCache worldCache = null;
@Override
public void onEnable(){
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init(), BukkitServerPlaceholders.init());
try{
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
}catch(ClassNotFoundException ignored){
try{
// Above class only exists since 1.19+. This is a fallback to see if an older version is used.
Class.forName("com.destroystokyo.paper.PaperConfig");
}catch(ClassNotFoundException ex){
printNoPaperWarning();
return;
}
}
this.core = AdvancedServerList.init(this, new PaperPlayerPlaceholders(), new PaperServerPlaceholders());
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
papiPlaceholders = PAPIPlaceholders.init(this);
papiPlaceholders = new PAPIPlaceholders(this);
}
@Override
@@ -86,8 +97,7 @@ public class PaperCore extends BukkitCore<CachedServerIcon>{
@Override
public void loadEvents(){
LoadEvent.init(this);
PaperPingEvent.init(this);
new LoadEvent(this);
}
@Override
@@ -143,11 +153,31 @@ public class PaperCore extends BukkitCore<CachedServerIcon>{
return "paper";
}
@Override
public WorldCache getWorldCache(){
if(worldCache != null)
return worldCache;
return (worldCache = new WorldCache());
}
private void printNoPaperWarning(){
getPluginLogger().warn("======================================================================================");
getPluginLogger().warn("THIS SERVER DOES NOT USE PAPER OR A COMPATIBLE FORK!");
getPluginLogger().warn("");
getPluginLogger().warn("AdvancedServerList 3.6.0 has dropped support for Spigot-based servers.");
getPluginLogger().warn("This means that only servers using Paper or a Paper-compatible fork may work.");
getPluginLogger().warn("");
getPluginLogger().warn("Reasons for this removal:");
getPluginLogger().warn(" - Reliance on a different plugin for core functionalities.");
getPluginLogger().warn(" - Bad dependency loading limited to MavenCentral only.");
getPluginLogger().warn("");
getPluginLogger().warn("Please consider switching to Paper or one of the Paper-compatible forks to benefit from");
getPluginLogger().warn("overall performance improvements amongst other things.");
getPluginLogger().warn("");
getPluginLogger().warn("AdvancedServerList will now disable itself. If you believe this was a mistake, report");
getPluginLogger().warn("this on Codeberg: https://codeberg.org/Andre601/AdvancedServerList");
getPluginLogger().warn("======================================================================================");
Bukkit.getPluginManager().disablePlugin(this);
}
}
@@ -0,0 +1,54 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper.commands;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class CmdAdvancedServerList extends Command{
private final PaperCore plugin;
public CmdAdvancedServerList(PaperCore plugin){
super(
"advancedserverlist",
"Main command of the plugin",
"/asl [reload|help|clearCache]",
Collections.singletonList("asl")
);
this.plugin = plugin;
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(new PaperCmdSender(sender), args);
return true;
}
}
@@ -23,9 +23,9 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.listeners;
package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -34,19 +34,15 @@ import org.bukkit.event.player.PlayerJoinEvent;
import java.net.InetSocketAddress;
public class JoinEvent<F> implements Listener{
public class JoinEvent implements Listener{
private final BukkitCore<F> plugin;
private final PaperCore plugin;
private JoinEvent(BukkitCore<F> plugin){
public JoinEvent(PaperCore plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public static <F> void init(BukkitCore<F> plugin){
new JoinEvent<>(plugin);
}
@EventHandler
public void onJoin(PlayerJoinEvent event){
InetSocketAddress address = event.getPlayer().getAddress();
@@ -23,34 +23,30 @@
*
*/
package ch.andre601.advancedserverlist.core.objects;
package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerLoadEvent;
public class GenericServerImpl implements GenericServer{
public class LoadEvent implements Listener{
private final int online;
private final int max;
private final String host;
private final PaperCore plugin;
public GenericServerImpl(int online, int max, String host){
this.online = online;
this.max = max;
this.host = host;
public LoadEvent(PaperCore plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@Override
public int getPlayersOnline(){
return online;
}
@Override
public int getPlayersMax(){
return max;
}
@Override
public String getHost(){
return host;
@EventHandler
public void onLoad(ServerLoadEvent event){
new JoinEvent(plugin);
new PingEvent(plugin);
new WorldEvents(plugin);
// Load currently loaded worlds into the WorldCache
Bukkit.getWorlds().forEach(world -> plugin.getWorldCache().addWorld(world));
}
}
@@ -28,16 +28,15 @@ package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.listeners.PreServerListSetEventImpl;
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitServerImpl;
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperPlayerImpl;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperServerImpl;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import com.destroystokyo.paper.profile.PlayerProfile;
import me.clip.placeholderapi.PlaceholderAPI;
@@ -49,7 +48,7 @@ import org.bukkit.util.CachedServerIcon;
import java.awt.image.BufferedImage;
import java.util.*;
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, BukkitPlayerImpl>{
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, PaperPlayerImpl>{
private final PaperCore plugin;
private final PaperServerListPingEvent event;
@@ -89,7 +88,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
}
@Override
public void setPlayers(List<String> lines, BukkitPlayerImpl player, GenericServer server){
public void setPlayers(List<String> lines, PaperPlayerImpl player, GenericServer server){
event.getPlayerSample().clear();
List<PlayerProfile> players = new ArrayList<>(lines.size());
@@ -159,7 +158,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
}
@Override
public String parsePAPIPlaceholders(String text, BukkitPlayerImpl player){
public String parsePAPIPlaceholders(String text, PaperPlayerImpl player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
@@ -172,20 +171,20 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
}
@Override
public BukkitCore<CachedServerIcon> getPlugin(){
public PluginCore<CachedServerIcon> getPlugin(){
return plugin;
}
@Override
public BukkitPlayerImpl createPlayer(CachedPlayer player, int protocol){
public PaperPlayerImpl createPlayer(CachedPlayer player, int protocol){
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
return new BukkitPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
return new PaperPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
}
@Override
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
return new BukkitServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
return new PaperServerImpl(plugin.getWorldCache().worlds(), playersOnline, playersMax, host);
}
@Override
@@ -31,19 +31,15 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class PaperPingEvent implements Listener{
public class PingEvent implements Listener{
private final PaperCore plugin;
private PaperPingEvent(PaperCore plugin){
public PingEvent(PaperCore plugin){
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public static void init(PaperCore plugin){
new PaperPingEvent(plugin);
}
@EventHandler
public void onPaperServerListPing(PaperServerListPingEvent event){
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.listeners;
package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.api.bukkit.events.PreServerListSetEvent;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
@@ -23,10 +23,9 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.listeners;
package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import org.bukkit.Bukkit;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
@@ -34,20 +33,15 @@ import org.bukkit.event.world.WorldUnloadEvent;
public class WorldEvents implements Listener{
private final BukkitCore<?> plugin;
private final PaperCore plugin;
private WorldEvents(BukkitCore<?> plugin){
public WorldEvents(PaperCore plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public static void init(BukkitCore<?> plugin){
new WorldEvents(plugin);
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event){
plugin.getWorldCache().addWorld(event.getWorld().getName(), event.getWorld());
plugin.getWorldCache().addWorld(event.getWorld());
}
@EventHandler
@@ -23,18 +23,18 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.logging;
package ch.andre601.advancedserverlist.paper.logging;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class BukkitLogger implements PluginLogger{
public class PaperLogger implements PluginLogger{
private final Logger logger;
public BukkitLogger(Logger logger){
public PaperLogger(Logger logger){
this.logger = logger;
}
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.objects;
package ch.andre601.advancedserverlist.paper.objects;
import org.bukkit.World;
@@ -36,15 +36,15 @@ public record WorldCache(Map<String, World> worlds){
this(new HashMap<>());
}
public boolean containsWorld(String key){
return worlds().containsKey(key);
public boolean containsWorld(String name){
return this.worlds.containsKey(name);
}
public void addWorld(String key, World world){
worlds().put(key, world);
public void addWorld(World world){
this.worlds.put(world.getName(), world);
}
public void removeWorld(String key){
worlds().remove(key);
public void removeWorld(String name){
this.worlds.remove(name);
}
}
@@ -23,31 +23,30 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.objects.impl;
package ch.andre601.advancedserverlist.paper.objects.impl;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitPlayer;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
import org.bukkit.OfflinePlayer;
public class BukkitPlayerImpl extends GenericPlayerImpl implements BukkitPlayer{
public class PaperPlayerImpl extends GenericPlayerImpl implements BukkitPlayer{
private final OfflinePlayer player;
private boolean playedBefore = false;
private boolean banned = false;
private boolean whitelisted = false;
public BukkitPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
public PaperPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
this.player = player;
this.name = player == null ? cachedPlayer.getName() : player.getName();
this.protocol = protocol;
this.uuid = player == null ? cachedPlayer.getUuid() : player.getUniqueId();
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
@@ -23,15 +23,14 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.objects.impl;
package ch.andre601.advancedserverlist.paper.objects.impl;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitServer;
import org.bukkit.World;
import java.util.Map;
public record BukkitServerImpl(Map<String, World> worlds, int playersOnline, int playersMax, String host) implements BukkitServer{
public record PaperServerImpl(Map<String, World> worlds, int playersOnline, int playersMax, String host) implements BukkitServer {
@Override
public Map<String, World> getWorlds(){
return worlds;
@@ -23,22 +23,19 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.objects.placeholders;
package ch.andre601.advancedserverlist.paper.objects.placeholders;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitPlayer;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.objects.impl.BukkitPlayerImpl;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.objects.GenericServerImpl;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.listeners.ProtocolLibEvents;
import com.comphenix.protocol.ProtocolLibrary;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperPlayerImpl;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperServerImpl;
import com.viaversion.viaversion.api.Via;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
@@ -46,22 +43,19 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class PAPIPlaceholders<F> extends PlaceholderExpansion{
public class PAPIPlaceholders extends PlaceholderExpansion{
private final BukkitCore<F> plugin;
private final PaperCore plugin;
private PAPIPlaceholders(BukkitCore<F> plugin){
public PAPIPlaceholders(PaperCore plugin){
this.plugin = plugin;
this.register();
}
public static <F> PAPIPlaceholders<F> init(BukkitCore<F> plugin){
return new PAPIPlaceholders<>(plugin);
}
@Override
public @NotNull String getIdentifier(){
return "asl";
@@ -84,16 +78,15 @@ public class PAPIPlaceholders<F> extends PlaceholderExpansion{
@Override
public String onPlaceholderRequest(Player pl, @NotNull String identifier){
InetSocketAddress address = pl.getAddress();
String host = resolveVirtualHost(pl, address);
String host = pl.getVirtualHost() == null ? null : pl.getVirtualHost().getHostString();
CachedPlayer cached = plugin.getCore().getPlayerHandler().getCachedPlayer(pl.getUniqueId());
int protocol = resolveProtocol(pl);
int online = Bukkit.getOnlinePlayers().size();
int max = Bukkit.getMaxPlayers();
GenericServer server = new GenericServerImpl(online, max, host);
GenericPlayer player = new BukkitPlayerImpl(pl, cached, protocol);
BukkitServer server = new PaperServerImpl(plugin.getWorldCache().worlds(), online, max, host);
BukkitPlayer player = new PaperPlayerImpl(pl, cached, protocol);
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
if(profile == null)
@@ -101,55 +94,48 @@ public class PAPIPlaceholders<F> extends PlaceholderExpansion{
ProfileEntry entry = ProfileManager.merge(profile);
if(ProfileManager.checkOption(entry.extraPlayersEnabled()))
Integer maxPlayers = null;
if(ProfileManager.checkOption(entry.maxPlayersEnabled())){
max = entry.maxPlayersCount() == null ? 0 : entry.maxPlayersCount();
maxPlayers = entry.maxPlayersCount();
}
Integer extraPlayers = null;
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
extraPlayers = entry.extraPlayersCount();
}
GenericServer finalServer = new GenericServerImpl(online, max, host);
BukkitServer finalServer = new PaperServerImpl(plugin.getWorldCache().worlds(), online, max, host);
return switch(identifier.toLowerCase(Locale.ROOT)){
case "motd" -> getOption(entry.motd(), pl, player, finalServer);
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer);
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
case "extra_players_max" -> String.valueOf(max);
case "playercount_extraplayers" -> extraPlayers == null ? "null" : String.valueOf(extraPlayers);
case "playercount_maxplayers" -> maxPlayers == null ? "null" : String.valueOf(maxPlayers);
case "server_playersmax" -> String.valueOf(max);
default -> null;
};
}
private String getOption(String str, Player pl, GenericPlayer player, GenericServer server){
return getOption(Collections.singletonList(str), pl, player, server);
}
private String getOption(List<String> list, Player pl, GenericPlayer player, GenericServer server){
return ComponentParser.list(list)
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
.modifyText(text -> StringReplacer.replace(text, player, server))
.toString();
}
private int resolveProtocol(Player player){
if(Bukkit.getPluginManager().isPluginEnabled("ViaVersion"))
return Via.getAPI().getPlayerVersion(player.getUniqueId());
// Since Spigot version requires ProtocolLib can we use it here safely if the plugin instance is SpigotCore.
if(plugin instanceof SpigotCore)
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
// getProtocolVersion is only in Paper, so this is only called when main class isn't SpigotCore.
// Also, ViaVersion is not present, so the player protocol *should* be the same as the server.
// Since ViaVersion isn't installed is the player's protocol version the same as the server.
//noinspection deprecation
return Bukkit.getUnsafe().getProtocolVersion();
}
private String resolveVirtualHost(Player player, InetSocketAddress address){
try {
// Server is a Paper Server with Player#getVirtualHost()
Class.forName("com.destroystokyo.paper.network.NetworkClient");
return player.getVirtualHost() == null ? null : player.getVirtualHost().getHostString();
}catch(ClassNotFoundException ignored){}
if(address == null)
return null;
return ProtocolLibEvents.getHostAddresses().get(address.getHostString());
private String getOption(String str, Player pl, BukkitPlayer player, BukkitServer server){
return getOption(Collections.singletonList(str), pl, player, server);
}
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server){
return ComponentParser.list(list)
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
.modifyText(text -> StringReplacer.replace(text, player, server))
.toString();
}
}
@@ -23,24 +23,31 @@
*
*/
package ch.andre601.advancedserverlist.core.objects;
package ch.andre601.advancedserverlist.paper.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperPlayerImpl;
public class ServerPlaceholders extends PlaceholderProvider{
public class PaperPlayerPlaceholders extends PlaceholderProvider{
public ServerPlaceholders(){
super("server");
public PaperPlayerPlaceholders(){
super("player");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer genericPlayer, GenericServer genericServer){
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!(player instanceof PaperPlayerImpl paperPlayer))
return null;
return switch(placeholder){
case "playersOnline" -> String.valueOf(genericServer.getPlayersOnline());
case "playersMax" -> String.valueOf(genericServer.getPlayersMax());
case "host" -> genericServer.getHost();
case "name" -> paperPlayer.getName();
case "protocol" -> String.valueOf(paperPlayer.getProtocol());
case "uuid" -> paperPlayer.getUUID().toString();
case "hasPlayedBefore" -> String.valueOf(paperPlayer.hasPlayedBefore());
case "isBanned" -> String.valueOf(paperPlayer.isBanned());
case "isWhitelisted" -> String.valueOf(paperPlayer.isWhitelisted());
default -> null;
};
}
@@ -23,38 +23,38 @@
*
*/
package ch.andre601.advancedserverlist.bukkit.objects.placeholders;
package ch.andre601.advancedserverlist.paper.objects.placeholders;
import ch.andre601.advancedserverlist.api.bukkit.objects.BukkitServer;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperServerImpl;
import org.bukkit.Bukkit;
import org.bukkit.World;
public class BukkitServerPlaceholders extends PlaceholderProvider{
public class PaperServerPlaceholders extends PlaceholderProvider{
private BukkitServerPlaceholders(){
public PaperServerPlaceholders(){
super("server");
}
public static BukkitServerPlaceholders init(){
return new BukkitServerPlaceholders();
}
@Override
public String parsePlaceholder(String placeholders, GenericPlayer player, GenericServer server){
if(!(server instanceof BukkitServer bukkitServer))
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!(server instanceof PaperServerImpl paperServer))
return null;
String[] args = placeholders.split("\\s", 2);
String[] args = placeholder.split("\\s", 2);
return switch(args[0]){
case "playersOnline" -> {
if(args.length >= 2){
String[] worlds = args[1].split(",");
int players = 0;
for(int i = 1; i < args.length; i++){
World world = bukkitServer.getWorlds().get(args[i]);
for(String worldName : worlds){
if(worldName.isEmpty())
continue;
World world = paperServer.worlds().get(worldName);
if(world == null)
continue;
@@ -64,19 +64,19 @@ public class BukkitServerPlaceholders extends PlaceholderProvider{
yield String.valueOf(players);
}
yield String.valueOf(bukkitServer.getPlayersOnline());
yield String.valueOf(paperServer.playersOnline());
}
case "playersMax" -> {
if(args.length >= 2)
yield null;
yield String.valueOf(bukkitServer.getPlayersMax());
yield String.valueOf(paperServer.getPlayersMax());
}
case "host" -> {
if(args.length >= 2)
yield null;
yield bukkitServer.getHost();
yield paperServer.getHost();
}
case "whitelistEnabled" -> {
if(args.length >= 2)
@@ -1,24 +1,24 @@
#
# This file is kept for Folia support.
#
name: 'AdvancedServerList'
author: 'Andre_601'
version: '${plugin.version}'
description: '${plugin.description}'
main: 'ch.andre601.advancedserverlist.spigot.SpigotCore'
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
api-version: 1.19
api-version: '1.19'
folia-supported: true
libraries:
- 'org.spongepowered:configurate-yaml: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'
- 'PlaceholderAPI'
- 'Maintenance'
+2 -2
View File
@@ -38,7 +38,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.commit/>
<plugin.version>3.5.0</plugin.version>
<plugin.version>3.6.0</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<api.version>v3.1.0</api.version>
@@ -57,7 +57,7 @@
<modules>
<module>core</module>
<module>bungeecord</module>
<module>bukkit</module>
<module>paper</module>
<module>velocity</module>
<module>version-uploader</module>
</modules>
+2 -2
View File
@@ -1,4 +1,4 @@
mkdocs-material==9.4.1
mkdocs-glightbox==0.3.4
mkdocs-material==9.4.14
mkdocs-glightbox==0.3.5
mkdocs-awesome-pages-plugin==2.9.2
git+https://github.com/Andre601/mkdocs-pagenav-generator
+2 -2
View File
@@ -84,7 +84,7 @@
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -106,7 +106,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -51,10 +51,14 @@ public class VelocityServerPlaceholders extends PlaceholderProvider{
return switch(args[0]){
case "playersOnline" -> {
if(args.length >= 2){
int players = 0;
String[] servers = args[1].split(",");
for(int i = 1; i < args.length; i++){
RegisteredServer registeredServer = proxy.getServers().get(args[i]);
int players = 0;
for(String serverName : servers){
if(serverName.isEmpty())
continue;
RegisteredServer registeredServer = proxy.getServers().get(serverName);
if(registeredServer == null)
continue;
+4 -4
View File
@@ -52,19 +52,19 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
<version>1.4.14</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
<version>5.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -109,7 +109,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
@@ -29,10 +29,10 @@ import java.util.List;
public enum PlatformInfo{
BUKKIT(
"bukkit",
"bukkit/target/AdvancedServerList-Bukkit-{{version}}.jar",
"spigot", "paper", "folia"
PAPER(
"paper",
"paper/target/AdvancedServerList-Paper-{{version}}.jar",
"paper", "folia"
),
BUNGEECORD(
"bungeecord",
@@ -85,7 +85,7 @@ public class VersionUploader{
return;
}
default -> {
LOGGER.warn("Unknown argument '{}' provided. Supported are '--all', '--modrinth' and '--hangar'", args[0]);
LOGGER.warn("Unknown argument '{}' provided. Supported are '--all', '--modrinth', '--hangar' and '--dryrun'", args[0]);
System.exit(1);
return;
}
@@ -38,7 +38,6 @@ import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.FileBody;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.entity.mime.StringBody;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpMessage;
@@ -79,8 +78,6 @@ public class HangarVersionUploader{
return CompletableFuture.completedFuture(null);
}
final Namespace project = new Namespace("Andre_601", "AdvancedServerList");
final String releaseVersion = release.tagName().startsWith("v") ? release.tagName().substring(1) : release.tagName();
final String pluginVersion = VersionUploader.retrieveVersion();
@@ -93,23 +90,23 @@ public class HangarVersionUploader{
boolean preRelease = release.prerelease();
final List<Path> filePaths = List.of(
new File(PlatformInfo.BUKKIT.getFilePath().replace("{{version}}", pluginVersion)).toPath(),
new File(PlatformInfo.PAPER.getFilePath().replace("{{version}}", pluginVersion)).toPath(),
new File(PlatformInfo.BUNGEECORD.getFilePath().replace("{{version}}", pluginVersion)).toPath(),
new File(PlatformInfo.VELOCITY.getFilePath().replace("{{version}}", pluginVersion)).toPath()
);
final List<Dependency> bukkitDependencies = List.of(
Dependency.fromNamespace("ViaVersion", false, new Namespace("ViaVersion", "ViaVersion")),
Dependency.fromNamespace("Maintenance", false, new Namespace("kennytv", "Maintenance")),
Dependency.fromUrl("PlaceholderAPI", false, "https://www.spigot.org/resources/6245/")
final List<Dependency> paperDependencies = List.of(
Dependency.fromNamespace("ViaVersion", false),
Dependency.fromNamespace("Maintenance", false),
Dependency.fromNamespace("PlaceholderAPI", false)
);
final List<Dependency> bungeeDependencies = List.of(
Dependency.fromNamespace("PapiProxyBridge", false, new Namespace("William278", "PAPIProxyBridge")),
Dependency.fromNamespace("Maintenance", false, new Namespace("kennytv", "Maintenance"))
Dependency.fromNamespace("PapiProxyBridge", false),
Dependency.fromNamespace("Maintenance", false)
);
final List<Dependency> velocityDependencies = List.of(
Dependency.fromNamespace("PapiProxyBridge", false, new Namespace("William278", "PAPIProxyBridge")),
Dependency.fromNamespace("Maintenance", false, new Namespace("kennytv", "Maintenance"))
Dependency.fromNamespace("PapiProxyBridge", false),
Dependency.fromNamespace("Maintenance", false)
);
final List<MultipartObject> fileInfo = List.of(
@@ -121,7 +118,7 @@ public class HangarVersionUploader{
final Version versionUpload = new Version(
releaseVersion,
Map.of(
Platform.PAPER, bukkitDependencies,
Platform.PAPER, paperDependencies,
Platform.WATERFALL, bungeeDependencies,
Platform.VELOCITY, velocityDependencies
),
@@ -130,7 +127,7 @@ public class HangarVersionUploader{
Platform.WATERFALL, List.of("1.19.x", "1.20.x"),
Platform.VELOCITY, Collections.singletonList("3.2")
),
changelog,
changelog.replaceAll("\r\n", "\n"),
fileInfo,
preRelease ? "Beta" : "Release"
);
@@ -138,21 +135,22 @@ public class HangarVersionUploader{
if(dryrun){
String json = GSON.toJson(versionUpload);
LOGGER.info("Namespace: {}", project);
LOGGER.info("Namespace: AdvancedServerList");
LOGGER.info("JSON: {}", json);
return CompletableFuture.completedFuture(json);
}
try(CloseableHttpClient client = HttpClients.createDefault()){
return uploadVersion(client, project, versionUpload, filePaths);
try{
HttpClient client = HttpClients.createDefault();
return uploadVersion(client, versionUpload, filePaths);
}catch(ParseException | IOException ex){
LOGGER.warn("Unable to upload to Hangar! Encountered an exception.", ex);
return CompletableFuture.failedFuture(ex);
LOGGER.warn("Encountered an exception while uploading to Hangar!", ex);
return CompletableFuture.completedFuture(ex);
}
}
private CompletableFuture<?> uploadVersion(HttpClient client, Namespace namespace, Version versionUpload, List<Path> filePaths) throws IOException, ParseException{
private CompletableFuture<?> uploadVersion(HttpClient client, Version versionUpload, List<Path> filePaths) throws IOException, ParseException{
return CompletableFuture.supplyAsync(() -> {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("versionUpload", new StringBody(GSON.toJson(versionUpload), ContentType.APPLICATION_JSON));
@@ -161,7 +159,7 @@ public class HangarVersionUploader{
builder.addPart("files", new FileBody(path.toFile(), ContentType.DEFAULT_BINARY));
}
HttpPost post = new HttpPost(API_URL + "projects/" + namespace + "/upload");
HttpPost post = new HttpPost(API_URL + "projects/AdvancedServerList/upload");
post.setEntity(builder.build());
try{
this.addAuthHeader(client, post);
@@ -173,6 +171,7 @@ public class HangarVersionUploader{
"Received non-successful response while uploading release. Code: %d, Message: %s", response.getCode(), response.getReasonPhrase()
));
}
LOGGER.info("Successfully uploaded new release on Hangar!");
return true;
});
}catch(IOException ex){
@@ -25,18 +25,18 @@
package ch.andre601.advancedserverlist.versionuploader.hangar.version;
public record Dependency(String name, boolean required, Namespace namespace, String externalUrl){
public record Dependency(String name, String externalUrl, boolean required){
public Dependency{
if(namespace == null && externalUrl == null)
if(name == null && externalUrl == null)
throw new IllegalStateException("Either a namespace or external URL needs to be defined.");
}
public static Dependency fromNamespace(String name, boolean required, Namespace namespace){
return new Dependency(name, required, namespace, null);
public static Dependency fromNamespace(String name, boolean required){
return new Dependency(name, null, required);
}
public static Dependency fromUrl(String name, boolean required, String url){
return new Dependency(name, required, null, url);
public static Dependency fromUrl(String url, boolean required){
return new Dependency(null, url, required);
}
}
@@ -1,33 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.versionuploader.hangar.version;
public record Namespace(String owner, String slug){
@Override
public String toString(){
return owner() + "/" + slug();
}
}
@@ -47,11 +47,11 @@ public class ModrinthVersionUploader{
private static final Logger LOGGER = LoggerFactory.getLogger(ModrinthVersionUploader.class);
private final List<PlatformInfo> platforms = List.of(
PlatformInfo.BUKKIT,
PlatformInfo.PAPER,
PlatformInfo.BUNGEECORD,
PlatformInfo.VELOCITY
);
private final List<String> versions = List.of("1.19.4", "1.20", "1.20.1", "1.20.2");
private final List<String> versions = List.of("1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1", "1.20.2");
private final ModrinthAPI api;
@@ -87,7 +87,9 @@ public class ModrinthVersionUploader{
List<ProjectVersion.ProjectDependency> dependencies = new ArrayList<>();
// Maintenance plugin
dependencies.add(new ProjectVersion.ProjectDependency(null, "VCAqN1ln", null, ProjectVersion.ProjectDependencyType.OPTIONAL));
if(!platforms.get(i).getPlatform().equalsIgnoreCase("bukkit")){
// ViaVersion plugin
dependencies.add(new ProjectVersion.ProjectDependency(null, "P1OZGk5p", null, ProjectVersion.ProjectDependencyType.OPTIONAL));
if(!platforms.get(i).getPlatform().equalsIgnoreCase("paper")){
// PAPIProxyBridge plugin
dependencies.add(new ProjectVersion.ProjectDependency(null, "bEIUEGTX", null, ProjectVersion.ProjectDependencyType.OPTIONAL));
}