Compare commits

...
121 Commits
Author SHA1 Message Date
Andre_601 8f9ae4a835 Merge pull request #43 from Andre601/fix/nullpointerexceptions
Fix some NullPointerExceptions
2023-01-09 20:32:01 +01:00
Andre601 0dccdaf7e4 Add a comment 2023-01-09 20:31:31 +01:00
Andre601 ec0dec8e7d Try to fix errors with OkHttpClient 2023-01-09 17:59:23 +01:00
Andre601 f399ed6886 Fix some NullPointerExceptions 2023-01-09 17:42:54 +01:00
Andre_601 f2737f2b19 Merge pull request #42 from Andre601/dependabot/maven/core/com.google.code.gson-gson-2.10.1
Bump gson from 2.10 to 2.10.1 in /core
2023-01-09 16:20:46 +01:00
dependabot[bot] 504e669ce7 Bump gson from 2.10 to 2.10.1 in /core
Bumps [gson](https://github.com/google/gson) from 2.10 to 2.10.1.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10...gson-parent-2.10.1)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 15:16:41 +00:00
Andre_601 1effc2574a Update release.yml 2022-12-28 20:15:16 +01:00
Andre_601 eb7a7fa6c7 Delete prerelease.yml 2022-12-28 20:15:07 +01:00
Andre601 9f6bdea168 Add better Version check (+ tests) 2022-12-28 16:58:23 +01:00
Andre_601 d247d832e6 Update prerelease.yml 2022-12-27 22:02:32 +01:00
Andre_601 708037bb6b Update release.yml 2022-12-27 22:02:05 +01:00
Andre_601 7da88771b6 Update prerelease.yml 2022-12-27 21:27:01 +01:00
Andre_601 9ccfd4674c Add workflow for beta-releases 2022-12-27 21:26:16 +01:00
Andre_601 9054ebdb0c Merge pull request #40 from Andre601/feature/multi-profiles
Implement system for multiple profiles in profiles
2022-12-27 21:22:25 +01:00
Andre601 edfd77e891 Fix wrong hidePlayersEnabled call. 2022-12-27 21:19:01 +01:00
Andre601 94391a8aed Make booleans and int nullable + version bump 2022-12-27 21:16:23 +01:00
Andre601 5a1f343cc2 Update config.yml 2022-12-27 18:03:07 +01:00
Andre601 e718a5c766 Improve descriptions 2022-12-27 18:01:40 +01:00
Andre601 565644ccd5 Add profiles example 2022-12-27 17:51:07 +01:00
Andre601 9531af1fdd Don't use random on a single entry 2022-12-27 16:56:50 +01:00
Andre601 7c1d7aadbc Try a system with fallback to def profile 2022-12-27 16:46:02 +01:00
Andre601 f26f2ba269 Implement system for multiple profiles in profiles 2022-12-27 16:03:01 +01:00
Andre_601 f5d2fd1534 Merge pull request #39 from Andre601/feature/multiple-motds
Add option to have multiple MOTDs.
2022-12-20 22:22:49 +01:00
Andre601 90537eb004 Bump Version for release 2022-12-20 22:22:14 +01:00
Andre601 ce6a9e3b0b Use a Builder class to make ServerListProfile immutable... I guess? 2022-12-18 21:32:35 +01:00
Andre601 4d29f9e45e Add option to have multiple MOTDs. 2022-12-18 17:45:38 +01:00
Andre601 bf49636d6a Update workflow 2022-12-09 22:27:44 +01:00
Andre601 4a6c9a55d4 Update required libraries 2022-12-09 22:26:44 +01:00
Andre601 a5bfc0b6e3 Smaller format correction + version bump 2022-12-09 22:23:24 +01:00
Andre_601 dff332a83a Merge pull request #37 from Andre601/dependabot/maven/spigot/net.kyori-adventure-platform-bukkit-4.2.0
Bump adventure-platform-bukkit from 4.1.2 to 4.2.0 in /spigot
2022-12-09 16:10:29 +01:00
dependabot[bot] 58a16baaab Bump adventure-platform-bukkit from 4.1.2 to 4.2.0 in /spigot
Bumps [adventure-platform-bukkit](https://github.com/KyoriPowered/adventure-platform) from 4.1.2 to 4.2.0.
- [Release notes](https://github.com/KyoriPowered/adventure-platform/releases)
- [Commits](https://github.com/KyoriPowered/adventure-platform/compare/v4.1.2...v4.2.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-platform-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-09 15:08:40 +00:00
Andre_601 c8acb4d90a Merge pull request #36 from Andre601/feature/unified-eventhandler
Create unified EventHandler
2022-12-08 21:56:48 +01:00
Andre_601 5575243a79 Merge pull request #35 from Andre601/dependabot/maven/core/com.google.code.gson-gson-2.10
Bump gson from 2.9.1 to 2.10 in /core
2022-12-08 16:43:13 +01:00
Andre601 4cd4aeb12a Move Favicon creation and logging to PingEventHandler 2022-12-08 16:42:23 +01:00
Andre601 5922b2235e Bump version 2022-12-07 21:19:23 +01:00
Andre601 2fcef08f5a Wrap up (no pun intended) remaining platform events 2022-12-07 16:28:39 +01:00
Andre601 30c28b07a4 Smaller changes 2022-12-06 21:32:16 +01:00
Andre601 08b4f1029c Make Protocol and ServerPing final 2022-12-06 21:27:09 +01:00
Andre601 f5051022aa Create unified EventHandler 2022-12-06 21:24:43 +01:00
dependabot[bot] fe51e78764 Bump gson from 2.9.1 to 2.10 in /core
Bumps [gson](https://github.com/google/gson) from 2.9.1 to 2.10.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.9.1...gson-parent-2.10)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-06 15:11:07 +00:00
Andre_601 5b2d9d910f Use env variables 2022-12-06 14:17:34 +01:00
Andre_601 6f06c47de7 Merge pull request #34 from Andre601/feature/update-checker
Add Update Checker
2022-12-06 14:03:25 +01:00
Andre601 ad3ba0c8b3 Update config description 2022-12-06 00:49:52 +01:00
Andre601 12d8d930dd Use a ScheduledExecutorService instead of Timer 2022-12-06 00:26:55 +01:00
Andre601 9a30a6b679 Add info line 2022-12-06 00:01:24 +01:00
Andre601 b82cf69d43 Simplify more. 2022-12-05 23:58:05 +01:00
Andre601 fb6d93b455 Init timer only when UpdateChecker is used. 2022-12-05 23:55:54 +01:00
Andre601 a1276da68f Fix exceptions 2022-12-05 23:13:21 +01:00
Andre601 25c053d495 Use timer class from Java 2022-12-05 22:24:19 +01:00
Andre601 39c1fb5452 Better version comparison. 2022-12-05 21:26:24 +01:00
Andre601 48edebc043 Add config option 2022-12-03 20:29:45 +01:00
Andre601 3a672378ff Add Update Checker 2022-12-03 20:23:21 +01:00
Andre_601 9db9f2be7f Merge pull request #33 from Andre601/dependabot/maven/core/net.kyori-adventure-api-4.12.0
Bump adventure-api from 4.11.0 to 4.12.0 in /core
2022-11-28 16:31:53 +01:00
Andre_601 2cf47e351b Merge pull request #32 from Andre601/dependabot/maven/core/net.kyori-adventure-text-minimessage-4.12.0
Bump adventure-text-minimessage from 4.11.0 to 4.12.0 in /core
2022-11-28 16:31:39 +01:00
Andre_601 36abdb83cd Merge pull request #31 from Andre601/dependabot/maven/core/net.kyori-adventure-text-serializer-legacy-4.12.0
Bump adventure-text-serializer-legacy from 4.11.0 to 4.12.0 in /core
2022-11-28 16:31:21 +01:00
dependabot[bot] ad950bf330 Bump adventure-api from 4.11.0 to 4.12.0 in /core
Bumps [adventure-api](https://github.com/KyoriPowered/adventure) from 4.11.0 to 4.12.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.11.0...v4.12.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 15:12:17 +00:00
dependabot[bot] 143753d309 Bump adventure-text-minimessage from 4.11.0 to 4.12.0 in /core
Bumps [adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.11.0 to 4.12.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.11.0...v4.12.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-minimessage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 15:12:10 +00:00
dependabot[bot] 0c37c21650 Bump adventure-text-serializer-legacy from 4.11.0 to 4.12.0 in /core
Bumps [adventure-text-serializer-legacy](https://github.com/KyoriPowered/adventure) from 4.11.0 to 4.12.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.11.0...v4.12.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-serializer-legacy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 15:12:04 +00:00
Andre_601 40a6b4f059 Merge pull request #30 from Andre601/dependabot/maven/core/com.github.ben-manes.caffeine-caffeine-3.1.2
Bump caffeine from 3.1.1 to 3.1.2 in /core
2022-11-24 16:24:36 +01:00
dependabot[bot] 965e87d71b Bump caffeine from 3.1.1 to 3.1.2 in /core
Bumps [caffeine](https://github.com/ben-manes/caffeine) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.1.1...v3.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-24 15:08:34 +00:00
Andre_601 202a22f33a Update README.md 2022-11-21 15:20:02 +01:00
Andre_601 a4b2a6c350 Update MODRINTH.md 2022-11-21 15:03:28 +01:00
Andre601 ba55f5299b Bump version 2022-11-07 22:29:04 +01:00
Andre_601 24fdf798cf Merge pull request #29 from Andre601/feature/disable-cache-option
Add option to disable Cache
2022-11-07 22:28:16 +01:00
Andre601 e208d181b7 Add option to disable Cache 2022-11-07 22:14:50 +01:00
Andre_601 6c15c7b259 Merge pull request #28 from Andre601/dependabot/maven/paper/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /paper
2022-10-27 17:55:21 +02:00
Andre_601 dcd76a43f5 Merge pull request #27 from Andre601/dependabot/maven/bungeecord/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /bungeecord
2022-10-27 17:55:10 +02:00
Andre_601 adc2060499 Merge pull request #26 from Andre601/dependabot/maven/velocity/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /velocity
2022-10-27 17:55:01 +02:00
Andre_601 4d6befc857 Merge pull request #25 from Andre601/dependabot/maven/core/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /core
2022-10-27 17:54:52 +02:00
dependabot[bot] 7cfb792471 Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /paper
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.0...maven-shade-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-27 15:41:21 +00:00
dependabot[bot] d46245eefa Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /bungeecord
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.0...maven-shade-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-27 15:41:17 +00:00
dependabot[bot] d5e0fd3d7a Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /velocity
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.0...maven-shade-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-27 15:41:11 +00:00
dependabot[bot] 496e246b9e Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /core
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.0...maven-shade-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-27 15:41:11 +00:00
Andre_601 e263a45f1c width and not height 2022-10-05 17:40:40 +02:00
Andre_601 edfc977730 Update MODRINTH.md 2022-10-05 17:40:01 +02:00
Andre_601 5910c26b4b Add waterfall badge 2022-10-03 23:49:07 +02:00
Andre_601 5b9c506a89 Use jsdelivr url 2022-09-26 00:17:47 +02:00
Andre_601 913ddd7834 Create MODRINTH.md 2022-09-22 13:41:05 +02:00
Andre_601 397c7ea59a Merge pull request #23 from Andre601/feature/readme-new-badges
Prepare readme for new badges
2022-09-21 01:48:30 +02:00
Andre_601 6e7b2541e1 Update README.md 2022-09-21 01:48:22 +02:00
Andre_601 241c15a452 Update README.md 2022-09-20 22:07:40 +02:00
Andre_601 62c5d13aa2 Prepare readme for new badges 2022-09-20 22:05:33 +02:00
Andre601 3a73c5ce6b Fix wrong open-perms for certain OS 2022-09-20 00:41:33 +02:00
Andre_601 bf54e8eb0b Yes I update the README a lot today... 2022-09-18 01:45:46 +02:00
Andre_601 aa2cabedbf Update README.md 2022-09-18 01:09:01 +02:00
Andre_601 66878626e1 Update README.md 2022-09-17 23:35:34 +02:00
Andre_601 f6f3f3d8b6 Update README.md 2022-09-17 23:25:48 +02:00
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
54 changed files with 2774 additions and 834 deletions

No files matched your search

+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
+96
View File
@@ -0,0 +1,96 @@
# AdvancedServerList
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Supported Platforms
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/spigot_vector.svg" width="64" alt="platform-spigot" title="Tested on Spigot">
</a>
<a href="https://papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" width="64" alt="platform-paper" title="Tested on Paper">
</a>
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/bungeecord_vector.svg" width="64" alt="platform-bungeecord" title="Tested on BungeeCord">
</a>
<a href="https://www.papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/waterfall_vector.svg" width="64" alt="platform-waterfall" title="Tested on Waterfall">
</a>
<a href="https://velocitypowered.com" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/velocity_vector.svg" width="64" alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
> [*Read More*][profiles]
### Conditions
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
> [*Read More*][conditions]
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
> [*Read More*][placeholders]
### Formatting
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
> [*Read More*][minimessage]
## Dependencies
| Dependency | Platforms | Required? |
| ---------------- | ------------- | --------- |
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
## Statistics
This plugin sends statistics to [bStats] to display.
You can disable this in the global bStats config file located in `/plugins/bstats/`
- [BungeeCord][bstats-bungee]
- [Paper/Spigot][bstats-spigot]
- [Velocity][bstats-velocity]
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/cozy/documentation/modrinth-gallery_vector.svg" width="208" alt="gallery" title="Check out the Gallery">
</a>
## Support
<a href="https://discord.gg/6dazXp6" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/discord-singular_vector.svg" width="64" alt="discord" title="Join my Discord Server">
</a>
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/revolt-singular_vector.svg" width="64" alt="revolt" title="Join my Revolt Server">
</a>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/minimal/social/mastodon-singular_vector.svg" width="64" alt="revolt" title="Chat with me on Mastodon">
</a>
<!-- Links -->
[profiles]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles
[conditions]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#conditions
[placeholders]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#placeholders
[minimessage]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#minimessage
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[bstats]: https://bstats.org
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
+19 -9
View File
@@ -7,7 +7,8 @@ name: Publish Assets
on:
release:
types: [published]
types:
- published
jobs:
buildJars:
@@ -55,15 +56,19 @@ jobs:
strategy:
matrix:
include:
- directory: bungeecord
- platforms: BungeeCord, Waterfall
directory: bungeecord
loaders: |
bungeecord
waterfall
- directory: paper
- platforms: Paper
directory: paper
loaders: paper
- directory: spigot
- platforms: Spigot
directory: spigot
loaders: spigot
- directory: velocity
- platforms: Velocity
directory: velocity
loaders: velocity
runs-on: ubuntu-latest
steps:
@@ -77,19 +82,24 @@ jobs:
id: github-release
run: |
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
echo "::set-output name=version::$version"
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
uses: Kir-Antipov/mc-publish@v3.2
with:
name: ${{ github.event.release.name }}
version: ${{ steps.github-release.outputs.version }}
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
version-type: release
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
files-secondary: ""
loaders: ${{ matrix.loaders }}
version-resolver: releases
game-versions: '1.19'
game-versions: |
1.19
1.19.1
1.19.2
1.19.3
java: 16
modrinth-id: xss83sOY
modrinth-featured: false
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
+37 -23
View File
@@ -1,7 +1,27 @@
# AdvancedServerList
![platform] ![tested]
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/available/modrinth_vector.svg" height="64" align="right" alt="modrinth" title="Available on Modrinth">
</a>
AdvancedServerList is a plugin made for SpigotMC, PaperMC, BungeeCord/Waterfall and Velocity. It allows you to create server list profiles to display based on priority and conditions.
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Supported Platforms
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
</a>
<a href="https://papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
</a>
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/bungeecord_vector.svg" height="64" alt="platform-bungeecord" title="Tested on BungeeCord">
</a>
<a href="https://www.papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/waterfall_vector.svg" height="64" alt="platform-waterfall" title="Tested on Waterfall">
</a>
<a href="https://velocitypowered.com" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/velocity_vector.svg" height="64" alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
@@ -30,11 +50,6 @@ Only certain options are usable for each option. As an example does motd support
> [*Read More*][minimessage]
## Downloads
AdvancedServerList can be downloaded from the following places:
[![dl-modrinth]][modrinth] [![dl-spigot]][spigot] [![dl-hangar]][hangar]
## Dependencies
| Dependency | Platforms | Required? |
@@ -45,7 +60,7 @@ AdvancedServerList can be downloaded from the following places:
## Statistics
This plugin sends statistics to [bStats] to display.
You can disable this in the `config.yml` by setting `send_statistics` to `false`.
You can disable this in the global bStats config file located in `/plugins/bstats/`
- [BungeeCord][bstats-bungee]
- [Paper/Spigot][bstats-spigot]
@@ -53,8 +68,20 @@ You can disable this in the `config.yml` by setting `send_statistics` to `false`
## Screenshots
Please see the [Gallery Tab][gallery] for some previews.
If you have any own screenshots, feel free to share them with me. I may add them to the Gallery if they are good.
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" alt="gallery" title="Check out the Gallery">
</a>
## Support
<a href="https://discord.gg/6dazXp6" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
</a>
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/revolt-singular_vector.svg" height="64" alt="revolt" title="Join my Revolt Server">
</a>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/social/mastodon-singular_vector.svg" height="64" alt="mastodon" title="Chat with me on Mastodon">
</a>
<!-- Links -->
[profiles]: https://github.com/Andre601/AdvancedServerList/wiki/Profiles
@@ -65,8 +92,6 @@ If you have any own screenshots, feel free to share them with me. I may add them
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[spigot]: https://www.spigotmc.org/resources/102910/
[hangar]: https://hangar.benndorf.dev/Andre_601/AdvancedServerList
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
@@ -77,14 +102,3 @@ If you have any own screenshots, feel free to share them with me. I may add them
[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=
[dl-modrinth]: https://img.shields.io/badge/Modrinth-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==
[dl-spigot]: https://img.shields.io/badge/Spigot-ed8106?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBmaWxsPSIjRkZGIj48cGF0aCBkPSJNNDE2IDQ4MGMwIDE3LjYyIDE0LjM4IDMyIDMyIDMyczMyLTE0LjM4IDMyLTMycy0zMi02NC0zMi02NFM0MTYgNDYyLjQgNDE2IDQ4MHpNMzUyIDE5MmgtMzguNTRDMjk3LjcgMTc4LjUgMjc3LjkgMTY4LjkgMjU2IDE2NFYxMTYuNUwyMjQgMTEzTDE5MiAxMTYuNVYxNjRDMTcwLjEgMTY5IDE1MC4zIDE3OC42IDEzNC41IDE5MkgxNkM3LjEyNSAxOTIgMCAxOTkuMSAwIDIwOHY5NkMwIDMxMi45IDcuMTI1IDMyMCAxNiAzMjBoOTIuNzhDMTI5LjQgMzU3LjggMTczIDM4NCAyMjQgMzg0czk0LjU5LTI2LjI1IDExNS4yLTY0SDM1MmMxNy42MiAwIDMyIDE0LjI5IDMyIDMxLjkxUzM5OC40IDM4NCA0MTYgMzg0aDY0YzE3LjYyIDAgMzItMTQuMzggMzItMzJDNTEyIDI2My42IDQ0MC40IDE5MiAzNTIgMTkyek04MS42MyA5NS44OEwyMjQgODAuODhsMTQyLjQgMTVDMzc1LjkgOTYuODggMzg0IDg5LjEyIDM4NCA3OS4xMlY0OC44OWMwLTEwLTguMTI1LTE3Ljc0LTE3LjYyLTE2Ljc0TDI1NiA0My43NVYxNkMyNTYgNy4xMjUgMjQ4LjkgMCAyNDAgMGgtMzJDMTk5LjEgMCAxOTIgNy4xMjUgMTkyIDE2djI3Ljc1TDgxLjYzIDMyLjE0QzcyLjEzIDMxLjE0IDY0IDM4Ljg5IDY0IDQ4Ljg5Vjc5LjEyQzY0IDg5LjEyIDcyLjEzIDk2Ljg4IDgxLjYzIDk1Ljg4eiIvPjwvc3ZnPg==
[dl-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==
+5 -1
View File
@@ -103,7 +103,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -123,6 +123,10 @@
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.caffeine</shadedPattern>
</relocation>
<relocation>
<pattern>okhttp3</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.okhttp3</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -30,17 +30,23 @@ 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.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
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<Favicon>{
public class BungeeCordCore extends Plugin implements ProxyCore<Favicon, ServerPing.PlayerInfo>{
private AdvancedServerList core;
private FaviconHandler<Favicon> faviconHandler = null;
@@ -77,6 +83,9 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@@ -86,7 +95,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -112,4 +121,25 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
public String getPlatformVersion(){
return getProxy().getVersion();
}
@Override
public String getLoader(){
return "bungeecord";
}
@Override
public List<ServerPing.PlayerInfo> createPlayers(List<String> lines, Placeholders... placeholders){
List<ServerPing.PlayerInfo> players = new ArrayList<>(lines.size());
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,156 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ProxyPingEvent;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Favicon>{
private final BungeeCordCore plugin;
private final ProxyPingEvent event;
private final ServerPing.Protocol protocol;
private final ServerPing ping;
public BungeeEventWrapper(BungeeCordCore plugin, ProxyPingEvent event){
this.plugin = plugin;
this.event = event;
this.protocol = event.getResponse().getVersion();
this.ping = event.getResponse();
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.getPlayers().setMax(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
}
@Override
public void hidePlayers(){
ping.setPlayers(null);
}
@Override
public void setPlayerCount(String name){
protocol.setName(name);
protocol.setProtocol(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<ProxiedPlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ServerPing.PlayerInfo[] playerInfos = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.PlayerInfo[0]);
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
}
@Override
public void setFavicon(Favicon favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFaviconObject());
}
@Override
public void updateEvent(){
this.ping.setVersion(this.protocol);
this.event.setResponse(this.ping);
}
@Override
public boolean isInvalidProtocol(){
return protocol == null;
}
@Override
public int getProtocolVersion(){
return this.protocol.getProtocol();
}
@Override
public int getOnlinePlayers(){
return ping.getPlayers().getOnline();
}
@Override
public int getMaxPlayers(){
return ping.getPlayers().getMax();
}
@Override
public String getPlayerIP(){
return ((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<ProxiedPlayer> player){
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getConnection().getVirtualHost());
}
@Override
public PluginCore<Favicon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<ProxiedPlayer> createPlayer(String name, int protocol){
return new BungeePlayer(name, protocol);
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
}
@@ -26,25 +26,12 @@
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.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.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.net.InetSocketAddress;
public class PingEvent implements Listener{
private final BungeeCordCore plugin;
@@ -56,101 +43,6 @@ public class PingEvent implements Listener{
@EventHandler(priority = EventPriority.LOW)
public void onProxyPing(ProxyPingEvent event){
ServerPing ping = event.getResponse();
ServerPing.Protocol protocol = ping.getVersion();
if(protocol == null)
return;
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(
((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString()
);
InetSocketAddress host = event.getConnection().getVirtualHost();
int online = ping.getPlayers().getOnline();
int max = ping.getPlayers().getMax();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new BungeePlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.getXMore() >= 0){
max = online + profile.getXMore();
ping.getPlayers().setMax(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
TextComponent component = new TextComponent(BungeeComponentSerializer.get().serialize(
ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
));
ping.setDescriptionComponent(component);
}
if(profile.shouldHidePlayers()){
ping.setPlayers(null);
ping.setFavicon(ping.getFaviconObject());
ping.setVersion(protocol);
event.setResponse(ping);
return;
}
if(!profile.getPlayerCount().isEmpty()){
protocol.setName(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
);
protocol.setProtocol(-1);
}
if(!profile.getPlayers().isEmpty()){
String players = ComponentParser.list(profile.getPlayers())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString();
ServerPing.PlayerInfo[] playerInfos = AdvancedServerList.getPlayers(ServerPing.PlayerInfo.class, players)
.toArray(new ServerPing.PlayerInfo[0]);
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFaviconObject());
}else{
ping.setFavicon(favicon);
}
}
ping.setVersion(protocol);
event.setResponse(ping);
PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
}
}
@@ -52,4 +52,9 @@ public class BungeeLogger implements PluginLogger{
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
}
}
+41 -5
View File
@@ -43,6 +43,13 @@
<maven.compiler.target>16</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>flexver-repo</id>
<url>https://repo.sleeping.town/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spongepowered</groupId>
@@ -52,24 +59,47 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.11.0</version>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.1</version>
<version>3.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>com.unascribed</groupId>
<artifactId>flexver-java</artifactId>
<version>1.0.2</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -89,7 +119,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
@@ -101,6 +131,12 @@
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.unascribed</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
@@ -25,29 +25,29 @@
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.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.*;
import java.util.Properties;
public class AdvancedServerList{
private final PluginCore plugin;
private final PluginCore<?> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private UpdateChecker updateChecker;
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,41 +56,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 void clearFaviconCache(){
plugin.clearFaviconCache();
}
public PluginLogger getPluginLogger(){
return plugin.getPluginLogger();
}
public Path getPath(){
return plugin.getPath();
public PluginCore<?> getPlugin(){
return plugin;
}
public FileHandler getFileHandler(){
@@ -109,58 +76,77 @@ public class AdvancedServerList{
return version;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving cache.data file...");
getPlayerHandler().save();
if(updateChecker != null){
getPlugin().getPluginLogger().info("Disabling Update Checker...");
updateChecker.disable();
}
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
}
public void clearFaviconCache(){
plugin.clearFaviconCache();
}
private void load(){
printBanner();
resolveVersion();
getPluginLogger().info("Starting AdvancedServerList v%s...", version);
getPluginLogger().info("Platform: " + 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;
}
if(!getPath().resolve("favicons").toFile().exists() && getPath().resolve("favicons").toFile().mkdirs())
getPluginLogger().info("Successfully created favicons folder.");
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 bStats metrics. Disable it in the global config under /plugins/bstats/");
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
plugin.loadMetrics();
getPluginLogger().info("Metrics loaded!");
getPlugin().getPluginLogger().info("Metrics loaded!");
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
getPluginLogger().info("AdvancedServerList is ready!");
if(getFileHandler().getBoolean("check_updates"))
this.updateChecker = new UpdateChecker(this);
}
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(){
@@ -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.core.check;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ThreadFactory;
public class UpdateCheckThread implements ThreadFactory{
@Override
public Thread newThread(@NotNull Runnable r){
return new Thread(r, "AdvancedServerList Update-Thread");
}
}
@@ -0,0 +1,223 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.check;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.unascribed.flexver.FlexVerComparator;
import io.leangen.geantyref.TypeToken;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class UpdateChecker{
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=[\"%s\"]";
private final OkHttpClient client = new OkHttpClient();
private final AdvancedServerList core;
private final PluginLogger logger;
private final String loader;
private final Type listType = new TypeToken<ArrayList<ModrinthVersion>>(){}.getType();
private final Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setPrettyPrinting()
.setLenient()
.create();
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
public UpdateChecker(AdvancedServerList core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.loader = core.getPlugin().getLoader();
startUpdateChecker();
}
public void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Checking for a new update...");
checkUpdate().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. See previous messages for reasons.");
return;
}
int result = version.compare(core.getVersion());
switch(result){
case -1 -> printUpdateBanner(version.getVersionNumber(), version.getId(), version.isRelease());
case 0 -> logger.info("No new update found. You're running the latest version!");
case 1 -> logger.info(
"Your version (%s) is higher than the latest release (%s). Are you running a dev build?",
core.getVersion(), version.getVersionNumber()
);
}
});
}, 0L, 12L, TimeUnit.HOURS);
}
public void disable(){
executor.shutdown();
client.dispatcher().executorService().shutdown();
try{
if(!executor.awaitTermination(1, TimeUnit.SECONDS)){
executor.shutdownNow();
if(!executor.awaitTermination(1, TimeUnit.SECONDS))
logger.warn("Scheduler didn't terminate in time!");
}
if(!client.dispatcher().executorService().awaitTermination(1, TimeUnit.SECONDS)){
client.dispatcher().executorService().shutdownNow();
if(!client.dispatcher().executorService().awaitTermination(1, TimeUnit.SECONDS))
logger.warn("OkHttp's Scheduler didn't terminate in time!");
}
}catch(InterruptedException ex){
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
private CompletableFuture<ModrinthVersion> checkUpdate(){
return CompletableFuture.supplyAsync(() -> {
PluginLogger logger = core.getPlugin().getPluginLogger();
if(core.getVersion().equals("UNKNOWN")){
logger.warn("Cannot perform Update check! Plugin version couldn't be parsed.");
return null;
}
Request request = new Request.Builder()
.url(String.format(url, loader))
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
.build();
try(Response response = client.newCall(request).execute()){
if(!response.isSuccessful()){
logger.warn("Encountered a non-successful response from Modrinth! Code: %d", response.code());
return null;
}
ResponseBody body = response.body();
if(body == null){
logger.warn("Received an empty Response body from Modrinth!");
return null;
}
String responseString = body.string();
if(responseString.isEmpty()){
logger.warn("Received an empty Response body from Modrinth!");
return null;
}
List<ModrinthVersion> list = gson.fromJson(responseString, listType);
if(list == null || list.isEmpty()){
logger.warn("Couldn't convert JSON Array into a valid list.");
return null;
}
ModrinthVersion version = list.get(0);
if(version.getVersionNumber() == null || version.getVersionNumber().isEmpty()){
logger.warn("Cannot check latest version. Received version number was null/empty.");
return null;
}
return version;
}catch(JsonSyntaxException ex){
logger.warn("Encountered invalid JSON from Response body!", ex);
return null;
}catch(IOException ex){
logger.warn("Encountered Exception while checking for an update!", ex);
return null;
}
});
}
private void printUpdateBanner(String version, String versionId, boolean isRelease){
logger.info("==================================================================");
logger.info("You are running an outdated version of AdvancedServerList!");
logger.info("");
logger.info("Your version: %s", core.getVersion());
logger.info("Modrinth version: %s", version);
logger.info("");
if(!isRelease){
logger.info("WARNING: This release is an Alpha/Beta! It may contain");
logger.info(" breaking changes!");
logger.info("");
}
logger.info("You can download the latest release from here:");
logger.info("https://modrinth.com/plugin/advancedserverlist/version/%s", versionId);
logger.info("==================================================================");
}
public static class ModrinthVersion{
@SuppressWarnings("FieldMayBeFinal")
private String id;
@SuppressWarnings("FieldMayBeFinal")
private String versionNumber;
@SuppressWarnings("FieldMayBeFinal")
private String versionType;
public ModrinthVersion(String id, String versionNumber, String versionType){
this.id = id;
this.versionNumber = versionNumber;
this.versionType = versionType;
}
public String getId(){
return id;
}
public String getVersionNumber(){
return versionNumber;
}
public boolean isRelease(){
return versionType.equals("release");
}
public int compare(String version){
return FlexVerComparator.compare(version, versionNumber);
}
}
}
@@ -62,7 +62,7 @@ public class CommandHandler{
}
if(core.getFileHandler().reloadProfiles()){
sender.sendMsg("%s <green>Loaded <grey>%s Profile(s)</grey>!", prefix, core.getFileHandler().getProfiles());
sender.sendMsg("%s <green>Loaded <grey>%d Profile(s)</grey>!", prefix, core.getFileHandler().getProfiles().size());
}else{
sender.sendMsg("%s <red>Cannot load Profiles!", errorPrefix);
}
@@ -0,0 +1,127 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.events;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
public class PingEventHandler{
public static <P, F> void handleEvent(GenericEventWrapper<P, F> event){
if(event.isInvalidProtocol())
return;
PluginCore<F> plugin = event.getPlugin();
GenericPlayer<P> player = event.createPlayer(
plugin.getCore().getPlayerHandler().getPlayerByIp(event.getPlayerIP()),
event.getProtocolVersion()
);
String host = event.getVirtualHost();
int online = event.getOnlinePlayers();
int max = event.getMaxPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host);
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
ProfileEntry entry = ProfileManager.merge(profile);
if(entry.isExtraPlayersEnabled().getValue(false)){
max = online + (entry.getExtraPlayersCount() == null ? 0 : entry.getExtraPlayersCount());
event.setMaxPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host);
if(!entry.getMOTD().isEmpty()){
event.setMotd(
ComponentParser.list(entry.getMOTD())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toComponent()
);
}
boolean hidePlayers = entry.isHidePlayersEnabled().getValue(false);
if(hidePlayers){
event.hidePlayers();
}
if(!entry.getPlayerCountText().isEmpty() && !hidePlayers){
event.setPlayerCount(
ComponentParser.text(entry.getPlayerCountText())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString()
);
}
if(!entry.getPlayers().isEmpty() && !hidePlayers){
event.setPlayers(entry.getPlayers(), player, playerPlaceholders, serverPlaceholders);
}
if(!entry.getFavicon().isEmpty()){
String favicon = StringReplacer.replace(entry.getFavicon(), playerPlaceholders.getReplacements());
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
try{
return event.createFavicon(image);
}catch(Exception ex){
plugin.getPluginLogger().warn("Encountered an Exception while creating Favicon!", ex);
return null;
}
});
if(fav == null){
event.setDefaultFavicon();
}else{
event.setFavicon(fav);
}
}
event.updateEvent();
}
}
@@ -27,7 +27,9 @@ package ch.andre601.advancedserverlist.core.file;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
@@ -52,12 +54,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(){
@@ -106,6 +108,7 @@ public class FileHandler{
return false;
}
}
return reloadProfiles();
}
@@ -127,7 +130,7 @@ public class FileHandler{
if(tmp == null)
continue;
profiles.add(new ServerListProfile(tmp, logger));
profiles.add(ServerListProfile.Builder.resolve(file.getName(), tmp, logger).build());
logger.info("Loaded " + file.getName());
}
@@ -142,6 +145,7 @@ public class FileHandler{
public ConfigurationNode getConfigurationNode(Path path){
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.defaultOptions(opts -> opts.serializers(build -> build.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.path(path)
.build();
@@ -156,4 +160,8 @@ public class FileHandler{
public String getString(String def, Object... path){
return node.node(path).getString(def);
}
public boolean getBoolean(Object... path){
return node.node(path).getBoolean();
}
}
@@ -32,4 +32,6 @@ public interface PluginLogger{
void warn(String msg, Object... args);
void warn(String msg, Throwable throwable);
void warn(String msg, Throwable throwable, Object... args);
}
@@ -23,14 +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<T>{
public interface PluginCore<F>{
void loadCommands();
@@ -42,13 +43,15 @@ public interface PluginCore<T>{
AdvancedServerList getCore();
Path getPath();
Path getFolderPath();
PluginLogger getPluginLogger();
FaviconHandler<T> getFaviconHandler();
FaviconHandler<F> getFaviconHandler();
String getPlatformName();
String getPlatformVersion();
String getLoader();
}
@@ -23,42 +23,12 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles;
package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
public class ProfileManager{
private final AdvancedServerList core;
private final Map<String, Object> replacements = new HashMap<>();
private ProfileManager(AdvancedServerList core){
this.core = core;
}
public static ProfileManager get(AdvancedServerList core){
return new ProfileManager(core);
}
public ProfileManager replacements(Placeholders placeholders){
this.replacements.putAll(placeholders.getReplacements());
return this;
}
public ServerListProfile getProfile(){
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
if(profile.getMotd().isEmpty() && profile.getPlayers().isEmpty() && profile.getPlayerCount().isEmpty())
continue;
if(profile.evalConditions(replacements))
return profile;
}
return null;
}
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);
}
@@ -0,0 +1,79 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.events;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
public interface GenericEventWrapper<P, F>{
void setMaxPlayers(int maxPlayers);
void setMotd(Component component);
void hidePlayers();
void setPlayerCount(String name);
void setPlayers(List<String> players, GenericPlayer<P> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders);
void setFavicon(F favicon);
void setDefaultFavicon();
void updateEvent();
boolean isInvalidProtocol();
int getProtocolVersion();
int getOnlinePlayers();
int getMaxPlayers();
String getPlayerIP();
String parsePAPIPlaceholders(String text, GenericPlayer<P> player);
String getVirtualHost();
PluginCore<F> getPlugin();
GenericPlayer<P> createPlayer(String name, int protocol);
F createFavicon(BufferedImage image) throws Exception;
default String resolveHost(InetSocketAddress address){
return address == null ? null : address.getHostString();
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer;
package ch.andre601.advancedserverlist.core.objects;
import java.util.AbstractMap;
import java.util.ArrayList;
@@ -0,0 +1,53 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.objects;
/*
* A simple class to allow having a nullable boolean without having to deal with possible NPEs
* when trying to get Boolean.getValue() while it is null...
*
* Here, it simply checks if the value is null and if it is, returns a default. Otherwise it gives
* the value.
*/
public class NullBool{
public static final NullBool FALSE = new NullBool(false);
public static final NullBool NULL = new NullBool(null);
private final Boolean value;
public NullBool(Boolean value){
this.value = value;
}
public boolean isNull(){
return value == null;
}
public boolean getValue(boolean def){
return isNull() ? def : value;
}
}
@@ -27,112 +27,162 @@ package ch.andre601.advancedserverlist.core.profiles;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.conditions.Expression;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileEntry;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class ServerListProfile{
private final int priority;
private final List<Expression> expressions;
private final ProfileEntry defaultProfile;
private final List<String> motd;
private final List<String> players;
private final String playerCount;
private final String favicon;
private final boolean hidePlayers;
private final int xMore;
private final List<ProfileEntry> profiles;
public ServerListProfile(ConfigurationNode node, PluginLogger logger){
this.priority = node.node("priority").getInt();
this.expressions = createExpressions(getList(node, "conditions", false), logger);
this.motd = getList(node, "motd", true);
this.players = getList(node, "players", false);
this.playerCount = node.node("playerCount").getString("");
this.favicon = node.node("favicon").getString("");
this.hidePlayers = node.node("hidePlayers").getBoolean();
this.xMore = node.node("xMore").getInt(-1);
private final Random random = new Random();
public ServerListProfile(int priority, List<Expression> expressions, List<ProfileEntry> profiles, ProfileEntry defaultProfile){
this.priority = priority;
this.expressions = expressions;
this.profiles = profiles;
this.defaultProfile = defaultProfile;
}
public int getPriority(){
return priority;
}
public List<String> getMotd(){
return motd;
}
public List<String> getPlayers(){
return players;
}
public String getPlayerCount(){
return playerCount;
}
public String getFavicon(){
return favicon;
}
public boolean shouldHidePlayers(){
return hidePlayers;
}
public int getXMore(){
return xMore;
}
public boolean evalConditions(Map<String, Object> replacements){
public boolean evaluateConditions(Map<String, Object> replacements){
if(expressions.isEmpty())
return true;
for(Expression expression : expressions){
if(!expression.evaluate(replacements)){
if(!expression.evaluate(replacements))
return false;
}
}
return true;
}
private List<Expression> createExpressions(List<String> list, PluginLogger logger) {
if(list.isEmpty())
return Collections.emptyList();
List<Expression> expressions = new ArrayList<>();
for(String str : list){
Expression expression = new Expression(str);
if(expression.getResult() != Expression.ExpressionResult.VALID){
logger.warn("Detected Invalid condition '%s'! Cause: %s", str, expression.getResult().getMessage());
continue;
}
expressions.add(expression);
public ProfileEntry getRandomProfile(){
if(profiles.isEmpty()){
return null;
}
return expressions;
if(profiles.size() == 1)
return profiles.get(0); // No need to run a random for 1 profile.
synchronized(random){
return profiles.get(random.nextInt(profiles.size()));
}
}
private List<String> getList(ConfigurationNode node, String key, boolean trim){
List<String> list;
try{
list = node.node(key).getList(String.class);
}catch(SerializationException ex){
return Collections.emptyList();
public ProfileEntry getDefaultProfile(){
return defaultProfile;
}
/*
* Returns true if the Profile...
* ...doesn't have any valid MOTD set AND
* ...doesn't have any player hover set AND
* ...doesn't have a player count text set and hidePlayers is false AND
* ...doesn't have a favicon set.
*/
public boolean isInvalidProfile(){
if(profiles.isEmpty())
return defaultProfile.isInvalidProfile();
boolean profilesValid = false;
for(ProfileEntry profile : profiles){
if(profile.isInvalidProfile())
continue;
profilesValid = true;
break;
}
return !profilesValid && defaultProfile.isInvalidProfile();
}
public static class Builder{
private final String fileName;
private final ConfigurationNode node;
private final int priority;
private final List<Expression> expressions = new ArrayList<>();
private final PluginLogger logger;
private List<ProfileEntry> profiles = new ArrayList<>();
private ProfileEntry defaultProfile = ProfileEntry.empty();
private Builder(String fileName, ConfigurationNode node, PluginLogger logger){
this.fileName = fileName;
this.node = node;
this.priority = node.node("priority").getInt();
this.logger = logger;
}
if(list == null)
return Collections.emptyList();
public static Builder resolve(String fileName, ConfigurationNode node, PluginLogger logger){
return new Builder(fileName, node, logger)
.resolveExpressions()
.resolveProfiles()
.resolveDefaultProfile();
}
if(trim && list.size() > 2)
return list.subList(0, 2);
private Builder resolveExpressions(){
List<String> temp;
try{
temp = node.node("conditions").getList(String.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving conditions for %s", ex, fileName);
return this;
}
if(temp == null || temp.isEmpty())
return this;
for(String str : temp){
Expression expr = new Expression(str);
if(expr.getResult() != Expression.ExpressionResult.VALID){
logger.warn("Found invalid expression in condition '%s'! Reason: %s", str, expr.getResult().getMessage());
continue;
}
this.expressions.add(expr);
}
return this;
}
return list;
private Builder resolveProfiles(){
try{
this.profiles = node.node("profiles").getList(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the profiles entry for %s", ex, fileName);
}
return this;
}
private Builder resolveDefaultProfile(){
try{
this.defaultProfile = node.get(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the global profile for %s", ex, fileName);
}
return this;
}
public ServerListProfile build(){
return new ServerListProfile(this.priority, this.expressions, this.profiles, this.defaultProfile);
}
}
}
@@ -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()){
@@ -193,9 +192,8 @@ public class Expression{
public enum ExpressionResult{
VALID(null),
INVALID_NO_EXPRESSION ("Received empty condition which isn't allowed!"),
INVALID_DOUBLE_OPERATOR("Condition contained two operands."),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
INVALID_NO_EXPRESSION("Received empty condition which isn't allowed!"),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
private final String message;
@@ -42,9 +42,9 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class FaviconHandler<T>{
public class FaviconHandler<F>{
private final Cache<String, T> favicons = Caffeine.newBuilder()
private final Cache<String, F> favicons = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
@@ -54,7 +54,7 @@ public class FaviconHandler<T>{
this.core = core;
}
public T getFavicon(String input, Function<BufferedImage, T> function){
public F getFavicon(String input, Function<BufferedImage, F> function){
return favicons.get(input, k -> {
BufferedImage image = resolveImage(core, input);
if(image == null)
@@ -75,9 +75,9 @@ public class FaviconHandler<T>{
stream = getFromUrl(core, input);
}else
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
File folder = core.getPath().resolve("favicons").toFile();
File folder = core.getPlugin().getFolderPath().resolve("favicons").toFile();
if(!folder.exists()){
core.getPluginLogger().warn("Cannot get Favicon %s from favicons folder. Folder doesn't exist!", input);
core.getPlugin().getPluginLogger().warn("Cannot get Favicon %s from favicons folder. Folder doesn't exist!", input);
return null;
}
@@ -86,8 +86,8 @@ public class FaviconHandler<T>{
try{
stream = new FileInputStream(file);
}catch(IOException ex){
core.getPluginLogger().warn("Cannot create Favicon from File %s.", input);
core.getPluginLogger().warn("Cause: %s", ex.getMessage());
core.getPlugin().getPluginLogger().warn("Cannot create Favicon from File %s.", input);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}else{
@@ -95,14 +95,14 @@ public class FaviconHandler<T>{
}
if(stream == null){
core.getPluginLogger().warn("Cannot create Favicon. InputStream was null.");
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. InputStream was null.");
return null;
}
try{
BufferedImage original = ImageIO.read(stream);
if(original == null){
core.getPluginLogger().warn("Cannot create Favicon. Unable to create BufferedImage.");
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. Unable to create BufferedImage.");
return null;
}
@@ -115,8 +115,8 @@ public class FaviconHandler<T>{
return favicon;
}catch(IOException ex){
core.getPluginLogger().warn("Unable to create Favicon. Encountered IOException during creation.");
core.getPluginLogger().warn("Cause: %s", ex.getMessage());
core.getPlugin().getPluginLogger().warn("Unable to create Favicon. Encountered IOException during creation.");
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}
@@ -130,8 +130,8 @@ public class FaviconHandler<T>{
return connection.getInputStream();
}catch(IOException ex){
core.getPluginLogger().warn("Error while connecting to %s for Favicon creation.", url);
core.getPluginLogger().warn("Cause: %s", ex.getMessage());
core.getPlugin().getPluginLogger().warn("Error while connecting to %s for Favicon creation.", url);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
}
@@ -26,14 +26,13 @@
package ch.andre601.advancedserverlist.core.profiles.players;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.replacer.EntryList;
import ch.andre601.advancedserverlist.core.objects.EntryList;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
@@ -46,24 +45,30 @@ 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;
}
if(core.getFileHandler().getBoolean("disable_cache")){
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player loading...");
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;
}
@@ -78,12 +83,17 @@ 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;
}
if(core.getFileHandler().getBoolean("disable_cache")){
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player saving...");
return;
}
@@ -93,25 +103,28 @@ public class PlayerHandler{
}
try{
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8, StandardOpenOption.WRITE);
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8);
writer.write(joiner.toString());
writer.close();
core.getPluginLogger().info("Successfully saved cache.data file.");
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);
}
}
public void addPlayer(String name, String ip){
if(players.containsKey(name))
if(players.containsKey(name) || core.getFileHandler().getBoolean("disable_cache"))
return;
players.add(name, ip);
}
public String getPlayerByIp(String ip){
if(core.getFileHandler().getBoolean("disable_cache"))
core.getFileHandler().getString("Anonymous", "unknown_player");
for(Map.Entry<String, String> entry : players){
if(entry.getValue().equals(ip))
return entry.getKey();
@@ -0,0 +1,194 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.profile;
import ch.andre601.advancedserverlist.core.objects.NullBool;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ProfileEntry{
private final List<String> motd;
private final List<String> players;
private final String playerCountText;
private final String favicon;
private final NullBool hidePlayersEnabled;
private final NullBool extraPlayersEnabled;
private final Integer extraPlayersCount;
public ProfileEntry(List<String> motd, List<String> players,
String playerCountText, String favicon, NullBool hidePlayersEnabled,
NullBool extraPlayersEnabled, Integer extraPlayersCount){
this.motd = motd;
this.players = players;
this.playerCountText = playerCountText;
this.favicon = favicon;
this.hidePlayersEnabled = hidePlayersEnabled;
this.extraPlayersEnabled = extraPlayersEnabled;
this.extraPlayersCount = extraPlayersCount;
}
public static ProfileEntry empty(){
return new ProfileEntry(Collections.emptyList(), Collections.emptyList(), "", "",
NullBool.FALSE, NullBool.FALSE, 0);
}
public List<String> getMOTD(){
return motd;
}
public List<String> getPlayers(){
return players;
}
public String getPlayerCountText(){
return playerCountText;
}
public String getFavicon(){
return favicon;
}
public NullBool isHidePlayersEnabled(){
return hidePlayersEnabled;
}
public NullBool isExtraPlayersEnabled(){
return extraPlayersEnabled;
}
public Integer getExtraPlayersCount(){
return extraPlayersCount;
}
public boolean isInvalidProfile(){
return getMOTD().isEmpty() &&
getPlayers().isEmpty() &&
(getPlayerCountText().isEmpty() && !isHidePlayersEnabled().getValue(false)) &&
getFavicon().isEmpty();
}
public static class Builder{
private final ConfigurationNode node;
private List<String> motd = new ArrayList<>();
private List<String> players = new ArrayList<>();
private String playerCountText = null;
private String favicon = null;
private NullBool hidePlayersEnabled = NullBool.FALSE;
private NullBool extraPlayersEnabled = NullBool.FALSE;
private Integer extraPlayersCount = 0;
private Builder(ConfigurationNode node){
this.node = node;
}
public static Builder resolve(ConfigurationNode node){
return new Builder(node)
.resolveMOTD()
.resolvePlayers()
.resolvePlayerCountText()
.resolveFavicon()
.resolveHidePlayersEnabled()
.resolveExtraPlayersEnabled()
.resolveExtraPlayersCount();
}
public Builder resolveMOTD(){
List<String> motd = resolveList(node, "motd");
if(motd.size() <= 2){
this.motd = motd;
return this;
}
this.motd = motd.subList(0, 2);
return this;
}
public Builder resolvePlayers(){
this.players = this.resolveList(node, "playerCount", "hover");
return this;
}
public Builder resolvePlayerCountText(){
this.playerCountText = node.node("playerCount", "text").getString("");
return this;
}
public Builder resolveFavicon(){
this.favicon = node.node("favicon").getString("");
return this;
}
public Builder resolveHidePlayersEnabled(){
if(node.node("playerCount", "hidePlayers").virtual()){
this.hidePlayersEnabled = NullBool.NULL;
return this;
}
this.hidePlayersEnabled = new NullBool(node.node("playerCount", "hidePlayers").getBoolean());
return this;
}
public Builder resolveExtraPlayersEnabled(){
if(node.node("playerCount", "extraPlayers", "enabled").virtual()){
this.extraPlayersEnabled = NullBool.NULL;
return this;
}
this.extraPlayersEnabled = new NullBool(node.node("playerCount", "extraPlayers", "enabled").getBoolean());
return this;
}
public Builder resolveExtraPlayersCount(){
if(node.node("playerCount", "extraPlayers", "amount").virtual()){
this.extraPlayersCount = null;
return this;
}
this.extraPlayersCount = node.node("playerCount", "extraPlayers", "amount").getInt();
return this;
}
public ProfileEntry build(){
return new ProfileEntry(this.motd, this.players, this.playerCountText,
this.favicon, this.hidePlayersEnabled, this.extraPlayersEnabled, this.extraPlayersCount);
}
private List<String> resolveList(ConfigurationNode node, Object... path){
try{
return node.node(path).getList(String.class);
}catch(SerializationException ex){
return Collections.emptyList();
}
}
}
}
@@ -0,0 +1,137 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.profile;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.objects.NullBool;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ProfileManager{
private final AdvancedServerList core;
private final Map<String, Object> replacements = new HashMap<>();
private ProfileManager(AdvancedServerList core){
this.core = core;
}
public static ProfileManager get(AdvancedServerList core){
return new ProfileManager(core);
}
public ProfileManager replacements(Placeholders placeholders){
this.replacements.putAll(placeholders.getReplacements());
return this;
}
public ServerListProfile getProfile(){
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
if(profile.isInvalidProfile())
continue;
if(profile.evaluateConditions(replacements))
return profile;
}
return null;
}
/*
* Convenience method to get a ProfileEntry instance with values merged.
* If the random profile's value is not null will it be used instead of the default one.
*/
public static ProfileEntry merge(ServerListProfile profile){
ProfileEntry entry = profile.getRandomProfile();
ProfileEntry defEntry = profile.getDefaultProfile();
List<String> motd = resolveMOTD(entry, defEntry);
List<String> players = resolvePlayers(entry, defEntry);
String playerCountText = resolvePlayerCountText(entry, defEntry);
String favicon = resolveFavicon(entry, defEntry);
boolean isHidePlayersEnabled = resolveHidePlayersEnabled(entry, defEntry);
boolean isExtraPlayersEnabled = resolveExtraPlayersEnabled(entry, defEntry);
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
return new ProfileEntry(motd, players, playerCountText, favicon,
new NullBool(isHidePlayersEnabled), new NullBool(isExtraPlayersEnabled), extraPlayersCount);
}
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.getMOTD().isEmpty())
return defaultProfile.getMOTD();
return profile.getMOTD();
}
private static List<String> resolvePlayers(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.getPlayers().isEmpty())
return defaultProfile.getPlayers();
return profile.getPlayers();
}
private static String resolvePlayerCountText(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.getPlayerCountText().isEmpty())
return defaultProfile.getPlayerCountText();
return profile.getPlayerCountText();
}
private static String resolveFavicon(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.getFavicon().isEmpty())
return defaultProfile.getFavicon();
return profile.getFavicon();
}
private static boolean resolveHidePlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.isHidePlayersEnabled().isNull())
return defaultProfile.isHidePlayersEnabled().getValue(false);
return profile.isHidePlayersEnabled().getValue(false);
}
private static boolean resolveExtraPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.isExtraPlayersEnabled().isNull())
return defaultProfile.isExtraPlayersEnabled().getValue(false);
return profile.isExtraPlayersEnabled().getValue(false);
}
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.getExtraPlayersCount() == null)
return defaultProfile.getExtraPlayersCount() == null ? 0 : defaultProfile.getExtraPlayersCount();
return profile.getExtraPlayersCount();
}
}
@@ -0,0 +1,58 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.profile;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
public static final ProfileSerializer INSTANCE = new ProfileSerializer();
@Override
public ProfileEntry deserialize(Type type, ConfigurationNode node){
return ProfileEntry.Builder.resolve(node).build();
}
@Override
public void serialize(Type type, @Nullable ProfileEntry profile, ConfigurationNode node) throws SerializationException{
if(profile == null){
node.raw(null);
return;
}
node.node("motd").set(profile.getMOTD());
node.node("playerCount", "hover").set(profile.getPlayers());
node.node("playerCount", "text").set(profile.getPlayerCountText());
node.node("favicon").set(profile.getFavicon());
node.node("playerCount", "hidePlayers").set(profile.isHidePlayersEnabled());
node.node("playerCount", "extraPlayers", "enabled").set(profile.isExtraPlayersEnabled());
node.node("playerCount", "extraPlayers", "amount").set(profile.getExtraPlayersCount());
}
}
+23 -1
View File
@@ -1,4 +1,26 @@
#
# Used for when AdvancedServerList doesn't have a cached player to use for ${player name}
#
unknown_player: "Anonymous"
# Defaults to 'Anonymous' when not present.
#
unknown_player: "Anonymous"
#
# Should the Caching of players be disabled?
#
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
# Placeholders that rely on the player being cached (such as ${player isWhitelisted}) will not work while this option is enabled.
#
# Defaults to false when not present.
#
disable_cache: false
#
# Should AdvancedServerList check for new versions?
#
# When set to true will AdvancedServerList check for a new version on modrinth.com every 12 hours and inform you in the
# console about whether it found any new update or not.
#
# Defaults to false when not present.
#
check_updates: true
+102 -52
View File
@@ -16,74 +16,124 @@ priority: 0
# - '{playerVersion} < 759'
#
# Set the MOTD that should be displayed.
# Option that allows you to define multiple profiles to use.
# Each entry supports the same options as the server list profile does. Whenever an option is not present, or set to
# an empty value (If supported) would the option in the file be used (if present).
# This allows you to f.e. randomize the MOTD while keeping other options the same, without copy-pasting the same options.
#
# A profile will be selected randomly.
#
# Remove this option or set it to profiles: [] to use the global options of this file.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#profiles
#
#profiles:
# - motd:
# - '<aqua>Line 1'
# - '<aqua>Line 2'
# favicon: ''
# playerCount:
# hidePlayers: false
# hover:
# - '<green>Line 1'
# - '<green>Line 2'
# - '<green>Line 3'
# text: ''
# extraPlayers:
# enabled: false
# amount: 0
#
# Set the default (Global) MOTD used by this server list profile.
# Supports HEX colors for 1.16+ servers including gradients using MiniMessage's <gradient:color:color> format.
#
# Remove this option or set it to motd: [] to not alter the MOTD.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motd
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motds
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
#
# 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 global (Default) favicon for this server list profile.
# You can use one of three possible options:
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
# 2. A URL pointing to a valid Image
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
#
hidePlayers: false
#
# 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.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#playercount
#
playerCount: '<grey>Text'
#
# Allows you to override the default Favicon used by the Server/Proxy.
# You can provide three specific inputs:
# - A valid URL pointing to a PNG file.
# - ${player name} for a per-player avatar being displayed (Uses mc-heads.net)
# - Image file name (i.e. example.png) for a file in the "favicons" folder.
#
# NOTE:
# - The favicon will be cached for 5 minutes to avoid spam and rate limits.
# - BungeeCord/Waterfall may report issues that the plugin takes a long time to process.
# This is something I cannot really get improved without help.
# Remove this option or set to favicon: '' to not replace the Favicon.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#favicon
#
favicon: ''
#
# When set to 0 or higher will alter the max player count to the online count + xMore.
# Example: With 20 online players would 'xMore: 1' show 20/21 and 'xMore: 0' show 20/20
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
#
# Note that this will also manipulate the ${server playersMax} placeholder when used
# in motd, players or playerCount.
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#playercount
#
# Remove this option or set it to -1 to not alter the max player count.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#xmore
#
xMore: -1
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
#
# Read more: https://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.
#
# Remove this option or set it to text: '' to not modify the player count text.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#text
#
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
@@ -0,0 +1,292 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.test;
import com.unascribed.flexver.FlexVerComparator;
import org.junit.Test;
public class FlexVerTests{
private final String baseVersion = "1.0.0";
private final String versionMinor = "1.0.1";
private final String versionMajor = "1.1.0";
private final String versionBoth = "1.1.1";
private final String versionBeta = "1.0.0-b1";
private final String versionBetaMinor = "1.0.1-b1";
private final String versionBetaMajor = "1.1.0-b1";
private final String versionBetaBoth = "1.1.1-b1";
private final String versionBeta2 = "1.0.0-b2";
private final String versionBeta2Minor = "1.0.1-b2";
private final String versionBeta2Major = "1.1.0-b2";
private final String versionBeta2Both = "1.1.1-b2";
@Test
public void testFlexVerChecks(){
System.out.println("START: Version comparison Tests");
compareBaseVersion();
compareMinorVersion();
compareMajorVersion();
compareBothVersion();
compareBetaVersion();
compareBetaMinorVersion();
compareBetaMajorVersion();
compareBetaBothVersion();
compareBeta2Version();
compareBeta2MinorVersion();
compareBeta2MajorVersion();
compareBeta2BothVersion();
System.out.println("END: Version comparison Tests");
}
private void compareBaseVersion(){
System.out.println("┌────────────────────────────────┐");
System.out.println("│ Normal Version │");
System.out.println("│ │");
compare(baseVersion, "=", baseVersion, 0);
compare(baseVersion, "<", versionMinor, -1);
compare(baseVersion, "<", versionMajor, -1);
compare(baseVersion, "<", versionBoth, -1);
compare(baseVersion, ">", versionBeta, 1);
compare(baseVersion, "<", versionBetaMinor, -1);
compare(baseVersion, "<", versionBetaMajor, -1);
compare(baseVersion, "<", versionBetaBoth, -1);
compare(baseVersion, ">", versionBeta2, 1);
compare(baseVersion, "<", versionBeta2Minor, -1);
compare(baseVersion, "<", versionBeta2Major, -1);
compare(baseVersion, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareMinorVersion(){
System.out.println("│ Minor Version │");
System.out.println("│ │");
compare(versionMinor, ">", baseVersion, 1);
compare(versionMinor, "=", versionMinor, 0);
compare(versionMinor, "<", versionMajor, -1);
compare(versionMinor, "<", versionBoth, -1);
compare(versionMinor, ">", versionBeta, 1);
compare(versionMinor, ">", versionBetaMinor, 1);
compare(versionMinor, "<", versionBetaMajor, -1);
compare(versionMinor, "<", versionBetaBoth, -1);
compare(versionMinor, ">", versionBeta2, 1);
compare(versionMinor, ">", versionBeta2Minor, 1);
compare(versionMinor, "<", versionBeta2Major, -1);
compare(versionMinor, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareMajorVersion(){
System.out.println("│ Major Version │");
System.out.println("│ │");
compare(versionMajor, ">", baseVersion, 1);
compare(versionMajor, ">", versionMinor, 1);
compare(versionMajor, "=", versionMajor, 0);
compare(versionMajor, "<", versionBoth, -1);
compare(versionMajor, ">", versionBeta, 1);
compare(versionMajor, ">", versionBetaMinor, 1);
compare(versionMajor, ">", versionBetaMajor, 1);
compare(versionMajor, "<", versionBetaBoth, -1);
compare(versionMajor, ">", versionBeta2, 1);
compare(versionMajor, ">", versionBeta2Minor, 1);
compare(versionMajor, ">", versionBeta2Major, 1);
compare(versionMajor, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBothVersion(){
System.out.println("│ Major + Minor Version │");
System.out.println("│ │");
compare(versionBoth, ">", baseVersion, 1);
compare(versionBoth, ">", versionMinor, 1);
compare(versionBoth, ">", versionMajor, 1);
compare(versionBoth, "=", versionBoth, 0);
compare(versionBoth, ">", versionBeta, 1);
compare(versionBoth, ">", versionBetaMinor, 1);
compare(versionBoth, ">", versionBetaMajor, 1);
compare(versionBoth, ">", versionBetaBoth, 1);
compare(versionBoth, ">", versionBeta2, 1);
compare(versionBoth, ">", versionBeta2Minor, 1);
compare(versionBoth, ">", versionBeta2Major, 1);
compare(versionBoth, ">", versionBeta2Both, 1);
System.out.println("├────────────────────────────────┤");
}
private void compareBetaVersion(){
System.out.println("│ Beta Version │");
System.out.println("│ │");
compare(versionBeta, "<", baseVersion, -1);
compare(versionBeta, "<", versionMinor, -1);
compare(versionBeta, "<", versionMajor, -1);
compare(versionBeta, "<", versionBoth, -1);
compare(versionBeta, "=", versionBeta, 0);
compare(versionBeta, "<", versionBetaMinor, -1);
compare(versionBeta, "<", versionBetaMajor, -1);
compare(versionBeta, "<", versionBetaBoth, -1);
compare(versionBeta, "<", versionBeta2, -1);
compare(versionBeta, "<", versionBeta2Minor, -1);
compare(versionBeta, "<", versionBeta2Major, -1);
compare(versionBeta, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBetaMinorVersion(){
System.out.println("│ Beta Version Minor │");
System.out.println("│ │");
compare(versionBetaMinor, ">", baseVersion, 1);
compare(versionBetaMinor, "<", versionMinor, -1);
compare(versionBetaMinor, "<", versionMajor, -1);
compare(versionBetaMinor, "<", versionBoth, -1);
compare(versionBetaMinor, ">", versionBeta, 1);
compare(versionBetaMinor, "=", versionBetaMinor, 0);
compare(versionBetaMinor, "<", versionBetaMajor, -1);
compare(versionBetaMinor, "<", versionBetaBoth, -1);
compare(versionBetaMinor, ">", versionBeta2, 1);
compare(versionBetaMinor, "<", versionBeta2Minor, -1);
compare(versionBetaMinor, "<", versionBeta2Major, -1);
compare(versionBetaMinor, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBetaMajorVersion(){
System.out.println("│ Beta Version Major │");
System.out.println("│ │");
compare(versionBetaMajor, ">", baseVersion, 1);
compare(versionBetaMajor, ">", versionMinor, 1);
compare(versionBetaMajor, "<", versionMajor, -1);
compare(versionBetaMajor, "<", versionBoth, -1);
compare(versionBetaMajor, ">", versionBeta, 1);
compare(versionBetaMajor, ">", versionBetaMinor, 1);
compare(versionBetaMajor, "=", versionBetaMajor, 0);
compare(versionBetaMajor, "<", versionBetaBoth, -1);
compare(versionBetaMajor, ">", versionBeta2, 1);
compare(versionBetaMajor, ">", versionBeta2Minor, 1);
compare(versionBetaMajor, "<", versionBeta2Major, -1);
compare(versionBetaMajor, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBetaBothVersion(){
System.out.println("│ Beta Version Major + Minor │");
System.out.println("│ │");
compare(versionBetaBoth, ">", baseVersion, 1);
compare(versionBetaBoth, ">", versionMinor, 1);
compare(versionBetaBoth, ">", versionMajor, 1);
compare(versionBetaBoth, "<", versionBoth, -1);
compare(versionBetaBoth, ">", versionBeta, 1);
compare(versionBetaBoth, ">", versionBetaMinor, 1);
compare(versionBetaBoth, ">", versionBetaMajor, 1);
compare(versionBetaBoth, "=", versionBetaBoth, 0);
compare(versionBetaBoth, ">", versionBeta2, 1);
compare(versionBetaBoth, ">", versionBeta2Minor, 1);
compare(versionBetaBoth, ">", versionBeta2Major, 1);
compare(versionBetaBoth, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBeta2Version(){
System.out.println("│ Beta Version 2 │");
System.out.println("│ │");
compare(versionBeta2, "<", baseVersion, -1);
compare(versionBeta2, "<", versionMinor, -1);
compare(versionBeta2, "<", versionMajor, -1);
compare(versionBeta2, "<", versionBoth, -1);
compare(versionBeta2, ">", versionBeta, 1);
compare(versionBeta2, "<", versionBetaMinor, -1);
compare(versionBeta2, "<", versionBetaMajor, -1);
compare(versionBeta2, "<", versionBetaBoth, -1);
compare(versionBeta2, "=", versionBeta2, 0);
compare(versionBeta2, "<", versionBeta2Minor, -1);
compare(versionBeta2, "<", versionBeta2Major, -1);
compare(versionBeta2, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBeta2MinorVersion(){
System.out.println("│ Beta Version 2 Minor │");
System.out.println("│ │");
compare(versionBeta2Minor, ">", baseVersion, 1);
compare(versionBeta2Minor, "<", versionMinor, -1);
compare(versionBeta2Minor, "<", versionMajor, -1);
compare(versionBeta2Minor, "<", versionBoth, -1);
compare(versionBeta2Minor, ">", versionBeta, 1);
compare(versionBeta2Minor, ">", versionBetaMinor, 1);
compare(versionBeta2Minor, "<", versionBetaMajor, -1);
compare(versionBeta2Minor, "<", versionBetaBoth, -1);
compare(versionBeta2Minor, ">", versionBeta2, 1);
compare(versionBeta2Minor, "=", versionBeta2Minor, 0);
compare(versionBeta2Minor, "<", versionBeta2Major, -1);
compare(versionBeta2Minor, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBeta2MajorVersion(){
System.out.println("│ Beta Version 2 Major │");
System.out.println("│ │");
compare(versionBeta2Major, ">", baseVersion, 1);
compare(versionBeta2Major, ">", versionMinor, 1);
compare(versionBeta2Major, "<", versionMajor, -1);
compare(versionBeta2Major, "<", versionBoth, -1);
compare(versionBeta2Major, ">", versionBeta, 1);
compare(versionBeta2Major, ">", versionBetaMinor, 1);
compare(versionBeta2Major, ">", versionBetaMajor, 1);
compare(versionBeta2Major, "<", versionBetaBoth, -1);
compare(versionBeta2Major, ">", versionBeta2, 1);
compare(versionBeta2Major, ">", versionBeta2Minor, 1);
compare(versionBeta2Major, "=", versionBeta2Major, 0);
compare(versionBeta2Major, "<", versionBeta2Both, -1);
System.out.println("├────────────────────────────────┤");
}
private void compareBeta2BothVersion(){
System.out.println("│ Beta Version 2 Major + Minor │");
System.out.println("│ │");
compare(versionBeta2Both, ">", baseVersion, 1);
compare(versionBeta2Both, ">", versionMinor, 1);
compare(versionBeta2Both, ">", versionMajor, 1);
compare(versionBeta2Both, "<", versionBoth, -1);
compare(versionBeta2Both, ">", versionBeta, 1);
compare(versionBeta2Both, ">", versionBetaMinor, 1);
compare(versionBeta2Both, ">", versionBetaMajor, 1);
compare(versionBeta2Both, ">", versionBetaBoth, 1);
compare(versionBeta2Both, ">", versionBeta2, 1);
compare(versionBeta2Both, ">", versionBeta2Minor, 1);
compare(versionBeta2Both, ">", versionBeta2Major, 1);
compare(versionBeta2Both, "=", versionBeta2Both, 0);
System.out.println("└────────────────────────────────┘");
}
private void compare(String version1, String comparator, String version2, int expected){
String expression = version1 + " " + comparator + " " + version2 + "?";
System.out.printf("│ %-24s %5b │\n", expression, FlexVerComparator.compare(version1, version2) == expected);
}
}
+1 -1
View File
@@ -101,7 +101,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -26,22 +26,31 @@
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<CachedServerIcon>{
public class PaperCore extends JavaPlugin implements ServerCore<CachedServerIcon, PlayerProfile, OfflinePlayer>{
private final PluginLogger logger = new PaperLogger(getLogger());
@@ -58,18 +67,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
Class.forName("com.destroystokyo.paper.PaperConfig");
enable();
}catch(ClassNotFoundException ex1){
getPluginLogger().warn("======================================== WARNING ========================================");
getPluginLogger().warn("");
getPluginLogger().warn("You are using the PaperMC version of AdvancedServerList on a SpigotMC server.");
getPluginLogger().warn("The PaperMC version is ONLY compatible with PaperMC itself due to it using exclusive");
getPluginLogger().warn("methods and events not available within SpigotMC.");
getPluginLogger().warn("");
getPluginLogger().warn("To avoid any exceptions and errors will AdvancedServerList disable itself now.");
getPluginLogger().warn("Please stop your server and either switch to PaperMC or use the Spigot version");
getPluginLogger().warn("of AdvancedServerList.");
getPluginLogger().warn("");
getPluginLogger().warn("======================================== WARNING ========================================");
printSpigotWarning();
getServer().getPluginManager().disablePlugin(this);
}
}
@@ -108,6 +106,9 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@@ -117,7 +118,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -144,7 +145,51 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
return getServer().getVersion();
}
@Override
public String getLoader(){
return "paper";
}
@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;
}
private void enable(){
this.core = new AdvancedServerList(this);
}
private void printSpigotWarning(){
getPluginLogger().warn("======================================== WARNING ========================================");
getPluginLogger().warn("");
getPluginLogger().warn("You are using the Paper version of AdvancedServerList on a SpigotMC server.");
getPluginLogger().warn("The Paper version is ONLY compatible with Paper itself due to it using exclusive");
getPluginLogger().warn("methods and events not available within SpigotMC.");
getPluginLogger().warn("");
getPluginLogger().warn("To avoid any exceptions and errors will AdvancedServerList disable itself now.");
getPluginLogger().warn("Please stop your server and either switch to Paper or use the Spigot version");
getPluginLogger().warn("of AdvancedServerList.");
getPluginLogger().warn("");
getPluginLogger().warn("Paper can be downloaded here:");
getPluginLogger().warn("https://papermc.io/downloads");
getPluginLogger().warn("");
getPluginLogger().warn("======================================== WARNING ========================================");
}
}
@@ -0,0 +1,160 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.util.CachedServerIcon;
import java.awt.image.BufferedImage;
import java.util.List;
public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, CachedServerIcon>{
private final PaperCore plugin;
private final PaperServerListPingEvent event;
public PaperEventWrapper(PaperCore plugin, PaperServerListPingEvent event){
this.plugin = plugin;
this.event = event;
}
@Override
public void setMaxPlayers(int maxPlayers){
event.setMaxPlayers(maxPlayers);
}
@Override
public void setMotd(Component component){
event.motd(component);
}
@Override
public void hidePlayers(){
event.setHidePlayers(true);
}
@Override
public void setPlayerCount(String name){
event.setVersion(name);
event.setProtocolVersion(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
event.getPlayerSample().clear();
event.getPlayerSample().addAll(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
@Override
public void setFavicon(CachedServerIcon favicon){
event.setServerIcon(favicon);
}
@Override
public void setDefaultFavicon(){
event.setServerIcon(event.getServerIcon());
}
// Not used in Paper
@Override
public void updateEvent(){}
// Not used in Paper
@Override
public boolean isInvalidProtocol(){
return false;
}
@Override
public int getProtocolVersion(){
return event.getClient().getProtocolVersion();
}
@Override
public int getOnlinePlayers(){
return event.getNumPlayers();
}
@Override
public int getMaxPlayers(){
return event.getMaxPlayers();
}
@Override
public String getPlayerIP(){
return event.getClient().getAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getClient().getVirtualHost());
}
@Override
public PluginCore<CachedServerIcon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
if(player == null){
player = Bukkit.getOfflinePlayer(name);
return new PaperPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new PaperPlayer(player, name, protocol);
}
@Override
public CachedServerIcon createFavicon(BufferedImage image) throws Exception{
return Bukkit.loadServerIcon(image);
}
}
@@ -25,28 +25,11 @@
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import 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.UUID;
public class PingEvent implements Listener{
@@ -59,116 +42,6 @@ public class PingEvent implements Listener{
@EventHandler
public void onServerPing(PaperServerListPingEvent event){
InetSocketAddress address = event.getClient().getAddress();
InetSocketAddress host = event.getClient().getVirtualHost();
PaperPlayer player = resolvePlayer(address, event.getClient().getProtocolVersion());
int online = event.getNumPlayers();
int max = event.getMaxPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.getXMore() >= 0){
max = online + profile.getXMore();
event.setMaxPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
event.motd(ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toComponent());
}
if(profile.shouldHidePlayers()){
event.setHidePlayers(true);
return;
}
if(!profile.getPlayerCount().isEmpty()){
event.setVersion(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString());
event.setProtocolVersion(-1);
}
if(!profile.getPlayers().isEmpty()){
event.getPlayerSample().clear();
event.getPlayerSample().addAll(getPlayers(profile.getPlayers(), playerPlaceholders, serverPlaceholders, player.getPlayer()));
}
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, Placeholders playerPlaceholders, Placeholders serverPlaceholders, OfflinePlayer player){
List<PlayerProfile> players = new ArrayList<>();
lines.forEach(line -> players.add(Bukkit.createProfile(UUID.randomUUID(), ComponentParser.text(line)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player, text);
return text;
})
.toString())));
return players;
}
private PaperPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
if(player == null){
player = Bukkit.getOfflinePlayer(playerName);
return new PaperPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return new PaperPlayer(player, playerName, protocol);
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
}
}
@@ -52,4 +52,9 @@ public class PaperLogger implements PluginLogger{
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
}
}
+3
View File
@@ -7,6 +7,9 @@ main: 'ch.andre601.advancedserverlist.paper.PaperCore'
api-version: 1.19
libraries:
- 'com.squareup.okhttp3:okhttp:4.10.0'
softdepend:
- 'PlaceholderAPI'
+2 -2
View File
@@ -12,7 +12,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.version>1.5.3</plugin.version>
<plugin.version>1.10.2</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<maven.compiler.source>16</maven.compiler.source>
@@ -21,10 +21,10 @@
<modules>
<module>core</module>
<module>velocity</module>
<module>bungeecord</module>
<module>paper</module>
<module>spigot</module>
<module>velocity</module>
</modules>
</project>
+2 -2
View File
@@ -74,7 +74,7 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.1.2</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
@@ -116,7 +116,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -26,21 +26,29 @@
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<WrappedServerPing.CompressedImage>{
public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPing.CompressedImage, WrappedGameProfile, OfflinePlayer>{
private final PluginLogger logger = new SpigotLogger(getLogger());
@@ -94,6 +102,9 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@@ -103,7 +114,7 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
}
@Override
public Path getPath(){
public Path getFolderPath(){
return getDataFolder().toPath();
}
@@ -130,11 +141,38 @@ public class SpigotCore extends JavaPlugin implements PluginCore<WrappedServerPi
return getServer().getVersion();
}
@Override
public String getLoader(){
return "spigot";
}
@Override
public List<WrappedGameProfile> createPlayers(List<String> lines, OfflinePlayer player, Placeholders... placeholders){
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
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("");
@@ -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;
@@ -25,40 +25,26 @@
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.Listener;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
public class PingEvent implements Listener{
private final SpigotCore plugin;
private final ProtocolManager protocolManager;
private final Map<String, String> hostAddresses = new HashMap<>();
public PingEvent(SpigotCore plugin, ProtocolManager protocolManager){
this.plugin = plugin;
this.protocolManager = protocolManager;
loadPacketListener(plugin);
@@ -81,127 +67,8 @@ public class PingEvent implements Listener{
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
@Override
public void onPacketSending(PacketEvent event){
WrappedServerPing ping = event.getPacket().getServerPings().read(0);
InetSocketAddress address = event.getPlayer().getAddress();
if(address == null)
return;
SpigotPlayer player = resolvePlayer(address, ping.getVersionProtocol());
int online = ping.getPlayersOnline();
int max = ping.getPlayersMaximum();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(player);
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
ServerListProfile profile = ProfileManager.get(spigotPlugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.getXMore() >= 0){
max = online + profile.getXMore();
ping.setPlayersMaximum(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, hostAddresses.get(address.getHostString()));
if(!profile.getMotd().isEmpty()){
Component component = ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toComponent();
ping.setMotD(AdventureComponentConverter.fromComponent(component));
}
if(profile.shouldHidePlayers()){
ping.setPlayersVisible(false);
return;
}
if(!profile.getPlayerCount().isEmpty()){
ping.setVersionName(ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString()
);
ping.setVersionProtocol(-1);
}
if(!profile.getPlayers().isEmpty()){
ping.setPlayers(getFakePlayers(
ComponentParser.list(profile.getPlayers())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString()
));
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
WrappedServerPing.CompressedImage favicon = spigotPlugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return WrappedServerPing.CompressedImage.fromPng(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
spigotPlugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
ping.setFavicon(ping.getFavicon());
}else{
ping.setFavicon(favicon);
}
}
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event, hostAddresses));
}
});
}
private 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 SpigotPlayer resolvePlayer(InetSocketAddress address, int protocol){
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(address.getHostString());
OfflinePlayer player = Bukkit.getPlayerExact(playerName);
if(player == null){
//noinspection deprecation
player = Bukkit.getOfflinePlayer(playerName);
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, playerName, protocol);
}
return new SpigotPlayer(player, playerName, protocol);
}
}
@@ -0,0 +1,170 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Map;
public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlayer, WrappedServerPing.CompressedImage>{
private final SpigotCore plugin;
private final PacketEvent event;
private final WrappedServerPing ping;
private final Map<String, String> hostAddresses;
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event, Map<String, String> hostAddresses){
this.plugin = plugin;
this.event = event;
this.ping = event.getPacket().getServerPings().read(0);
this.hostAddresses = hostAddresses;
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.setPlayersMaximum(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setMotD(AdventureComponentConverter.fromComponent(component));
}
@Override
public void hidePlayers(){
ping.setPlayersVisible(false);
}
@Override
public void setPlayerCount(String name){
ping.setVersionName(name);
ping.setVersionProtocol(-1);
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ping.setPlayers(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
}
@Override
public void setFavicon(WrappedServerPing.CompressedImage favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFavicon());
}
// Not used in ProtocolLib
@Override
public void updateEvent(){}
@Override
public boolean isInvalidProtocol(){
return event.getPlayer().getAddress() == null;
}
@Override
public int getProtocolVersion(){
return ping.getVersionProtocol();
}
@Override
public int getOnlinePlayers(){
return ping.getPlayersOnline();
}
@Override
public int getMaxPlayers(){
return ping.getPlayersMaximum();
}
@Override
public String getPlayerIP(){
return event.getPlayer().getAddress() == null ? "UNKNOWN" : event.getPlayer().getAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
}
@Override
public String getVirtualHost(){
String host = this.resolveHost(event.getPlayer().getAddress());
if(host == null)
return null;
return hostAddresses.get(host);
}
@Override
public PluginCore<WrappedServerPing.CompressedImage> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
if(player == null){
//noinspection deprecation
player = Bukkit.getOfflinePlayer(name);
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new SpigotPlayer(player, name, protocol);
}
@Override
public WrappedServerPing.CompressedImage createFavicon(BufferedImage image) throws Exception{
return WrappedServerPing.CompressedImage.fromPng(image);
}
}
@@ -52,4 +52,9 @@ public class SpigotLogger implements PluginLogger{
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
}
}
+5 -4
View File
@@ -9,10 +9,11 @@ api-version: 1.19
libraries:
- 'org.spongepowered:configurate-yaml:4.1.2'
- 'net.kyori:adventure-api:4.11.0'
- 'net.kyori:adventure-text-minimessage:4.11.0'
- 'net.kyori:adventure-text-serializer-legacy:4.11.0'
- 'net.kyori:adventure-platform-bukkit:4.1.2'
- 'net.kyori:adventure-api:4.12.0'
- 'net.kyori:adventure-text-minimessage:4.12.0'
- 'net.kyori:adventure-text-serializer-legacy:4.12.0'
- 'net.kyori:adventure-platform-bukkit:4.2.0'
- 'com.squareup.okhttp3:okhttp:4.10.0'
softdepend:
- 'ProtocolLib'
+5 -1
View File
@@ -88,7 +88,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -104,6 +104,10 @@
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.caffeine</shadedPattern>
</relocation>
<relocation>
<pattern>okhttp3</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.okhttp3</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -26,9 +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.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.ProxyCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.velocity.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.velocity.events.JoinEvent;
import ch.andre601.advancedserverlist.velocity.events.PingEvent;
@@ -40,14 +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<Favicon>{
public class VelocityCore implements ProxyCore<Favicon, ServerPing.SamplePlayer>{
private final PluginLogger logger;
private final ProxyServer proxy;
@@ -101,6 +107,9 @@ public class VelocityCore implements PluginCore<Favicon>{
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@@ -110,7 +119,7 @@ public class VelocityCore implements PluginCore<Favicon>{
}
@Override
public Path getPath(){
public Path getFolderPath(){
return path;
}
@@ -127,6 +136,22 @@ public class VelocityCore implements PluginCore<Favicon>{
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();
@@ -137,6 +162,11 @@ public class VelocityCore implements PluginCore<Favicon>{
return getProxy().getVersion().getVersion();
}
@Override
public String getLoader(){
return "velocity";
}
public ProxyServer getProxy(){
return proxy;
}
@@ -25,23 +25,11 @@
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.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import java.net.InetSocketAddress;
import java.util.List;
public class PingEvent{
@@ -54,93 +42,6 @@ public class PingEvent{
@Subscribe(order = PostOrder.EARLY)
public void onProxyPing(ProxyPingEvent event){
ServerPing ping = event.getPing();
ServerPing.Version protocol = ping.getVersion();
if(protocol == null)
return;
ServerPing.Builder builder = ping.asBuilder();
String playerName = plugin.getCore().getPlayerHandler().getPlayerByIp(event.getConnection().getRemoteAddress().getHostString());
InetSocketAddress host = event.getConnection().getVirtualHost().orElse(null);
int online = builder.getOnlinePlayers();
int max = builder.getMaximumPlayers();
PlayerPlaceholders playerPlaceholders = new PlayerPlaceholders(new VelocityPlayer(playerName, protocol.getProtocol()));
ServerPlaceholders serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
ServerListProfile profile = ProfileManager.get(plugin.getCore())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.getProfile();
if(profile == null)
return;
if(profile.getXMore() >= 0){
max = online + profile.getXMore();
builder.maximumPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host == null ? null : host.getHostString());
if(!profile.getMotd().isEmpty()){
List<String> motd = profile.getMotd();
builder.description(ComponentParser.list(motd)
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toComponent()
);
}
if(profile.shouldHidePlayers()){
builder.nullPlayers();
event.setPing(builder.build());
return;
}
if(!profile.getPlayerCount().isEmpty()){
builder.version(new ServerPing.Version(
-1,
ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString()
));
}
if(!profile.getPlayers().isEmpty()){
String players = ComponentParser.list(profile.getPlayers())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
.toString();
ServerPing.SamplePlayer[] playerSamples = AdvancedServerList.getPlayers(ServerPing.SamplePlayer.class, players)
.toArray(new ServerPing.SamplePlayer[0]);
if(playerSamples.length > 0)
builder.clearSamplePlayers().samplePlayers(playerSamples);
}
if(!profile.getFavicon().isEmpty()){
String favName = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
Favicon favicon = plugin.getFaviconHandler().getFavicon(favName, image -> {
try{
return Favicon.create(image);
}catch(Exception ex){
return null;
}
});
if(favicon == null){
plugin.getPluginLogger().warn("Could not obtain valid Favicon to use.");
}else{
builder.favicon(favicon);
}
}
event.setPing(builder.build());
PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
}
}
@@ -0,0 +1,150 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.velocity.events;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.PlayerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.ServerPlaceholders;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import ch.andre601.advancedserverlist.velocity.VelocityPlayer;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.util.List;
public class VelocityEventWrapper implements GenericEventWrapper<Player, Favicon>{
private final VelocityCore plugin;
private final ProxyPingEvent event;
private final ServerPing.Builder builder;
private final ServerPing.Version protocol;
public VelocityEventWrapper(VelocityCore plugin, ProxyPingEvent event){
this.plugin = plugin;
this.event = event;
this.builder = event.getPing().asBuilder();
this.protocol = event.getPing().getVersion();
}
@Override
public void setMaxPlayers(int maxPlayers){
builder.maximumPlayers(maxPlayers);
}
@Override
public void setMotd(Component component){
builder.description(component);
}
@Override
public void hidePlayers(){
builder.nullPlayers();
}
@Override
public void setPlayerCount(String name){
builder.version(new ServerPing.Version(-1, name));
}
@Override
public void setPlayers(List<String> players, GenericPlayer<Player> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ServerPing.SamplePlayer[] playerSamples = plugin.createPlayers(players, playerPlaceholders, serverPlaceholders)
.toArray(new ServerPing.SamplePlayer[0]);
if(playerSamples.length > 0)
builder.clearSamplePlayers().samplePlayers(playerSamples);
}
@Override
public void setFavicon(Favicon favicon){
builder.favicon(favicon);
}
// Not used in Velocity
@Override
public void setDefaultFavicon(){}
@Override
public void updateEvent(){
event.setPing(builder.build());
}
@Override
public boolean isInvalidProtocol(){
return protocol == null;
}
@Override
public int getProtocolVersion(){
return protocol.getProtocol();
}
@Override
public int getOnlinePlayers(){
return builder.getOnlinePlayers();
}
@Override
public int getMaxPlayers(){
return builder.getMaximumPlayers();
}
@Override
public String getPlayerIP(){
return event.getConnection().getRemoteAddress().getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<Player> player){
return text;
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getConnection().getVirtualHost().orElse(null));
}
@Override
public PluginCore<Favicon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<Player> createPlayer(String name, int protocol){
return new VelocityPlayer(name, protocol);
}
@Override
public Favicon createFavicon(BufferedImage image){
return Favicon.create(image);
}
}
@@ -50,4 +50,9 @@ public class VelocityLogger implements PluginLogger{
public void warn(String msg, Throwable throwable){
logger.warn(msg, throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.warn(String.format(msg, args), throwable);
}
}