Compare commits

...
103 Commits
Author SHA1 Message Date
Andre601 85e41b6c7e Fix wrong formatted messages in /asl reload 2022-09-17 22:51:33 +02:00
Andre_601 a220efc624 Update README.md 2022-09-17 17:58:49 +02:00
Andre_601 ea8871ce8f Update README.md 2022-09-17 17:50:32 +02:00
Andre_601 ea0fdc3798 Update README.md 2022-09-17 17:50:06 +02:00
Andre_601 1188ab0c9c Create config.yml 2022-09-15 01:52:30 +02:00
Andre_601 aaefd4c928 Create feature_request.yml 2022-09-15 01:50:28 +02:00
Andre_601 940bf2fb9d fix typo 2022-09-15 01:20:23 +02:00
Andre_601 0c24bf8d24 Update bug_report.yml 2022-09-15 01:19:36 +02:00
Andre_601 564ce7a820 Create bug_report.yml 2022-09-15 01:18:54 +02:00
Andre_601 bb8cd21b86 Merge pull request #22 from Andre601/dependabot/maven/velocity/org.apache.maven.plugins-maven-shade-plugin-3.4.0
Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /velocity
2022-09-14 18:33:57 +02:00
Andre_601 2d2d8a6175 Merge pull request #20 from Andre601/dependabot/maven/bungeecord/org.apache.maven.plugins-maven-shade-plugin-3.4.0
Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /bungeecord
2022-09-14 18:33:48 +02:00
Andre_601 fcd4bdbe14 Merge pull request #19 from Andre601/dependabot/maven/paper/org.apache.maven.plugins-maven-shade-plugin-3.4.0
Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /paper
2022-09-14 18:33:37 +02:00
Andre_601 3a9b2a7c5a Merge pull request #18 from Andre601/dependabot/maven/core/org.apache.maven.plugins-maven-shade-plugin-3.4.0
Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /core
2022-09-14 18:33:27 +02:00
dependabot[bot] 3b3793ab9a Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /velocity
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 16:33:17 +00:00
Andre_601 d679694d6e Merge pull request #21 from Andre601/dependabot/maven/spigot/org.apache.maven.plugins-maven-shade-plugin-3.4.0
Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /spigot
2022-09-14 18:33:09 +02:00
dependabot[bot] 47405f7492 Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /spigot
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 16:31:57 +00:00
dependabot[bot] af7408dcd5 Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /bungeecord
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 16:31:30 +00:00
dependabot[bot] 17d0930195 Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /paper
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 16:31:28 +00:00
dependabot[bot] 91cd3b6032 Bump maven-shade-plugin from 3.3.0 to 3.4.0 in /core
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 16:31:26 +00:00
Andre601 2d67145ae5 Bump version 2022-09-09 23:33:22 +02:00
Andre601 ba1dd8a70d Fix clearFaviconCache() + expression error 2022-09-09 23:33:00 +02:00
Andre_601 4ea77f2907 Update README.md 2022-09-09 15:11:42 +02:00
Andre_601 7fdc23baa1 Update release.yml 2022-09-09 14:52:13 +02:00
Andre601 d630b472ca Simplify validation check 2022-09-09 01:39:15 +02:00
Andre_601 99509b538b Merge pull request #16 from Andre601/feature/improve-fakeplayers-creation
Improve handling of fake players
2022-09-08 15:27:17 +02:00
Andre601 4539fe4628 Bump version 2022-09-08 15:25:31 +02:00
Andre601 8c81f4f5c8 Rewrite server list profile 2022-09-08 15:19:25 +02:00
Andre601 f34ef3fbe4 Add missing getPlugin() call 2022-09-08 14:16:30 +02:00
Andre601 45f68294c1 Use methods from PluginCore 2022-09-07 21:49:05 +02:00
Andre601 f4056e51ef Rename getPath to getFolderPath 2022-09-07 21:36:35 +02:00
Andre601 7f38c0f224 Update FaviconHandler 2022-09-07 21:34:33 +02:00
Andre601 17a4ba0f8c Improve Fake player creation 2022-09-07 21:33:29 +02:00
Andre_601 5cb1245126 Update README.md 2022-09-05 21:27:42 +02:00
Andre_601 0963d9ffb4 Don't feature a release 2022-09-05 13:50:30 +02:00
Andre_601 6dedd9368f Use release-title 2022-09-05 13:33:55 +02:00
Andre601 f2df3727a7 Add getFaviconHandler to PluginCore
Also, make bStats rely on global config
2022-09-05 13:29:10 +02:00
Andre_601 2b7c24daa4 Create FUNDING.yml 2022-09-04 15:15:54 +02:00
Andre_601 1e042461ac Update README.md 2022-09-04 14:17:42 +02:00
Andre_601 599c2db2bc Re-add modrinth 2022-09-03 16:56:38 +02:00
Andre_601 87505f820c try upload/download artifact 2022-09-03 16:27:44 +02:00
Andre_601 28109c8b5b Add needs to second job 2022-09-03 16:02:45 +02:00
Andre_601 243854592d Merge pull request #15 from Andre601/feature/action-improvements
Make Jar build only happen once
2022-09-03 16:01:05 +02:00
Andre_601 4648bc30e9 test out with github only for now... 2022-09-03 16:00:57 +02:00
Andre_601 f9a96e5525 typo 2022-09-03 00:28:50 +02:00
Andre_601 d158fb852f Update release.yml 2022-09-03 00:14:11 +02:00
Andre_601 77f95900e2 Use cache 2022-09-03 00:10:00 +02:00
Andre_601 912fec1875 Make Jar build only happen once 2022-09-02 23:44:51 +02:00
Andre_601 dba9ca20a4 Merge pull request #14 from Andre601/dependabot/github_actions/Kir-Antipov/mc-publish-3.2
Bump Kir-Antipov/mc-publish from 3.1 to 3.2
2022-09-02 18:35:37 +02:00
dependabot[bot] 7b94ae52db Bump Kir-Antipov/mc-publish from 3.1 to 3.2
Bumps [Kir-Antipov/mc-publish](https://github.com/Kir-Antipov/mc-publish) from 3.1 to 3.2.
- [Release notes](https://github.com/Kir-Antipov/mc-publish/releases)
- [Commits](https://github.com/Kir-Antipov/mc-publish/compare/v3.1...v3.2)

---
updated-dependencies:
- dependency-name: Kir-Antipov/mc-publish
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-02 15:40:17 +00:00
Andre601 6d3bf50278 Actually bump version -_- 2022-09-02 04:27:50 +02:00
Andre_601 8039088fb9 typo -_- 2022-09-02 03:43:39 +02:00
Andre601 ecaaf7bbf3 get rid of abstraction in ExpressionResult + better command output 2022-09-02 03:37:50 +02:00
Andre_601 dd970cfabf Merge pull request #13 from Andre601/feature/auto-publish-action
Create action for auto-publishing to Modrinth
2022-09-02 03:04:06 +02:00
Andre_601 a888481674 Use | definition for loaders. 2022-09-02 02:25:29 +02:00
Andre_601 ee68eafc63 Don't define changelog (Is added automatically) 2022-09-02 02:24:21 +02:00
Andre_601 f22313a5c8 Add proper credits 2022-09-02 02:01:14 +02:00
Andre_601 9603155722 Create action for auto-publishing to Modrinth 2022-09-02 01:57:53 +02:00
Andre_601 df938485b2 It's JDK 16 2022-08-30 21:32:25 +02:00
Andre_601 0ddda8bd78 Update README.md 2022-08-28 16:39:36 +02:00
Andre_601 56a83e88fb Add files via upload 2022-08-28 16:37:54 +02:00
Andre_601 1947f627ef Update README.md 2022-08-28 01:32:38 +02:00
Andre_601 3c344f9a5d Merge pull request #11 from Andre601/feature/improved-favicon-handling
Better Favicon handling
2022-08-27 21:32:01 +02:00
Andre601 8e2004cb81 Move relocations to platform modules 2022-08-27 21:29:57 +02:00
Andre601 004d723c81 Remove minimizeJar to fix ClassNotFoundExceptions 2022-08-27 21:08:24 +02:00
Andre601 90fb6a2654 Add clear favicon function and better favicon handling 2022-08-26 23:33:30 +02:00
Andre_601 0eb5daac81 Update README.md 2022-08-23 00:39:50 +02:00
Andre_601 f23f282ba9 Merge pull request #10 from Andre601/dependabot/maven/core/com.github.ben-manes.caffeine-caffeine-3.1.1
Bump caffeine from 1.3.3 to 3.1.1 in /core
2022-08-22 17:48:41 +02:00
dependabot[bot] df705c0c14 Bump caffeine from 1.3.3 to 3.1.1 in /core
Bumps [caffeine](https://github.com/ben-manes/caffeine) from 1.3.3 to 3.1.1.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v1.3.3...v3.1.1)

---
updated-dependencies:
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 15:47:24 +00:00
Andre_601 f27202f2df Update README.md 2022-08-22 00:25:32 +02:00
Andre_601 0d84335db9 Merge pull request #9 from Andre601/feature/favicon-support
Add Favicon support for Server list profiles.
2022-08-21 23:32:46 +02:00
Andre601 50f878e39c Add assets 2022-08-21 23:30:59 +02:00
Andre601 b88ee87c96 Add notes to favicon setting 2022-08-21 23:28:11 +02:00
Andre601 a5f6e689f0 Shade in Caffeine 2022-08-21 01:31:20 +02:00
Andre601 dd0bc8a43a Cache the bytes array 2022-08-20 23:53:32 +02:00
Andre601 563362504f Use some kind of caching... I guess? 2022-08-20 23:43:55 +02:00
Andre601 bd95be080e Add missing profile comments 2022-08-18 16:11:04 +02:00
Andre601 2d02d48d3c Add Favicon support for Server list profiles. 2022-08-18 16:05:00 +02:00
Andre_601 15f7b5def3 Update README.md 2022-08-18 00:02:49 +02:00
Andre_601 f37813d5b7 Merge pull request #8 from Andre601/feature/xMore-option
Add xMore profile option
2022-08-17 21:26:17 +02:00
Andre601 93c2dda56b Add xMore profile option 2022-08-17 21:19:38 +02:00
Andre601 55f5132b37 Add oneMore profile option. 2022-08-17 13:55:25 +02:00
Andre_601 f1e48c2a9c Update README.md 2022-08-14 22:08:18 +02:00
Andre_601 de01db4c12 Update README.md 2022-08-12 00:51:51 +02:00
Andre_601 eefb2b44dd Doesn't work 2022-08-12 00:39:16 +02:00
Andre_601 799d06dee1 Add files via upload 2022-08-12 00:38:19 +02:00
Andre_601 b9338a43e0 Create tmp 2022-08-12 00:38:03 +02:00
Andre601 c89c5f0b49 Make naming bit more consistent 2022-08-04 22:06:39 +02:00
Andre601 1fac910ca1 Keep BufferedWriter at default cache size 2022-08-04 22:04:13 +02:00
Andre601 69061f1a75 Bump version 2022-08-04 22:01:30 +02:00
Andre_601 0d93dcf00d Merge pull request #6 from Andre601/feature/better-placeholder-handling
Better placeholder handling (Hopefully)
2022-08-04 22:00:09 +02:00
Andre601 bb2828e47d Use a BufferedWriter for cache file saving. 2022-08-04 21:58:06 +02:00
Andre601 cdcc872f3a Improve a bit 2022-08-04 20:57:39 +02:00
Andre601 f9192001ba Better placeholder handling (Hopefully) 2022-08-04 18:23:17 +02:00
Andre_601 0bd92862db Update README.md 2022-08-04 14:52:19 +02:00
Andre_601 773fbb55c3 Update README.md 2022-08-04 14:50:59 +02:00
Andre_601 ad4c69a269 Merge pull request #5 from Andre601/dependabot/maven/spigot/me.clip-placeholderapi-2.11.2
Bump placeholderapi from 2.11.1 to 2.11.2 in /spigot
2022-08-04 13:24:42 +02:00
Andre_601 b7a2599178 Merge pull request #4 from Andre601/dependabot/maven/paper/me.clip-placeholderapi-2.11.2
Bump placeholderapi from 2.11.1 to 2.11.2 in /paper
2022-08-04 13:24:21 +02:00
dependabot[bot] bd279d3673 Bump placeholderapi from 2.11.1 to 2.11.2 in /spigot
Bumps placeholderapi from 2.11.1 to 2.11.2.

---
updated-dependencies:
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-04 11:21:00 +00:00
dependabot[bot] 5882372ce6 Bump placeholderapi from 2.11.1 to 2.11.2 in /paper
Bumps placeholderapi from 2.11.1 to 2.11.2.

---
updated-dependencies:
- dependency-name: me.clip:placeholderapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-04 11:20:29 +00:00
Andre_601 55d74f1abe Create dependabot.yml 2022-08-04 13:17:50 +02:00
Andre_601 0056a0e958 Delete dependabot.yml 2022-08-04 13:15:04 +02:00
Andre_601 06396a1622 Create dependabot.yml 2022-08-03 22:57:29 +02:00
Andre601 8d7df60398 Update dependencies 2022-08-03 22:43:36 +02:00
54 changed files with 1602 additions and 552 deletions

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
patreon: andre_601
ko_fi: andre_601
+62
View File
@@ -0,0 +1,62 @@
name: Bug Report
description: Report an issue with the plugin
body:
- type: markdown
attributes:
value: |-
## Before opening
Please make sure you've checked the following things first:
- You're using the latest release of AdvancedServerList [[Download from Modrinth](https://modrinth.com/plugin/advancedserverlist)]
- You're using a supported Proxy/Server version. As of right now is only 1.19.x supported.
- The issue happens with just AdvancedServerList installed.
- type: dropdown
attributes:
label: Platform
description: On what platform do you use the plugin?
options:
- BungeeCord
- Other (Please specify)
- Paper
- Purpur
- Spigot
- Velocity
- Waterfall
validations:
required: true
- type: input
attributes:
label: Other platform
description: |-
Please provide the name of the platform (Proxy/Server) you use, if you selected `Other (Please specify)` in the above section.
Leave empty otherwise.
placeholder: SomeProxy
- type: textarea
attributes:
label: What happened?
description: |-
Give a detailed description of what exactly happened.
You can provide screenshots to further explain the issues.
When sharing errors, make sure to use a site such as https://paste.helpch.at to do so.
placeholder: When I do ... does ... happen.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Provide a detailed step-by-step explanation on how to reproduce this issue.
placeholder: |-
1. Do this
2. ...
3. Profit!
validations:
required: true
- type: textarea
attributes:
label: Server List Profiles
description: |-
**Optional**
Provide any Server List Profiles you use, if you believe those to be the cause of the issue.
This text field will automatically render the text as YAML code.
render: yaml
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Discord Server
about: Ask questions about the plugin in the `#advancedserverlist` channel.
url: https://discord.gg/6dazXp6
- name: Wiki
about: Check the Wiki for explanations about the features and examples.
url: https://github.com/Andre601/AdvancedServerList/wiki
@@ -0,0 +1,34 @@
name: Feature Request
description: Suggest a new feature for the plugin
body:
- type: markdown
attributes:
value: |-
## Before opening
Please make sure you've checked the following things first:
- You're using the latest release of AdvancedServerList [[Download from Modrinth](https://modrinth.com/plugin/advancedserverlist)]
- You're using a supported Proxy/Server version. As of right now is only 1.19.x supported.
- The Feature you suggest hasn't been suggested before.
- type: dropdown
attributes:
label: Platforms
description: What platforms should this feature be usable on
multiple: true
options:
- Proxy (BungeeCord, Waterfall, ...)
- Proxy (Velocity)
- Server (Spigot, Paper, ...)
validations:
required: true
- type: textarea
attributes:
label: Feature
description: |-
Give a detailed description of what exactly should be added and/or changed in AdvancedServerList.
You can provide screenshots to further explain the idea.
When sharing code snippets, make sure to use a site such as https://paste.helpch.at to do so.
placeholder: AdvancedServerList should get ... because ...
validations:
required: true
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

+50
View File
@@ -0,0 +1,50 @@
version: 2
updates:
- package-ecosystem: maven
directory: "/bungeecord"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: BungeeCord'
- package-ecosystem: maven
directory: "/core"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: Core'
- package-ecosystem: maven
directory: "/paper"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: PaperMC'
- package-ecosystem: maven
directory: "/spigot"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: Spigot'
- package-ecosystem: maven
directory: "/velocity"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: Velocity'
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: GitHub Action'
+88 -8
View File
@@ -1,23 +1,103 @@
name: Build Jars
#
# Big thank you to @Kir-Antipov for providing this workflow file.
# Check out his mc-publish action here: https://github.com/Kir-Antipov/mc-publish
#
name: Publish Assets
on:
release:
types: [published]
jobs:
build:
buildJars:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.11
- name: Set up JDK 1.16
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '16'
- name: Build jar
cache: 'maven'
- name: Build Jar files
run: mvn clean install
- name: Upload jar
uses: AButler/upload-release-assets@v2.0
- name: Save BungeeCord Jar file
uses: actions/upload-artifact@v3
with:
files: 'bungeecord/target/AdvancedServerList-*.jar;paper/target/AdvancedServerList-*.jar;spigot/target/AdvancedServerList-*.jar;velocity/target/AdvancedServerList-*.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }}
name: asl-bungeecord
path: bungeecord/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Paper Jar file
uses: actions/upload-artifact@v3
with:
name: asl-paper
path: paper/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Spigot Jar file
uses: actions/upload-artifact@v3
with:
name: asl-spigot
path: spigot/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Velocity Jar file
uses: actions/upload-artifact@v3
with:
name: asl-velocity
path: velocity/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
publish:
needs: [buildJars]
strategy:
matrix:
include:
- platforms: BungeeCord, Waterfall
directory: bungeecord
loaders: |
bungeecord
waterfall
- platforms: Paper
directory: paper
loaders: paper
- platforms: Spigot
directory: spigot
loaders: spigot
- platforms: Velocity
directory: velocity
loaders: velocity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get Jar files
uses: actions/download-artifact@v3
with:
name: asl-${{ matrix.directory }}
path: ${{ matrix.directory }}/target
- name: Get Version
id: github-release
run: |
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
echo "::set-output name=version::$version"
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
uses: Kir-Antipov/mc-publish@v3.2
with:
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
version: ${{ steps.github-release.outputs.version }}
version-type: release
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
files-secondary: ""
loaders: ${{ matrix.loaders }}
version-resolver: releases
game-versions: |
1.19
1.19.1
1.19.2
java: 16
modrinth-id: xss83sOY
modrinth-featured: false
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
+73 -49
View File
@@ -1,60 +1,84 @@
<!-- Badges -->
[platforms]: https://img.shields.io/badge/Platforms-Spigot%20%7C%20PaperMC%20%7C%20BungeeCord%20%7C%20Velocity-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMDYzIDEuNDU2YTEuNzUgMS43NSAwIDAxMS44NzQgMGw4LjM4MyA1LjMxNmExLjc1IDEuNzUgMCAwMTAgMi45NTZsLTguMzgzIDUuMzE2YTEuNzUgMS43NSAwIDAxLTEuODc0IDBMMi42OCA5LjcyOGExLjc1IDEuNzUgMCAwMTAtMi45NTZsOC4zODMtNS4zMTZ6bTEuMDcxIDEuMjY3YS4yNS4yNSAwIDAwLS4yNjggMEwzLjQ4MyA4LjAzOWEuMjUuMjUgMCAwMDAgLjQyMmw4LjM4MyA1LjMxNmEuMjUuMjUgMCAwMC4yNjggMGw4LjM4My01LjMxNmEuMjUuMjUgMCAwMDAtLjQyMmwtOC4zODMtNS4zMTZ6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTIuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTYuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PC9zdmc+
[tested]: https://img.shields.io/badge/Tested%20Versions-1.19-blue?style=for-the-badge&logo=image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTE3LjI4IDkuMjhhLjc1Ljc1IDAgMDAtMS4wNi0xLjA2bC01Ljk3IDUuOTctMi40Ny0yLjQ3YS43NS43NSAwIDAwLTEuMDYgMS4wNmwzIDNhLjc1Ljc1IDAgMDAxLjA2IDBsNi41LTYuNXoiPjwvcGF0aD48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjc1IDJBMS43NSAxLjc1IDAgMDAyIDMuNzV2MTYuNWMwIC45NjYuNzg0IDEuNzUgMS43NSAxLjc1aDE2LjVBMS43NSAxLjc1IDAgMDAyMiAyMC4yNVYzLjc1QTEuNzUgMS43NSAwIDAwMjAuMjUgMkgzLjc1ek0zLjUgMy43NWEuMjUuMjUgMCAwMS4yNS0uMjVoMTYuNWEuMjUuMjUgMCAwMS4yNS4yNXYxNi41YS4yNS4yNSAwIDAxLS4yNS4yNUgzLjc1YS4yNS4yNSAwIDAxLS4yNS0uMjVWMy43NXoiPjwvcGF0aD48L3N2Zz4=
[download modrinth]: https://img.shields.io/badge/Modrinth%20(Coming%20Soon)-30b27b?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEuNSIgY2xpcC1ydWxlPSJldmVub2RkIiB2aWV3Qm94PSIwIDAgNjggNjgiPjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0uMDUgMGg2NnY2NmgtNjZ6Ii8+PGNsaXBQYXRoIGlkPSJhIj48cGF0aCBkPSJNLjA1IDBoNjZ2NjZoLTY2eiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj48Y2xpcFBhdGggaWQ9ImIiPjxjaXJjbGUgY3g9IjMzLjA1IiBjeT0iMzMiIHI9IjMzIi8+PC9jbGlwUGF0aD48ZyBjbGlwLXBhdGg9InVybCgjYikiPjxjbGlwUGF0aCBpZD0iYyI+PHBhdGggZD0iTTgzLjA1LTE3aC0xMDBWODNoMTAwVi0xN1pNMjkuMDUxIDMyLjI5NWwuMDc3IDEuNzU3IDguODI5IDMyLjk2MyA3Ljg0NC0yLjEwMi04LjU5Ny0zMi4wOTRMNDMuMDA5LS4xMTNsLTcuOTk3LTEuNDEtNS45NjEgMzMuODE4WiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI2MpIj48cGF0aCBmaWxsPSIjRkZGIiBkPSJNMzMuMDUgMGMxOC4yMDYgMCAzMi45ODggMTQuNzg3IDMyLjk4OCAzM1M1MS4yNTYgNjYgMzMuMDUgNjZDMTQuODQzIDY2IC4wNjEgNTEuMjEzLjA2MSAzM1MxNC44NDMgMCAzMy4wNSAwWm0wIDljMTMuMjQgMCAyMy45ODggMTAuNzU1IDIzLjk4OCAyNFM0Ni4yOSA1NyAzMy4wNSA1N0MxOS44MDkgNTcgOS4wNjEgNDYuMjQ1IDkuMDYxIDMzUzE5LjgwOSA5IDMzLjA1IDlaIi8+PC9nPjxjbGlwUGF0aCBpZD0iZCI+PHBhdGggZD0iTS0xNi45NS0xN3Y0Nmg1MGwxLjM2OC4yNDFMODIuMDUgNDYuNTc4bC0yLjczNyA3LjUxN0wzMi4zNDQgMzdILTE2Ljk1djQ2aDEwMFYtMTdoLTEwMFoiLz48L2NsaXBQYXRoPjxnIGNsaXAtcGF0aD0idXJsKCNkKSI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTMzLjA1LTE3YzI3LjU5NSAwIDUwIDIyLjQwNCA1MCA1MHMtMjIuNDA1IDUwLTUwIDUwYy0yNy41OTYgMC01MC0yMi40MDQtNTAtNTBzMjIuNDA0LTUwIDUwLTUwWm0wIDljMjIuNjI4IDAgNDEgMTguMzcxIDQxIDQxcy0xOC4zNzIgNDEtNDEgNDFjLTIyLjYyOSAwLTQxLTE4LjM3MS00MS00MXMxOC4zNzEtNDEgNDEtNDFaIi8+PC9nPjxjbGlwUGF0aCBpZD0iZSI+PHBhdGggZD0iTTMzLjA1LTE3YzI3LjU5NSAwIDUwIDIyLjQwNCA1MCA1MHMtMjIuNDA1IDUwLTUwIDUwYy0yNy41OTYgMC01MC0yMi40MDQtNTAtNTBzMjIuNDA0LTUwIDUwLTUwWm0wIDM5LjU0OWM1Ljc2NyAwIDEwLjQ1IDQuNjgzIDEwLjQ1IDEwLjQ1MSAwIDUuNzY4LTQuNjgzIDEwLjQ1MS0xMC40NSAxMC40NTEtNS43NjggMC0xMC40NTEtNC42ODMtMTAuNDUxLTEwLjQ1MSAwLTUuNzY4IDQuNjgzLTEwLjQ1MSAxMC40NTEtMTAuNDUxWiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI2UpIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNGRkYiIHN0cm9rZS13aWR0aD0iOSIgZD0ibTMzLjA1IDMzLTQ0LjgyOSAyNS44ODIiLz48L2c+PGNsaXBQYXRoIGlkPSJmIj48cGF0aCBkPSJNMzMuMDUtMTdjMjcuNTk1IDAgNTAgMjIuNDA0IDUwIDUwcy0yMi40MDUgNTAtNTAgNTBjLTI3LjU5NiAwLTUwLTIyLjQwNC01MC01MHMyMi40MDQtNTAgNTAtNTBabTAgMjUuMzZjMTMuNTk5IDAgMjQuNjQgMTEuMDQxIDI0LjY0IDI0LjY0UzQ2LjY0OSA1Ny42NCAzMy4wNSA1Ny42NEMxOS40NSA1Ny42NCA4LjQwOSA0Ni41OTkgOC40MDkgMzNTMTkuNDUgOC4zNiAzMy4wNSA4LjM2WiIvPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI2YpIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNGRkYiIHN0cm9rZS13aWR0aD0iOSIgZD0ibTMzLjA1IDMzIDUwLTEzLjM5NyIvPjwvZz48cGF0aCBmaWxsPSIjRkZGIiBkPSJNMjAuMjkzIDM1Ljc0NiAxOC4wNSAyOGw4LTkgMTEtMyA0IDQtNiA2LTQgMS0zIDQgMS4xMiA0LjI0IDMuMTEyIDMuMDkgNC45NjQtLjU5OCAyLjg2Ni0yLjk2NCA4LjE5Ni0yLjE5NiAxLjQ2NCA1LjQ2NC04LjA5OCA4LjAyNkwyOS44OCA0OC40OWwtNS41ODctNS44MTUtNC02LjkyOVoiLz48L2c+PC9nPjwvc3ZnPg==
[download spigot]: https://img.shields.io/badge/Spigot-ed8106?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBmaWxsPSIjRkZGIj48cGF0aCBkPSJNNDE2IDQ4MGMwIDE3LjYyIDE0LjM4IDMyIDMyIDMyczMyLTE0LjM4IDMyLTMycy0zMi02NC0zMi02NFM0MTYgNDYyLjQgNDE2IDQ4MHpNMzUyIDE5MmgtMzguNTRDMjk3LjcgMTc4LjUgMjc3LjkgMTY4LjkgMjU2IDE2NFYxMTYuNUwyMjQgMTEzTDE5MiAxMTYuNVYxNjRDMTcwLjEgMTY5IDE1MC4zIDE3OC42IDEzNC41IDE5MkgxNkM3LjEyNSAxOTIgMCAxOTkuMSAwIDIwOHY5NkMwIDMxMi45IDcuMTI1IDMyMCAxNiAzMjBoOTIuNzhDMTI5LjQgMzU3LjggMTczIDM4NCAyMjQgMzg0czk0LjU5LTI2LjI1IDExNS4yLTY0SDM1MmMxNy42MiAwIDMyIDE0LjI5IDMyIDMxLjkxUzM5OC40IDM4NCA0MTYgMzg0aDY0YzE3LjYyIDAgMzItMTQuMzggMzItMzJDNTEyIDI2My42IDQ0MC40IDE5MiAzNTIgMTkyek04MS42MyA5NS44OEwyMjQgODAuODhsMTQyLjQgMTVDMzc1LjkgOTYuODggMzg0IDg5LjEyIDM4NCA3OS4xMlY0OC44OWMwLTEwLTguMTI1LTE3Ljc0LTE3LjYyLTE2Ljc0TDI1NiA0My43NVYxNkMyNTYgNy4xMjUgMjQ4LjkgMCAyNDAgMGgtMzJDMTk5LjEgMCAxOTIgNy4xMjUgMTkyIDE2djI3Ljc1TDgxLjYzIDMyLjE0QzcyLjEzIDMxLjE0IDY0IDM4Ljg5IDY0IDQ4Ljg5Vjc5LjEyQzY0IDg5LjEyIDcyLjEzIDk2Ljg4IDgxLjYzIDk1Ljg4eiIvPjwvc3ZnPg==
[download hangar]: https://img.shields.io/badge/Hangar%20(Beta)-444?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNDEgMjI0LjUiPjxkZWZzPjxzdHlsZT4uYXtmaWxsOm5vbmU7fS5iLC5se2ZpbGw6I2ZmZjt9LmIsLmMsLmQsLmUsLmYsLmcsLmgsLmksLmp7ZmlsbC1ydWxlOmV2ZW5vZGQ7fS5je2ZpbGw6I2ZhMDt9LmR7ZmlsbDojYWFhO30uZXtmaWxsOiM1NWY7fS5me2ZpbGw6IzVmNTt9Lmd7ZmlsbDojNjdjYmRmO30uaHtmaWxsOiNmNTU7fS5pe2ZpbGw6I2Y1Zjt9Lmp7ZmlsbDojZmY1O30ua3tmaWxsOiM0NDQ7fTwvc3R5bGU+PC9kZWZzPjxyZWN0IGNsYXNzPSJhIiB4PSIyMS4yIiB5PSIxMy42IiB3aWR0aD0iMjE0LjciIGhlaWdodD0iMTk5Ljk0Ii8+PHBhdGggY2xhc3M9ImIiIGQ9Ik01NTAuOCwzOTkuNSwzOTEuMiw0NzUuMyw0NzIuNSw2MjRsMTU5LjYtNzUuOEw1NTAuOCwzOTkuNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PHBhdGggY2xhc3M9ImMiIGQ9Ik01NTcsNDAxLjYsMzkzLjQsNDY5LjVsNzIuOCwxNTIuNEw2MjkuOSw1NTRaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzkxLjIgLTM5OS41KSIvPjxwYXRoIGNsYXNzPSJkIiBkPSJNNTYzLjIsNDA0LDM5NS45LDQ2My44bDY0LjIsMTU1LjgsMTY3LjMtNTkuOFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PHBhdGggY2xhc3M9ImUiIGQ9Ik01NjkuMiw0MDYuNiwzOTguOCw0NTguMmw1NS4zLDE1OC43LDE3MC40LTUxLjZMNTY5LjIsNDA2LjZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzkxLjIgLTM5OS41KSIvPjxwYXRoIGNsYXNzPSJmIiBkPSJNNTc1LDQwOS42LDQwMiw0NTIuOGw0Ni4zLDE2MS4xLDE3My4xLTQzLjFaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzkxLjIgLTM5OS41KSIvPjxwYXRoIGNsYXNzPSJnIiBkPSJNNTgxLjEsNDEyLjVsLTE3NS41LDM1TDQ0My4yLDYxMWwxNzUuNS0zNUw1ODEuMSw0MTIuNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PHBhdGggY2xhc3M9ImgiIGQ9Ik01ODYuMSw0MTYuMyw0MDkuMiw0NDIuNGwyOCwxNjQuOCwxNzYuOS0yNi4xLTI4LTE2NC44WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM5MS4yIC0zOTkuNSkiLz48cGF0aCBjbGFzcz0iaSIgZD0iTTU5MS40LDQyMC4xLDQxMy4yLDQzNy41bDE4LjcsMTY2TDYxMC4xLDU4Niw1OTEuNCw0MjAuMVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PHBhdGggY2xhc3M9ImoiIGQ9Ik01OTYuNCw0MjQuMWwtMTc4LjksOC43LDkuNCwxNjYuNiwxNzguOS04LjctOS40LTE2Ni42WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM5MS4yIC0zOTkuNSkiLz48cmVjdCBjbGFzcz0iayIgeD0iMzAuOSIgeT0iMjguOCIgd2lkdGg9IjE3OS4yIiBoZWlnaHQ9IjE2Ni44OCIvPjxwYXRoIGNsYXNzPSJsIiBkPSJNNTU0LjcsNTAyLjdjLTkuNy0zLjYtMjQsMTAuMi0zMSwzMS40YTgzLjksODMuOSwwLDAsMC0zLjUsMzUuOWwtNC41LTEuOWMtOC42LTI2LjctMy44LTU1LjksMTEuMS03N1oiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PHBhdGggY2xhc3M9ImwiIGQ9Ik01NjEsNTQ4LjNsLTMzLjItMTMuN2M2LjEtMTguNSwxNy40LTI5LjYsMjQuNy0yOS42YTcuOCw3LjgsMCwwLDEsMi4yLjRsLjYuM2MyLjYsMS4yLDEwLjUsOCw1LjcsNDIuNiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM5MS4yIC0zOTkuNSkiLz48cGF0aCBjbGFzcz0ibCIgZD0iTTU0OS4xLDQ2Ni4yYTczLjQsNzMuNCwwLDAsMC0yNS44LDIzLjRjLTE0LjYsMjEuMi0xOS42LDQ5LjktMTIsNzYuN2E4Mi4yLDgyLjIsMCwwLDAsMy4zLDkuNWwtNDQuNS0xOC40Yy0xNi44LTQxLjItMS40LTkwLjMsMzQuNS0xMDkuN1oiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0zOTEuMiAtMzk5LjUpIi8+PC9zdmc+Cg==
[download github]: https://img.shields.io/badge/GitHub-000?style=for-the-badge&logo=github
<!-- Wiki links -->
[wiki]: https://github.com/Andre601/AdvancedServerList/wiki
[minimessage]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#minimessage
[placeholders]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#placeholders
<!-- Download links -->
[modrinth]: https://modrinth.com
[spigot]: https://www.spigotmc.org/resources/102910/
[hangar]: https://hangar.benndorf.dev/Andre_601/AdvancedServerList
[github]: https://github.com/Andre601/AdvancedServerList/releases
<!-- Stats -->
[stats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
[stats-bungeecord]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
[stats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
<!-- Other -->
[license]: https://github.com/Andre601/AdvancedServerList/blob/master/LICENSE
# AdvancedServerList
![platform] ![tested]
![platforms] ![tested]
AdvancedServerList is a plugin made for SpigotMC, PaperMC, BungeeCord/Waterfall and Velocity. It allows you to create server list profiles to display based on priority and conditions.
AdvancedServerList is a server and proxy plugin that allows you to create custom MOTDs and more in your server list with priority and conditions.
## What is a Server List Profile?
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
> [*Read More*][profiles]
### Conditions
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
> [*Read More*][conditions]
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
> [*Read More*][placeholders]
### Formatting
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
> [*Read More*][minimessage]
## Downloads
You can download AdvancedServerList on the following locations:
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/main/badges/modrinth_vector.svg" height="64" />
</a>
[![download modrinth]][modrinth] [![download spigot]][spigot] [![download hangar]][hangar] [![download github]][github]
## Dependencies
## Features
| Dependency | Platforms | Required? |
| ---------------- | ------------- | --------- |
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
- Create multiple profiles with
- Priority (Higher number = Higher Priority).
- Conditions for displaying the profile.
- Custom MOTD.
- Custom Player count text.
- Custom hover for the player count hover.
- Hide player count (Turn to `???`)
- MiniMessage formatting for MOTD, player count and player count hover [[Read More][minimessage]]
- Placeholder support [[Read More][placeholders]]
## Statistics
## Links
This plugin sends statistics to [bStats] to display.
You can disable this in the global bStats config file located in `/plugins/bstats/`
- [Wiki][wiki]
- Statistics
- [Spigot/PaperMC][stats-spigot]
- [BungeeCord][stats-bungeecord]
- [Velocity][stats-velocity]
- [License][license]
- [BungeeCord][bstats-bungee]
- [Paper/Spigot][bstats-spigot]
- [Velocity][bstats-velocity]
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/main/badges/modrinth-gallery_vector.svg" height="64" />
</a>
<!-- Links -->
[profiles]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles
[conditions]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#conditions
[placeholders]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#placeholders
[minimessage]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#minimessage
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[bstats]: https://bstats.org
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
<!-- Badges -->
[platform]: https://img.shields.io/badge/Platforms-Spigot%20%7C%20Paper%20%7C%20BungeeCord%20%7C%20Velocity-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMDYzIDEuNDU2YTEuNzUgMS43NSAwIDAxMS44NzQgMGw4LjM4MyA1LjMxNmExLjc1IDEuNzUgMCAwMTAgMi45NTZsLTguMzgzIDUuMzE2YTEuNzUgMS43NSAwIDAxLTEuODc0IDBMMi42OCA5LjcyOGExLjc1IDEuNzUgMCAwMTAtMi45NTZsOC4zODMtNS4zMTZ6bTEuMDcxIDEuMjY3YS4yNS4yNSAwIDAwLS4yNjggMEwzLjQ4MyA4LjAzOWEuMjUuMjUgMCAwMDAgLjQyMmw4LjM4MyA1LjMxNmEuMjUuMjUgMCAwMC4yNjggMGw4LjM4My01LjMxNmEuMjUuMjUgMCAwMDAtLjQyMmwtOC4zODMtNS4zMTZ6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTIuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS44NjcgMTYuMzI0YS43NS43NSAwIDAxMS4wMzUtLjIzMmw4Ljk2NCA1LjY4NWEuMjUuMjUgMCAwMC4yNjggMGw4Ljk2NC01LjY4NWEuNzUuNzUgMCAwMS44MDQgMS4yNjdsLTguOTY1IDUuNjg1YTEuNzUgMS43NSAwIDAxLTEuODc0IDBsLTguOTY1LTUuNjg1YS43NS43NSAwIDAxLS4yMzEtMS4wMzV6Ij48L3BhdGg+PC9zdmc+
[tested]: https://img.shields.io/badge/Tested%20Versions-1.19%20%7C%201.19.1%20%7C%201.19.2-blue?style=for-the-badge&logo=image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTE3LjI4IDkuMjhhLjc1Ljc1IDAgMDAtMS4wNi0xLjA2bC01Ljk3IDUuOTctMi40Ny0yLjQ3YS43NS43NSAwIDAwLTEuMDYgMS4wNmwzIDNhLjc1Ljc1IDAgMDAxLjA2IDBsNi41LTYuNXoiPjwvcGF0aD48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjc1IDJBMS43NSAxLjc1IDAgMDAyIDMuNzV2MTYuNWMwIC45NjYuNzg0IDEuNzUgMS43NSAxLjc1aDE2LjVBMS43NSAxLjc1IDAgMDAyMiAyMC4yNVYzLjc1QTEuNzUgMS43NSAwIDAwMjAuMjUgMkgzLjc1ek0zLjUgMy43NWEuMjUuMjUgMCAwMS4yNS0uMjVoMTYuNWEuMjUuMjUgMCAwMS4yNS4yNXYxNi41YS4yNS4yNSAwIDAxLS4yNS4yNUgzLjc1YS4yNS4yNSAwIDAxLS4yNS0uMjVWMy43NXoiPjwvcGF0aD48L3N2Zz4=
+10 -6
View File
@@ -75,7 +75,7 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.1.0</version>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -103,22 +103,26 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.spongepowered.configurate</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.configurate</shadedPattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.configurate</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori.adventure</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.adventure</shadedPattern>
<pattern>net.kyori</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.kyori</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -30,17 +30,26 @@ import ch.andre601.advancedserverlist.bungeecord.events.JoinEvent;
import ch.andre601.advancedserverlist.bungeecord.events.PingEvent;
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class BungeeCordCore extends Plugin implements PluginCore{
public class BungeeCordCore extends Plugin implements ProxyCore<Favicon, ServerPing.PlayerInfo>{
private AdvancedServerList core;
private FaviconHandler<Favicon> faviconHandler = null;
private final PluginLogger logger = new BungeeLogger(getLogger());
@Override
@@ -72,13 +81,21 @@ public class BungeeCordCore extends Plugin implements PluginCore{
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList getCore(){
return core;
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -87,6 +104,14 @@ public class BungeeCordCore extends Plugin implements PluginCore{
return logger;
}
@Override
public FaviconHandler<Favicon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getProxy().getName();
@@ -96,4 +121,20 @@ public class BungeeCordCore extends Plugin implements PluginCore{
public String getPlatformVersion(){
return getProxy().getVersion();
}
@Override
public List<ServerPing.PlayerInfo> createPlayers(List<String> lines, Placeholders... placeholders){
List<ServerPing.PlayerInfo> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.replacements(placeholders[0])
.replacements(placeholders[1])
.toString();
players.add(new ServerPing.PlayerInfo(parsed, UUID.randomUUID()));
}
return players;
}
}
@@ -0,0 +1,37 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeePlayer extends GenericPlayer<ProxiedPlayer>{
public BungeePlayer(String name, int protocol){
this.name = name;
this.protocol = protocol;
}
}
@@ -26,12 +26,15 @@
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.Placeholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.event.ProxyPingEvent;
@@ -40,7 +43,6 @@ import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.net.InetSocketAddress;
import java.util.Map;
public class PingEvent implements Listener{
@@ -58,27 +60,37 @@ public class PingEvent implements Listener{
if(protocol == null)
return;
InetSocketAddress address = (InetSocketAddress)event.getConnection().getSocketAddress();
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(
((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString()
);
InetSocketAddress host = event.getConnection().getVirtualHost();
Map<String, Object> replacements = Placeholders.get(plugin.getCore())
.withProtocol(protocol.getProtocol())
.withPlayersOnline(ping.getPlayers().getOnline())
.withPlayersMax(ping.getPlayers().getMax())
.withPlayerName(address)
.withHostAddress(host)
.getReplacements();
int online = ping.getPlayers().getOnline();
int max = ping.getPlayers().getMax();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new BungeePlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
ping.getPlayers().setMax(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
TextComponent component = new TextComponent(BungeeComponentSerializer.get().serialize(
ComponentParser.list(profile.getMotd())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
));
@@ -87,36 +99,45 @@ public class PingEvent implements Listener{
if(profile.shouldHidePlayers()){
ping.setPlayers(null);
ping.setFavicon(ping.getFaviconObject());
ping.setVersion(protocol);
event.setResponse(ping);
return;
}
if(!profile.getPlayerCount().isEmpty()){
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
protocol.setName(ComponentParser.text(profile.getPlayerCount())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
);
protocol.setProtocol(-1);
}
if(!profile.getPlayers().isEmpty()){
String players = ComponentParser.list(profile.getPlayers())
.replacements(replacements)
.toString();
ServerPing.PlayerInfo[] playerInfos = AdvancedServerList.getPlayers(ServerPing.PlayerInfo.class, players)
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.PlayerInfo[0]);
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
}
ping.setFavicon(ping.getFaviconObject());
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
plugin.getPluginLogger().warn("Unable to create Favicon. %s", ex.getMessage());
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFaviconObject());
}else{
ping.setFavicon(favicon);
}
}
ping.setVersion(protocol);
event.setResponse(ping);
+12 -6
View File
@@ -47,22 +47,28 @@
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>${plugin.depend.configurate}</version>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>${plugin.depend.kyori-adventure}</version>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>${plugin.depend.kyori-minimessage}</version>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>${plugin.depend.kyori-legacy}</version>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -83,9 +89,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
@@ -27,27 +27,24 @@ package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.util.*;
public class AdvancedServerList{
private final PluginCore plugin;
private final PluginCore<?> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private String version;
public AdvancedServerList(PluginCore plugin){
public AdvancedServerList(PluginCore<?> plugin){
this.plugin = plugin;
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
@@ -56,37 +53,8 @@ public class AdvancedServerList{
load();
}
public static <T> List<T> getPlayers(Class<T> clazz, String text){
try{
String[] lines = text.split("\n");
final List<T> players = new ArrayList<>(lines.length);
final Constructor<T> constructor = clazz.getDeclaredConstructor(String.class, UUID.class);
constructor.setAccessible(true);
for(String line : lines){
players.add(constructor.newInstance(line, UUID.randomUUID()));
}
return players;
}catch(NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex){
return Collections.emptyList();
}
}
public void disable(){
getPluginLogger().info("Saving cache.data file...");
getPlayerHandler().save();
getPluginLogger().info("AdvancedServerList disabled!");
}
public PluginLogger getPluginLogger(){
return plugin.getPluginLogger();
}
public Path getPath(){
return plugin.getPath();
public PluginCore<?> getPlugin(){
return plugin;
}
public FileHandler getFileHandler(){
@@ -105,59 +73,69 @@ public class AdvancedServerList{
return version;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving cache.data file...");
getPlayerHandler().save();
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
}
public void clearFaviconCache(){
plugin.clearFaviconCache();
}
private void load(){
printBanner();
resolveVersion();
getPluginLogger().info("Starting AdvancedServerList v%s...", version);
getPluginLogger().info("Proxy: " + plugin.getPlatformName() + " " + plugin.getPlatformVersion());
getPlugin().getPluginLogger().info("Starting AdvancedServerList v%s...", version);
getPlugin().getPluginLogger().info("Platform: " + plugin.getPlatformName() + " " + plugin.getPlatformVersion());
if(getFileHandler().loadConfig()){
getPluginLogger().info("Successfully loaded config.yml!");
getPlugin().getPluginLogger().info("Successfully loaded config.yml!");
}else{
getPluginLogger().warn("Unable to load config.yml! Check previous lines for errors.");
getPlugin().getPluginLogger().warn("Unable to load config.yml! Check previous lines for errors.");
return;
}
if(getFileHandler().loadProfiles()){
getPluginLogger().info("Successfully loaded " + getFileHandler().getProfiles().size() + " profiles!");
getPlugin().getPluginLogger().info("Successfully loaded " + getFileHandler().getProfiles().size() + " profiles!");
}else{
getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
getPlugin().getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
return;
}
getPluginLogger().info("Loading Commands...");
Path folder = getPlugin().getFolderPath().resolve("favicons");
if(!folder.toFile().exists() && folder.toFile().mkdirs())
getPlugin().getPluginLogger().info("Successfully created favicons folder.");
getPlugin().getPluginLogger().info("Loading Commands...");
plugin.loadCommands();
getPluginLogger().info("Commands loaded!");
getPluginLogger().info("Loading events...");
getPlugin().getPluginLogger().info("Commands loaded!");
getPlugin().getPluginLogger().info("Loading events...");
plugin.loadEvents();
getPluginLogger().info("Events loaded!");
getPluginLogger().info("Loading cache.data...");
getPlugin().getPluginLogger().info("Events loaded!");
getPlugin().getPluginLogger().info("Loading cache.data...");
getPlayerHandler().load();
getPluginLogger().info("Loading Metrics for bStats...");
if(getFileHandler().getBoolean("send_statistics")){
plugin.loadMetrics();
getPluginLogger().info("Metrics loaded!");
}else{
getPluginLogger().info("'send_statistics' disabled in config.yml. Not loading Metrics for bStats...");
}
getPluginLogger().info("AdvancedServerList is ready!");
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("AdvancedServerList is ready!");
}
private void printBanner(){
getPluginLogger().info("");
getPluginLogger().info(" _____ _");
getPluginLogger().info(" /\\ / ____| |");
getPluginLogger().info(" / \\ | (___ | |");
getPluginLogger().info(" / /\\ \\ \\___ \\| |");
getPluginLogger().info(" / ____ \\ ____) | |____");
getPluginLogger().info("/_/ \\_\\_____/|______|");
getPluginLogger().info("");
getPlugin().getPluginLogger().info("");
getPlugin().getPluginLogger().info(" _____ _");
getPlugin().getPluginLogger().info(" /\\ / ____| |");
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
getPlugin().getPluginLogger().info(" / /\\ \\ \\___ \\| |");
getPlugin().getPluginLogger().info(" / ____ \\ ____) | |____");
getPlugin().getPluginLogger().info("/_/ \\_\\_____/|______|");
getPlugin().getPluginLogger().info("");
}
private void resolveVersion(){
@@ -37,37 +37,45 @@ public class CommandHandler{
}
public void handle(CmdSender sender, String[] args){
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>]";
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>]";
if(args.length == 0 || args[0].equalsIgnoreCase("help")){
if(sender.hasPermission("advancedserverlist.command.help")){
sender.sendMsg("AdvancedServerList Commands");
sender.sendMsg("%s - Commands", prefix);
sender.sendMsg();
sender.sendMsg("<aqua>/asl help <grey>- Shows this help.");
sender.sendMsg("<gradient:aqua:white>/asl help</gradient> <grey>- Shows this Help");
sender.sendMsg();
sender.sendMsg("<aqua>/asl reload <grey>- Reloads the config and profiles.");
sender.sendMsg("<gradient:aqua:white>/asl reload</gradient> <grey>- Reloads the plugin");
}else{
sender.sendMsg("<red>You do not have the permissions to execute this command!");
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
}
}else
if(args[0].equalsIgnoreCase("reload")){
if(sender.hasPermission("advancedserverlist.command.reload")){
sender.sendMsg("<grey>Reloading config.yml...");
sender.sendMsg("%s Reloading plugin...", prefix);
if(core.getFileHandler().reloadConfig()){
sender.sendMsg("<green>Successfully reloaded <grey>config.yml</grey>!");
sender.sendMsg("%s <green>Reloaded <grey>config.yml</grey>!", prefix);
}else{
sender.sendMsg("<red>Error while reloading the config.yml.");
sender.sendMsg("%s <red>Error while reloading the <grey>config.yml</grey>!", errorPrefix);
}
sender.sendMsg("<grey>Reloading Profiles...");
if(core.getFileHandler().reloadProfiles()){
sender.sendMsg("<green>Successfully loaded <grey>%d</grey> Profiles!", core.getFileHandler().getProfiles().size());
sender.sendMsg("%s <green>Loaded <grey>%d Profile(s)</grey>!", prefix, core.getFileHandler().getProfiles().size());
}else{
sender.sendMsg("<red>Error while reloading Profiles. No profiles have been loaded.");
sender.sendMsg("%s <red>Cannot load Profiles!", errorPrefix);
}
sender.sendMsg("<green>Reload complete!");
core.clearFaviconCache();
sender.sendMsg("%s <green>Successfully cleared Favicon cache!", prefix);
sender.sendMsg("%s <green>Reload complete!", prefix);
}else{
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
}
}else{
sender.sendMsg("<red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", args[0]);
sender.sendMsg("%s <red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", prefix, args[0]);
}
}
}
@@ -32,7 +32,6 @@ import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -43,8 +42,6 @@ import java.util.List;
public class FileHandler{
private final FilenameFilter profileFilter = (dir, name) -> name.endsWith(".yml");
private final AdvancedServerList plugin;
private final PluginLogger logger;
@@ -55,12 +52,12 @@ public class FileHandler{
private ConfigurationNode node = null;
public FileHandler(AdvancedServerList plugin){
this.plugin = plugin;
this.logger = plugin.getPluginLogger();
public FileHandler(AdvancedServerList core){
this.plugin = core;
this.logger = core.getPlugin().getPluginLogger();
this.config = plugin.getPath().resolve("config.yml");
this.profilesFolder = plugin.getPath().resolve("profiles");
this.config = core.getPlugin().getFolderPath().resolve("config.yml");
this.profilesFolder = core.getPlugin().getFolderPath().resolve("profiles");
}
public List<ServerListProfile> getProfiles(){
@@ -119,7 +116,7 @@ public class FileHandler{
public boolean reloadProfiles(){
profiles.clear();
File[] files = profilesFolder.toFile().listFiles(profileFilter);
File[] files = profilesFolder.toFile().listFiles(((dir, name) -> name.endsWith(".yml")));
if(files == null || files.length == 0){
logger.warn("Cannot load files from profiles folder! No valid YAML files present.");
return false;
@@ -159,8 +156,4 @@ public class FileHandler{
public String getString(String def, Object... path){
return node.node(path).getString(def);
}
public boolean getBoolean(Object... path){
return node.node(path).getBoolean(true);
}
}
@@ -25,8 +25,6 @@
package ch.andre601.advancedserverlist.core.interfaces;
import net.kyori.adventure.text.format.NamedTextColor;
public interface CmdSender{
boolean hasPermission(String permission);
@@ -23,13 +23,15 @@
*
*/
package ch.andre601.advancedserverlist.core.interfaces;
package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import java.nio.file.Path;
public interface PluginCore{
public interface PluginCore<F>{
void loadCommands();
@@ -37,12 +39,16 @@ public interface PluginCore{
void loadMetrics();
void clearFaviconCache();
AdvancedServerList getCore();
Path getPath();
Path getFolderPath();
PluginLogger getPluginLogger();
FaviconHandler<F> getFaviconHandler();
String getPlatformName();
String getPlatformVersion();
@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.List;
public interface ProxyCore<F, P> extends PluginCore<F>{
List<P> createPlayers(List<String> lines, Placeholders... placeholders);
}
@@ -0,0 +1,34 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.List;
public interface ServerCore<F, P, P2> extends PluginCore<F>{
List<P> createPlayers(List<String> lines, P2 player, Placeholders... placeholders);
}
@@ -26,12 +26,12 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
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.Map;
import java.util.function.Function;
public class ComponentParser{
@@ -58,8 +58,8 @@ public class ComponentParser{
return new ComponentParser(String.join("\n", lines));
}
public ComponentParser replacements(Map<String, Object> replacements){
text = StringReplacer.replace(text, replacements);
public ComponentParser replacements(Placeholders placeholders){
text = StringReplacer.replace(text, placeholders.getReplacements());
return this;
}
@@ -26,6 +26,7 @@
package ch.andre601.advancedserverlist.core.profiles;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.HashMap;
import java.util.Map;
@@ -34,7 +35,7 @@ public class ProfileManager{
private final AdvancedServerList core;
private Map<String, Object> replacements = new HashMap<>();
private final Map<String, Object> replacements = new HashMap<>();
private ProfileManager(AdvancedServerList core){
this.core = core;
@@ -44,14 +45,14 @@ public class ProfileManager{
return new ProfileManager(core);
}
public ProfileManager replacements(Map<String, Object> replacements){
this.replacements = replacements;
public ProfileManager replacements(Placeholders placeholders){
this.replacements.putAll(placeholders.getReplacements());
return this;
}
public ServerListProfile getProfile(){
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
if(profile.getMotd().isEmpty() && profile.getPlayers().isEmpty() && profile.getPlayerCount().isEmpty())
if(profile.isInvalid())
continue;
if(profile.evalConditions(replacements))
@@ -43,16 +43,22 @@ public class ServerListProfile{
private final List<String> motd;
private final List<String> players;
private final String playerCount;
private final String favicon;
private final boolean hidePlayers;
private final boolean extraPlayersEnabled;
private final int extraPlayers;
public ServerListProfile(ConfigurationNode node, PluginLogger logger){
this.priority = node.node("priority").getInt();
this.expressions = createExpressions(getList(node, "conditions", false), logger);
this.expressions = createExpressions(getList(node, false, "conditions"), logger);
this.motd = getList(node, "motd", true);
this.players = getList(node, "players", false);
this.playerCount = node.node("playerCount").getString("");
this.hidePlayers = node.node("hidePlayers").getBoolean();
this.motd = getList(node, true, "motd");
this.players = getList(node, false, "playerCount", "hover");
this.playerCount = node.node("playerCount", "text").getString("");
this.favicon = node.node("favicon").getString("");
this.hidePlayers = node.node("playerCount", "hidePlayers").getBoolean();
this.extraPlayersEnabled = node.node("playerCount", "extraPlayers", "enabled").getBoolean();
this.extraPlayers = node.node("playerCount", "extraPlayers", "amount").getInt();
}
public int getPriority(){
@@ -71,10 +77,22 @@ public class ServerListProfile{
return playerCount;
}
public String getFavicon(){
return favicon;
}
public boolean shouldHidePlayers(){
return hidePlayers;
}
public boolean isExtraPlayersEnabled(){
return extraPlayersEnabled;
}
public int getExtraPlayers(){
return extraPlayers;
}
public boolean evalConditions(Map<String, Object> replacements){
if(expressions.isEmpty())
return true;
@@ -88,6 +106,13 @@ public class ServerListProfile{
return true;
}
public boolean isInvalid(){
return getMotd().isEmpty() &&
getPlayers().isEmpty() &&
(getPlayerCount().isEmpty() && !shouldHidePlayers()) &&
getFavicon().isEmpty();
}
private List<Expression> createExpressions(List<String> list, PluginLogger logger) {
if(list.isEmpty())
return Collections.emptyList();
@@ -107,10 +132,10 @@ public class ServerListProfile{
return expressions;
}
private List<String> getList(ConfigurationNode node, String key, boolean trim){
private List<String> getList(ConfigurationNode node, boolean trim, Object... path){
List<String> list;
try{
list = node.node(key).getList(String.class);
list = node.node(path).getList(String.class);
}catch(SerializationException ex){
return Collections.emptyList();
}
@@ -70,22 +70,21 @@ public class Expression{
char next = (i == (chars.length - 1)) ? '\0' : chars[i + 1];
Operator tmp = Operator.getOperand(c, next);
if(tmp == Operator.UNKNOWN){
if(foundOperator){
right.append(c);
}else{
left.append(c);
}
if(tmp != Operator.UNKNOWN && !foundOperator){
operator = tmp;
foundOperator = true;
if(tmp.hasSecond())
i++; // Skip next character if operator has 2
continue;
}
if(foundOperator){
result = ExpressionResult.INVALID_DOUBLE_OPERATOR;
return;
right.append(c);
}else{
left.append(c);
}
operator = tmp;
foundOperator = true;
}
if(left.isEmpty() || right.isEmpty()){
@@ -98,7 +97,7 @@ public class Expression{
}
public enum Operator{
LESS_THAN('<', '\0'){
LESS('<', '\0'){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
@@ -128,7 +127,7 @@ public class Expression{
return !left.equals(right);
}
},
GREATER_THAN('>', '\0'){
GREATER('>', '\0'){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
@@ -191,32 +190,19 @@ public class Expression{
}
public enum ExpressionResult{
VALID{
@Override
public String getMessage(){
return null;
}
},
VALID(null),
INVALID_NO_EXPRESSION{
@Override
public String getMessage(){
return "Received empty condition which isn't allowed!";
}
},
INVALID_DOUBLE_OPERATOR{
@Override
public String getMessage(){
return "Condition contained two operands.";
}
},
INVALID_EMPTY_PARTS{
@Override
public String getMessage(){
return "Received condition with either left or right part being empty.";
}
};
INVALID_NO_EXPRESSION ("Received empty condition which isn't allowed!"),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
public abstract String getMessage();
private final String message;
ExpressionResult(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
}
@@ -0,0 +1,138 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.favicon;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class FaviconHandler<F>{
private final Cache<String, F> favicons = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
private final AdvancedServerList core;
public FaviconHandler(AdvancedServerList core){
this.core = core;
}
public F getFavicon(String input, Function<BufferedImage, F> function){
return favicons.get(input, k -> {
BufferedImage image = resolveImage(core, input);
if(image == null)
return null;
return function.apply(image);
});
}
public void clearCache(){
favicons.invalidateAll();
}
private BufferedImage resolveImage(AdvancedServerList core, String input){
InputStream stream;
if(input.toLowerCase(Locale.ROOT).startsWith("https://")){
stream = getFromUrl(core, input);
}else
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
File folder = core.getPlugin().getFolderPath().resolve("favicons").toFile();
if(!folder.exists()){
core.getPlugin().getPluginLogger().warn("Cannot get Favicon %s from favicons folder. Folder doesn't exist!", input);
return null;
}
File file = new File(folder, input);
try{
stream = new FileInputStream(file);
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon from File %s.", input);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}else{
stream = getFromUrl(core, "https://mc-heads.net/avatar/" + input + "/64");
}
if(stream == null){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. InputStream was null.");
return null;
}
try{
BufferedImage original = ImageIO.read(stream);
if(original == null){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. Unable to create BufferedImage.");
return null;
}
BufferedImage favicon = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D img = favicon.createGraphics();
// Resize original image to 64x64 and apply to favicon.
img.drawImage(original, 0, 0, 64, 64, null);
img.dispose();
return favicon;
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Unable to create Favicon. Encountered IOException during creation.");
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}
private InputStream getFromUrl(AdvancedServerList core, String url){
try{
URL faviconUrl = new URL(url);
URLConnection connection = faviconUrl.openConnection();
connection.setRequestProperty("User-Agent", "AdvancedServerList/" + core.getVersion());
connection.connect();
return connection.getInputStream();
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Error while connecting to %s for Favicon creation.", url);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}
}
@@ -0,0 +1,72 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.players;
import java.util.UUID;
public abstract class GenericPlayer<T>{
protected T player = null;
protected String name = null;
protected String version = null;
protected int protocol = -1;
protected boolean playedBefore = false;
protected boolean banned = false;
protected boolean whitelisted = false;
protected UUID uuid = null;
public T getPlayer(){
return player;
}
public String getName(){
return name;
}
public int getProtocol(){
return protocol;
}
public String getVersion(){
return version;
}
public boolean hasPlayedBefore(){
return playedBefore;
}
public boolean isBanned(){
return banned;
}
public boolean isWhitelisted(){
return whitelisted;
}
public UUID getUniqueId(){
return uuid;
}
}
@@ -28,13 +28,12 @@ package ch.andre601.advancedserverlist.core.profiles.players;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.replacer.EntryList;
import java.io.ByteArrayInputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
@@ -47,25 +46,24 @@ public class PlayerHandler{
public PlayerHandler(AdvancedServerList core){
this.core = core;
this.cache = core.getPath().resolve("cache.data");
this.cache = core.getPlugin().getFolderPath().resolve("cache.data");
}
public void load(){
if(!cache.toFile().exists()){
core.getPluginLogger().info("No cache.data present. Skipping...");
core.getPlugin().getPluginLogger().info("No cache.data present. Skipping...");
return;
}
List<String> lines;
try{
lines = Files.readAllLines(cache);
}catch(IOException ex){
core.getPluginLogger().warn("Encountered IOException while trying to read cache.data", ex);
core.getPlugin().getPluginLogger().warn("Encountered IOException while trying to read cache.data", ex);
return;
}
if(lines.isEmpty()){
core.getPluginLogger().info("cache.data is empty. Skipping...");
core.getPlugin().getPluginLogger().info("cache.data is empty. Skipping...");
return;
}
@@ -80,12 +78,12 @@ public class PlayerHandler{
players.add(parts[0], parts[1]);
}
core.getPluginLogger().info("Loaded " + players.size() + " players into cache!");
core.getPlugin().getPluginLogger().info("Loaded " + players.size() + " players into cache!");
}
public void save(){
if(players.isEmpty()){
core.getPluginLogger().info("No data to save. Skipping...");
core.getPlugin().getPluginLogger().info("No data to save. Skipping...");
return;
}
@@ -93,12 +91,16 @@ public class PlayerHandler{
for(Map.Entry<String, String> entry : players){
joiner.add(entry.getKey() + "=" + entry.getValue());
}
try(InputStream stream = new ByteArrayInputStream(joiner.toString().getBytes(StandardCharsets.UTF_8))){
Files.copy(stream, cache, StandardCopyOption.REPLACE_EXISTING);
core.getPluginLogger().info("Saved cache.data file.");
try{
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8, StandardOpenOption.WRITE);
writer.write(joiner.toString());
writer.close();
core.getPlugin().getPluginLogger().info("Successfully saved cache.data file.");
}catch(IOException ex){
core.getPluginLogger().warn("Cannot save player data to cache.data file!", ex);
core.getPlugin().getPluginLogger().warn("Cannot save player data to cache.data file!", ex);
}
}
@@ -41,7 +41,7 @@ public class EntryList<K, V> extends ArrayList<Map.Entry<K, V>>{
public boolean containsKey(K key){
for(Map.Entry<K, V> entry : this){
if(entry.getKey() == key)
if(entry.getKey().equals(key))
return true;
}
return false;
@@ -1,93 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
public class Placeholders{
private final AdvancedServerList core;
private final Map<String, Object> replacements;
public Placeholders(AdvancedServerList core){
this.core = core;
this.replacements = new HashMap<>();
}
public static Placeholders get(AdvancedServerList core){
return new Placeholders(core);
}
public Placeholders withProtocol(int protocol){
this.replacements.put("${player protocol}", protocol);
return this;
}
public Placeholders withPlayersOnline(int online){
this.replacements.put("${players online}", online);
return this;
}
public Placeholders withPlayersMax(int max){
this.replacements.put("${players max}", max);
return this;
}
public Placeholders withPlayerName(InetSocketAddress playerAddress){
if(playerAddress != null)
this.replacements.put("${player name}", core.getPlayerHandler().getPlayerByIp(playerAddress.getHostString()));
return this;
}
public Placeholders withHostAddress(InetSocketAddress hostAddress){
if(hostAddress != null)
this.replacements.put("${server host}", hostAddress.getHostString());
return this;
}
public Placeholders withHostAddress(String hostAddress){
if(hostAddress != null)
this.replacements.put("${server host}", hostAddress);
return this;
}
public Placeholders withPlayerVersion(String version){
this.replacements.put("${player version}", version);
return this;
}
public Map<String, Object> getReplacements(){
return replacements;
}
}
@@ -0,0 +1,33 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
import java.util.Map;
public interface Placeholders{
Map<String, Object> getReplacements();
}
@@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import java.util.HashMap;
import java.util.Map;
public class PlayerPlaceholders implements Placeholders{
private final Map<String, Object> replacements = new HashMap<>();
public PlayerPlaceholders(GenericPlayer<?> player){
this.replacements.put("${player name}", player.getName());
this.replacements.put("${player protocol}", player.getProtocol());
if(player.getVersion() != null)
this.replacements.put("${player version}", player.getVersion());
if(player.getPlayer() == null)
return;
this.replacements.put("${player hasPlayedBefore}", player.hasPlayedBefore());
this.replacements.put("${player isBanned}", player.isBanned());
this.replacements.put("${player isWhitelisted}", player.isWhitelisted());
this.replacements.put("${player uuid}", player.getUniqueId());
}
@Override
public Map<String, Object> getReplacements(){
return replacements;
}
}
@@ -0,0 +1,47 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
import java.util.HashMap;
import java.util.Map;
public class ServerPlaceholders implements Placeholders{
private final Map<String, Object> replacements = new HashMap<>();
public ServerPlaceholders(int online, int max, String host){
this.replacements.put("${server playersOnline}", online);
this.replacements.put("${server playersMax}", max);
if(host != null)
this.replacements.put("${server host}", host);
}
@Override
public Map<String, Object> getReplacements(){
return this.replacements;
}
}
+1 -5
View File
@@ -1,8 +1,4 @@
#
# Used for when AdvancedServerList doesn't have a cached player to use for ${player name}
#
unknown_player: "Anonymous"
#
# Whether statistics should be sent to bStats or not.
#
send_statistics: true
unknown_player: "Anonymous"
+69 -23
View File
@@ -28,33 +28,79 @@ motd:
- '<grey>Line 2'
#
# Sets if players should be hidden.
# When set to true will the player count be replaced with ???
# Additionally will the options 'players' and 'playerCount' be ignored by the plugin.
# Allows you to set a favicon for this server list profile.
# You can use one of three possible options:
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
# 2. A URL pointing to a valid Image
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#favicon
#
hidePlayers: false
favicon: ''
#
# Set the hover text that usually displays online players.
# Only normal colours such as <grey> or <aqua> are supported.
#
# Remove this option or set it to players: [] to not alter the hover text.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#players
#
players:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
#
# Set the text that usually shows online players and max that can join.
# Only normal colours such as <grey> or <aqua> are supported.
#
# Remove this option or set it to playerCount: '' to not alter the player count text.
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#playercount
#
playerCount: '<grey>Text'
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
# You can set this to 'hover: []' or remove the option to not modify the hover text.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hover
#
hover:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
#
# Modifies the text that usually displays '<online>/<max>'
#
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
# This is nothing that can be fixed or avoided and would require changes from Mojang.
#
# You can set this to 'count: ''' or remove the option to not modify the player count text.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#text
#
text: ''
#
# Allows you to modify the max player count displayed.
# Note that this will affect ${server playersMax} (Except for when used in conditions).
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#extraPlayers
#
extraPlayers:
#
# Enables/Disables the extraPlayers option.
# When enabled will the total amount of players allowed be modified to the current
# number of online players + 'amount'
#
# Defaults to false when not present.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#enabled
#
enabled: false
#
# Sets how much should be added/subtracted from the current number of online players
# to then use for the max player count.
#
# Example:
# When set to 1 while 10 players are online would the player count - if unmodified -
# display '10/11'. When -1 is used will it display '10/9'
#
# Defaults to 0 when not present.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#amount
#
amount: 0
+9 -5
View File
@@ -76,13 +76,13 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.1</version>
<version>2.11.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-PaperMC-${plugin.version}</finalName>
<finalName>AdvancedServerList-Paper-${plugin.version}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -101,9 +101,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.spongepowered.configurate</pattern>
@@ -111,7 +111,11 @@
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.bstats</shadedPattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
@@ -26,33 +26,46 @@
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.ServerCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.paper.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.paper.events.JoinEvent;
import ch.andre601.advancedserverlist.paper.events.PingEvent;
import ch.andre601.advancedserverlist.paper.logging.PaperLogger;
import com.destroystokyo.paper.profile.PlayerProfile;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.CachedServerIcon;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PaperCore extends JavaPlugin implements PluginCore{
public class PaperCore extends JavaPlugin implements ServerCore<CachedServerIcon, PlayerProfile, OfflinePlayer>{
private final PluginLogger logger = new PaperLogger(getLogger());
private AdvancedServerList core;
private FaviconHandler<CachedServerIcon> faviconHandler;
@Override
public void onEnable(){
try{
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
this.core = new AdvancedServerList(this);
enable();
}catch(ClassNotFoundException ex){
try{
Class.forName("com.destroystokyo.paper.PaperConfig");
this.core = new AdvancedServerList(this);
enable();
}catch(ClassNotFoundException ex1){
getPluginLogger().warn("======================================== WARNING ========================================");
getPluginLogger().warn("");
@@ -102,13 +115,21 @@ public class PaperCore extends JavaPlugin implements PluginCore{
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList getCore(){
return core;
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -117,6 +138,14 @@ public class PaperCore extends JavaPlugin implements PluginCore{
return logger;
}
@Override
public FaviconHandler<CachedServerIcon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getServer().getName();
@@ -126,4 +155,30 @@ public class PaperCore extends JavaPlugin implements PluginCore{
public String getPlatformVersion(){
return getServer().getVersion();
}
private void enable(){
this.core = new AdvancedServerList(this);
}
@Override
public List<PlayerProfile> createPlayers(List<String> lines, OfflinePlayer player, Placeholders... placeholders){
List<PlayerProfile> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.replacements(placeholders[0])
.replacements(placeholders[1])
.modifyText(text -> {
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return text;
})
.toString();
players.add(Bukkit.createProfile(UUID.randomUUID(), parsed));
}
return players;
}
}
@@ -0,0 +1,47 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import org.bukkit.OfflinePlayer;
public class PaperPlayer extends GenericPlayer<OfflinePlayer>{
public PaperPlayer(OfflinePlayer player, String name, int protocol){
this.player = player;
this.name = player == null ? name : player.getName();
this.protocol = protocol;
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
this.uuid = player.getUniqueId();
}
}
@@ -28,21 +28,20 @@ package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.Placeholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import com.destroystokyo.paper.profile.PlayerProfile;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.util.CachedServerIcon;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class PingEvent implements Listener{
@@ -57,29 +56,37 @@ public class PingEvent implements Listener{
public void onServerPing(PaperServerListPingEvent event){
InetSocketAddress address = event.getClient().getAddress();
InetSocketAddress host = event.getClient().getVirtualHost();
Map<String, Object> replacements = Placeholders.get(plugin.getCore())
.withProtocol(event.getClient().getProtocolVersion())
.withPlayersOnline(event.getNumPlayers())
.withPlayersMax(event.getMaxPlayers())
.withPlayerName(address)
.withHostAddress(host)
.getReplacements();
PaperPlayer player = resolvePlayer(address, event.getClient().getProtocolVersion());
int online = event.getNumPlayers();
int max = event.getMaxPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
event.setMaxPlayers(max);
}
OfflinePlayer player = resolvePlayer(address);
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
event.motd(ComponentParser.list(profile.getMotd())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
@@ -88,15 +95,15 @@ public class PingEvent implements Listener{
if(profile.shouldHidePlayers()){
event.setHidePlayers(true);
return;
}
if(!profile.getPlayerCount().isEmpty()){
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
event.setVersion(ComponentParser.text(profile.getPlayerCount())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
@@ -104,39 +111,44 @@ public class PingEvent implements Listener{
event.setProtocolVersion(-1);
}
if(!profile.getPlayers().isEmpty()){
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
event.getPlayerSample().clear();
event.getPlayerSample().addAll(getPlayers(profile.getPlayers(), replacements, player));
event.getPlayerSample().addAll(
plugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
event.setServerIcon(event.getServerIcon());
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
CachedServerIcon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Bukkit.loadServerIcon(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
event.setServerIcon(event.getServerIcon());
}else{
event.setServerIcon(favicon);
}
}
}
private List<PlayerProfile> getPlayers(List<String> lines, Map<String, Object> replacements, OfflinePlayer player){
List<PlayerProfile> players = new ArrayList<>();
lines.forEach(line -> players.add(Bukkit.createProfile(UUID.randomUUID(), ComponentParser.text(line)
.replacements(replacements)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return text;
})
.toString())));
return players;
}
private OfflinePlayer resolvePlayer(InetSocketAddress address){
private PaperPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
if(player == null){
player = Bukkit.getOfflinePlayer(playerName);
return player.hasPlayedBefore() ? player : null;
return new PaperPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return player;
return new PaperPlayer(player, playerName, protocol);
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ softdepend:
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [reload]'
usage: '/<command> [help|reload]'
aliases:
- 'asl'
permission: 'advancedserverlist.admin'
+1 -12
View File
@@ -12,20 +12,9 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.version>1.2.0</plugin.version>
<plugin.version>1.6.2</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<plugin.depend.mc>1.19-R0.1-SNAPSHOT</plugin.depend.mc>
<plugin.depend.velocity>3.1.1-SNAPSHOT</plugin.depend.velocity>
<plugin.depend.configurate>4.1.2</plugin.depend.configurate>
<plugin.depend.kyori-adventure>4.11.0</plugin.depend.kyori-adventure>
<plugin.depend.kyori-minimessage>4.11.0</plugin.depend.kyori-minimessage>
<plugin.depend.kyori-legacy>4.11.0</plugin.depend.kyori-legacy>
<plugin.depend.kyori-platform-bungeecord>4.1.0</plugin.depend.kyori-platform-bungeecord>
<plugin.depend.kyori-platform-bukkit>4.1.1</plugin.depend.kyori-platform-bukkit>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
+10 -6
View File
@@ -68,13 +68,13 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${plugin.depend.mc}</version>
<version>1.19-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>${plugin.depend.kyori-platform-bukkit}</version>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
@@ -91,7 +91,7 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.1</version>
<version>2.11.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -116,13 +116,17 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.bstats</shadedPattern>
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
@@ -26,22 +26,34 @@
package ch.andre601.advancedserverlist.spigot;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.ServerCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.spigot.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.spigot.events.LoadEvent;
import ch.andre601.advancedserverlist.spigot.logging.SpigotLogger;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class SpigotCore extends JavaPlugin implements PluginCore{
public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPing.CompressedImage, WrappedGameProfile, OfflinePlayer>{
private final PluginLogger logger = new SpigotLogger(getLogger());
private AdvancedServerList core;
private final PluginLogger logger = new SpigotLogger(getLogger());
FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
@Override
public void onEnable(){
@@ -88,13 +100,21 @@ public class SpigotCore extends JavaPlugin implements PluginCore{
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList getCore(){
return core;
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -103,6 +123,14 @@ public class SpigotCore extends JavaPlugin implements PluginCore{
return logger;
}
@Override
public FaviconHandler<WrappedServerPing.CompressedImage> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getServer().getName();
@@ -113,11 +141,33 @@ public class SpigotCore extends JavaPlugin implements PluginCore{
return getServer().getVersion();
}
@Override
public List<WrappedGameProfile> createPlayers(List<String> lines, OfflinePlayer player, Placeholders... placeholders){
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.replacements(placeholders[0])
.replacements(placeholders[1])
.modifyText(text -> {
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return text;
})
.toString();
players.add(new WrappedGameProfile(UUID.randomUUID(), parsed));
}
return players;
}
private void printPaperInfo(){
getPluginLogger().warn("======================================================================================");
getPluginLogger().warn("You are using the Spigot version of AdvancedServerList on a PaperMC server.");
getPluginLogger().warn("It is recommended to use the dedicated PaperMC version, to benefit from the");
getPluginLogger().warn("Following improvements:");
getPluginLogger().warn("You are using the Spigot version of AdvancedServerList on a Paper server.");
getPluginLogger().warn("It is recommended to use the dedicated Paper version, to benefit from the");
getPluginLogger().warn("following improvements:");
getPluginLogger().warn(" - No need to download external libraries already provided by PaperMC.");
getPluginLogger().warn(" - No dependency on ProtocolLib thanks to provided Events.");
getPluginLogger().warn("");
@@ -0,0 +1,47 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import org.bukkit.OfflinePlayer;
public class SpigotPlayer extends GenericPlayer<OfflinePlayer>{
public SpigotPlayer(OfflinePlayer player, String name, int protocol){
this.player = player;
this.name = player == null ? name : player.getName();
this.protocol = protocol;
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
this.uuid = player.getUniqueId();
}
}
@@ -46,7 +46,7 @@ public class LoadEvent implements Listener{
PluginManager manager = plugin.getServer().getPluginManager();
if(!manager.isPluginEnabled("ProtocolLib")){
plugin.getCore().getPluginLogger().warn("ProtocolLib not found! AdvancedServerList requires it to work on Spigot!");
plugin.getCore().getPlugin().getPluginLogger().warn("ProtocolLib not found! AdvancedServerList requires it to work on Spigot!");
manager.disablePlugin(plugin);
return;
@@ -28,15 +28,17 @@ package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.Placeholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
@@ -82,32 +84,37 @@ public class PingEvent implements Listener{
InetSocketAddress address = event.getPlayer().getAddress();
if(address == null)
return;
Map<String, Object> replacements = Placeholders.get(spigotPlugin.getCore())
.withProtocol(ping.getVersionProtocol())
.withPlayersOnline(ping.getPlayersOnline())
.withPlayersMax(ping.getPlayersMaximum())
.withPlayerName(address)
.withHostAddress(hostAddresses.get(address.getHostString()))
.getReplacements();
spigotPlugin.getPluginLogger().info(hostAddresses.get(address.getHostString()));
SpigotPlayer player = resolvePlayer(address, ping.getVersionProtocol());
int online = ping.getPlayersOnline();
int max = ping.getPlayersMaximum();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
ServerListProfile profile = ProfileManager.get(spigotPlugin.getCore())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
ping.setPlayersMaximum(max);
}
OfflinePlayer player = resolvePlayer(address);
serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
if(!profile.getMotd().isEmpty()){
Component component = ComponentParser.list(profile.getMotd())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
@@ -117,15 +124,15 @@ public class PingEvent implements Listener{
if(profile.shouldHidePlayers()){
ping.setPlayersVisible(false);
return;
}
if(!profile.getPlayerCount().isEmpty()){
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
ping.setVersionName(ComponentParser.text(profile.getPlayerCount())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
@@ -134,35 +141,35 @@ public class PingEvent implements Listener{
ping.setVersionProtocol(-1);
}
if(!profile.getPlayers().isEmpty()){
ping.setPlayers(getFakePlayers(
ComponentParser.list(profile.getPlayers())
.replacements(replacements)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ping.setPlayers(
spigotPlugin.createPlayers(profile.getPlayers(), player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
return text;
})
.toString()
));
WrappedServerPing.CompressedImage favicon = spigotPlugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return WrappedServerPing.CompressedImage.fromPng(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
spigotPlugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFavicon());
}else{
ping.setFavicon(favicon);
}
}
}
});
}
private List<WrappedGameProfile> getFakePlayers(String text){
String[] lines = text.split("\n");
List<WrappedGameProfile> profiles = new ArrayList<>();
for(String line : lines){
profiles.add(new WrappedGameProfile(UUID.randomUUID(), line));
}
return profiles;
}
private OfflinePlayer resolvePlayer(InetSocketAddress address){
private SpigotPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
@@ -170,9 +177,9 @@ public class PingEvent implements Listener{
//noinspection deprecation
player = Bukkit.getOfflinePlayer(playerName);
return player.hasPlayedBefore() ? player : null;
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return player;
return new SpigotPlayer(player, playerName, protocol);
}
}
+6 -6
View File
@@ -8,11 +8,11 @@ main: 'ch.andre601.advancedserverlist.spigot.SpigotCore'
api-version: 1.19
libraries:
- 'org.spongepowered:configurate-yaml:${plugin.depend.configurate}'
- 'net.kyori:adventure-api:${plugin.depend.kyori-adventure}'
- 'net.kyori:adventure-text-minimessage:${plugin.depend.kyori-minimessage}'
- 'net.kyori:adventure-text-serializer-legacy:${plugin.depend.kyori-legacy}'
- 'net.kyori:adventure-platform-bukkit:${plugin.depend.kyori-platform-bukkit}'
- 'org.spongepowered:configurate-yaml:4.1.2'
- 'net.kyori:adventure-api:4.11.0'
- 'net.kyori:adventure-text-minimessage:4.11.0'
- 'net.kyori:adventure-text-serializer-legacy:4.11.0'
- 'net.kyori:adventure-platform-bukkit:4.1.2'
softdepend:
- 'ProtocolLib'
@@ -21,7 +21,7 @@ softdepend:
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [reload]'
usage: '/<command> [help|reload]'
aliases:
- 'asl'
permission: 'advancedserverlist.admin'
+8 -2
View File
@@ -35,6 +35,8 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>velocity</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
@@ -86,9 +88,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.spongepowered.configurate</pattern>
@@ -98,6 +100,10 @@
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -26,8 +26,11 @@
package ch.andre601.advancedserverlist.velocity;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.velocity.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.velocity.events.JoinEvent;
import ch.andre601.advancedserverlist.velocity.events.PingEvent;
@@ -39,13 +42,18 @@ import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import org.bstats.charts.SimplePie;
import org.bstats.velocity.Metrics;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class VelocityCore implements PluginCore{
public class VelocityCore implements ProxyCore<Favicon, ServerPing.SamplePlayer>{
private final PluginLogger logger;
private final ProxyServer proxy;
@@ -53,6 +61,7 @@ public class VelocityCore implements PluginCore{
private final Metrics.Factory metrics;
private AdvancedServerList core;
private FaviconHandler<Favicon> faviconHandler = null;
@Inject
public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
@@ -96,13 +105,21 @@ public class VelocityCore implements PluginCore{
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList getCore(){
return core;
}
@Override
public Path getPath(){
public Path getFolderPath(){
return path;
}
@@ -111,6 +128,30 @@ public class VelocityCore implements PluginCore{
return logger;
}
@Override
public FaviconHandler<Favicon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public List<ServerPing.SamplePlayer> createPlayers(List<String> lines, Placeholders... placeholders){
List<ServerPing.SamplePlayer> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.replacements(placeholders[0])
.replacements(placeholders[1])
.toString();
players.add(new ServerPing.SamplePlayer(parsed, UUID.randomUUID()));
}
return players;
}
@Override
public String getPlatformName(){
return getProxy().getVersion().getName();
@@ -0,0 +1,39 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.velocity;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.Player;
public class VelocityPlayer extends GenericPlayer<Player>{
public VelocityPlayer(String name, int protocol){
this.name = name;
this.protocol = protocol;
this.version = ProtocolVersion.getProtocolVersion(protocol).getVersionIntroducedIn();
}
}
@@ -25,21 +25,22 @@
package ch.andre601.advancedserverlist.velocity.events;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.Placeholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
public class PingEvent{
@@ -58,61 +59,79 @@ public class PingEvent{
return;
ServerPing.Builder builder = ping.asBuilder();
InetSocketAddress address = event.getConnection().getRemoteAddress();
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(event.getConnection().getRemoteAddress().getHostString());
InetSocketAddress host = event.getConnection().getVirtualHost().orElse(null);
Map<String, Object> replacements = Placeholders.get(plugin.getCore())
.withProtocol(protocol.getProtocol())
.withPlayersOnline(builder.getOnlinePlayers())
.withPlayersMax(builder.getMaximumPlayers())
.withPlayerName(address)
.withHostAddress(host)
.withPlayerVersion(ProtocolVersion.getProtocolVersion(protocol.getProtocol()).toString())
.getReplacements();
int online = builder.getOnlinePlayers();
int max = builder.getMaximumPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new VelocityPlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
builder.maximumPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
List<String> motd = profile.getMotd();
builder.description(ComponentParser.list(motd)
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
);
}
if(profile.shouldHidePlayers()){
builder.nullPlayers();
event.setPing(builder.build());
return;
}
if(!profile.getPlayerCount().isEmpty()){
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
builder.version(new ServerPing.Version(
-1,
ComponentParser.text(profile.getPlayerCount())
.replacements(replacements)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
));
}
if(!profile.getPlayers().isEmpty()){
String players = ComponentParser.list(profile.getPlayers())
.replacements(replacements)
.toString();
ServerPing.SamplePlayer[] playerSamples = AdvancedServerList.getPlayers(ServerPing.SamplePlayer.class, players)
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.SamplePlayer[0]);
if(playerSamples.length > 0)
builder.clearSamplePlayers().samplePlayers(playerSamples);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
}else{
builder.favicon(favicon);
}
}
event.setPing(builder.build());
}
}
@@ -38,12 +38,12 @@ public class VelocityLogger implements PluginLogger{
@Override
public void info(String msg, Object... args){
logger.info(msg, args);
logger.info(String.format(msg, args));
}
@Override
public void warn(String msg, Object... args){
logger.warn(msg, args);
logger.warn(String.format(msg, args));
}
@Override