mirror of
https://codeberg.org/Andre601/AdvancedServerList.git
synced 2026-11-05 09:00:15 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e2d760ea6 | ||
|
|
c1e7e6b3ff | ||
|
|
96d383a5a1 | ||
|
|
79ba7877bf | ||
|
|
86b9aaa7c6 | ||
|
|
0cb3c036af | ||
|
|
b1f7b75e2d | ||
|
|
e9bc72c165 | ||
|
|
93203249fe | ||
|
|
2523ccb425 | ||
|
|
94972dad31 | ||
|
|
f8ac310259 | ||
|
|
5d8f5d81ed | ||
|
|
3111d7933d | ||
|
|
55f7e17d34 | ||
|
|
0e88a50deb | ||
|
|
83f351de6d | ||
|
|
b96d1cb1a9 | ||
|
|
517ff1df82 | ||
|
|
e8c7c4ee18 | ||
|
|
da44eac70e | ||
|
|
e85c121ee4 | ||
|
|
0c175999fc | ||
|
|
9c3f237f6d | ||
|
|
777545c94f | ||
|
|
dd197609e1 | ||
|
|
14ee306463 | ||
|
|
a635aa8c91 | ||
|
|
050ac3262a | ||
|
|
89aa309c90 | ||
|
|
e9b004c3f2 | ||
|
|
3ecca64a3d | ||
|
|
96dcea4e5b | ||
|
|
400f4709f5 | ||
|
|
5d4307128b | ||
|
|
65c96690f6 | ||
|
|
483d582cd1 | ||
|
|
6f14e17ae7 | ||
|
|
ff32cc1005 | ||
|
|
bcc18d7738 | ||
|
|
629079b438 | ||
|
|
bce03b68a8 | ||
|
|
841c32de0d | ||
|
|
f321ef0162 | ||
|
|
eca32d1858 | ||
|
|
f2c1f6e491 | ||
|
|
af31aac07e | ||
|
|
f8db3e7706 | ||
|
|
3d3ea2913c | ||
|
|
7b7042a856 | ||
|
|
c66c4f21f3 | ||
|
|
890a3f7b46 | ||
|
|
73b969bc51 | ||
|
|
55c93d8d59 | ||
|
|
e1ed8c1cb2 | ||
|
|
e2a91a461a | ||
|
|
8a454004a4 | ||
|
|
8df862530d | ||
|
|
4a1c93fb1b | ||
|
|
e795cf31eb | ||
|
|
e8d93d064f | ||
|
|
6a2a90b868 | ||
|
|
9cea1d3841 | ||
|
|
7453b43d6b | ||
|
|
7e30f937bd | ||
|
|
176a8ac42e | ||
|
|
f480ff51e1 | ||
|
|
e72b772cb9 | ||
|
|
c91faa899e | ||
|
|
e5c6d77e3d | ||
|
|
e8ad2c8266 | ||
|
|
d244f2816a | ||
|
|
73f3172504 | ||
|
|
d7c9f73898 | ||
|
|
2b6818180f | ||
|
|
c7c14799e3 | ||
|
|
59774347f6 | ||
|
|
e45f9a1e73 | ||
|
|
a44235dc10 | ||
|
|
52569a3588 | ||
|
|
602a8e27ea | ||
|
|
81a23953e5 | ||
|
|
9daf8f3a3e | ||
|
|
3d5b4501e3 | ||
|
|
67047e9877 | ||
|
|
7fcb0e78e3 | ||
|
|
8b8018245e | ||
|
|
b34143d4f5 | ||
|
|
a33c096cf4 | ||
|
|
0957edbcd8 | ||
|
|
70adf4e216 | ||
|
|
da42e8c137 | ||
|
|
f4eecda209 | ||
|
|
b934d1a856 | ||
|
|
bbec0aa064 | ||
|
|
ba1f620eee | ||
|
|
f0281adf8a | ||
|
|
c702f61c21 | ||
|
|
dec23e0412 | ||
|
|
782dcb8382 | ||
|
|
e401d1f8c1 | ||
|
|
5e6654b3ef | ||
|
|
25a9e8ef63 | ||
|
|
558e47a7da | ||
|
|
740896c304 | ||
|
|
62d9aa81a3 | ||
|
|
7220b633cf | ||
|
|
0908ddad5e | ||
|
|
d1549b1441 | ||
|
|
57f618e7e2 | ||
|
|
911c64f7ad | ||
|
|
fdeeb35fa9 | ||
|
|
c2c653e613 | ||
|
|
8fa7c1593d | ||
|
|
b2dc74951f | ||
|
|
099c45e4c4 | ||
|
|
e38f6648ee | ||
|
|
2d701aa8a8 | ||
|
|
1f32c22ebf | ||
|
|
610d86ad1b | ||
|
|
658ec8dd74 | ||
|
|
85b7210e7c | ||
|
|
98b99b37de | ||
|
|
bc3aaa4d28 | ||
|
|
a3d0342f28 | ||
|
|
6e057422b6 | ||
|
|
7ee65c6c21 | ||
|
|
b4b754e483 | ||
|
|
b7c0c8a312 | ||
|
|
cf6006f9d6 | ||
|
|
6bf44f6208 | ||
|
|
428dd3cd06 | ||
|
|
871e2efbe2 | ||
|
|
a5b45e2c82 | ||
|
|
9feb3dfac6 | ||
|
|
5961d0dca0 | ||
|
|
ea0f0f09f4 | ||
|
|
3d5d4fcab2 | ||
|
|
0763a9b3b4 | ||
|
|
2d67a89fc2 | ||
|
|
4207d875f9 | ||
|
|
5da420c6c6 | ||
|
|
1ffa4842c3 | ||
|
|
819e194f27 | ||
|
|
269e55b93f | ||
|
|
04412f7138 | ||
|
|
0fce9d01e1 | ||
|
|
1c29301635 | ||
|
|
8bd7bbb5d7 | ||
|
|
1a99663b59 | ||
|
|
36e31279b2 | ||
|
|
4aa7eba675 | ||
|
|
3bbe2d26b8 | ||
|
|
782ad838be | ||
|
|
ceddb26137 | ||
|
|
ff044d75c7 | ||
|
|
8955df695d | ||
|
|
8ddcb208f5 | ||
|
|
95834df89f | ||
|
|
2f67f26cbe | ||
|
|
00957f9458 | ||
|
|
2e9e886c48 | ||
|
|
d2d4e48b73 | ||
|
|
fe16df27f2 | ||
|
|
cc29f70dff | ||
|
|
e136f7cfaf | ||
|
|
fd52f124fb | ||
|
|
5a656cee39 | ||
|
|
21a89f9b14 | ||
|
|
9ded4d2d57 | ||
|
|
fb64d92879 | ||
|
|
1a4bcae4d1 | ||
|
|
25ee4da4f4 | ||
|
|
35cb39c35e | ||
|
|
3a5f232f92 |
No files matched your search
@@ -0,0 +1,43 @@
|
||||
name: "Deploy Wiki"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags-ignore:
|
||||
- "**"
|
||||
paths:
|
||||
- ".forgejo/workflows/deploy_wiki.yml"
|
||||
- "docs/**"
|
||||
- "domains"
|
||||
- "mkdocs.yml"
|
||||
- "requirements.txt"
|
||||
|
||||
jobs:
|
||||
deployWiki:
|
||||
runs-on: codeberg-tiny
|
||||
steps:
|
||||
- name: "Checkout Source Repository"
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
token: "${{ secrets.BOT_TOKEN }}"
|
||||
- name: "Checkout Target Repository"
|
||||
run: "git clone -b pages https://codeberg.org/Andre601/asl-docs site"
|
||||
- name: "Setup Python 3.x"
|
||||
uses: https://code.forgejo.org/actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: "Install Dependencies"
|
||||
run: "pip install -r requirements.txt"
|
||||
- name: "Build Website"
|
||||
run: "mkdocs build"
|
||||
- name: "Commit and Push"
|
||||
run: |
|
||||
git config --global user.email "andre_601-bot@noreply.codeberg.org"
|
||||
git config --global user.name "ASL Wiki Builder"
|
||||
mv domains site/.domains
|
||||
cd site
|
||||
git remote set-url origin https://${{ secrets.BOT_TOKEN }}@codeberg.org/Andre601/asl-docs
|
||||
git add --all
|
||||
git commit -m "Update Wiki ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" ))"
|
||||
git push
|
||||
@@ -0,0 +1,116 @@
|
||||
name: Pull Request Preview
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
paths:
|
||||
- ".forgejo/workflows/pr_preview.yml"
|
||||
- "docs/**"
|
||||
- "mkdocs.yml"
|
||||
- "preview_domains"
|
||||
- "requirements.txt"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BRANCH_NAME: "${{ github.event.repository.name }}/${{ github.event.pull_request.number }}"
|
||||
RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
|
||||
|
||||
jobs:
|
||||
createPreview:
|
||||
runs-on: codeberg-tiny
|
||||
steps:
|
||||
#
|
||||
# Finding and updating comment in Pull request.
|
||||
# If not found, have one created instead.
|
||||
#
|
||||
- name: "Find Comment"
|
||||
id: find-comment
|
||||
uses: https://github.com/peter-evans/find-comment@v3
|
||||
with:
|
||||
issue-number: "${{ github.event.pull_request.number }}"
|
||||
comment-author: "Andre_601-Bot"
|
||||
- name: "Create or update Comment"
|
||||
id: comment
|
||||
uses: https://github.com/peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
body: |-
|
||||
## Pull request Preview
|
||||
|
||||
Creating Preview for Pull request. Please wait...
|
||||
comment-id: "${{ steps.find-comment.outputs.comment-id }}"
|
||||
issue-number: "${{ github.event.pull_request.number }}"
|
||||
token: "${{ secrets.BOT_TOKEN }}"
|
||||
edit-mode: replace
|
||||
#
|
||||
# Setup source and target repository.
|
||||
# Build website and push.
|
||||
#
|
||||
- name: "Checkout Source Repository"
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
ref: "${{ github.event.pull_request.head.sha }}"
|
||||
- name: "Checkout Target Repository"
|
||||
run: |
|
||||
git clone https://codeberg.org/Andre601/preview site
|
||||
cd site
|
||||
git switch ${{ env.BRANCH_NAME }} 2>/dev/null || git switch -c ${{ env.BRANCH_NAME }}
|
||||
- name: "Setup Python 3.x"
|
||||
uses: https://code.forgejo.org/actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: "Install Dependencies"
|
||||
run: "pip install -r requirements.txt"
|
||||
- name: "Build Website"
|
||||
run: "mkdocs build"
|
||||
- name: "Commit and Push"
|
||||
run: |
|
||||
git config --global user.email "andre_601-bot@noreply.codeberg.org"
|
||||
git config --global user.name "PR Docs Preview Builder"
|
||||
mv preview_domains site/.domains
|
||||
cd site
|
||||
git remote add upstream https://${{ secrets.BOT_TOKEN }}@codeberg.org/Andre601/preview.git
|
||||
git add --all
|
||||
git commit -m "Update Preview for ${{ env.BRANCH_NAME }} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" ))"
|
||||
git push --set-upstream upstream ${{ env.BRANCH_NAME }} -f
|
||||
#
|
||||
# Update comment on success or failure.
|
||||
#
|
||||
- name: "Comment Success"
|
||||
uses: https://github.com/peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
body: |-
|
||||
## Pull request Preview
|
||||
|
||||
Pull request Preview created successfully!
|
||||
|
||||
| Name | Link |
|
||||
|---------|----------------------------------------------------------------------------------------------------------|
|
||||
| Commit | ${{ github.event.pull_request.head.sha }} |
|
||||
| Preview | https://preview.andre601.ch/@${{ github.event.repository.name }}~${{ github.event.pull_request.number }} |
|
||||
| Logs | ${{ env.RUN_URL }} |
|
||||
comment-id: "${{ steps.comment.outputs.comment-id }}"
|
||||
issue-number: "${{ github.event.pull_request.number }}"
|
||||
token: "${{ secrets.BOT_TOKEN }}"
|
||||
edit-mode: replace
|
||||
- name: "Comment Failure"
|
||||
if: ${{ failure() }}
|
||||
uses: https://github.com/peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
body: |-
|
||||
## Pull request Preview
|
||||
|
||||
Pull request Preview failed! Check the logs for details.
|
||||
|
||||
| Name | Link |
|
||||
|---------|-------------------------------------------|
|
||||
| Commit | ${{ github.event.pull_request.head.sha }} |
|
||||
| Logs | ${{ RUN_URL }} |
|
||||
comment-id: "${{ steps.comment.outputs.comment-id }}"
|
||||
issue-number: "${{ github.event.pull_request.number }}"
|
||||
token: "${{ secrets.BOT_TOKEN }}"
|
||||
edit-mode: replace
|
||||
@@ -98,6 +98,6 @@ Spanish Video by Ajneb97
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg&h=48" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<a href="https://swiss.social/@andre_601" target="_blank">
|
||||
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg&h=48" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
@@ -11,7 +11,7 @@ variables:
|
||||
|
||||
steps:
|
||||
- name: "Clone Preview Repository"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- <<: *setup_git
|
||||
@@ -24,7 +24,7 @@ steps:
|
||||
settings:
|
||||
pip_install_file: requirements.txt
|
||||
- name: "Commit and Push"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
secrets:
|
||||
- bot_token
|
||||
commands:
|
||||
@@ -5,20 +5,22 @@ when:
|
||||
steps:
|
||||
- name: "Build Jar and Upload"
|
||||
image: maven:3.9.9-eclipse-temurin-21
|
||||
secrets:
|
||||
- modrinth_api_token
|
||||
- hangar_api_token
|
||||
- discord_webhook_url
|
||||
environment:
|
||||
CODEBERG_API_TOKEN:
|
||||
from_secret: cb_token
|
||||
MODRINTH_API_TOKEN:
|
||||
from_secret: modrinth_api_token
|
||||
HANGAR_API_TOKEN:
|
||||
from_secret: hangar_api_token
|
||||
DISCORD_WEBHOOK_URL:
|
||||
from_secret: discord_webhook_url
|
||||
commands:
|
||||
- mvn clean install
|
||||
- cd version-uploader/target
|
||||
- mv VersionUploader.jar ../../
|
||||
- cd ../../
|
||||
- java -jar VersionUploader.jar --all
|
||||
- name: "Upload Jars to Codeber"
|
||||
- name: "Upload Jars to Codeberg"
|
||||
image: woodpeckerci/plugin-gitea-release
|
||||
settings:
|
||||
base_url: https://codeberg.org
|
||||
|
||||
@@ -12,7 +12,7 @@ variables:
|
||||
|
||||
steps:
|
||||
- name: "Clone target Repository"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
commands:
|
||||
- chmod -R a+w .
|
||||
- <<: *setup_git
|
||||
@@ -23,7 +23,7 @@ steps:
|
||||
settings:
|
||||
pip_install_file: requirements.txt
|
||||
- name: "Commit and Push"
|
||||
image: alpine:3.18.4
|
||||
image: alpine:3.20.3
|
||||
secrets:
|
||||
- bot_token
|
||||
commands:
|
||||
@@ -86,6 +86,9 @@ Below can you find a collection of videos made for my plugin. If you made a vide
|
||||
<details><summary>Click to show/hide Videos</summary>
|
||||
<p>
|
||||
|
||||
English Video by KasaiSora
|
||||
[](https://youtube.com/watch?v=9cU0uUWHOO0)
|
||||
|
||||
Spanish Video by Ajneb97
|
||||
[](https://youtube.com/watch?v=rIbljm_4HVI)
|
||||
|
||||
@@ -108,6 +111,6 @@ Spanish Video by Ajneb97
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg" height="48" alt="revolt" title="Join my Revolt Server">
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://blobfox.coffee/@andre_601" target="_blank">
|
||||
<a href="https://swiss.social/@andre_601" target="_blank">
|
||||
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg" height="48" alt="revolt" title="Chat with me on Mastodon">
|
||||
</a>
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
# Supported Versions
|
||||
|
||||
To ensure proper safety and support are only certain versions and Platforms of AdvancedServerList maintained and supported.
|
||||
|
||||
## Supported Plugin Versions
|
||||
|
||||
| Major Version | Supported |
|
||||
|---------------|-----------|
|
||||
| v5 | Yes |
|
||||
| v4 | Yes* |
|
||||
| v3 | Yes** |
|
||||
| v2 | No |
|
||||
| v1 | No |
|
||||
|
||||
\*Only receives support but no updates or bug fixes.
|
||||
\*\*Support ends at the end of 2024.
|
||||
|
||||
## Supported Server/Proxy Versions
|
||||
|
||||
| Server/Proxy Version* | Supported |
|
||||
|-----------------------|-----------|
|
||||
| 1.21.x | Yes |
|
||||
| 1.20.x | Yes |
|
||||
| 1.19.x | No |
|
||||
| 1.18.x | No |
|
||||
| 1.17.x | No |
|
||||
| 1.16.x | No |
|
||||
| 1.15.x | No |
|
||||
| 1.14.x | No |
|
||||
| 1.13.x | No |
|
||||
| 1.12.x | No |
|
||||
| 1.11.x | No |
|
||||
| 1.10.x | No |
|
||||
| 1.19.x | No |
|
||||
| 1.8.x | No |
|
||||
|
||||
\*Only the latest patch version is actively supported should "Supported" have "Yes".
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
### Servers
|
||||
|
||||
| Server | Supported |
|
||||
|--------|-----------|
|
||||
| Spigot | No |
|
||||
| Paper | Yes |
|
||||
| Purpur | Yes* |
|
||||
| Mohist | No |
|
||||
|
||||
\*Support hasn't actively been tested, but should work without issues.
|
||||
|
||||
### Proxies
|
||||
|
||||
| Proxy | Supported |
|
||||
|------------|-----------|
|
||||
| BungeeCord | Yes** |
|
||||
| Waterfall | Yes** |
|
||||
| Velocity | Yes |
|
||||
|
||||
\*\*Platform version of this plugin is maintenance only, not receiving any bug fixes for major breaking changes anymore.
|
||||
+20
-22
@@ -31,32 +31,10 @@ import com.google.common.primitives.UnsignedLongs;
|
||||
import me.leoko.advancedban.manager.PunishmentManager;
|
||||
import me.leoko.advancedban.utils.Punishment;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AdvancedBanProvider implements PunishmentProvider{
|
||||
|
||||
private static PunishmentManager getAPI(){
|
||||
return PunishmentManager.get();
|
||||
}
|
||||
|
||||
private static String noDashesUUID(UUID uuid){
|
||||
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
private static Punishment mute(GenericPlayer player){
|
||||
return getAPI().getMute(noDashesUUID(player.getUUID()));
|
||||
}
|
||||
|
||||
private static Punishment ban(GenericPlayer player){
|
||||
return getAPI().getBan(noDashesUUID(player.getUUID()));
|
||||
}
|
||||
|
||||
private static String hexString(long unsigned){
|
||||
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
|
||||
}
|
||||
|
||||
@Override
|
||||
public String muted(GenericPlayer player){
|
||||
return String.valueOf(getAPI().isMuted(noDashesUUID(player.getUUID())));
|
||||
@@ -136,4 +114,24 @@ public class AdvancedBanProvider implements PunishmentProvider{
|
||||
|
||||
return ban.getDuration(fromStart);
|
||||
}
|
||||
|
||||
private PunishmentManager getAPI(){
|
||||
return PunishmentManager.get();
|
||||
}
|
||||
|
||||
private String noDashesUUID(UUID uuid){
|
||||
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
private Punishment mute(GenericPlayer player){
|
||||
return getAPI().getMute(noDashesUUID(player.getUUID()));
|
||||
}
|
||||
|
||||
private Punishment ban(GenericPlayer player){
|
||||
return getAPI().getBan(noDashesUUID(player.getUUID()));
|
||||
}
|
||||
|
||||
private String hexString(long unsigned){
|
||||
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ name: 'ASLBanPluginsAddon'
|
||||
author: 'Andre_601'
|
||||
version: '${plugin.version}'
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.banplugins.paper.AdvancedBanPlaceholders'
|
||||
main: 'ch.andre601.advancedserverlist.banplugins.paper.PaperBanPluginsAddon'
|
||||
|
||||
api-version: '1.19'
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
AdvancedServerList:
|
||||
required: false
|
||||
load: BEFORE
|
||||
AdvancedBans:
|
||||
AdvancedBan:
|
||||
required: false
|
||||
load: BEFORE
|
||||
LibertyBans:
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bungeecord</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+28
-1
@@ -30,6 +30,7 @@ import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
|
||||
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeePlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeProxyPlaceholders;
|
||||
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeServerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
@@ -40,6 +41,7 @@ import com.alessiodp.libby.Library;
|
||||
import de.myzelyam.api.vanish.BungeeVanishAPI;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
@@ -50,10 +52,14 @@ import java.awt.image.BufferedImage;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
|
||||
private final PluginLogger logger = new BungeeLogger(this);
|
||||
private final Map<String, ServerPing> fetchedServers = new ConcurrentHashMap<>();
|
||||
|
||||
private boolean successfulLoad = false;
|
||||
|
||||
@@ -83,12 +89,14 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
}
|
||||
|
||||
this.audiences = BungeeAudiences.create(this);
|
||||
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
|
||||
this.core = AdvancedServerList.init(this,
|
||||
BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this), BungeeProxyPlaceholders.init(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable(){
|
||||
core.disable();
|
||||
getProxy().getScheduler().cancel(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,6 +148,11 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScheduler(){
|
||||
getProxy().getScheduler().schedule(this, this::fetchServers, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
@@ -198,6 +211,10 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
return players.size();
|
||||
}
|
||||
|
||||
public Map<String, ServerPing> getFetchedServers(){
|
||||
return fetchedServers;
|
||||
}
|
||||
|
||||
private boolean loadLibs(){
|
||||
try{
|
||||
if(libraryManager == null){
|
||||
@@ -213,4 +230,14 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchServers(){
|
||||
fetchedServers.clear();
|
||||
getProxy().getServers().forEach((name, server) -> server.ping((ping, throwable) -> {
|
||||
if(throwable != null)
|
||||
return;
|
||||
|
||||
fetchedServers.put(name, ping);
|
||||
}));
|
||||
}
|
||||
}
|
||||
+6
@@ -79,6 +79,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
ping.getPlayers().setMax(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
ping.getPlayers().setOnline(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
|
||||
@@ -102,6 +107,7 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
|
||||
for(int i = 0; i < players.length; i++){
|
||||
String parsed = ComponentParser.text(lines.get(i))
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
ServerPing.PlayerInfo pi = new ServerPing.PlayerInfo(parsed, UUID.randomUUID());
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public class BungeeProxyPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private final BungeeCordCore plugin;
|
||||
|
||||
private BungeeProxyPlaceholders(BungeeCordCore plugin){
|
||||
super("proxy");
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static BungeeProxyPlaceholders init(BungeeCordCore plugin){
|
||||
return new BungeeProxyPlaceholders(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
String[] args = placeholder.split("\\s", 2);
|
||||
if(args.length < 2)
|
||||
return null;
|
||||
|
||||
ServerPing ping = plugin.getFetchedServers().get(args[1]);
|
||||
|
||||
return switch(args[0]){
|
||||
case "status" -> ping == null ? "offline" : "online";
|
||||
case "motd" -> {
|
||||
if(ping == null)
|
||||
yield "none";
|
||||
|
||||
BaseComponent[] components = new BaseComponent[]{ping.getDescriptionComponent()};
|
||||
Component component = BungeeComponentSerializer.get().deserialize(components);
|
||||
|
||||
yield ComponentParser.toMMString(component);
|
||||
}
|
||||
case "players" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(ping.getPlayers().getOnline());
|
||||
}
|
||||
case "maxPlayers" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(ping.getPlayers().getMax());
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -79,18 +79,18 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
|
||||
case "playersMax" -> {
|
||||
// ServerInfo doesn't provide the max players that could join, so we won't allow an extra argument
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(proxy.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length > 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
|
||||
ServerInfo info = proxy.getServers().get(args[1]);
|
||||
if(info == null)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
|
||||
}
|
||||
|
||||
+17
-5
@@ -41,7 +41,7 @@
|
||||
<properties>
|
||||
<maven.compiler.source>16</maven.compiler.source>
|
||||
<maven.compiler.target>16</maven.compiler.target>
|
||||
<plugin.config.version>5</plugin.config.version>
|
||||
<plugin.config.version>6</plugin.config.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@@ -77,9 +77,11 @@
|
||||
<dependency>
|
||||
<groupId>ch.andre601</groupId>
|
||||
<artifactId>expressionparser</artifactId>
|
||||
<version>1.4.3</version>
|
||||
<version>1.5.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Configuration -->
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
@@ -129,7 +131,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.3.0-jre</version>
|
||||
<version>33.4.0-jre</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -137,7 +139,7 @@
|
||||
<dependency>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<version>1.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -157,7 +159,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<version>5.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -168,6 +170,16 @@
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>char-widths.json.gz</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<filtering>false</filtering>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
<includes>
|
||||
<include>char-widths.json.gz</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
|
||||
@@ -32,6 +32,7 @@ import ch.andre601.advancedserverlist.core.commands.CommandHandler;
|
||||
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenancePlaceholder;
|
||||
import ch.andre601.advancedserverlist.core.file.FileHandler;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
|
||||
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
|
||||
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
|
||||
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
|
||||
|
||||
@@ -47,6 +48,8 @@ public class AdvancedServerList<F>{
|
||||
private final FileHandler fileHandler;
|
||||
private final CommandHandler commandHandler;
|
||||
private final PlayerHandler playerHandler;
|
||||
private final TextCenterUtil textCenterUtil;
|
||||
|
||||
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
|
||||
private final ProfileConditionParser parser = ProfileConditionParser.create();
|
||||
|
||||
@@ -59,6 +62,7 @@ public class AdvancedServerList<F>{
|
||||
this.fileHandler = new FileHandler(this);
|
||||
this.commandHandler = new CommandHandler(this);
|
||||
this.playerHandler = new PlayerHandler(this);
|
||||
this.textCenterUtil = new TextCenterUtil(this);
|
||||
|
||||
plugin.getPluginLogger().info("Registering internal Placeholders...");
|
||||
|
||||
@@ -110,6 +114,10 @@ public class AdvancedServerList<F>{
|
||||
return updateChecker;
|
||||
}
|
||||
|
||||
public TextCenterUtil getTextCenterUtil(){
|
||||
return textCenterUtil;
|
||||
}
|
||||
|
||||
public void disable(){
|
||||
getPlugin().getPluginLogger().info("Saving playercache.json file...");
|
||||
getPlayerHandler().save();
|
||||
@@ -177,6 +185,10 @@ public class AdvancedServerList<F>{
|
||||
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
|
||||
plugin.loadMetrics();
|
||||
getPlugin().getPluginLogger().info("Metrics loaded!");
|
||||
|
||||
getPlugin().getPluginLogger().info("Enabling Schedulers...");
|
||||
plugin.startScheduler();
|
||||
getPlugin().getPluginLogger().info("Schedulers enabled.");
|
||||
|
||||
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ package ch.andre601.advancedserverlist.core.check;
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
|
||||
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
|
||||
import ch.andre601.advancedserverlist.core.objects.CacheUtil;
|
||||
import ch.andre601.advancedserverlist.core.objects.ValueCache;
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -59,7 +59,7 @@ public class UpdateChecker{
|
||||
|
||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
|
||||
|
||||
private final CacheUtil<CompletableFuture<ModrinthVersion>> cache = new CacheUtil<>(Duration.ofMinutes(5));
|
||||
private final ValueCache<CompletableFuture<ModrinthVersion>> cache = new ValueCache<>(Duration.ofMinutes(5));
|
||||
|
||||
private final AdvancedServerList<?> core;
|
||||
private final PluginLogger logger;
|
||||
|
||||
@@ -25,22 +25,24 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.core.compat.papi;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.objects.CacheUtil;
|
||||
import ch.andre601.advancedserverlist.core.objects.ValueCache;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import net.william278.papiproxybridge.api.PlaceholderAPI;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class PAPIUtil{
|
||||
|
||||
private static PAPIUtil instance;
|
||||
|
||||
private final CacheUtil<String> cache = new CacheUtil<>(Duration.ofSeconds(5));
|
||||
private final ValueCache<CompletableFuture<Set<String>>> serversCache = new ValueCache<>(Duration.ofSeconds(10));
|
||||
private final Cache<UUID, CompletableFuture<String>> textCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(Duration.ofSeconds(10))
|
||||
.build();
|
||||
private final PlaceholderAPI papi;
|
||||
|
||||
private PAPIUtil(){
|
||||
@@ -66,24 +68,11 @@ public class PAPIUtil{
|
||||
}
|
||||
|
||||
public String getServer(){
|
||||
return cache.get(() -> {
|
||||
List<String> servers;
|
||||
|
||||
try{
|
||||
Set<String> value = papi.getServers().getNow(null);
|
||||
if(value == null)
|
||||
return null;
|
||||
|
||||
servers = List.copyOf(value);
|
||||
}catch(CancellationException | CompletionException ex){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(servers == null || servers.isEmpty())
|
||||
return null;
|
||||
|
||||
return servers.get(0);
|
||||
});
|
||||
Set<String> values = serversCache.get(papi::getServers).getNow(Collections.emptySet());
|
||||
if(values.isEmpty())
|
||||
return null;
|
||||
|
||||
return List.copyOf(values).get(0);
|
||||
}
|
||||
|
||||
public <P> P getPlayer(Collection<P> players){
|
||||
@@ -95,8 +84,8 @@ public class PAPIUtil{
|
||||
|
||||
public String parse(String text, UUID carrier, UUID player){
|
||||
try{
|
||||
return papi.formatPlaceholders(text, carrier, player).getNow(text);
|
||||
}catch(IllegalArgumentException | CancellationException | CompletionException ex){
|
||||
return textCache.get(player, () -> papi.formatPlaceholders(text, carrier, player)).getNow(text);
|
||||
}catch(ExecutionException ex){
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
+60
-19
@@ -36,6 +36,10 @@ 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 net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PingEventHandler{
|
||||
|
||||
@@ -84,47 +88,84 @@ public class PingEventHandler{
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
|
||||
|
||||
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
if(ProfileManager.checkOption(entry.onlinePlayersEnabled()) && ignoreMaintenance(event, "onlinePlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> onlinePlayers -> enabled' option is true. Trying to apply '%s'...", entry.onlinePlayersCount());
|
||||
String onlinePlayers = ComponentParser.text(entry.onlinePlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
|
||||
|
||||
event.setMaxPlayers(max);
|
||||
try{
|
||||
online = onlinePlayers == null ? online : Integer.parseInt(onlinePlayers);
|
||||
event.setOnlinePlayers(online);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> onlinePlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
|
||||
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
|
||||
boolean extraPlayersEnabled = ProfileManager.checkOption(entry.extraPlayersEnabled());
|
||||
|
||||
if(extraPlayersEnabled && ignoreMaintenance(event, "extraPlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> enabled' option is true. Trying to apply '%s'...", entry.extraPlayersCount());
|
||||
String extraPlayers = ComponentParser.text(entry.extraPlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
|
||||
try{
|
||||
max = online + (extraPlayers == null ? 0 : Integer.parseInt(extraPlayers));
|
||||
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> amount' is a valid number. Applying it...");
|
||||
event.setMaxPlayers(max);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> extraPlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayersEnabled && ignoreMaintenance(event, "maxPlayers")){
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> enabled' option is true. Trying to apply '%s'...", entry.maxPlayersCount());
|
||||
String maxPlayers = ComponentParser.text(entry.maxPlayersCount())
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
event.setMaxPlayers(max);
|
||||
try{
|
||||
max = maxPlayers == null ? 0 : Integer.parseInt(maxPlayers);
|
||||
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> amount' is a valid number. Applying it...");
|
||||
event.setMaxPlayers(max);
|
||||
}catch(NumberFormatException ex){
|
||||
logger.warn("Option 'playerCount -> maxPlayers -> amount' is not a valid Number!");
|
||||
}
|
||||
}
|
||||
|
||||
GenericServer finalServer = event.createGenericServer(online, max, host);
|
||||
|
||||
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
|
||||
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
|
||||
logger.debug(PingEventHandler.class, "'motd' option present. Applying ['%s']...", String.join("', '", entry.motd()));
|
||||
|
||||
event.setMotd(
|
||||
ComponentParser.list(entry.motd())
|
||||
List<Component> motd = entry.motd().stream()
|
||||
.map(line -> ComponentParser.text(line)
|
||||
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
|
||||
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
|
||||
.modifyText(text -> plugin.getCore().getTextCenterUtil().getCenteredText(text))
|
||||
.toComponent()
|
||||
);
|
||||
)
|
||||
.toList();
|
||||
|
||||
event.setMotd(Component.join(JoinConfiguration.separator(Component.newline()), motd));
|
||||
}
|
||||
|
||||
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
|
||||
|
||||
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
|
||||
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayers' enabled. Hiding player count...");
|
||||
|
||||
event.hidePlayers();
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
|
||||
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> text' option set. Applying '%s'...", entry.playerCountText());
|
||||
|
||||
event.setPlayerCount(
|
||||
ComponentParser.text(entry.playerCountText())
|
||||
@@ -135,13 +176,13 @@ public class PingEventHandler{
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
|
||||
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
|
||||
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying '%s'...", String.join("\\n", entry.players()));
|
||||
|
||||
event.setPlayers(entry.players(), player, server);
|
||||
}
|
||||
|
||||
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
|
||||
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
|
||||
logger.debug(PingEventHandler.class, "'favicon' option set. Resolving '%s'...", entry.favicon());
|
||||
|
||||
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
|
||||
|
||||
|
||||
@@ -46,13 +46,24 @@ public class ConfigMigrator{
|
||||
public static ConfigurationTransformation.Versioned create(){
|
||||
return ConfigurationTransformation.versionedBuilder()
|
||||
.versionKey("configVersion")
|
||||
.addVersion(LATEST, fourToFive())
|
||||
.addVersion(LATEST, fiveToSix())
|
||||
.addVersion(5, fourToFive())
|
||||
.addVersion(4, threeToFour())
|
||||
.addVersion(3, twoToThree())
|
||||
.addVersion(2, oneToTwo())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfigurationTransformation fiveToSix(){
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
|
||||
value.node("onlinePlayers").set(true);
|
||||
|
||||
return null;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfigurationTransformation fourToFive(){
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(NodePath.path(), (path, value) -> {
|
||||
|
||||
+4
-4
@@ -29,14 +29,14 @@ import java.util.Locale;
|
||||
|
||||
public abstract class PluginCommand{
|
||||
|
||||
private final String argument;
|
||||
private final String name;
|
||||
|
||||
public PluginCommand(String argument){
|
||||
this.argument = argument;
|
||||
public PluginCommand(String name){
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String name(){
|
||||
return argument;
|
||||
return name;
|
||||
}
|
||||
|
||||
public String permission(){
|
||||
|
||||
@@ -46,6 +46,8 @@ public interface PluginCore<F>{
|
||||
|
||||
void downloadLibrary(String groupId, String artifactId, String version);
|
||||
|
||||
void startScheduler();
|
||||
|
||||
AdvancedServerList<F> getCore();
|
||||
|
||||
Path getFolderPath();
|
||||
|
||||
+2
@@ -42,6 +42,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
|
||||
|
||||
void setMaxPlayers(int maxPlayers);
|
||||
|
||||
void setOnlinePlayers(int onlinePlayers);
|
||||
|
||||
void setMotd(Component component);
|
||||
|
||||
void hidePlayers();
|
||||
|
||||
+4
-4
@@ -110,14 +110,14 @@ public class MiniMOTDConfigMigrator{
|
||||
if(config.iconEnabled()){
|
||||
if(config.motds().size() == 1){
|
||||
MiniMOTDConfig.Motd motd = config.motds().get(0);
|
||||
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
|
||||
if(!motd.icon().isEmpty()){
|
||||
profileBuilder.favicon(motd.icon());
|
||||
}
|
||||
}else
|
||||
if(config.motds().size() > 1){
|
||||
for(int i = 0; i < config.motds().size(); i++){
|
||||
MiniMOTDConfig.Motd motd = config.motds().get(i);
|
||||
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
|
||||
if(!motd.icon().isEmpty()){
|
||||
profilesBuilders.get(i).favicon(motd.icon());
|
||||
}
|
||||
}
|
||||
@@ -135,9 +135,9 @@ public class MiniMOTDConfigMigrator{
|
||||
|
||||
profileBuilder.hidePlayersEnabled(hidePlayers)
|
||||
.extraPlayersEnabled(xMoreEnabled)
|
||||
.extraPlayersCount(xMore)
|
||||
.extraPlayersCount(String.valueOf(xMore))
|
||||
.maxPlayersEnabled(maxPlayersEnabled)
|
||||
.maxPlayersCount(maxPlayers);
|
||||
.maxPlayersCount(String.valueOf(maxPlayers));
|
||||
}
|
||||
|
||||
ProfileEntry entry = profileBuilder.build();
|
||||
|
||||
+38
-32
@@ -59,14 +59,43 @@ public class SLPConfigMigrator{
|
||||
"(?<end>#[a-fA-F0-9]{6})" + // Ending color
|
||||
"%" +
|
||||
"(?<text>.+?)" + // Text
|
||||
"%gradient%");
|
||||
"%gradient%"
|
||||
);
|
||||
|
||||
private static final Map<String, String> STATIC_REPLACEMENTS = Map.of(
|
||||
"%player%", "${player name}",
|
||||
"%uuid%", "${player uuid}",
|
||||
"%_uuid_%", "${player uuid}",
|
||||
"%online%", "${server playersOnline}",
|
||||
"%max%", "${server playersMax}");
|
||||
"%max%", "${server playersMax}"
|
||||
);
|
||||
private static final Map<String, String> COLOR_TO_MINIMESSAGE_TAG = new HashMap<>(){{
|
||||
// Color Codes.
|
||||
put("a", "<green>");
|
||||
put("b", "<aqua>");
|
||||
put("c", "<red>");
|
||||
put("d", "<light_purple>");
|
||||
put("e", "<yellow>");
|
||||
put("f", "<white>");
|
||||
put("0", "<black>");
|
||||
put("1", "<dark_blue>");
|
||||
put("2", "<dark_green>");
|
||||
put("3", "<dark_aqua>");
|
||||
put("4", "<dark_red>");
|
||||
put("5", "<dark_purple>");
|
||||
put("6", "<gold>");
|
||||
put("7", "<grey>");
|
||||
put("8", "<dark_grey>");
|
||||
put("9", "<blue>");
|
||||
|
||||
// Formatting Codes
|
||||
put("k", "<obfuscated>");
|
||||
put("l", "<bold>");
|
||||
put("m", "<strikethrough>");
|
||||
put("n", "<underlined>");
|
||||
put("o", "<italic>");
|
||||
put("r", "<reset>");
|
||||
}};
|
||||
|
||||
public static int migrate(AdvancedServerList<?> core, CmdSender sender){
|
||||
ServerListPlusCore slpCore = ServerListPlusCore.getInstance();
|
||||
@@ -129,7 +158,7 @@ public class SLPConfigMigrator{
|
||||
apply(motds, builder, profiles, ProfileEntry.Builder::motd);
|
||||
apply(favicons, builder, profiles, ProfileEntry.Builder::favicon);
|
||||
apply(hovers, builder, profiles, ProfileEntry.Builder::players);
|
||||
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(count));
|
||||
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(String.valueOf(count)));
|
||||
apply(playerCount, builder, profiles, ProfileEntry.Builder::playerCountText);
|
||||
|
||||
builder.hidePlayersEnabled(hidePlayers);
|
||||
@@ -194,9 +223,7 @@ public class SLPConfigMigrator{
|
||||
|
||||
if(type == Type.PERSONALIZED){
|
||||
node.node("condition")
|
||||
.set("${player name} != \"" +
|
||||
core.getFileHandler().getString("Anonymous", "unknownPlayer", "name") +
|
||||
"\"");
|
||||
.set("${player name} != \"" + core.getFileHandler().getString("Anonymous", "unknownPlayer", "name") + "\"");
|
||||
}else
|
||||
if(type == Type.BANNED){
|
||||
node.node("condition")
|
||||
@@ -372,32 +399,11 @@ public class SLPConfigMigrator{
|
||||
if(colorCodeMatcher.find()){
|
||||
builder.setLength(0);
|
||||
do{
|
||||
String color = colorCodeMatcher.group("color").toLowerCase(Locale.ROOT);
|
||||
switch(color){
|
||||
case "a" -> colorCodeMatcher.appendReplacement(builder, "<green>");
|
||||
case "b" -> colorCodeMatcher.appendReplacement(builder, "<aqua>");
|
||||
case "c" -> colorCodeMatcher.appendReplacement(builder, "<red>");
|
||||
case "d" -> colorCodeMatcher.appendReplacement(builder, "<light_purple>");
|
||||
case "e" -> colorCodeMatcher.appendReplacement(builder, "<yellow>");
|
||||
case "f" -> colorCodeMatcher.appendReplacement(builder, "<white>");
|
||||
case "k" -> colorCodeMatcher.appendReplacement(builder, "<obfuscated>");
|
||||
case "l" -> colorCodeMatcher.appendReplacement(builder, "<bold>");
|
||||
case "m" -> colorCodeMatcher.appendReplacement(builder, "<strikethrough>");
|
||||
case "n" -> colorCodeMatcher.appendReplacement(builder, "<underlined>");
|
||||
case "o" -> colorCodeMatcher.appendReplacement(builder, "<italic>");
|
||||
case "r" -> colorCodeMatcher.appendReplacement(builder, "<reset>");
|
||||
case "0" -> colorCodeMatcher.appendReplacement(builder, "<black>");
|
||||
case "1" -> colorCodeMatcher.appendReplacement(builder, "<dark_blue>");
|
||||
case "2" -> colorCodeMatcher.appendReplacement(builder, "<dark_green>");
|
||||
case "3" -> colorCodeMatcher.appendReplacement(builder, "<dark_aqua>");
|
||||
case "4" -> colorCodeMatcher.appendReplacement(builder, "<dark_red>");
|
||||
case "5" -> colorCodeMatcher.appendReplacement(builder, "<dark_purple>");
|
||||
case "6" -> colorCodeMatcher.appendReplacement(builder, "<gold>");
|
||||
case "7" -> colorCodeMatcher.appendReplacement(builder, "<grey>");
|
||||
case "8" -> colorCodeMatcher.appendReplacement(builder, "<dark_grey>");
|
||||
case "9" -> colorCodeMatcher.appendReplacement(builder, "<blue>");
|
||||
// This one shouldn't be reachable given the pattern, but you never know...
|
||||
default -> colorCodeMatcher.appendReplacement(builder, "&" + color);
|
||||
for(Map.Entry<String, String> colorCodes : COLOR_TO_MINIMESSAGE_TAG.entrySet()){
|
||||
if(!colorCodeMatcher.group("color").equalsIgnoreCase(colorCodes.getKey()))
|
||||
continue;
|
||||
|
||||
colorCodeMatcher.appendReplacement(builder, colorCodes.getValue());
|
||||
}
|
||||
}while(colorCodeMatcher.find());
|
||||
|
||||
|
||||
+2
-2
@@ -28,12 +28,12 @@ package ch.andre601.advancedserverlist.core.objects;
|
||||
import java.time.Duration;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class CacheUtil<T>{
|
||||
public class ValueCache<T>{
|
||||
|
||||
private final Duration duration;
|
||||
private CacheValue<T> cache = null;
|
||||
|
||||
public CacheUtil(Duration duration){
|
||||
public ValueCache(Duration duration){
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ComponentParser{
|
||||
@@ -52,10 +51,6 @@ public class ComponentParser{
|
||||
return new ComponentParser(text);
|
||||
}
|
||||
|
||||
public static ComponentParser list(List<String> lines){
|
||||
return new ComponentParser(String.join("\n", lines));
|
||||
}
|
||||
|
||||
public ComponentParser modifyText(Function<String, String> function){
|
||||
this.text = function.apply(text);
|
||||
return this;
|
||||
@@ -65,6 +60,10 @@ public class ComponentParser{
|
||||
return mm.deserialize(text);
|
||||
}
|
||||
|
||||
public static String toMMString(Component component){
|
||||
return mm.serialize(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return legacy.serialize(toComponent());
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package ch.andre601.advancedserverlist.core.parsing;
|
||||
|
||||
import ch.andre601.advancedserverlist.core.AdvancedServerList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import net.kyori.adventure.text.flattener.ComponentFlattener;
|
||||
import net.kyori.adventure.text.flattener.FlattenerListener;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class TextCenterUtil{
|
||||
private final ComponentFlattener COMPONENT_FLATTENER = ComponentFlattener.textOnly();
|
||||
|
||||
private final double MAX_WIDTH = 270.0; // Max width of the MOTD
|
||||
private final int SPACE_WIDTH = 4;
|
||||
|
||||
private final Map<String, FontInfo> charWidths;
|
||||
|
||||
public TextCenterUtil(AdvancedServerList<?> plugin){
|
||||
charWidths = loadFontWidths(plugin);
|
||||
}
|
||||
|
||||
public String getCenteredText(String text){
|
||||
if(!text.toLowerCase(Locale.ROOT).startsWith("<center>"))
|
||||
return text;
|
||||
|
||||
if(getDefault() == null)
|
||||
return text;
|
||||
|
||||
text = text.substring("<center>".length());
|
||||
TextFlattenerListener listener = new TextFlattenerListener(this);
|
||||
|
||||
COMPONENT_FLATTENER.flatten(ComponentParser.text(text).toComponent(), listener);
|
||||
|
||||
double width = listener.getWidth();
|
||||
if(width >= MAX_WIDTH)
|
||||
return text;
|
||||
|
||||
return createSpaces(width) + text;
|
||||
}
|
||||
|
||||
private double getCharWidth(int codePoint, boolean isBold, String fontName){
|
||||
FontInfo font = charWidths.getOrDefault(fontName, getDefault());
|
||||
if(font == null)
|
||||
return -1.0;
|
||||
|
||||
int index = Arrays.binarySearch(font.codePoints, codePoint);
|
||||
if(index < 0){
|
||||
return isBold ? 7.0 : 6.0;
|
||||
}else{
|
||||
return isBold ? font.advanceBf[index] : font.advance[index];
|
||||
}
|
||||
}
|
||||
|
||||
private FontInfo getDefault(){
|
||||
return charWidths.get("minecraft:default");
|
||||
}
|
||||
|
||||
private String createSpaces(double length){
|
||||
double remainder = MAX_WIDTH - length;
|
||||
int padding = (int)Math.max(0, Math.floor(remainder / 2.0) - 1);
|
||||
|
||||
return " ".repeat(Math.floorDiv(padding, SPACE_WIDTH));
|
||||
}
|
||||
|
||||
private Map<String, FontInfo> loadFontWidths(AdvancedServerList<?> plugin){
|
||||
try(InputStream stream = plugin.getClass().getResourceAsStream("/char-widths.json.gz")){
|
||||
if(stream == null){
|
||||
plugin.getPlugin().getPluginLogger().warn("Internal char-widths.json.gz couldn't be retrieved.");
|
||||
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
GZIPInputStream gzipStream = new GZIPInputStream(stream);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipStream));
|
||||
|
||||
return new Gson().fromJson(reader, new TypeToken<Map<String, FontInfo>>(){}.getType());
|
||||
}catch(IOException ex){
|
||||
plugin.getPlugin().getPluginLogger().warn("Encountered IOException while loading font widths.");
|
||||
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
|
||||
plugin.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
private static class TextFlattenerListener implements FlattenerListener{
|
||||
private double width = 0.0;
|
||||
private boolean isBold = false;
|
||||
private String font = "minecraft:default";
|
||||
|
||||
private final TextCenterUtil instance;
|
||||
|
||||
public TextFlattenerListener(TextCenterUtil instance){
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushStyle(@NotNull Style style){
|
||||
if(style.hasDecoration(TextDecoration.BOLD))
|
||||
isBold = true;
|
||||
|
||||
if(style.font() != null)
|
||||
font = style.font().asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void component(@NotNull String text){
|
||||
for(int i = 0; i < text.length(); i++){
|
||||
width += instance.getCharWidth(text.codePointAt(i), isBold, font);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popStyle(@NotNull Style style){
|
||||
if(style.hasDecoration(TextDecoration.BOLD))
|
||||
isBold = false;
|
||||
}
|
||||
|
||||
public double getWidth(){
|
||||
return width;
|
||||
}
|
||||
}
|
||||
|
||||
private record FontInfo(int[] codePoints, float[] advance, float[] advanceBf){}
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
|
||||
for(ParseWarnCollector.Context context : collector.getWarnings()){
|
||||
logger.warn(" - At position %s:", context.position() == -1 ? "Unknown" : context.position());
|
||||
logger.warn(" %s", condition);
|
||||
logger.warn(" ".repeat(context.position() + 4) + "^");
|
||||
logger.warn(" ".repeat(context.position() + 3) + "^");
|
||||
logger.warn(" -> %s", context.message());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -76,7 +76,14 @@ public class CustomExpressionTokenizer{
|
||||
}
|
||||
}
|
||||
|
||||
collector.appendWarningFormatted(position.getIndex(), "Illegal Token '%c'.", text.charAt(position.getIndex()));
|
||||
if(position.getIndex() >= text.length()){
|
||||
collector.appendWarningFormatted(
|
||||
"Current index position (%d) is larger or equal to Text length (%d) for condition '%s'",
|
||||
position.getIndex(), text.length(), text
|
||||
);
|
||||
}else{
|
||||
collector.appendWarningFormatted(position.getIndex(), "Illegal Token '%c'.", text.charAt(position.getIndex()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+27
-3
@@ -42,9 +42,8 @@ import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -57,6 +56,7 @@ public class FaviconHandler<F>{
|
||||
|
||||
private final Map<String, F> localFavicons = new HashMap<>();
|
||||
private final HttpClient client = HttpClient.newHttpClient();
|
||||
private final Random random = new Random();
|
||||
|
||||
public FaviconHandler(AdvancedServerList<F> core){
|
||||
this.core = core;
|
||||
@@ -77,6 +77,11 @@ public class FaviconHandler<F>{
|
||||
}
|
||||
}
|
||||
|
||||
if(input.equalsIgnoreCase("random")){
|
||||
logger.debug(FaviconHandler.class, "Input matches 'random'. Returning random Favicon...");
|
||||
return getRandomized();
|
||||
}
|
||||
|
||||
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT))){
|
||||
logger.debug(FaviconHandler.class, "Input matches local favicon Image. Returning it...");
|
||||
return localFavicons.get(input.toLowerCase(Locale.ROOT));
|
||||
@@ -101,6 +106,9 @@ public class FaviconHandler<F>{
|
||||
logger.debug(FaviconHandler.class, "Resolving URL '%s'...", input);
|
||||
return CompletableFuture.supplyAsync(() -> fromURL(core, input), this.faviconThreadPool);
|
||||
}else
|
||||
if(input.equalsIgnoreCase("random")){
|
||||
return CompletableFuture.completedFuture(getRandomized());
|
||||
}else
|
||||
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
|
||||
logger.debug(FaviconHandler.class, "Resolving image file '%s'...", input);
|
||||
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT)));
|
||||
@@ -110,6 +118,22 @@ public class FaviconHandler<F>{
|
||||
}
|
||||
}
|
||||
|
||||
private F getRandomized(){
|
||||
logger.debug(FaviconHandler.class, "Obtaining random Favicon...");
|
||||
if(localFavicons.isEmpty())
|
||||
return null;
|
||||
|
||||
List<F> faviconList = List.copyOf(localFavicons.values());
|
||||
|
||||
// Don't use Random for just one entry.
|
||||
if(faviconList.size() == 1)
|
||||
return faviconList.get(0);
|
||||
|
||||
synchronized(random){
|
||||
return faviconList.get(random.nextInt(faviconList.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLocalFavicons(){
|
||||
this.localFavicons.clear();
|
||||
|
||||
|
||||
-2
@@ -114,8 +114,6 @@ public class PlayerHandler{
|
||||
}catch(IOException ex){
|
||||
logger.warn("Encountered IOException while saving cached players to playercache.json!", ex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void addPlayer(String ip, String name, UUID uuid){
|
||||
|
||||
+25
-8
@@ -55,11 +55,24 @@ public class ProfileManager{
|
||||
NullBool hidePlayersEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersEnabled);
|
||||
NullBool extraPlayersEnabled = resolve(defEntry, entry, ProfileEntry::extraPlayersEnabled);
|
||||
NullBool maxPlayersEnabled = resolve(defEntry, entry, ProfileEntry::maxPlayersEnabled);
|
||||
Integer extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
|
||||
Integer maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
|
||||
NullBool onlinePlayersEnabled = resolve(defEntry, entry, ProfileEntry::onlinePlayersEnabled);
|
||||
String extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
|
||||
String maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
|
||||
String onlinePlayersCount = resolve(defEntry, entry, ProfileEntry::onlinePlayersCount);
|
||||
|
||||
return new ProfileEntry(motd, players, playerCountText, favicon, hidePlayersEnabled, extraPlayersEnabled,
|
||||
maxPlayersEnabled, extraPlayersCount, maxPlayersCount);
|
||||
return new ProfileEntry.Builder()
|
||||
.motd(motd)
|
||||
.players(players)
|
||||
.playerCountText(playerCountText)
|
||||
.favicon(favicon)
|
||||
.hidePlayersEnabled(hidePlayersEnabled)
|
||||
.extraPlayersEnabled(extraPlayersEnabled)
|
||||
.maxPlayersEnabled(maxPlayersEnabled)
|
||||
.onlinePlayersEnabled(onlinePlayersEnabled)
|
||||
.extraPlayersCount(extraPlayersCount)
|
||||
.maxPlayersCount(maxPlayersCount)
|
||||
.onlinePlayersCount(onlinePlayersCount)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ServerListProfile resolveProfile(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
|
||||
@@ -82,8 +95,10 @@ public class ProfileManager{
|
||||
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
|
||||
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
|
||||
NullBool maxPlayersEnabled = resolveNullBool(node, "playerCount", "maxPlayers", "enabled");
|
||||
Integer extraPlayers = resolveNullableInt(node, "playerCount", "extraPlayers", "amount");
|
||||
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
|
||||
NullBool onlinePlayersEnabled = resolveNullBool(node, "playerCount", "onlinePlayers", "enabled");
|
||||
String extraPlayers = resolveNullableString(node, "playerCount", "extraPlayers", "amount");
|
||||
String maxPlayers = resolveNullableString(node, "playerCount", "maxPlayers", "amount");
|
||||
String onlinePlayers = resolveNullableString(node, "playerCount", "onlinePlayers", "amount");
|
||||
|
||||
return new ProfileEntry.Builder()
|
||||
.motd(motd)
|
||||
@@ -93,8 +108,10 @@ public class ProfileManager{
|
||||
.hidePlayersEnabled(hidePlayers)
|
||||
.extraPlayersEnabled(extraPlayersEnabled)
|
||||
.maxPlayersEnabled(maxPlayersEnabled)
|
||||
.onlinePlayersEnabled(onlinePlayersEnabled)
|
||||
.extraPlayersCount(extraPlayers)
|
||||
.maxPlayersCount(maxPlayers)
|
||||
.onlinePlayersCount(onlinePlayers)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -137,10 +154,10 @@ public class ProfileManager{
|
||||
return NullBool.resolve(node.node(path).getBoolean());
|
||||
}
|
||||
|
||||
private static Integer resolveNullableInt(ConfigurationNode node, Object... path){
|
||||
private static String resolveNullableString(ConfigurationNode node, Object... path){
|
||||
if(node.node(path).virtual())
|
||||
return null;
|
||||
|
||||
return node.node(path).getInt();
|
||||
return node.node(path).getString();
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -54,8 +54,10 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
|
||||
node.node("favicon").set(profile.favicon());
|
||||
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? 0 : profile.extraPlayersCount());
|
||||
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? "0" : profile.extraPlayersCount());
|
||||
node.node("playerCount", "maxPlayers", "enabled").set(profile.maxPlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? 0 : profile.maxPlayersCount());
|
||||
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? "0" : profile.maxPlayersCount());
|
||||
node.node("playerCount", "onlinePlayers", "enabled").set(profile.onlinePlayersEnabled().getOrDefault(false));
|
||||
node.node("playerCount", "onlinePlayers", "amount").set(profile.onlinePlayersCount() == null ? "0" : profile.onlinePlayersCount());
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -72,6 +72,9 @@ public class StringReplacer{
|
||||
boolean identified = false;
|
||||
boolean invalid = true;
|
||||
|
||||
int placeholderStart = position.getIndex() - 1;
|
||||
int valueStart = position.getIndex() - 1;
|
||||
|
||||
char[] chars = input.substring(index).toCharArray();
|
||||
for(final char c : chars){
|
||||
index++;
|
||||
@@ -83,6 +86,7 @@ public class StringReplacer{
|
||||
|
||||
if(c == ' ' && !identified){
|
||||
identified = true;
|
||||
valueStart = index + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -98,10 +102,6 @@ public class StringReplacer{
|
||||
|
||||
StringBuilder raw = new StringBuilder();
|
||||
|
||||
// Condition parsing needs one extra increase of index... for some reason
|
||||
if(collector != null)
|
||||
index++;
|
||||
|
||||
position.setIndex(index);
|
||||
|
||||
if(invalid){
|
||||
@@ -126,7 +126,7 @@ public class StringReplacer{
|
||||
raw.append('}');
|
||||
|
||||
if(collector != null)
|
||||
collector.appendWarningFormatted(index, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
|
||||
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
|
||||
|
||||
return raw.toString();
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public class StringReplacer{
|
||||
raw.append('}');
|
||||
|
||||
if(collector != null)
|
||||
collector.appendWarningFormatted(index, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
|
||||
collector.appendWarningFormatted(valueStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
|
||||
|
||||
return raw.toString();
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -107,6 +107,12 @@ disableDuringMaintenance:
|
||||
# Default: true
|
||||
#
|
||||
maxPlayers: true
|
||||
#
|
||||
# Whether the online players feature should be disabled while Maintenance mode is active.
|
||||
#
|
||||
# Default: true
|
||||
#
|
||||
onlinePlayers: true
|
||||
|
||||
#
|
||||
# DO NOT EDIT!
|
||||
|
||||
@@ -58,12 +58,17 @@ motd:
|
||||
# This option supports three types of inputs:
|
||||
#
|
||||
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
|
||||
# 2. URL pointing to an image.*
|
||||
# 3. Player name, UUID or placeholders returning one of these.*
|
||||
# 2. "random" to display a random PNG from the favicons folder.
|
||||
# 3. URL pointing to an image.
|
||||
# 4. Player name, UUID or placeholders returning one of these.
|
||||
# https://mc-heads.net will be used to retrieve an image of the provided name/UUID.
|
||||
#
|
||||
# * These images are loaded asynchronously, meaning they may not yet be "ready" when AdvancedServerList is done with
|
||||
# the event, requiring a refresh of the server list by the player to have it shown.
|
||||
# Note on favicons not showing:
|
||||
# AdvancedServerList has to create a Favicon object for the Proxy/Server to use which takes time to do so.
|
||||
# To not delay the Proxy/Server from being displayed (increase the loading time on the player end) is this creation
|
||||
# done asynchronously for URL/Player name/UUID. This has the downside that the Proxy/Server may be done handling the
|
||||
# ping before the Favicon is created, causing none to be displayed.
|
||||
# Note that this won't happen with local favicons, as those are created during the plugin's startup.
|
||||
#
|
||||
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
|
||||
#
|
||||
@@ -134,6 +139,7 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be added to the online player count to then use as the new max player count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
|
||||
# 9 when 8 are online and so on.
|
||||
@@ -162,9 +168,34 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new max players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to 0.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
#
|
||||
# The onlinePlayers feature allows to set a number to use as the online player count to display.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers
|
||||
#
|
||||
onlinePlayers:
|
||||
#
|
||||
# Set whether the onlinePlayers feature should be enabled or not.
|
||||
# When set to true, the max player count will be set to the 'amount' value.
|
||||
#
|
||||
# If not present, defaults to false.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-enabled
|
||||
#
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new online players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to current online player count.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
@@ -0,0 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block announce %}
|
||||
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
|
||||
Celebrating <a href="https://andre601.ch/blog/2024/12-13-history-of-asl/" target="_blank" rel="nofollow">25,000 downloads!</a> Thank you!
|
||||
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
[discord]: https://discord.gg/MyPTjpsgGH
|
||||
|
||||
[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
|
||||
|
||||
[modrinth]: https://modrinth.com/plugin/advancedserverlist
|
||||
[hangar]: https://hangar.papermc.io/Andre_601/AdvancedServerList
|
||||
[codeberg]: https://codeberg.org/Andre601/AdvancedServerList
|
||||
@@ -1,7 +1,14 @@
|
||||
---
|
||||
icon: octicons/stop-24
|
||||
---
|
||||
# BanPlugins Addon
|
||||
|
||||
The BanPlugins Addon was made to provide placeholders for different punishment plugins to use in AdvancedServerList.
|
||||
|
||||
/// info
|
||||
The BanPlugins Addon is available in downloads of AdvancedServerList on [:simple-modrinth: Modrinth](https://modrinth.com/plugin/advancedserverlist) and in [Releases on :simple-codeberg: Codeberg](https://codeberg.org/Andre601/AdvancedServerList/releases).
|
||||
///
|
||||
|
||||
## Placeholders
|
||||
|
||||
/// tab | AdvancedBan
|
||||
|
||||
@@ -7,6 +7,23 @@ icon: octicons/log-24
|
||||
This page lists the recent changes made towards the AdvancedServerListAPI.
|
||||
They are ordered newest to oldest.
|
||||
|
||||
## v4.0.0 { #v4.0.0 }
|
||||
|
||||
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v4.0.0-breaking }
|
||||
|
||||
- Changed `extraPlayersCount()` and `maxPlayersCount()` from using an Integer to using a String instead.
|
||||
- This also affects their corresponding `ProfileEntry.Builder` methods.
|
||||
- Removed all previously deprecated methods.
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v4.0.0-added }
|
||||
|
||||
- New setter methods added to [`ProfileEntry.Builder`][profileentry.builder] class:
|
||||
- [`onlinePlayersCount(String)`][onlinePlayersCount]
|
||||
- [`onlinePlayersEnabled(NullBool)`][onlinePlayersEnabled]
|
||||
|
||||
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount(integer)
|
||||
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled(nullbool)
|
||||
|
||||
## v3.3.0 { #v3.3.0 }
|
||||
|
||||
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.3.0-added }
|
||||
|
||||
+12
-14
@@ -11,7 +11,7 @@ AdvancedServerList offers an API that other plugins can use to add their own pla
|
||||
Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depending on what you use:
|
||||
|
||||
/// tab | :simple-apachemaven: Maven
|
||||
```xml title="pom.xml"
|
||||
```xml { data-md-component="api-version" title="pom.xml" }
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>codeberg</id>
|
||||
@@ -51,7 +51,7 @@ Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depend
|
||||
///
|
||||
|
||||
/// tab | :simple-gradle: Gradle
|
||||
```groovy title="build.gradle"
|
||||
```groovy { data-md-component="api-version" title="build.gradle" }
|
||||
repositorories {
|
||||
maven { url = 'https://codeberg.org/api/packages/Andre601/maven/' }
|
||||
}
|
||||
@@ -68,7 +68,7 @@ dependencies {
|
||||
///
|
||||
|
||||
/// tab | :simple-gradle: Gradle (KTS)
|
||||
```kotlin title="build.gradle.kts"
|
||||
```kotlin { data-md-component="api-version" title="build.gradle.kts" }
|
||||
repositories {
|
||||
maven("https://codeberg.org/api/packages/Andre601/maven/")
|
||||
}
|
||||
@@ -96,11 +96,11 @@ To add your own placeholders, follow these steps:
|
||||
|
||||
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:
|
||||
|
||||
```java
|
||||
```java { .annotate title="Creating PlaceholderProvider class" }
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
public MyPlaceholders(String identifier) {
|
||||
super(identifier);
|
||||
super(identifier); // (1)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,14 +110,12 @@ public class MyPlaceholders extends PlaceholderProvider {
|
||||
}
|
||||
```
|
||||
|
||||
/// 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");
|
||||
}
|
||||
```
|
||||
///
|
||||
1. It is recommended to replace this constructor with a no-args Constructor and have the placeholder name set in the `super` directly:
|
||||
```java
|
||||
public MyPlaceholders() {
|
||||
super("myplaceholders");
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -128,7 +126,7 @@ What you return is completely up to you. Just keep in mind that returning `null`
|
||||
/// details | Example of final class
|
||||
type: example
|
||||
|
||||
```java
|
||||
```java title="MyPlaceholders.java"
|
||||
public class MyPlaceholders extends PlaceholderProvider {
|
||||
|
||||
public MyPlaceholders() {
|
||||
|
||||
+28
-186
@@ -119,6 +119,34 @@ methods:
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
- name: 'onlinePlayersCount'
|
||||
description: |
|
||||
Sets the value to resolve into a number by AdvancedServerList.<br>
|
||||
Strings not resolving into valid numbers will be treated as this option not being set.
|
||||
parameters:
|
||||
- name: 'onlinePlayersCount'
|
||||
description: 'The number of online players to set.'
|
||||
type: 'String'
|
||||
attribute:
|
||||
- 'nullable'
|
||||
returns: 'This Builder after the max player count has been set. Useful for chaining.'
|
||||
- name: 'onlinePlayersEnabled'
|
||||
description: |
|
||||
Sets whether the online players feature should be enabled.<br>
|
||||
<br>
|
||||
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
|
||||
<br>
|
||||
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should onlinePlayersEnabled be null.
|
||||
parameters:
|
||||
- name: 'onlinePlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: 'NullBool'
|
||||
attribute:
|
||||
- 'notnull'
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
- name: 'playerCountText'
|
||||
description: |
|
||||
Sets the text to override the player count with.<br>
|
||||
@@ -155,192 +183,6 @@ methods:
|
||||
name: 'ProfileEntry'
|
||||
type: 'object'
|
||||
link: './..'
|
||||
#
|
||||
# Deprecated stuff
|
||||
#
|
||||
- name: 'setExtraPlayerCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersCount'
|
||||
description: |
|
||||
Sets the number of players to add to the online players to use as the new max players value.<br>
|
||||
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersCount'
|
||||
description: 'The number of extra players to add.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayerscount(integer)">extraPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setExtraPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the extra players feature should be enabled or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'extraPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayersenabled(nullbool)">extraPlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setFavicon'
|
||||
description: |
|
||||
Sets the value to use for the favicon.<br>
|
||||
The following values are supported:
|
||||
<ul>
|
||||
<li>URL to a valid PNG file.</li>
|
||||
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
|
||||
<li><code>${player uuid}</code> to display the avatar of the player.</li>
|
||||
</ul>
|
||||
returns: 'This Builder after the favicon has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'favicon'
|
||||
description: 'The favicon to set'
|
||||
type: String
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#favicon(string)">favicon(String)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setHidePlayersEnabled'
|
||||
description: |
|
||||
Sets whether the player count should be hidden or not.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'hidePlayersEnabled'
|
||||
description: 'Whether the player count should be hidden or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#hideplayersenabled(nullbool)">hidePlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersCount'
|
||||
description: |
|
||||
Sets the number of max players allowed to join this server.<br>
|
||||
This option has no effect when <a href="../#maxplayersenabled()"><code>maxPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
|
||||
<br>
|
||||
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setmaxplayersenabled(nullbool)"><code>setMaxPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
|
||||
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersCount'
|
||||
description: 'The number of max players to set.'
|
||||
type: Integer
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayerscount(integer)">maxPlayersCount(Integer)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMaxPlayersEnabled'
|
||||
description: |
|
||||
Sets whether the max players feature should be enabled.<br>
|
||||
<br>
|
||||
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
|
||||
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'maxPlayersEnabled'
|
||||
description: 'Whether the extra players feature should be enabled or not.'
|
||||
type: NullBool
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled(NullBool)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setMotd'
|
||||
description: |
|
||||
Sets a new MOTD to use.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the MOTD.<br>
|
||||
Only the first two entries of the list will be considered and any additional ones discarded.
|
||||
returns: 'This Builder after the motd has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'motd'
|
||||
description: 'The MOTD to use.'
|
||||
type: 'List<String>'
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#motd(string)">motd(String)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayerCountText'
|
||||
description: |
|
||||
Sets the text to override the player count with.<br>
|
||||
<br>
|
||||
Set to an empty String or <code>null</code> to not alter the player count text.
|
||||
returns: 'This Builder after the player count text has been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'playerCountText'
|
||||
description: 'The text to show in the player count.'
|
||||
type: String
|
||||
attribute:
|
||||
- nullable
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#playercounttext(string)">playerCountText(String)</a> instead.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
- name: 'setPlayers'
|
||||
description: |
|
||||
Sets the players (lines) to use for the hover.<br>
|
||||
<br>
|
||||
Set to an empty list to not change the hover text.
|
||||
returns: 'This Builder after the players have been set. Useful for chaining.'
|
||||
parameters:
|
||||
- name: 'players'
|
||||
description: 'The lines to set for the hover.'
|
||||
type: 'List<String>'
|
||||
attribute:
|
||||
- notnull
|
||||
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#players(list<string>)">players(List<String>)</a> instead.'
|
||||
throws:
|
||||
- name: 'IllegalArgumentException'
|
||||
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
|
||||
type:
|
||||
name: 'Builder'
|
||||
type: 'object'
|
||||
---
|
||||
|
||||
# <api__class></api__class> Builder
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -4,7 +4,7 @@ document$.subscribe(async () => {
|
||||
|
||||
const repo_stats = document.querySelector('[data-md-component="source"] .md-source__repository');
|
||||
|
||||
function loadCodebergInfo(data) {
|
||||
async function loadCodebergInfo(data) {
|
||||
const facts = document.createElement("ul");
|
||||
facts.className = "md-source__facts";
|
||||
|
||||
@@ -28,22 +28,36 @@ document$.subscribe(async () => {
|
||||
repo_stats.appendChild(facts);
|
||||
}
|
||||
|
||||
function loadApiInfo(data) {
|
||||
async function loadApiInfo(data) {
|
||||
const codeBlocks = document.querySelectorAll('[data-md-component="api-version"] pre code')
|
||||
if (codeBlocks === null)
|
||||
return;
|
||||
|
||||
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.substring(1));
|
||||
}
|
||||
const regex = new RegExp('{apiVersion}', 'g');
|
||||
codeBlocks.forEach((codeBlock) => {
|
||||
var walker = document.createTreeWalker(codeBlock, NodeFilter.SHOW_TEXT);
|
||||
var node;
|
||||
while (node = walker.nextNode()) {
|
||||
node.nodeValue = node.nodeValue.replace(regex, version.substring(1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPluginVersion(data) {
|
||||
async function loadPluginVersion(data) {
|
||||
const entries = document.querySelectorAll('code[data-md-component="plugin-version"]');
|
||||
if(entries === null)
|
||||
return;
|
||||
|
||||
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.substring(1));
|
||||
}
|
||||
const regex = new RegExp('{version}', 'g');
|
||||
entries.forEach((entry) => {
|
||||
var walker = document.createTreeWalker(entry, NodeFilter.SHOW_TEXT);
|
||||
var node;
|
||||
while (node = walker.nextNode()) {
|
||||
node.nodeValue = node.nodeValue.replace(regex, version.substring(1));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchApiInfo() {
|
||||
|
||||
@@ -44,4 +44,11 @@
|
||||
|
||||
.md-source__repository .md-source__facts {
|
||||
animation: facts .25s ease-in;
|
||||
}
|
||||
|
||||
.md-nav--secondary li.md-nav__item > .md-nav__link {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ icon: octicons/list-unordered-24
|
||||
|
||||
This page lists some examples you may want to use for your proxy or server.
|
||||
|
||||
Feel free to suggest additional examples in the `advancedserverlist` category on the [M.O.S.S. Discord Server](https://discord.gg/MyPTjpsgGH){ target="_blank" rel="nofollow" }.
|
||||
Feel free to suggest additional examples in the `advancedserverlist` category on the [M.O.S.S. Discord Server][discord]{ target="_blank" rel="nofollow" }.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ icon: octicons/milestone-24
|
||||
# Getting Started
|
||||
|
||||
This page will explain how to set up AdvancedServerList and make it work for your server.
|
||||
The guide is designed to be as easy to understand as possible. If you still have problems or questions, join the [M.O.S.S Discord Server](https://discord.gg/MyPTjpsgGH){ target="_blank" rel="nofollow" } for more help.
|
||||
The guide is designed to be as easy to understand as possible. If you still have problems or questions, join the [M.O.S.S Discord Server][discord]{ target="_blank" rel="nofollow" } for more help.
|
||||
|
||||
## 1. Download the plugin { #download-the-plugin }
|
||||
|
||||
@@ -109,10 +109,6 @@ The plugin also supports these additional plugins. They are all optional.
|
||||
|
||||
</div>
|
||||
|
||||
[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
|
||||
[addon]: ../addons/banplugins.md
|
||||
|
||||
## 2. Installation { #installation }
|
||||
@@ -120,11 +116,11 @@ The plugin also supports these additional plugins. They are all optional.
|
||||
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` | Paper |
|
||||
| `AdvancedServerList-BungeeCord-{version}.jar` | BungeeCord, Waterfall |
|
||||
| `AdvancedServerList-Velocity-{version}.jar` | Velocity |
|
||||
| Jar file name | Platforms |
|
||||
|-------------------------------------------------------------------------------------|-----------------------|
|
||||
| `AdvancedServerList-Paper-{version}.jar`{ data-md-component="plugin-version" } | Paper |
|
||||
| `AdvancedServerList-BungeeCord-{version}.jar`{ data-md-component="plugin-version" } | BungeeCord, Waterfall |
|
||||
| `AdvancedServerList-Velocity-{version}.jar`{ data-md-component="plugin-version" } | Velocity |
|
||||
|
||||
After you added it to your plugins folder - alongside any other dependency you may want - (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.
|
||||
@@ -214,12 +210,17 @@ motd:
|
||||
# This option supports three types of inputs:
|
||||
#
|
||||
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
|
||||
# 2. URL pointing to an image.*
|
||||
# 3. Player name, UUID or placeholders returning one of these.*
|
||||
# 2. "random" to display a random PNG from the favicons folder.
|
||||
# 3. URL pointing to an image.
|
||||
# 4. Player name, UUID or placeholders returning one of these.
|
||||
# https://mc-heads.net will be used to retrieve an image of the provided name/UUID.
|
||||
#
|
||||
# * These images are loaded asynchronously, meaning they may not yet be "ready" when AdvancedServerList is done with
|
||||
# the event, requiring a refresh of the server list by the player to have it shown.
|
||||
# Note on favicons not showing:
|
||||
# AdvancedServerList has to create a Favicon object for the Proxy/Server to use which takes time to do so.
|
||||
# To not delay the Proxy/Server from being displayed (increase the loading time on the player end) is this creation
|
||||
# done asynchronously for URL/Player name/UUID. This has the downside that the Proxy/Server may be done handling the
|
||||
# ping before the Favicon is created, causing none to be displayed.
|
||||
# Note that this won't happen with local favicons, as those are created during the plugin's startup.
|
||||
#
|
||||
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
|
||||
#
|
||||
@@ -290,6 +291,7 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be added to the online player count to then use as the new max player count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
|
||||
# 9 when 8 are online and so on.
|
||||
@@ -318,12 +320,37 @@ playerCount:
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new max players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to 0.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
#
|
||||
# The onlinePlayers feature allows to set a number to use as the online player count to display.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers
|
||||
#
|
||||
onlinePlayers:
|
||||
#
|
||||
# Set whether the onlinePlayers feature should be enabled or not.
|
||||
# When set to true, the max player count will be set to the 'amount' value.
|
||||
#
|
||||
# If not present, defaults to false.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-enabled
|
||||
#
|
||||
enabled: false
|
||||
#
|
||||
# Set the number that should be used as the new online players count.
|
||||
# Placeholders resolving to numbers can be used here.
|
||||
#
|
||||
# If not present, defaults to current online player count.
|
||||
#
|
||||
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-amount
|
||||
#
|
||||
amount: 0
|
||||
```
|
||||
///
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
icon: octicons/project-roadmap-24
|
||||
---
|
||||
|
||||
# Tutorials
|
||||
|
||||
This page lists tutorials made by the community of AdvancedServerList.
|
||||
Be aware that any info shown may be outdated.
|
||||
|
||||
Can't find a tutorial that exists? Join the [M.O.S.S. Discord][discord]{ target="_blank" rel="nofollow" } and suggest it in `#asl-support` to be added.
|
||||
|
||||
## Video Tutorials
|
||||
|
||||
Below is a collection of video tutorials made.
|
||||
|
||||
/// note
|
||||
For privacy reasons are only thumbnails of the videos displayed, as otherwise sensitive data would be sent via embedding the videos themself.
|
||||
you can click the image to be sent to the actual video.
|
||||
///
|
||||
|
||||
### KasaiSora
|
||||
|
||||
**Video Language:** :flag_gb: English
|
||||
|
||||
[](https://youtube.com/watch?v=9cU0uUWHOO0){ target="_blank" rel="nofollow" }
|
||||
|
||||
### Ajneb97
|
||||
|
||||
**Video Language:** :flag_es: Spanish
|
||||
|
||||
[](https://youtube.com/watch?v=rIbljm_4HVI){ target="_blank" rel="nofollow" }
|
||||
|
||||
## Text Tutorials
|
||||
|
||||
Text-based tutorials (Forum Posts, Blog Posts, etc).
|
||||
|
||||
*No entries yet*
|
||||
@@ -11,13 +11,13 @@ These pages may include important information about the migration process and wh
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [**MiniMOTD**](minimotd.md)
|
||||
- [**MiniMOTD**](plugins/minimotd.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from the Plugin [MiniMOTD](https://github.com/jpenilla/MiniMOTD){ target="_blank" rel="nofollow" }
|
||||
|
||||
- [**ServerListPlus**](serverlistplus.md)
|
||||
- [**ServerListPlus**](plugins/serverlistplus.md)
|
||||
|
||||
----
|
||||
|
||||
@@ -32,31 +32,31 @@ These guides are only for the Server List Profile files, as the config.yml gets
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [**v3.8.0 to v3.9.0**](v3_8_0-to-v3_9_0.md)
|
||||
- [**v3.8.0 to v3.9.0**](versions/v3.8.0-to-v3.9.0.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from version 3.8.0 to 3.9.0.
|
||||
|
||||
- [**v3.7.0 to v3.8.0**](v3_7_0-to-v3_8_0.md)
|
||||
- [**v3.7.0 to v3.8.0**](versions/v3.7.0-to-v3.8.0.md)
|
||||
|
||||
----
|
||||
|
||||
Migrating from version 3.7.0 to 3.8.0.
|
||||
|
||||
- [**< v3.7.0 to v3.7.0**](pre-v3_7_0-to-v3_7_0.md)
|
||||
- [**< v3.7.0 to v3.7.0**](versions/pre-v3.7.0-to-v3.7.0.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from any version prior to 3.7.0 to 3.7.0 or newer.
|
||||
|
||||
- [**v1.9.0 to v1.10.0**](v1_9_0-to-v1_10_0.md)
|
||||
- [**v1.9.0 to v1.10.0**](versions/v1.9.0-to-v1.10.0.md)
|
||||
|
||||
----
|
||||
|
||||
Migrate from version 1.9.0 to 1.10.0.
|
||||
|
||||
- [**v1.5.3 to v1.6.0**](v1_5_3-to-v1_6_0.md)
|
||||
- [**v1.5.3 to v1.6.0**](versions/v1.5.3-to-v1.6.0.md)
|
||||
|
||||
----
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ Version `4.10.0` added support for migrating your existing `main.conf` configura
|
||||
|
||||
## How to Migrate
|
||||
|
||||
Execute the command [`/asl migrate minimotd`](../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
|
||||
Execute the command [`/asl migrate minimotd`](../../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
|
||||
|
||||
## Example
|
||||
|
||||
Below can you find a full example of a `main.conf` file and the corresponding migrated files from AdvancedServerList:
|
||||
|
||||
/// tab | :octicons-file-code-24: main.conf
|
||||
```conf
|
||||
```ruby
|
||||
icon-enabled=true
|
||||
motd-enabled=true
|
||||
motds=[
|
||||
@@ -48,7 +48,7 @@ The following Favicon options get converted into an equivalent one:
|
||||
|
||||
## How to Migrate
|
||||
|
||||
Execute the command [`/asl migrate serverlistplus`](../commands/index.md#migrate) to start the migration process. Make sure that ServerListPlus is present and enabled.
|
||||
Execute the command [`/asl migrate serverlistplus`](../../commands/index.md#migrate) to start the migration process. Make sure that ServerListPlus is present and enabled.
|
||||
|
||||
## Example
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ icon: octicons/arrow-right-24
|
||||
# < v3.7.0 to v3.7.0
|
||||
|
||||
Version 3.7.0 of AdvancedServerList brought significant changes to its conditions system.
|
||||
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../profiles/index.md#condition) option should now be used instead.
|
||||
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../../profiles/index.md#condition) option should now be used instead.
|
||||
|
||||
## Migration
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,8 +6,6 @@ icon: material/percent
|
||||
|
||||
AdvancedServerList provides support for [PlaceholderAPI] placeholders to be used, while also providing its own set of placeholders.
|
||||
|
||||
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
|
||||
|
||||
## Own placeholders
|
||||
|
||||
The below listed placeholders can be used through PlaceholderAPI in other plugins.
|
||||
|
||||
+69
-11
@@ -91,6 +91,8 @@ motd:
|
||||
|
||||
## Motd
|
||||
|
||||
<!-- admo:tip Start a line with <code><center></code> to have it centered. -->
|
||||
|
||||
The `motd` option allows you to alter the "Message of the day" that is being displayed on a server in the multiplayer screen.
|
||||
Please see the [Formatting](formatting.md) for all supported formatting options.
|
||||
|
||||
@@ -119,15 +121,28 @@ motd:
|
||||
|
||||
The `favicon` option can be used to define an image to display in the server list.
|
||||
|
||||
The Value can be one of three possible options, each being checked for in order:
|
||||
The Value can be one of the following:
|
||||
|
||||
- A URL pointing to an image file. The URL needs to start with `https://` to work.
|
||||
- A PNG filename, including `.png` file extension, matching a PNG file in the `favicons` folder.
|
||||
- A player name or UUID, or a [placeholder](placeholders.md) that resolves into one.
|
||||
- A URL pointing to a Image file. The URL needs to start with `https://` for it to work.
|
||||
- A filename matching a pre-existing file in the `favicons` folder of the Plugin.
|
||||
- Only PNG files are supported for now and the provided filename needs to end with `.png`
|
||||
- `random` can be used to have the plugin select a random image from the Favicons folder.
|
||||
- A player name or UUID.
|
||||
- `${player name}`, `${player uuid}` or any [placeholder](placeholders.md) that resolves into a player name/UUID can be used.
|
||||
- Uses [mc-heads.net](https://mc-heads.net) to resolve the Player Name/UUID.
|
||||
|
||||
/// details | Why is the favicon from URL/Placeholder not showing?
|
||||
type: question
|
||||
|
||||
AdvancedServerList has to create a Favicon instance to use, as the Proxy/Server doesn't directly use PNG images.
|
||||
This action takes time, so to not unnecessarely delay the Pinged Proxy/Server from showing is this done asynchrnously.
|
||||
This has the issue that the Proxy/Server may be done with handling the Ping before AdvancedServerList is done creating the Favicon, resulting in no favicon being displayed.
|
||||
|
||||
This issue is only present for when using either a URL or a Player name/uuid and not for local favicons, as those are created when the plugin loads.
|
||||
|
||||
Favicons *should* display on the second ping, if pinged within the configured favicon cache time (Default: 1 minute).
|
||||
///
|
||||
|
||||
Note that for the name/UUID, the site https://mc-heads.net is being used.
|
||||
Use the URL option with the `${player uuid}` placeholder if you want to use another service.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -161,7 +176,7 @@ When set to true will the player count be replaced with `???`.
|
||||
In addition are the [`playerCount -> text`](#text) and [`playerCount -> hover`](#hover) options ignored.
|
||||
|
||||
If you want to not show any text at all, set this option to `false` (or remove it) and instead use the [`playerCount -> text`](#text) option.
|
||||
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -227,7 +242,7 @@ Please take note of the following caveats:
|
||||
If you want to not show any text, just use a single color (i.e. `text: '<grey>'`) to do so.
|
||||
|
||||
This option only supports basic colors and no HEX colors.
|
||||
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -267,7 +282,9 @@ Use the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option t
|
||||
The `playerCount -> extraPlayers -> amount` option defines how much should be added to the current online player count to then use as max player count.
|
||||
|
||||
Example: Setting this option to `1` while currently 10 players are online will result in `10/11` being displayed on the player count (Assuming it is not being overriden by the [`playerCount -> text`](#text) option).
|
||||
|
||||
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -309,7 +326,9 @@ Use the [`playerCount -> maxPlayers -> amount`](#maxplayers-amount) option to se
|
||||
|
||||
The `playerCount -> maxPlayers -> amount` option defines the number to use as the server's max players count.
|
||||
Unlike the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option does this one not first add the current online player count to the number to then set.
|
||||
|
||||
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
@@ -330,5 +349,44 @@ playerCount:
|
||||
|
||||
{ loading="lazy" }
|
||||
|
||||
</div>
|
||||
///
|
||||
|
||||
### OnlinePlayers
|
||||
|
||||
<!-- admo:warning Using this option alters the output of <code>playerCount -> extraPlayers</code> -->
|
||||
|
||||
The `playerCount -> onlinePlayers` option contains settings to enable and set the number of players online on the server.
|
||||
|
||||
#### Enabled { #onlineplayers-enabled }
|
||||
|
||||
Enables the online players feature.
|
||||
Use the [`playerCount -> onlinePlayers -> amount`](#onlineplayers-amount) option to set the online players value itself.
|
||||
|
||||
#### Amount { #onlineplayers-amount }
|
||||
|
||||
Sets the number to display as the server's only player count.
|
||||
You can use placeholders that resolve into numbers for this option.
|
||||
|
||||
/// details | Example
|
||||
type: example
|
||||
|
||||
```yaml title="YAML file"
|
||||
priority: 0
|
||||
|
||||
# Hides the MOTD for demonstration purposes
|
||||
motd:
|
||||
- '<grey>'
|
||||
- '<grey>'
|
||||
|
||||
playerCount:
|
||||
onlinePlayers:
|
||||
enabled: true
|
||||
amount: 10
|
||||
```
|
||||
<div class="result" markdown>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
///
|
||||
@@ -44,7 +44,8 @@ These placeholders use values given by the server/proxy AdvancedServerList runs
|
||||
|
||||
[^4]:
|
||||
A comma-separated list of world (On Paper) or Server (On BungeeCord/Velocity) names can be provided to display the added numbers of players in these worlds/servers.
|
||||
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
|
||||
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
|
||||
Using the [onlinePlayers' `amount`](index.md#onlineplayers-amount) option will modify the output of this placeholder, except when used in [`condition`](index.md#condition).
|
||||
[^5]:
|
||||
Using either the [extraPlayers' `amount`](index.md#extraplayers-amount) or [maxPlayers' `amount`](index.md#maxplayers-amount) option will make this placeholder return the modified max players count.
|
||||
Only exception to this rule is when the placeholder is used in the [`condition`](index.md#condition) option in which case it returns the actual max player count of the proxy/server.
|
||||
@@ -52,6 +53,23 @@ These placeholders use values given by the server/proxy AdvancedServerList runs
|
||||
An optional server name can be provided to display the IP/Domain associated with that server. This only works on BungeeCord or Velocity.
|
||||
**Example:** `${server host survival}` would display the IP/Domain associated with the `survival` server.
|
||||
|
||||
### Proxy
|
||||
|
||||
These placeholders are only available on the BungeeCord and Velocity versions of AdvancedServerList.
|
||||
|
||||
/// note
|
||||
Servers are pinged every 10 seconds by the plugin and cached for that time period.
|
||||
///
|
||||
|
||||
| Placeholders | Description | Default[^7] |
|
||||
|------------------------------|-------------------------------------------------------------------|-------------|
|
||||
| `${proxy status <name>}` | Returns `online` or `offline` based on the Server's availability. | `offline` |
|
||||
| `${proxy motd <name>}` | Returns the Server's MOTD as MiniMessage String. | `none` |
|
||||
| `${proxy players <name>}` | Returns the number of online Players on the Server. | `0` |
|
||||
| `${proxy maxPlayers <name>}` | Returns the max number of Players allowed to join the Server. | `0` |
|
||||
|
||||
[^7]: The default value returned, should the Server or parts of it not be available.
|
||||
|
||||
### Maintenance
|
||||
|
||||
These placeholders require the [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) plugin to work.
|
||||
|
||||
+24
-8
@@ -68,6 +68,18 @@ extra:
|
||||
plugins:
|
||||
- search
|
||||
- glightbox
|
||||
- redirects:
|
||||
redirect_maps:
|
||||
# Plugin Migration Pages
|
||||
'migration/minimotd.md': 'migration/plugins/minimotd.md'
|
||||
'migration/serverlistplus.md': 'migration/plugins/serverlistplus.md'
|
||||
#
|
||||
# Version Migration Pages
|
||||
'migration/v3_8_0-to-v3_9_0.md': 'migration/versions/v3.8.0-to-v3.9.0.md'
|
||||
'migration/v3_7_0-to-v3_8_0.md': 'migration/versions/v3.7.0-to-v3.8.0.md'
|
||||
'migration/pre-v3_7_0-to-v3_7_0.md': 'migration/versions/pre-v3.7.0-to-v3.7.0.md'
|
||||
'migration/v1_9_0-to-v1_10_0.md': 'migration/versions/v1.9.0-to-v1.10.0.md'
|
||||
'migration/v1_5_3-to-v1_6_0.md': 'migration/versions/v1.5.3-to-v1.6.0.md'
|
||||
- pagenav-generator
|
||||
|
||||
markdown_extensions:
|
||||
@@ -84,6 +96,8 @@ markdown_extensions:
|
||||
- pymdownx.superfences:
|
||||
- pymdownx.snippets:
|
||||
base_path: docs/.snippets
|
||||
auto_append:
|
||||
- links.md
|
||||
- pymdownx.blocks.admonition:
|
||||
types:
|
||||
- note
|
||||
@@ -108,7 +122,9 @@ hooks:
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Getting Started: getting-started/index.md
|
||||
- Getting Started:
|
||||
- getting-started/index.md
|
||||
- Tutorials: getting-started/tutorials.md
|
||||
- Commands: commands/index.md
|
||||
- Profiles:
|
||||
- profiles/index.md
|
||||
@@ -119,14 +135,14 @@ nav:
|
||||
- Migration:
|
||||
- migration/index.md
|
||||
- Other Plugins:
|
||||
- MiniMOTD: migration/minimotd.md
|
||||
- ServerListPlus: migration/serverlistplus.md
|
||||
- MiniMOTD: migration/plugins/minimotd.md
|
||||
- ServerListPlus: migration/plugins/serverlistplus.md
|
||||
- AdvancedServerList:
|
||||
- v3.8.0 to v3.9.0: migration/v3_8_0-to-v3_9_0.md
|
||||
- v3.7.0 to v3.8.0: migration/v3_7_0-to-v3_8_0.md
|
||||
- '< v3.7.0 to v3.7.0': migration/pre-v3_7_0-to-v3_7_0.md
|
||||
- v1.9.0 to v1.10.0: migration/v1_9_0-to-v1_10_0.md
|
||||
- v1.5.3 to v1.6.0: migration/v1_5_3-to-v1_6_0.md
|
||||
- v3.8.0 to v3.9.0: migration/versions/v3.8.0-to-v3.9.0.md
|
||||
- v3.7.0 to v3.8.0: migration/versions/v3.7.0-to-v3.8.0.md
|
||||
- '< v3.7.0 to v3.7.0': migration/versions/pre-v3.7.0-to-v3.7.0.md
|
||||
- v1.9.0 to v1.10.0: migration/versions/v1.9.0-to-v1.10.0.md
|
||||
- v1.5.3 to v1.6.0: migration/versions/v1.5.3-to-v1.6.0.md
|
||||
- API:
|
||||
- api/index.md
|
||||
- Changelog: api/changelog.md
|
||||
|
||||
+12
-2
@@ -85,7 +85,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion-api</artifactId>
|
||||
<version>5.0.3</version>
|
||||
<version>5.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -118,6 +118,16 @@
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>char-widths.json.gz</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<filtering>false</filtering>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
<includes>
|
||||
<include>char-widths.json.gz</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
|
||||
@@ -67,18 +67,6 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
|
||||
@Override
|
||||
public void onEnable(){
|
||||
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(this));
|
||||
|
||||
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
|
||||
@@ -149,6 +137,11 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScheduler(){
|
||||
// Unused
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<CachedServerIcon> getCore(){
|
||||
return core;
|
||||
@@ -220,27 +213,6 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
|
||||
return players.size();
|
||||
}
|
||||
|
||||
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");
|
||||
getPluginLogger().warn("from overall performance improvements amongst other things.");
|
||||
getPluginLogger().warn("");
|
||||
getPluginLogger().warn("Disabling AdvancedServerList. If you believe this is an error, report it on");
|
||||
getPluginLogger().warn("Codeberg: https://codeberg.org/Andre601/AdvancedServerList");
|
||||
getPluginLogger().warn("======================================================================================");
|
||||
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
private String getNewVersion(){
|
||||
ServerBuildInfo info = ServerBuildInfo.buildInfo();
|
||||
|
||||
|
||||
@@ -48,5 +48,20 @@ public class LoadEvent implements Listener{
|
||||
|
||||
// Load currently loaded worlds into the WorldCache
|
||||
Bukkit.getWorlds().forEach(world -> plugin.getWorldCache().addWorld(world));
|
||||
|
||||
// Print a warning if server load was after a reload.
|
||||
if(event.getType() != ServerLoadEvent.LoadType.RELOAD)
|
||||
return;
|
||||
|
||||
plugin.getPluginLogger().warn("======================================================================================");
|
||||
plugin.getPluginLogger().warn("SERVER RELOAD DETECTED!");
|
||||
plugin.getPluginLogger().warn("");
|
||||
plugin.getPluginLogger().warn("A server reload has been detected by AdvancedServerList, meaning either the /reload");
|
||||
plugin.getPluginLogger().warn("command or Bukkit.reload() was executed.");
|
||||
plugin.getPluginLogger().warn("");
|
||||
plugin.getPluginLogger().warn("YOU WILL GET NO SUPPORT FOR THE PLUGIN FOR ANY ISSUES YOU ENCOUNTER AFTER A SERVER");
|
||||
plugin.getPluginLogger().warn("RELOAD!");
|
||||
plugin.getPluginLogger().warn("ALWAYS RESTART YOUR SERVER. NEVER RELOAD IT!");
|
||||
plugin.getPluginLogger().warn("======================================================================================");
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -74,6 +74,11 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
event.setMaxPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
event.setNumPlayers(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
event.motd(component);
|
||||
@@ -200,12 +205,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
|
||||
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;
|
||||
})
|
||||
.modifyText(text -> parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
playerList.add(function.apply(parsed));
|
||||
|
||||
+2
-2
@@ -70,7 +70,7 @@ public record FakePlayerProfile(String name, UUID uuid) implements PlayerProfile
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerTextures getTextures(){
|
||||
return new FakePlayeerTextures();
|
||||
return new FakePlayerTextures();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,7 +153,7 @@ public record FakePlayerProfile(String name, UUID uuid) implements PlayerProfile
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private static record FakePlayeerTextures() implements PlayerTextures{
|
||||
private record FakePlayerTextures() implements PlayerTextures{
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(){
|
||||
|
||||
+40
-10
@@ -46,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
|
||||
@@ -94,26 +95,33 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
|
||||
ProfileEntry entry = ProfileManager.merge(profile);
|
||||
|
||||
Integer onlinePlayers = null;
|
||||
if(ProfileManager.checkOption(entry.onlinePlayersEnabled())){
|
||||
onlinePlayers = parseNumberOption(entry.onlinePlayersCount(), pl, player, server);
|
||||
online = onlinePlayers == null ? online : onlinePlayers;
|
||||
}
|
||||
|
||||
Integer maxPlayers = null;
|
||||
if(ProfileManager.checkOption(entry.maxPlayersEnabled())){
|
||||
max = entry.maxPlayersCount() == null ? 0 : entry.maxPlayersCount();
|
||||
maxPlayers = entry.maxPlayersCount();
|
||||
maxPlayers = parseNumberOption(entry.maxPlayersCount(), pl, player, server);
|
||||
max = maxPlayers == null ? 0 : maxPlayers;
|
||||
}
|
||||
|
||||
Integer extraPlayers = null;
|
||||
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
|
||||
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
|
||||
extraPlayers = entry.extraPlayersCount();
|
||||
extraPlayers = parseNumberOption(entry.extraPlayersCount(), pl, player, server);
|
||||
max = online + (extraPlayers == null ? 0 : extraPlayers);
|
||||
}
|
||||
|
||||
BukkitServer finalServer = new PaperServerImpl(plugin.getWorldCache().worlds(), online, max, host);
|
||||
return switch(identifier.toLowerCase(Locale.ROOT)){
|
||||
case "motd" -> getOption(entry.motd(), pl, player, finalServer);
|
||||
case "motd" -> getOption(entry.motd(), pl, player, finalServer, true);
|
||||
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
|
||||
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer);
|
||||
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer, false);
|
||||
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
|
||||
case "playercount_extraplayers" -> extraPlayers == null ? "null" : String.valueOf(extraPlayers);
|
||||
case "playercount_maxplayers" -> maxPlayers == null ? "null" : String.valueOf(maxPlayers);
|
||||
case "playercount_onlineplayers" -> onlinePlayers == null ? "null" : String.valueOf(onlinePlayers);
|
||||
case "server_playersmax" -> String.valueOf(max);
|
||||
default -> null;
|
||||
};
|
||||
@@ -129,13 +137,35 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
|
||||
}
|
||||
|
||||
private String getOption(String str, Player pl, BukkitPlayer player, BukkitServer server){
|
||||
return getOption(Collections.singletonList(str), pl, player, server);
|
||||
return getOption(Collections.singletonList(str), pl, player, server, false);
|
||||
}
|
||||
|
||||
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server){
|
||||
return ComponentParser.list(list)
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server, boolean isMotd){
|
||||
return list.stream()
|
||||
.map(line -> ComponentParser.text(line)
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.modifyText(text -> {
|
||||
if(isMotd)
|
||||
return plugin.getCore().getTextCenterUtil().getCenteredText(text);
|
||||
|
||||
return text;
|
||||
})
|
||||
.toString()
|
||||
)
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private Integer parseNumberOption(String option, Player pl, BukkitPlayer player, BukkitServer server){
|
||||
String parsed = ComponentParser.text(option)
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
|
||||
.toString();
|
||||
|
||||
try{
|
||||
return Integer.parseInt(parsed);
|
||||
}catch(NumberFormatException ex){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -73,19 +73,19 @@ public class PaperServerPlaceholders extends PlaceholderProvider{
|
||||
}
|
||||
case "playersMax" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(paperServer.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield paperServer.getHost();
|
||||
}
|
||||
case "whitelistEnabled" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(Bukkit.hasWhitelist());
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ description: '${plugin.description}'
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
|
||||
|
||||
api-version: '1.19'
|
||||
api-version: '1.20'
|
||||
|
||||
folia-supported: true
|
||||
|
||||
@@ -24,15 +24,6 @@ dependencies:
|
||||
load: BEFORE
|
||||
required: false
|
||||
|
||||
# The below stuff is NOT used by Paper plugin.
|
||||
commands:
|
||||
advancedserverlist:
|
||||
description: 'Main command of AdvancedServerList'
|
||||
usage: '/<command> [help|reload]'
|
||||
aliases:
|
||||
- 'asl'
|
||||
permission: 'advancedserverlist.admin'
|
||||
|
||||
# This is actually supported(?)
|
||||
permissions:
|
||||
advancedserverlist.*:
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#
|
||||
# This file is kept for Folia support.
|
||||
#
|
||||
|
||||
name: 'AdvancedServerList'
|
||||
author: 'Andre_601'
|
||||
version: '${plugin.version}'
|
||||
description: '${plugin.description}'
|
||||
|
||||
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
|
||||
|
||||
api-version: '1.19'
|
||||
|
||||
folia-supported: true
|
||||
|
||||
libraries:
|
||||
- 'org.spongepowered:configurate-yaml:4.1.2'
|
||||
- 'net.kyori:adventure-text-serializer-legacy:4.12.0'
|
||||
- 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
|
||||
softdepend:
|
||||
- 'PlaceholderAPI'
|
||||
- 'Maintenance'
|
||||
|
||||
commands:
|
||||
advancedserverlist:
|
||||
description: 'Main command of AdvancedServerList'
|
||||
usage: '/<command> [help|reload|clearCache]'
|
||||
aliases:
|
||||
- 'asl'
|
||||
permission: 'advancedserverlist.admin'
|
||||
|
||||
permissions:
|
||||
advancedserverlist.*:
|
||||
description: 'Grants access to all permissions'
|
||||
default: op
|
||||
children:
|
||||
- 'advancedserverlist.admin'
|
||||
advancedserverlist.admin:
|
||||
description: 'Grants access to all permissions'
|
||||
default: op
|
||||
children:
|
||||
- 'advancedserverlist.command.*'
|
||||
advancedserverlist.command.*:
|
||||
description: 'Grants access to all commands'
|
||||
default: op
|
||||
children:
|
||||
- 'advancedserverlist.command.help'
|
||||
- 'advancedserverlist.command.reload'
|
||||
advancedserverlist.command.help:
|
||||
description: 'Grants access to /asl help'
|
||||
default: op
|
||||
advancedserverlist.command.reload:
|
||||
description: 'Grants access to /asl reload'
|
||||
default: op
|
||||
advancedserverlist.command.clearcache:
|
||||
description: 'Clears the Player and Favicon cache'
|
||||
default: op
|
||||
@@ -37,10 +37,10 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<plugin.version>4.13.1</plugin.version>
|
||||
<plugin.version>5.2.0</plugin.version>
|
||||
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
|
||||
|
||||
<api.version>3.3.0</api.version>
|
||||
<api.version>4.0.0</api.version>
|
||||
|
||||
<dependency.adventure-api>4.17.0</dependency.adventure-api>
|
||||
<dependency.adventure-text-minimessage>4.17.0</dependency.adventure-text-minimessage>
|
||||
|
||||
File renamed without changes.
+2
-1
@@ -1,3 +1,4 @@
|
||||
mkdocs-material==9.5.33
|
||||
mkdocs-material==9.5.49
|
||||
mkdocs-glightbox==0.4.0
|
||||
mkdocs-redirects==1.2.2
|
||||
git+https://github.com/Andre601/mkdocs-pagenav-generator
|
||||
+1
-1
@@ -76,7 +76,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-velocity</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import ch.andre601.advancedserverlist.velocity.listeners.JoinEvent;
|
||||
import ch.andre601.advancedserverlist.velocity.listeners.PingEvent;
|
||||
import ch.andre601.advancedserverlist.velocity.logging.VelocityLogger;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityPlayerPlaceholders;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityProxyPlaceholders;
|
||||
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityServerPlaceholders;
|
||||
import com.alessiodp.libby.Library;
|
||||
import com.alessiodp.libby.VelocityLibraryManager;
|
||||
@@ -46,6 +47,8 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import de.myzelyam.api.vanish.VelocityVanishAPI;
|
||||
import org.bstats.charts.SimplePie;
|
||||
@@ -58,10 +61,14 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger("AdvancedServerList");
|
||||
private final Map<String, ServerPing> fetchedServers = new ConcurrentHashMap<>();
|
||||
|
||||
private final PluginLogger pluginLogger;
|
||||
private final ProxyServer proxy;
|
||||
@@ -73,6 +80,8 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
private VelocityLibraryManager<VelocityCore> libraryManager = null;
|
||||
|
||||
private ScheduledTask scheduledTask = null;
|
||||
|
||||
@Inject
|
||||
public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
|
||||
this.pluginLogger = new VelocityLogger(this, this.logger);
|
||||
@@ -84,12 +93,15 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
@Subscribe
|
||||
public void init(ProxyInitializeEvent event){
|
||||
this.core = AdvancedServerList.init(this, VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init(this));
|
||||
this.core = AdvancedServerList.init(this,
|
||||
VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init(this), VelocityProxyPlaceholders.init(this));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void pluginDisable(ProxyShutdownEvent event){
|
||||
core.disable();
|
||||
if(scheduledTask != null)
|
||||
scheduledTask.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,6 +157,13 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
libraryManager.loadLibrary(lib);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScheduler(){
|
||||
scheduledTask = getProxy().getScheduler().buildTask(this, this::fetchServers)
|
||||
.repeat(10, TimeUnit.SECONDS)
|
||||
.schedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancedServerList<Favicon> getCore(){
|
||||
return core;
|
||||
@@ -208,4 +227,18 @@ public class VelocityCore implements PluginCore<Favicon>{
|
||||
|
||||
return players.size();
|
||||
}
|
||||
|
||||
public Map<String, ServerPing> getFetchedServers(){
|
||||
return fetchedServers;
|
||||
}
|
||||
|
||||
private void fetchServers(){
|
||||
fetchedServers.clear();
|
||||
getProxy().getAllServers().forEach(server -> server.ping().whenComplete((ping, throwable) -> {
|
||||
if(throwable != null)
|
||||
return;
|
||||
|
||||
fetchedServers.put(server.getServerInfo().getName(), ping);
|
||||
}));
|
||||
}
|
||||
}
|
||||
+6
@@ -82,6 +82,11 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
builder.maximumPlayers(maxPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnlinePlayers(int onlinePlayers){
|
||||
builder.onlinePlayers(onlinePlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotd(Component component){
|
||||
builder.description(component);
|
||||
@@ -104,6 +109,7 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
|
||||
for(int i = 0; i < players.length; i++){
|
||||
String parsed = ComponentParser.text(lines.get(i))
|
||||
.modifyText(text -> StringReplacer.replace(text, player, server))
|
||||
.modifyText(text -> parsePAPIPlaceholders(text, player))
|
||||
.toString();
|
||||
|
||||
players[i] = new ServerPing.SamplePlayer(parsed, UUID.randomUUID());
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package ch.andre601.advancedserverlist.velocity.objects.placeholders;
|
||||
|
||||
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
|
||||
import ch.andre601.advancedserverlist.api.objects.GenericServer;
|
||||
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
|
||||
import ch.andre601.advancedserverlist.velocity.VelocityCore;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
|
||||
public class VelocityProxyPlaceholders extends PlaceholderProvider{
|
||||
|
||||
private final VelocityCore plugin;
|
||||
|
||||
private VelocityProxyPlaceholders(VelocityCore plugin){
|
||||
super("proxy");
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static VelocityProxyPlaceholders init(VelocityCore plugin){
|
||||
return new VelocityProxyPlaceholders(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
|
||||
String[] args = placeholder.split("\\s", 2);
|
||||
if(args.length < 2)
|
||||
return null;
|
||||
|
||||
ServerPing ping = plugin.getFetchedServers().get(args[1]);
|
||||
return switch(args[0]){
|
||||
case "status" -> ping == null ? "offline" : "online";
|
||||
case "motd" -> {
|
||||
if(ping == null)
|
||||
yield "none";
|
||||
|
||||
yield ComponentParser.toMMString(ping.getDescriptionComponent());
|
||||
}
|
||||
case "players" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
ServerPing.Players players = ping.getPlayers().orElse(null);
|
||||
if(players == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(players.getOnline());
|
||||
}
|
||||
case "maxPlayers" -> {
|
||||
if(ping == null)
|
||||
yield "0";
|
||||
|
||||
ServerPing.Players players = ping.getPlayers().orElse(null);
|
||||
if(players == null)
|
||||
yield "0";
|
||||
|
||||
yield String.valueOf(players.getMax());
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -80,18 +80,18 @@ public class VelocityServerPlaceholders extends PlaceholderProvider{
|
||||
}
|
||||
case "playersMax" -> {
|
||||
if(args.length >= 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield String.valueOf(proxy.getPlayersMax());
|
||||
}
|
||||
case "host" -> {
|
||||
if(args.length > 2)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
|
||||
RegisteredServer info = proxy.getServers().get(args[1]);
|
||||
if(info == null)
|
||||
yield null;
|
||||
yield "";
|
||||
|
||||
yield info.getServerInfo().getAddress().getHostString();
|
||||
}
|
||||
|
||||
@@ -52,13 +52,13 @@
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.14</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<version>5.4.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ public class VersionUploader{
|
||||
|
||||
if(args.length == 0){
|
||||
LOGGER.warn("MISSING ARGUMENT!");
|
||||
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar [--dryrun] --all | --modrinth | --hangar");
|
||||
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar --all | --modrinth | --hangar [--dryrun]");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class VersionUploader{
|
||||
}
|
||||
default -> {
|
||||
LOGGER.warn("Unknown argument '{}' provided.", args[0]);
|
||||
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar [--dryrun] --all | --modrinth | --hangar");
|
||||
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar --all | --modrinth | --hangar [--dryrun]");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
+3
-3
@@ -50,9 +50,9 @@ public class CodebergReleaseFetcher{
|
||||
|
||||
public static CodebergRelease fetch(){
|
||||
String tag = System.getenv("CI_COMMIT_TAG");
|
||||
String codbergToken = System.getenv("CODEBERG_API_TOKEN");
|
||||
String codebergToken = System.getenv("CODEBERG_API_TOKEN");
|
||||
|
||||
if(tag == null || codbergToken == null || tag.isEmpty() || codbergToken.isEmpty()){
|
||||
if(tag == null || codebergToken == null || tag.isEmpty() || codebergToken.isEmpty()){
|
||||
LOGGER.warn("Cannot fetch release data. Either Tag or Codeberg token was null/empty.");
|
||||
return null;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class CodebergReleaseFetcher{
|
||||
.url(url)
|
||||
.header("User-Agent", "VersionUploader-CodebergReleaseFetcher/v1.0.0")
|
||||
.header("Accept", "application/json")
|
||||
.header("Authorization", "token " + codbergToken)
|
||||
.header("Authorization", "token " + codebergToken)
|
||||
.build();
|
||||
|
||||
try(Response response = CLIENT.newCall(request).execute()){
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ public class HangarVersionUploader{
|
||||
Platform.VELOCITY, velocityDependencies
|
||||
),
|
||||
Map.of(
|
||||
Platform.PAPER, List.of("1.20.x", "1.21"),
|
||||
Platform.PAPER, List.of("1.20.x", "1.21.x"),
|
||||
Platform.WATERFALL, List.of("1.19.x", "1.20.x", "1.21"),
|
||||
Platform.VELOCITY, Collections.singletonList("3.2")
|
||||
),
|
||||
|
||||
+5
-3
@@ -25,8 +25,8 @@
|
||||
|
||||
package ch.andre601.advancedserverlist.versionuploader.modrinth;
|
||||
|
||||
import ch.andre601.advancedserverlist.versionuploader.ReleaseHolder;
|
||||
import ch.andre601.advancedserverlist.versionuploader.PlatformInfo;
|
||||
import ch.andre601.advancedserverlist.versionuploader.ReleaseHolder;
|
||||
import ch.andre601.advancedserverlist.versionuploader.VersionUploader;
|
||||
import ch.andre601.advancedserverlist.versionuploader.data.CodebergRelease;
|
||||
import com.google.gson.Gson;
|
||||
@@ -55,7 +55,8 @@ public class ModrinthVersionUploader{
|
||||
PlatformInfo.VELOCITY
|
||||
);
|
||||
private final List<String> versions = List.of(
|
||||
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6", "1.21"
|
||||
"1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6",
|
||||
"1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4"
|
||||
);
|
||||
|
||||
private final ModrinthAPI api;
|
||||
@@ -143,7 +144,8 @@ public class ModrinthVersionUploader{
|
||||
String url = versionUrl + projectVersion.getId();
|
||||
|
||||
logger.info("Created new release!");
|
||||
logger.info("Link: {}", url);
|
||||
logger.info("Link: {}", url);
|
||||
logger.info("Platform: {}", platforms.get(index).getPlatform());
|
||||
|
||||
releaseHolder.addRelease(
|
||||
"modrinth",
|
||||
|
||||
Reference in new issue
Block a user