Compare commits

...
276 Commits
Author SHA1 Message Date
Andre_601 38d6ac3972 Merge pull request #94 from Andre601/fix/81-noclassdeffoundexception-issue
Fix ProtocolLib component issue
2023-05-08 17:38:06 +02:00
Andre601 360b961221 Bump version 2023-05-08 17:34:57 +02:00
Andre601 ef22ede56d Fix ProtocolLib component issue 2023-05-08 17:03:09 +02:00
Andre_601 ec9ea799cf Merge pull request #93 from Andre601/dependabot/pip/mkdocs-material-9.1.9
Bump mkdocs-material from 9.1.8 to 9.1.9
2023-05-02 18:12:08 +02:00
dependabot[bot] 99f762ff18 Bump mkdocs-material from 9.1.8 to 9.1.9
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.8 to 9.1.9.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.8...9.1.9)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-02 16:04:19 +00:00
Andre601 2bd59ff554 Load JoinEvent properly on Paper 2023-04-26 23:21:07 +02:00
Andre601 53157a7c06 Bump version 2023-04-26 23:11:20 +02:00
Andre_601 bfc39ab172 Merge pull request #91 from Andre601/feature/plugin-improvements
Plugin improvements
2023-04-26 23:08:39 +02:00
Andre_601 fa44192bd3 Ignore non-code files 2023-04-26 18:30:58 +02:00
Andre_601 53fc434bdd Merge pull request #92 from Andre601/dependabot/pip/mkdocs-material-9.1.8
Bump mkdocs-material from 9.1.7 to 9.1.8
2023-04-26 18:28:42 +02:00
dependabot[bot] b6152372a8 Bump mkdocs-material from 9.1.7 to 9.1.8
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.7 to 9.1.8.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.7...9.1.8)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-26 16:03:16 +00:00
Andre_601 5441d2bd96 Merge pull request #88 from Andre601/dependabot/maven/velocity/com.squareup.okhttp3-okhttp-4.11.0
Bump okhttp from 4.10.0 to 4.11.0 in /velocity
2023-04-24 18:35:57 +02:00
Andre_601 2d358f76c0 Merge pull request #89 from Andre601/dependabot/maven/core/com.squareup.okhttp3-okhttp-4.11.0
Bump okhttp from 4.10.0 to 4.11.0 in /core
2023-04-24 18:34:34 +02:00
Andre_601 d1cbaa3ef6 Merge pull request #90 from Andre601/dependabot/pip/mkdocs-material-9.1.7
Bump mkdocs-material from 9.1.6 to 9.1.7
2023-04-24 18:34:05 +02:00
dependabot[bot] 29513d953d Bump mkdocs-material from 9.1.6 to 9.1.7
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.6 to 9.1.7.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.6...9.1.7)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 16:06:42 +00:00
dependabot[bot] 365ec3d6f5 Bump okhttp from 4.10.0 to 4.11.0 in /core
Bumps [okhttp](https://github.com/square/okhttp) from 4.10.0 to 4.11.0.
- [Release notes](https://github.com/square/okhttp/releases)
- [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/square/okhttp/compare/parent-4.10.0...parent-4.11.0)

---
updated-dependencies:
- dependency-name: com.squareup.okhttp3:okhttp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 16:02:45 +00:00
dependabot[bot] d4babddc31 Bump okhttp from 4.10.0 to 4.11.0 in /velocity
Bumps [okhttp](https://github.com/square/okhttp) from 4.10.0 to 4.11.0.
- [Release notes](https://github.com/square/okhttp/releases)
- [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/square/okhttp/compare/parent-4.10.0...parent-4.11.0)

---
updated-dependencies:
- dependency-name: com.squareup.okhttp3:okhttp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 16:02:17 +00:00
Andre601 648b656dd4 Reduce duplicate code. 2023-04-22 00:04:21 +02:00
Andre601 b2b71144d9 Improve plugin code... I guess? 2023-04-21 23:34:22 +02:00
Andre601 f696fc2160 Add missing perms and command info 2023-04-16 23:35:39 +02:00
Andre_601 97a71958e1 Add permission 2023-04-14 23:32:19 +02:00
Andre_601 b15d5f0633 Add permissions 2023-04-14 23:32:03 +02:00
Andre601 b4e39ca985 Add examples to profiles page 2023-04-13 16:24:56 +02:00
Andre_601 5aae2cccdc Add comment info output 2023-04-11 21:48:11 +02:00
Andre_601 c7ccd48037 Add some info lines 2023-04-11 21:47:31 +02:00
Andre_601 2b6c904fbf Update pr-comment.yml 2023-04-11 21:36:16 +02:00
Andre_601 eeefea3f6a Make finding comment more precise 2023-04-11 21:33:45 +02:00
Andre_601 2840c29a90 Merge pull request #85 from Andre601/dependabot/pip/mkdocs-material-9.1.6
Bump mkdocs-material from 9.1.5 to 9.1.6
2023-04-10 18:07:20 +02:00
Andre_601 862e631405 Merge pull request #84 from Andre601/dependabot/maven/core/net.kyori-adventure-text-serializer-legacy-4.13.1
Bump adventure-text-serializer-legacy from 4.13.0 to 4.13.1 in /core
2023-04-10 18:06:45 +02:00
dependabot[bot] f00737b0f0 Bump mkdocs-material from 9.1.5 to 9.1.6
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.5 to 9.1.6.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.5...9.1.6)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:06:42 +00:00
Andre_601 2d4d1d3136 Merge pull request #83 from Andre601/dependabot/maven/core/net.kyori-adventure-api-4.13.1
Bump adventure-api from 4.13.0 to 4.13.1 in /core
2023-04-10 18:06:38 +02:00
Andre_601 04d255bb54 Merge pull request #82 from Andre601/dependabot/maven/core/net.kyori-adventure-text-minimessage-4.13.1
Bump adventure-text-minimessage from 4.13.0 to 4.13.1 in /core
2023-04-10 18:06:30 +02:00
dependabot[bot] f77db9c760 Bump adventure-text-serializer-legacy from 4.13.0 to 4.13.1 in /core
Bumps [adventure-text-serializer-legacy](https://github.com/KyoriPowered/adventure) from 4.13.0 to 4.13.1.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.13.0...v4.13.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:03:03 +00:00
dependabot[bot] 9cde35aa2f Bump adventure-api from 4.13.0 to 4.13.1 in /core
Bumps [adventure-api](https://github.com/KyoriPowered/adventure) from 4.13.0 to 4.13.1.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.13.0...v4.13.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:02:53 +00:00
dependabot[bot] 13ca53140c Bump adventure-text-minimessage from 4.13.0 to 4.13.1 in /core
Bumps [adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.13.0 to 4.13.1.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.13.0...v4.13.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:02:46 +00:00
Andre_601 bc1d0722fa Merge pull request #80 from Andre601/feature/gh-actions-include-commit
Include Commit SHA in PR builds
2023-04-08 02:12:09 +02:00
Andre601 6201342ca7 Trigger new workflow 2023-04-08 02:06:42 +02:00
Andre_601 801e0a2749 Use PR SHA 2023-04-08 02:04:22 +02:00
Andre601 10718e6d03 Include Commit SHA in PR builds 2023-04-08 01:52:31 +02:00
Andre601 03203345c0 Include commit SHA for PR builds 2023-04-08 01:49:23 +02:00
Andre601 3ade0952e2 Folia support 2023-04-06 21:22:33 +02:00
Andre_601 f0e30d47dc typo fixes 2023-04-05 19:37:11 +02:00
Andre_601 bb94510858 Update URL and add expire date 2023-04-05 19:33:03 +02:00
Andre_601 c9d94619dd Merge pull request #77 from Andre601/dependabot/github_actions/peter-evans/create-or-update-comment-3
Bump peter-evans/create-or-update-comment from 2 to 3
2023-04-05 18:59:21 +02:00
dependabot[bot] 7ab8749421 Bump peter-evans/create-or-update-comment from 2 to 3
Bumps [peter-evans/create-or-update-comment](https://github.com/peter-evans/create-or-update-comment) from 2 to 3.
- [Release notes](https://github.com/peter-evans/create-or-update-comment/releases)
- [Commits](https://github.com/peter-evans/create-or-update-comment/compare/v2...v3)

---
updated-dependencies:
- dependency-name: peter-evans/create-or-update-comment
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-05 16:00:47 +00:00
Andre_601 a9216cc82c Improve badges 2023-04-05 17:13:28 +02:00
Andre_601 f14ef643b8 Improve badge 2023-04-05 17:10:47 +02:00
Andre_601 cc876d2f21 Fix Java version 2023-04-05 16:57:20 +02:00
Andre_601 0f8693add2 typo fixes 2023-04-05 16:50:55 +02:00
Andre_601 dcc9d18dbe typo fixes 2023-04-05 16:50:29 +02:00
Andre_601 f579aa0088 Fix broken ref 2023-04-05 16:48:19 +02:00
Andre601 579b945fbd Update workflow 2023-04-04 15:55:28 +02:00
Andre601 664bea8109 Create actions for PR previews. 2023-04-04 15:53:13 +02:00
Andre601 73d94e99e4 Fix length check 2023-04-03 21:26:09 +02:00
Andre601 389ed1df53 Improve HangarUploader 2023-04-03 21:22:01 +02:00
Andre601 5f4a07cb71 Remove cache 2023-04-03 20:59:23 +02:00
Andre601 b16f5e193c fix wrong path (hopefully) 2023-04-03 20:56:58 +02:00
Andre601 1c423e6cfa Add debug workflow 2023-04-03 20:52:10 +02:00
Andre601 a27dcd5248 Fix workflow file 2023-04-03 20:42:08 +02:00
Andre601 17bd1782fb Remove Paper module 2023-04-03 20:33:52 +02:00
Andre_601 96c44dafe2 Merge pull request #75 from Andre601/feature/hangar-automation
Automate Hangar publishing
2023-04-03 20:30:24 +02:00
Andre601 d4d9a7e3c5 Temporarely disable pr-build action 2023-04-03 20:29:32 +02:00
Andre601 9f0f7297f0 Final touches 2023-04-03 20:20:16 +02:00
Andre601 691cb14c63 Merge actions 2023-04-03 18:37:44 +02:00
Andre601 8670ea026e Pretty-print date (Also temp remove ViaVersion) 2023-04-03 17:40:09 +02:00
Andre601 27c019c00d Remove posting of the JSON Body 2023-04-03 17:25:33 +02:00
Andre601 d34ea9c2ad Further reduce dependency sizes 2023-04-03 17:21:47 +02:00
Andre601 74a61f2e09 Don't include ViaVersion dependency. 2023-04-03 16:33:36 +02:00
Andre601 5e550d5a7f Add JSON body for debugging 2023-04-03 15:13:11 +02:00
Andre601 b1180c0a8e Make plugin run on Folia 2023-04-03 01:38:40 +02:00
Andre601 fc4253acce Include body in error logging 2023-04-03 01:37:48 +02:00
Andre601 a4e2cc29d5 Add more logging messages 2023-04-03 01:24:19 +02:00
Andre601 95097a581a Fix jar names and add logback.xml 2023-04-03 01:10:33 +02:00
Andre601 aff3aefb72 Add mainClass attribute 2023-04-03 01:04:22 +02:00
Andre_601 089e56be70 Set working-directory 2023-04-03 00:58:05 +02:00
Andre601 e7b8f1a0dc First attempt at hangar automation... 2023-04-03 00:54:17 +02:00
Andre_601 a2252f55c4 Update hangar.yml 2023-04-03 00:53:24 +02:00
Andre_601 dcd6a1e867 try with just one file 2023-04-02 23:04:46 +02:00
Andre_601 24bf5193ff fix file names 2023-04-02 22:50:14 +02:00
Andre_601 2e0068115d Create hangar.yml 2023-04-02 22:43:29 +02:00
Andre_601 1accbfb5f0 Merge pull request #73 from Andre601/dependabot/pip/mkdocs-material-9.1.5
Bump mkdocs-material from 9.1.4 to 9.1.5
2023-03-31 18:10:44 +02:00
dependabot[bot] f0f520d12b Bump mkdocs-material from 9.1.4 to 9.1.5
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.4 to 9.1.5.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.4...9.1.5)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-31 16:03:53 +00:00
Andre601 3edef1c2e4 Bump API and plugin version for release 2023-03-29 18:41:31 +02:00
Andre_601 0c835da51a Merge pull request #72 from Andre601/dependabot/maven/velocity/org.bstats-bstats-velocity-3.0.2
Bump bstats-velocity from 3.0.1 to 3.0.2 in /velocity
2023-03-29 18:31:46 +02:00
dependabot[bot] 1dc937e7b6 Bump bstats-velocity from 3.0.1 to 3.0.2 in /velocity
Bumps [bstats-velocity](https://github.com/Bastian/bStats-Metrics) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-velocity
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 16:10:44 +00:00
Andre_601 8d63d92ab0 Merge pull request #71 from Andre601/dependabot/maven/paper/org.bstats-bstats-bukkit-3.0.2
Bump bstats-bukkit from 3.0.1 to 3.0.2 in /paper
2023-03-29 18:02:40 +02:00
dependabot[bot] 2ade1c2506 Bump bstats-bukkit from 3.0.1 to 3.0.2 in /paper
Bumps [bstats-bukkit](https://github.com/Bastian/bStats-Metrics) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 16:01:29 +00:00
Andre_601 c1b699aab7 Merge pull request #69 from Andre601/dependabot/maven/paper/com.viaversion-viaversion-api-4.6.2
Bump viaversion-api from 4.6.1 to 4.6.2 in /paper
2023-03-27 18:08:25 +02:00
dependabot[bot] 6d5fc7a697 Bump viaversion-api from 4.6.1 to 4.6.2 in /paper
Bumps viaversion-api from 4.6.1 to 4.6.2.

---
updated-dependencies:
- dependency-name: com.viaversion:viaversion-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 16:07:49 +00:00
Andre_601 a5acd73482 Add "Available on SpigotMC" badge 2023-03-24 23:03:16 +01:00
Andre_601 f1afcc0fd8 Merge pull request #68 from Andre601/dependabot/pip/mkdocs-material-9.1.4
Bump mkdocs-material from 9.1.3 to 9.1.4
2023-03-24 17:23:02 +01:00
dependabot[bot] 9922485c34 Bump mkdocs-material from 9.1.3 to 9.1.4
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.3 to 9.1.4.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.3...9.1.4)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 16:13:48 +00:00
Andre601 9ee543fe28 Use old Command handling for Spigot 2023-03-23 20:11:30 +01:00
Andre_601 da4eccdfcc remove spigot 2023-03-23 20:00:45 +01:00
Andre_601 89f5a45809 Use own fork for hangar badge 2023-03-23 18:24:25 +01:00
Andre601 29664fde70 Fix wrong artifact name 2023-03-23 16:50:39 +01:00
Andre601 40f362f1de Fix some PAPI placeholder stuff 2023-03-23 16:41:08 +01:00
Andre_601 07cef34a37 Merge pull request #50 from Andre601/feature/paper-plugin-support
First steps towards paper-plugin support
2023-03-23 16:22:43 +01:00
Andre601 afa80581e5 Bump version to 3.0.0-b1 2023-03-23 16:22:15 +01:00
Andre601 db2366e2ce Merge branch 'master' into feature/paper-plugin-support 2023-03-23 16:18:46 +01:00
Andre601 b54151813f Update release action to allow beta-releases 2023-03-23 16:14:59 +01:00
Andre601 2be041a613 Fix wrong path (Also ignore other jobs for now 2023-03-23 16:04:33 +01:00
Andre601 86411571ef Test out pre-release detection 2023-03-23 15:52:32 +01:00
Andre_601 d80236fef8 Remove paper module 2023-03-21 02:59:32 +01:00
Andre601 fe6fae58e3 Add Profiles example and fix badges width 2023-03-21 02:54:36 +01:00
Andre_601 b2e2b18d33 Add Pip (Python) to dependabot checks 2023-03-21 02:20:51 +01:00
Andre_601 d8e54c7ff0 Remove mike from requirements.txt 2023-03-21 02:16:53 +01:00
Andre_601 f0743d691f Merge pull request #66 from Andre601/dependabot/maven/spigot/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /spigot
2023-03-20 17:10:25 +01:00
Andre_601 4b68253c7d Merge pull request #65 from Andre601/dependabot/maven/spigot/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /spigot
2023-03-20 17:10:12 +01:00
Andre_601 d1cee68355 Merge pull request #64 from Andre601/dependabot/maven/spigot/me.clip-placeholderapi-2.11.3
Bump placeholderapi from 2.11.2 to 2.11.3 in /spigot
2023-03-20 17:09:38 +01:00
Andre_601 07d3ea088a Merge pull request #63 from Andre601/dependabot/maven/paper/me.clip-placeholderapi-2.11.3
Bump placeholderapi from 2.11.2 to 2.11.3 in /paper
2023-03-20 17:09:23 +01:00
dependabot[bot] 912fb967fb Bump maven-shade-plugin from 3.4.0 to 3.4.1 in /spigot
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>
2023-03-20 16:07:52 +00:00
dependabot[bot] d960644cc1 Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /spigot
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 16:07:39 +00:00
dependabot[bot] 34908b4123 Bump placeholderapi from 2.11.2 to 2.11.3 in /spigot
Bumps placeholderapi from 2.11.2 to 2.11.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 16:07:31 +00:00
dependabot[bot] 00466f1ffb Bump placeholderapi from 2.11.2 to 2.11.3 in /paper
Bumps placeholderapi from 2.11.2 to 2.11.3.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 16:07:22 +00:00
Andre601 d05527634d Add clearCache subcommand.
Also, add convenience methods for sending prefixed messages.
2023-03-20 15:09:02 +01:00
Andre601 6e017219b4 Add ViaVersion as soft-depend 2023-03-20 14:33:31 +01:00
Andre601 8fa66867bc Load PaperPingEvent and also improve PAPI placeholders 2023-03-18 17:07:28 +01:00
Andre601 1df167b66a Merge branch 'master' into feature/paper-plugin-support 2023-03-18 16:13:51 +01:00
Andre601 ffee02095f Remove unused import 2023-03-18 16:07:48 +01:00
Andre601 0fc7c7f047 Bump ProtocolLib version 2023-03-18 15:58:07 +01:00
Andre_601 c8ae03da16 Merge pull request #62 from Andre601/dependabot/github_actions/actions/cache-3
Bump actions/cache from 2 to 3
2023-03-17 18:06:33 +01:00
dependabot[bot] dc4165465e Bump actions/cache from 2 to 3
Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 16:01:55 +00:00
Andre601 05c32cd721 [Docs] Update badges to v3 2023-03-17 14:43:36 +01:00
Andre601 ccd326f036 Add ViaVersion to dependencies list 2023-03-17 14:31:03 +01:00
Andre601 e9117c8040 Revert docs to MkDocs only
(Mike kinda sucks, ngl)
2023-03-17 14:24:43 +01:00
Andre601 116714f9a4 Try fixing page deploy. 2023-03-17 01:30:27 +01:00
Andre601 06f025c50e Add missing page to nav 2023-03-17 01:26:57 +01:00
Andre601 25787e8c51 Include 1.19.4 in supported versions 2023-03-17 01:22:40 +01:00
Andre601 741ca73c62 Add PlaceholderAPI placeholders 2023-03-17 01:22:02 +01:00
Andre601 50944717ea Merge docs update into releas action 2023-03-17 01:01:21 +01:00
Andre_601 89d2d04c12 Merge pull request #61 from Andre601/dependabot/maven/spigot/net.kyori-adventure-platform-bukkit-4.3.0
Bump adventure-platform-bukkit from 4.2.0 to 4.3.0 in /spigot
2023-03-16 17:07:19 +01:00
dependabot[bot] 2aa53c556a Bump adventure-platform-bukkit from 4.2.0 to 4.3.0 in /spigot
Bumps [adventure-platform-bukkit](https://github.com/KyoriPowered/adventure-platform) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/KyoriPowered/adventure-platform/releases)
- [Commits](https://github.com/KyoriPowered/adventure-platform/compare/v4.2.0...v4.3.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>
2023-03-16 16:05:18 +00:00
Andre_601 7eb67c1571 Merge pull request #58 from Andre601/dependabot/maven/core/net.kyori-adventure-api-4.13.0
Bump adventure-api from 4.12.0 to 4.13.0 in /core
2023-03-15 17:14:39 +01:00
Andre_601 e6ebf0964b Merge pull request #60 from Andre601/dependabot/maven/core/net.kyori-adventure-text-serializer-legacy-4.13.0
Bump adventure-text-serializer-legacy from 4.12.0 to 4.13.0 in /core
2023-03-15 17:05:33 +01:00
Andre_601 2f7bbe8bae Merge pull request #59 from Andre601/dependabot/maven/core/net.kyori-adventure-text-minimessage-4.13.0
Bump adventure-text-minimessage from 4.12.0 to 4.13.0 in /core
2023-03-15 17:05:15 +01:00
dependabot[bot] cc3e75f41b Bump adventure-text-serializer-legacy from 4.12.0 to 4.13.0 in /core
Bumps [adventure-text-serializer-legacy](https://github.com/KyoriPowered/adventure) from 4.12.0 to 4.13.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.12.0...v4.13.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>
2023-03-15 16:03:13 +00:00
dependabot[bot] 7706dd245f Bump adventure-text-minimessage from 4.12.0 to 4.13.0 in /core
Bumps [adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.12.0 to 4.13.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.12.0...v4.13.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>
2023-03-15 16:03:06 +00:00
dependabot[bot] d4018ff666 Bump adventure-api from 4.12.0 to 4.13.0 in /core
Bumps [adventure-api](https://github.com/KyoriPowered/adventure) from 4.12.0 to 4.13.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.12.0...v4.13.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>
2023-03-15 16:03:01 +00:00
Andre_601 4c7a2ca94d Update wiki links to link to latest 2023-03-13 01:35:17 +01:00
Andre_601 21632711ea Merge pull request #57 from Andre601/dependabot/maven/core/com.github.ben-manes.caffeine-caffeine-3.1.5
Bump caffeine from 3.1.4 to 3.1.5 in /core
2023-03-06 17:15:29 +01:00
dependabot[bot] e82ed84c11 Bump caffeine from 3.1.4 to 3.1.5 in /core
Bumps [caffeine](https://github.com/ben-manes/caffeine) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.1.4...v3.1.5)

---
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>
2023-03-06 16:12:19 +00:00
Andre601 1f44b34dd2 Update workflow titles 2023-03-03 21:05:36 +01:00
Andre601 b7b6d8b82b Make dev a default for mkdocs-material 2023-03-03 20:56:50 +01:00
Andre601 53e270b183 Try dev build of Mike from GitHub 2023-03-03 17:28:49 +01:00
Andre601 f633bb393e Revert "Make fetch-depht 1"
This reverts commit 42907c7f74.
2023-03-03 17:27:49 +01:00
Andre601 41ac71e346 Revert "Make fetch-depth 1"
This reverts commit e04b9b4a09.
2023-03-03 17:27:35 +01:00
Andre_601 e04b9b4a09 Make fetch-depth 1 2023-03-02 01:19:56 +01:00
Andre_601 42907c7f74 Make fetch-depht 1 2023-03-02 01:19:33 +01:00
Andre_601 69bf90c20f Make dev the default branch 2023-03-01 13:58:27 +01:00
Andre601 b2f70b605c Update CSS stuff 2023-03-01 03:35:52 +01:00
Andre601 fb5e4b57bc Create versioned docs 2023-03-01 02:33:29 +01:00
Andre601 49c17d941a Fix wrong workflow file names 2023-03-01 00:05:42 +01:00
Andre601 ec6b852497 typo 2023-03-01 00:03:03 +01:00
Andre_601 9bd2c4b8d5 Merge pull request #54 from Andre601/feature/versioned-docs
Set up versioned docs
2023-02-28 23:01:11 +01:00
Andre_601 57bb677578 Merge pull request #56 from Andre601/dependabot/maven/velocity/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /velocity
2023-02-28 17:07:00 +01:00
Andre_601 40c4726fd6 Merge pull request #55 from Andre601/dependabot/maven/paper/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /paper
2023-02-28 17:06:48 +01:00
dependabot[bot] c1eefbe114 Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /velocity
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 16:04:25 +00:00
dependabot[bot] 082345fb66 Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /paper
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 16:04:19 +00:00
Andre601 1bedc472b3 Extend the theme 2023-02-28 03:06:18 +01:00
Andre601 aa9d6ff7d2 Set up versioned docs 2023-02-28 02:35:47 +01:00
Andre601 5e4fc3d69c Smaller typo fix in api docs 2023-02-28 02:13:10 +01:00
Andre_601 b429e75797 Merge pull request #53 from Andre601/dependabot/maven/bungeecord/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /bungeecord
2023-02-27 17:13:39 +01:00
Andre_601 c2eacf716f Merge pull request #52 from Andre601/dependabot/maven/core/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /core
2023-02-27 17:13:28 +01:00
dependabot[bot] aca52b528d Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /bungeecord
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 16:13:20 +00:00
dependabot[bot] cd1469c554 Bump maven-compiler-plugin from 3.10.1 to 3.11.0 in /core
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 16:12:46 +00:00
Andre601 ce4347ca1e Improve CommandHandler 2023-02-23 01:51:04 +01:00
Andre601 acc59e0af7 Prepare docs for next ASL API. 2023-02-23 00:49:14 +01:00
Andre601 099abcda67 Make sure paper-plugin loads after PlaceholderAPI 2023-02-23 00:37:07 +01:00
Andre601 2ced4db199 Small formatting for actions 2023-02-22 22:27:18 +01:00
Andre601 4f7c16ae5a Use PaperMC Maven repo 2023-02-20 23:30:19 +01:00
Andre_601 06739bb68e Merge pull request #51 from Andre601/dependabot/maven/core/com.github.ben-manes.caffeine-caffeine-3.1.4
Bump caffeine from 3.1.3 to 3.1.4 in /core
2023-02-20 17:13:37 +01:00
dependabot[bot] d1c9ab5b82 Bump caffeine from 3.1.3 to 3.1.4 in /core
Bumps [caffeine](https://github.com/ben-manes/caffeine) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.1.3...v3.1.4)

---
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>
2023-02-20 16:10:36 +00:00
Andre601 d06f767e51 Rename to BukkitPlayerPlaceholders for clarity 2023-02-20 14:10:58 +01:00
Andre601 02e0821bd0 Merge CmdAdvancedServerList instances into one 2023-02-20 14:07:25 +01:00
Andre601 981d4e8146 First steps towards paper-plugin support 2023-02-20 01:53:02 +01:00
Andre_601 05667c0f87 Update MODRINTH.md 2023-02-13 22:44:54 +01:00
Andre_601 54f0f59925 Updated badges to v3 2023-02-13 22:41:49 +01:00
Andre_601 de2c8a7547 Merge pull request #49 from Andre601/dependabot/maven/velocity/org.bstats-bstats-velocity-3.0.1
Bump bstats-velocity from 3.0.0 to 3.0.1 in /velocity
2023-02-13 17:14:04 +01:00
Andre_601 50c31a3348 Merge pull request #48 from Andre601/dependabot/maven/paper/org.bstats-bstats-bukkit-3.0.1
Bump bstats-bukkit from 3.0.0 to 3.0.1 in /paper
2023-02-13 17:13:54 +01:00
Andre_601 93e94aa9d3 Merge pull request #47 from Andre601/dependabot/maven/spigot/org.bstats-bstats-bukkit-3.0.1
Bump bstats-bukkit from 3.0.0 to 3.0.1 in /spigot
2023-02-13 17:13:42 +01:00
dependabot[bot] 1f71aeb7e5 Bump bstats-velocity from 3.0.0 to 3.0.1 in /velocity
Bumps [bstats-velocity](https://github.com/Bastian/bStats-Metrics) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-velocity
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 16:13:04 +00:00
dependabot[bot] 5d01adfa49 Bump bstats-bukkit from 3.0.0 to 3.0.1 in /paper
Bumps [bstats-bukkit](https://github.com/Bastian/bStats-Metrics) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 16:13:02 +00:00
dependabot[bot] da7e3eca09 Bump bstats-bukkit from 3.0.0 to 3.0.1 in /spigot
Bumps [bstats-bukkit](https://github.com/Bastian/bStats-Metrics) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/Bastian/bStats-Metrics/releases)
- [Commits](https://github.com/Bastian/bStats-Metrics/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: org.bstats:bstats-bukkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 16:12:48 +00:00
Andre_601 66b305bbea Merge pull request #46 from Andre601/dependabot/maven/core/com.github.ben-manes.caffeine-caffeine-3.1.3
Bump caffeine from 3.1.2 to 3.1.3 in /core
2023-02-10 17:16:03 +01:00
dependabot[bot] 3c1abf4f3a Bump caffeine from 3.1.2 to 3.1.3 in /core
Bumps [caffeine](https://github.com/ben-manes/caffeine) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.1.2...v3.1.3)

---
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>
2023-02-10 16:07:29 +00:00
Andre_601 856be1e32e Update index.md 2023-02-03 22:33:28 +01:00
Andre601 5303bb00a0 More docs corrections 2023-02-01 15:55:19 +01:00
Andre601 9b43428e5d Another fix for changelog... 2023-02-01 15:47:18 +01:00
Andre601 d34d926f9a Fix wrong version in api changelog 2023-02-01 15:46:57 +01:00
Andre601 844279b32d Rename the other Placeholder classes too. 2023-02-01 15:38:00 +01:00
Andre601 5916e9b495 Version was already bumped... whoops 2023-02-01 15:31:56 +01:00
Andre_601 72384488d8 Merge pull request #45 from Andre601/feature/events
Add PreServerListSetEvent
2023-02-01 15:29:38 +01:00
Andre601 11a8b07f32 Bump version 2023-02-01 15:24:13 +01:00
Andre601 cd7dfc9c15 Rename to resolve 2023-01-31 18:12:43 +01:00
Andre601 c715ed6163 Make values of Expression final 2023-01-31 18:12:21 +01:00
Andre601 5a35ebbef4 Trim left and right string to avoid comparison issues 2023-01-31 17:17:10 +01:00
Andre601 830eee5da3 Fix missing favicon from resolver. 2023-01-28 23:22:08 +01:00
Andre601 09b845e86e Changes 2023-01-28 23:13:41 +01:00
Andre601 a2bdd5c4e5 Add changelog file 2023-01-27 14:59:12 +01:00
Andre601 a72c0d326a Update to latest API changes 2023-01-27 00:59:29 +01:00
Andre601 40ef2e35d4 Make GenericPlayer.getVersion VelocityPlayer only 2023-01-25 22:13:39 +01:00
Andre601 8422d6d2de Minor doc improvements 2023-01-25 16:19:43 +01:00
Andre601 4683dab513 limit motd in ProfileEntry.Builder directly 2023-01-25 16:15:07 +01:00
Andre601 d5947b20e5 Update docs 2023-01-25 01:11:45 +01:00
Andre601 147f01dd1b Rename GenericProfileEntryEvent to GenericServerListEvent 2023-01-25 00:29:07 +01:00
Andre601 a6eddb3828 Remove unused method in ComponentParser 2023-01-25 00:05:09 +01:00
Andre601 41e11f79cc Move ProfileEntry completely. 2023-01-25 00:01:51 +01:00
Andre601 66597ce7fa Add PreServerListSetEvent 2023-01-24 23:38:23 +01:00
Andre_601 77f17b202c Update MODRINTH.md 2023-01-23 21:28:57 +01:00
Andre_601 d3673a79af Update README.md 2023-01-23 20:59:26 +01:00
Andre_601 29c6930ce1 Merge pull request #38 from Andre601/feature/add-api
Start with an API for custom placeholder support
2023-01-23 20:54:03 +01:00
Andre601 125e9c0918 Add missing files to git 2023-01-23 20:53:21 +01:00
Andre601 2ac6931f26 Remove unused files and add workflow 2023-01-23 20:52:37 +01:00
Andre601 e301ef38f0 Bump version + Docs 2023-01-23 20:36:28 +01:00
Andre_601 3f6ada4599 Create api_support.yml 2023-01-23 14:27:41 +01:00
Andre601 45d3f17faa Use a Constructor for PlaceholderProvider 2023-01-22 15:00:01 +01:00
Andre601 d8fca2ca03 Improve Javadocs and rename getUuid to getUUID 2023-01-21 00:14:06 +01:00
Andre601 730b2e3aa8 Get rid of <T> nonsense for GenericPlayer 2023-01-21 00:03:55 +01:00
Andre601 e4e3543b9b Check for null/empty before lowercasing identifier 2023-01-20 23:18:59 +01:00
Andre_601 a955109db5 Merge pull request #44 from Andre601/dependabot/maven/core/com.unascribed-flexver-java-1.1.0
Bump flexver-java from 1.0.2 to 1.1.0 in /core
2023-01-17 16:55:01 +01:00
dependabot[bot] d399c7df63 Bump flexver-java from 1.0.2 to 1.1.0 in /core
Bumps flexver-java from 1.0.2 to 1.1.0.

---
updated-dependencies:
- dependency-name: com.unascribed:flexver-java
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 15:11:31 +00:00
Andre601 973620925d fix wrong char position 2023-01-16 15:22:42 +01:00
Andre601 697e9e265d Update javadoc 2023-01-11 23:14:28 +01:00
Andre601 cabed6aa65 Update missing copyright headers 2023-01-11 23:10:00 +01:00
Andre601 b408658026 Apply fixes 2023-01-11 23:08:41 +01:00
Andre601 15f611445c Merge branch 'master' into feature/add-api
# Conflicts:
#	api/src/main/java/ch/andre601/advancedserverlist/api/exceptions/InvalidPlaceholderProviderException.java
#	bungeecord/src/main/java/ch/andre601/advancedserverlist/bungeecord/events/BungeeEventWrapper.java
#	core/src/main/java/ch/andre601/advancedserverlist/core/events/PingEventHandler.java
#	core/src/main/java/ch/andre601/advancedserverlist/core/interfaces/events/GenericEventWrapper.java
#	paper/src/main/java/ch/andre601/advancedserverlist/paper/events/PaperEventWrapper.java
#	paper/src/main/java/ch/andre601/advancedserverlist/paper/objects/PaperPlayer.java
#	paper/src/main/java/ch/andre601/advancedserverlist/paper/objects/PlayerPlaceholders.java
#	spigot/src/main/java/ch/andre601/advancedserverlist/spigot/events/ProtocolLibEventWrapper.java
#	spigot/src/main/java/ch/andre601/advancedserverlist/spigot/objects/SpigotPlayer.java
#	velocity/src/main/java/ch/andre601/advancedserverlist/velocity/events/VelocityEventWrapper.java
#	velocity/src/main/java/ch/andre601/advancedserverlist/velocity/objects/VelocityPlayer.java
2023-01-11 22:45:43 +01:00
Andre_601 3859f2970f Merge pull request #41 from Andre601/feature/uuid-usage
Improve player caching behaviour
2023-01-10 20:36:34 +01:00
Andre601 71079bf9d8 Bump version 2023-01-09 20:47:46 +01:00
Andre601 4fa7e92264 Make CachedPlayer its own class 2023-01-09 20:46:46 +01:00
Andre_601 828d907371 Merge branch 'master' into feature/uuid-usage 2023-01-09 20:37:36 +01:00
Andre601 986c36a334 tiny typo fix 2023-01-09 20:36:08 +01:00
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
Andre601 0cae58c9b6 Update Copyright 2023-01-01 00:33:39 +01:00
Andre_601 a8d6fc48bf Merge branch 'master' into feature/add-api 2022-12-31 23:06:26 +01:00
Andre601 91dcb49e81 Update log messages 2022-12-31 16:40:57 +01:00
Andre601 c8a1224f53 Fix broken logic and make ${player uuid} always available 2022-12-31 16:21:26 +01:00
Andre601 5722700d20 Improve player caching behaviour 2022-12-31 01:25:57 +01: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
Andre601 c964c942dc Implement latest changes from v1.10.0 2022-12-28 14:00:19 +01:00
Andre601 27c591d92c Merge branch 'master' into feature/add-api
# Conflicts:
#	core/src/main/java/ch/andre601/advancedserverlist/core/events/PingEventHandler.java
#	core/src/main/java/ch/andre601/advancedserverlist/core/profiles/ProfileManager.java
#	core/src/main/java/ch/andre601/advancedserverlist/core/profiles/ServerListProfile.java
2022-12-28 13:47:46 +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
Andre601 de2d43f01c fix methods and imports 2022-12-20 23:48:03 +01:00
Andre_601 3fde989eb5 Merge branch 'master' into feature/add-api 2022-12-20 23:44:28 +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 c1fa8d0df1 Add maven-compiler-plugin + throws docs 2022-12-16 17:05:06 +01:00
Andre601 f0446fe8f4 Move API to own module 2022-12-16 16:55:21 +01:00
Andre601 5509fb4380 Add and improve javadoc comments 2022-12-11 23:46:26 +01:00
Andre601 d0f7bf9897 Start with an API for custom placeholder support 2022-12-11 23:26:54 +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
112 changed files with 4194 additions and 1357 deletions

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
name: API support
description: Ask for help with the API.
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)] and the right API version.
- 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: On what platform(s) are you using the API?
multiple: true
options:
- Proxy (BungeeCord, Waterfall, ...)
- Proxy (Velocity)
- Server (Spigot, Paper, ...)
validations:
required: true
- type: textarea
attributes:
label: Description
description: |-
Give a detailed description of what exactly you try to do, what steps you did and what you need help with.
placeholder: I tried to...
validations:
required: true
- type: textarea
attributes:
label: Code
description: |-
Provide code-snippets to help us better understand what you tried.
The code is automatically parsed as Java Code.
render: java
validations:
required: true
+13 -17
View File
@@ -4,19 +4,19 @@ AdvancedServerList is a plugin that allowys you to customize your server's MOTD,
## 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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/velocity_vector.svg" width="64" alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
@@ -61,29 +61,25 @@ You can disable this in the global bStats config file located in `/plugins/bstat
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://raw.githubusercontent.com/intergrav/devins-badges/v2/assets/cozy/documentation/modrinth-gallery_vector.svg" width="208" alt="gallery" title="Check out the Gallery">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-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
[profiles]: https://andre601.ch/AdvancedServerList/profiles
[conditions]: https://andre601.ch/AdvancedServerList/profiles/#conditions
[placeholders]: https://andre601.ch/AdvancedServerList/profiles/placeholders
[minimessage]: https://andre601.ch/AdvancedServerList/profiles/formatting
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
+8
View File
@@ -48,3 +48,11 @@ updates:
labels:
- 'Type: Update Dependency'
- 'Target: GitHub Action'
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'Type: Update Dependency'
- 'Target: MkDocs'
+100
View File
@@ -0,0 +1,100 @@
name: Create PR Artifacts
on:
pull_request_target:
types:
- opened
- reopened
- synchronize
branches:
- master
paths-ignore:
- '.github/**'
- 'docs/**'
- '.gitignore'
- 'LICENSE'
- 'README.md'
- 'mkdocs.yml'
- 'requirements.txt'
concurrency:
group: '${{ github.workflow }}-${{ github.head_ref }}'
cancel-in-progress: false
permissions:
issues: write
pull-requests: write
jobs:
buildArtifacts:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: Find Comment
uses: peter-evans/find-comment@v2
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: '<!-- pr-build comment -->'
- name: Print Comment info
run: |
echo "Comment ID: ${{ steps.find-comment.outputs.comment-id }}"
echo "Comment Author: ${{ steps.find-comment.outputs.comment-author }}"
echo "Comment created at: ${{ steps.find-comment.outputs.comment-created-at }}"
- name: Post/Update Comment
uses: peter-evans/create-or-update-comment@v3
id: comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: |-
<!-- pr-build comment -->
![badge]
Please wait while we're building the Jar files for this Pull request...
[badge]: https://img.shields.io/badge/Building...-0d1117?style=for-the-badge&labelColor=7a8490&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNNC43NSAyaDE0LjVhLjc1Ljc1IDAgMCAxIDAgMS41aC0uNzV2Mi45ODJhNC43NSA0Ljc1IDAgMCAxLTIuMjE1IDQuMDE3bC0yLjA0NCAxLjI5YS4yNS4yNSAwIDAgMCAwIC40MjJsMi4wNDQgMS4yOWE0Ljc1IDQuNzUgMCAwIDEgMi4yMTUgNC4wMTdWMjAuNWguNzVhLjc1Ljc1IDAgMCAxIDAgMS41SDQuNzVhLjc1Ljc1IDAgMCAxIDAtMS41aC43NXYtMi45ODJhNC43NSA0Ljc1IDAgMCAxIDIuMjE1LTQuMDE3bDIuMDQ0LTEuMjlhLjI1LjI1IDAgMCAwIDAtLjQyMmwtMi4wNDQtMS4yOUE0Ljc1IDQuNzUgMCAwIDEgNS41IDYuNDgyVjMuNWgtLjc1YS43NS43NSAwIDAgMSAwLTEuNVpNMTcgMy41SDd2Mi45ODJBMy4yNSAzLjI1IDAgMCAwIDguNTE2IDkuMjNsMi4wNDQgMS4yOWExLjc1IDEuNzUgMCAwIDEgMCAyLjk2bC0yLjA0NCAxLjI5QTMuMjUgMy4yNSAwIDAgMCA3IDE3LjUxOFYyMC41aDEwdi0yLjk4MmEzLjI1IDMuMjUgMCAwIDAtMS41MTYtMi43NDhsLTIuMDQ0LTEuMjlhMS43NSAxLjc1IDAgMCAxIDAtMi45NmwyLjA0NC0xLjI5QTMuMjUgMy4yNSAwIDAgMCAxNyA2LjQ4MloiPjwvcGF0aD48L3N2Zz4=
- name: Set up JDK 1.16
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '16'
cache: 'maven'
- name: Obtain short Commit SHA
id: get-commit
run: 'echo "sha_short=$(git rev-parse --short ${{ github.event.pull_request.head.sha }})" >> $GITHUB_OUTPUT'
- name: Build Jar files
run: mvn clean install
env:
COMMIT_SHA: ${{ steps.get-commit.outputs.sha_short }}
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: AdvancedServerList-Artifacts
path: '*/target/AdvancedServerList-*.jar'
if-no-files-found: error
- name: Update Comment (Failure)
if: failure()
uses: peter-evans/create-or-update-comment@v3
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.comment.outputs.comment-id }}
edit-mode: replace
body: |-
<!-- pr-build comment -->
![badge]
The Build of this Pull request failed.
Please check the below linked logs for a possible cause.
| Name | Link |
| ------ | ----------------------------------------------------------------------------------- |
| Commit | ${{ github.event.pull_request.head.sha }} |
| Logs | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
[badge]: https://img.shields.io/badge/Build_Failure!-0d1117?style=for-the-badge&labelColor=f85149&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNNS43MiA1LjcyYS43NS43NSAwIDAgMSAxLjA2IDBMMTIgMTAuOTRsNS4yMi01LjIyYS43NDkuNzQ5IDAgMCAxIDEuMjc1LjMyNi43NDkuNzQ5IDAgMCAxLS4yMTUuNzM0TDEzLjA2IDEybDUuMjIgNS4yMmEuNzQ5Ljc0OSAwIDAgMS0uMzI2IDEuMjc1Ljc0OS43NDkgMCAwIDEtLjczNC0uMjE1TDEyIDEzLjA2bC01LjIyIDUuMjJhLjc1MS43NTEgMCAwIDEtMS4wNDItLjAxOC43NTEuNzUxIDAgMCAxLS4wMTgtMS4wNDJMMTAuOTQgMTIgNS43MiA2Ljc4YS43NS43NSAwIDAgMSAwLTEuMDZaIj48L3BhdGg+PC9zdmc+
+35
View File
@@ -0,0 +1,35 @@
name: 'Deploy Site (Push)'
on:
workflow_dispatch:
push:
paths:
- 'docs/**'
- 'mkdocs.yml'
- 'mkdocs-theme/**'
- 'requirements.txt'
branches:
- master
tags-ignore:
- '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.7
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Create/Get Cache
uses: actions/cache@v3
with:
key: ${{ github.ref }}
path: .cache
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
python -m pip install -r requirements.txt
- name: Deploy Files
run: mkdocs gh-deploy --force
+99
View File
@@ -0,0 +1,99 @@
name: Comment on Pull request
on:
workflow_run:
types:
- completed
workflows:
- 'Create PR Artifacts'
permissions:
issues: write
pull-requests: write
jobs:
comment:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- name: Get Artifact and Pull request info
env:
GITHUB_TOKEN: ${{ github.token }} # No idea why this is set here when ${{ secrets.GITHUB_TOKEN }} is a thing...
WORKFLOW_RUN_EVENT_OBJ: ${{ toJSON(github.event.workflow_run) }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
run: |
PREVIOUS_JOB_ID=$(jq -r '.id' <<< "$WORKFLOW_RUN_EVENT_OBJ")
echo "Previous Job ID: $PREVIOUS_JOB_ID"
echo "PREVIOUS_JOB_ID=$PREVIOUS_JOB_ID" >> "$GITHUB_ENV"
SUITE_ID=$(jq -r '.check_suite_id' <<< "$WORKFLOW_RUN_EVENT_OBJ")
echo "Previous Suite ID: $SUITE_ID"
echo "SUITE_ID=$SUITE_ID" >> "$GITHUB_ENV"
ARTIFACT_ID=$(gh api "/repos/$OWNER/$REPO/actions/artifacts" \
--jq ".artifacts.[] |
select(.workflow_run.id==${PREVIOUS_JOB_ID}) |
select(.expired==false) |
.id")
echo "Artifact ID: $ARTIFACT_ID"
echo "ARTIFACT_ID=$ARTIFACT_ID" >> "$GITHUB_ENV"
ARTIFACT_EXPIRE_DATE=$(gh api "/repos/$OWNER/$REPO/actions/artifacts" \
--jq ".artifacts.[] |
select(.workflow_run.id==${PREVIOUS_JOB_ID}) |
select(.expired==false) |
.expires_at")
echo "Artifact Expire Date: $ARTIFACT_EXPIRE_DATE"
echo "ARTIFACT_EXPIRE_DATE=$ARTIFACT_EXPIRE_DATE" >> "$GITHUB_ENV"
PR_NUMBER=$(jq -r '.pull_requests[0].number' \
<<< "$WORKFLOW_RUN_EVENT_OBJ")
echo "Pull request Number: $PR_NUMBER"
echo "PR_NUMBER=$PR_NUMBER" >> "$GITHUB_ENV"
HEAD_SHA=$(jq -r '.pull_requests[0].head.sha' \
<<< "$WORKFLOW_RUN_EVENT_OBJ")
echo "Head SHA: $HEAD_SHA"
echo "HEAD_SHA=$HEAD_SHA" >> "$GITHUB_ENV"
- name: Find Comment
uses: peter-evans/find-comment@v2
id: find-comment
with:
issue-number: ${{ env.PR_NUMBER }}
comment-author: 'github-actions[bot]'
body-includes: '<!-- pr-build comment -->'
- name: Print Comment info
run: |
echo "Comment ID: ${{ steps.find-comment.outputs.comment-id }}"
echo "Comment Author: ${{ steps.find-comment.outputs.comment-author }}"
echo "Comment created at: ${{ steps.find-comment.outputs.comment-created-at }}"
- name: Update Comment
env:
JOB_PATH: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ env.PREVIOUS_JOB_ID }}"
ARTIFACT_URL: "${{ github.server_url }}/${{ github.repository }}/suites/${{ env.SUITE_ID }}/artifacts/${{ env.ARTIFACT_ID }}"
ARTIFACT_EXPIRE_DATE: "${{ env.ARTIFACT_EXPIRE_DATE }}"
HEAD_SHA: "${{ env.HEAD_SHA }}"
uses: peter-evans/create-or-update-comment@v3
with:
issue-number: ${{ env.PR_NUMBER }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: |-
<!-- pr-build comment -->
![badge]
Build Successful! You can find a link to the downloadable artifact below.
Expire Date: `${{ env.ARTIFACT_EXPIRE_DATE }}`
| Name | Link |
| -------- | ----------------------- |
| Commit | ${{ env.HEAD_SHA }} |
| Logs | ${{ env.JOB_PATH }} |
| Download | ${{ env.ARTIFACT_URL }} |
[badge]: https://img.shields.io/badge/Build_Success!-0d1117?style=for-the-badge&labelColor=3fb950&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmZmZmZmIj48cGF0aCBkPSJNMjEuMDMgNS43MmEuNzUuNzUgMCAwIDEgMCAxLjA2bC0xMS41IDExLjVhLjc0Ny43NDcgMCAwIDEtMS4wNzItLjAxMmwtNS41LTUuNzVhLjc1Ljc1IDAgMSAxIDEuMDg0LTEuMDM2bDQuOTcgNS4xOTVMMTkuOTcgNS43MmEuNzUuNzUgMCAwIDEgMS4wNiAwWiI+PC9wYXRoPjwvc3ZnPg==
+69 -41
View File
@@ -7,13 +7,22 @@ name: Publish Assets
on:
release:
types: [published]
types:
- published
jobs:
buildJars:
runs-on: ubuntu-latest
outputs:
plugin_release: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
steps:
- uses: actions/checkout@v3
- name: Checkout Repository
uses: actions/checkout@v3
- name: Get Version from Release
id: github-release
run: |
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
- name: Set up JDK 1.16
uses: actions/setup-java@v3
with:
@@ -22,32 +31,13 @@ jobs:
cache: 'maven'
- name: Build Jar files
run: mvn clean install
- name: Save BungeeCord Jar file
- name: Save All files
uses: actions/upload-artifact@v3
with:
name: asl-bungeecord
path: bungeecord/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Paper Jar file
uses: actions/upload-artifact@v3
with:
name: asl-paper
path: paper/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Spigot Jar file
uses: actions/upload-artifact@v3
with:
name: asl-spigot
path: spigot/target/AdvancedServerList-*.jar
if-no-files-found: error
retention-days: 1
- name: Save Velocity Jar file
uses: actions/upload-artifact@v3
with:
name: asl-velocity
path: velocity/target/AdvancedServerList-*.jar
name: asl-files
path: |
*/target/AdvancedServerList-*.jar
hangar-uploader/target/HangarUploader.jar
if-no-files-found: error
retention-days: 1
publish:
@@ -60,12 +50,11 @@ jobs:
loaders: |
bungeecord
waterfall
- platforms: Paper
directory: paper
loaders: paper
- platforms: Spigot
directory: spigot
loaders: spigot
- platforms: Spigot, Paper
directory: bukkit
loaders: |
spigot
paper
- platforms: Velocity
directory: velocity
loaders: velocity
@@ -75,18 +64,13 @@ jobs:
- name: Get Jar files
uses: actions/download-artifact@v3
with:
name: asl-${{ matrix.directory }}
path: ${{ matrix.directory }}/target
- name: Get Version
id: github-release
run: |
version=$(echo ${{ github.event.release.tag_name }} | cut -d'v' -f2)
echo "PLUGIN_RELEASE=$version" >> $GITHUB_OUTPUT
- name: Upload AdvancedServerList (${{ matrix.loaders }}) to GitHub and Modrinth
name: asl-files
- name: Upload AdvancedServerList v${{ needs.buildJars.outputs.plugin_release }} (${{ matrix.loaders }}) to GitHub and Modrinth
if: '!github.event.release.prerelease'
uses: Kir-Antipov/mc-publish@v3.2
with:
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
version: ${{ steps.github-release.outputs.PLUGIN_RELEASE }}
version: ${{ needs.buildJars.outputs.plugin_release }}
version-type: release
files: ${{ matrix.directory}}/target/AdvancedServerList-*.jar
files-secondary: ""
@@ -96,8 +80,52 @@ jobs:
1.19
1.19.1
1.19.2
1.19.3
1.19.4
java: 16
modrinth-id: xss83sOY
modrinth-featured: false
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload AdvancedServerList v${{ needs.buildJars.outputs.plugin_release }} (${{ matrix.loaders }}) to GitHub and Modrinth [Pre-Release]
if: 'github.event.release.prerelease'
uses: Kir-Antipov/mc-publish@v3.2
with:
name: ${{ github.event.release.tag_name }} (${{ matrix.platforms }})
version: ${{ needs.buildJars.outputs.plugin_release }}
version-type: beta
files: ${{ matrix.directory }}/target/AdvancedServerList-*.jar
files-secondary: ""
loaders: ${{ matrix.loaders }}
version-resolver: releases
game-versions: |
1.19
1.19.1
1.19.2
1.19.3
1.19.4
java: 16
modrinth-id: xss83sOY
modrinth-featured: false
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
publishHangar:
needs: [buildJars]
runs-on: ubuntu-latest
steps:
- name: Set up JDK 1.16
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '16'
- name: Download Release Assets
uses: actions/download-artifact@v3
with:
name: asl-files
- name: Move HangarUploader.jar
working-directory: hangar-uploader/target/
run: mv HangarUploader.jar ../../
- name: Execute HangarUploader.jar
run: java -jar HangarUploader.jar ${{ secrets.HANGAR_TOKEN }} ${{ needs.buildJars.outputs.plugin_release }} ${{ github.event.release.prerelease }}
env:
GITHUB_RELEASE_BODY: ${{ github.event.release.body }}
+1 -1
View File
@@ -1,6 +1,6 @@
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
+31 -19
View File
@@ -1,26 +1,36 @@
# AdvancedServerList
<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 that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Downloads
<a href="https://modrinth.com/plugin/advancedserverlist" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg" height="46" alt="modrinth" title="Available on Modrinth">
</a>
<br>
<a href="https://hangar.papermc.io/Andre_601/AdvancedServerList" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg" height="46" alt="hangar" title="Available on Hangar">
</a>
<br>
<a href="https://www.spigotmc.org/resources/102910" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@b9ff12b/assets/compact/available/spigot_vector.svg" height="46" alt="spigot" title="Available on SpigotMC">
</a>
## 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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/spigot_vector.svg" height="64" alt="platform-spigot" title="Tested on Spigot">
</a>
<a href="https://papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
</a>
<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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/velocity_vector.svg" height="64" alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
@@ -42,6 +52,8 @@ The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlu
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.
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
> [*Read More*][placeholders]
### Formatting
@@ -53,9 +65,10 @@ Only certain options are usable for each option. As an example does motd support
## Dependencies
| Dependency | Platforms | Required? |
| ---------------- | ------------- | --------- |
|------------------|---------------|-----------|
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
| [ViaVersion] | Spigot, Paper | No |
## Statistics
@@ -69,32 +82,31 @@ You can disable this in the global bStats config file located in `/plugins/bstat
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@2/assets/cozy/documentation/modrinth-gallery_vector.svg" height="64" alt="gallery" title="Check out the Gallery">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
</a>
<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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-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
[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/
[profiles]: https://www.andre601.ch/AdvancedServerList/profiles/
[conditions]: https://www.andre601.ch/AdvancedServerList/profiles/#conditions
[placeholders]: https://www.andre601.ch/AdvancedServerList/profiles/placeholders/
[minimessage]: https://www.andre601.ch/AdvancedServerList/profiles/formatting/
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[viaversion]: https://www.spigotmc.org/resources/19254/
[bstats]: https://bstats.org
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
+36 -13
View File
@@ -2,7 +2,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
@@ -34,7 +34,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spigot</artifactId>
<artifactId>bukkit</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
@@ -44,6 +44,10 @@
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>spigot</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
@@ -56,6 +60,10 @@
<id>placeholderapi-repo</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>viaversion</id>
<url>https://repo.viaversion.com/</url>
</repository>
</repositories>
<dependencies>
@@ -65,6 +73,18 @@
<version>${plugin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-spigot</artifactId>
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
@@ -74,30 +94,37 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.1.2</version>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.8.0</version>
<version>5.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.2</version>
<version>2.11.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.6.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Spigot-${plugin.version}</finalName>
<finalName>AdvancedServerList-Bukkit-${plugin.version}${project.build.commit}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -108,7 +135,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.0</version>
<configuration>
<release>16</release>
</configuration>
@@ -116,7 +143,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.0</version>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -124,10 +151,6 @@
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.spigot.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -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,12 +23,14 @@
*
*/
package ch.andre601.advancedserverlist.core.interfaces.core;
package ch.andre601.advancedserverlist.bukkit;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
public interface ProxyCore<F, P> extends PluginCore<F>{
List<P> createPlayers(List<String> lines, Placeholders... placeholders);
}
/*
* Small convenience class to "merge" the PluginCore and JavaPlugin classes.
* Allows me to have BukkitCore<?> for whenever I also need a JavaPlugin (i.e. registering events).
* See JoinEvent class for an example.
*/
public abstract class BukkitCore<F> extends JavaPlugin implements PluginCore<F>{}
@@ -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,29 +23,53 @@
*
*/
package ch.andre601.advancedserverlist.spigot.commands;
package ch.andre601.advancedserverlist.bukkit.commands;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.paper.commands.PaperCmdSender;
import ch.andre601.advancedserverlist.spigot.commands.SpigotCmdSender;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class CmdAdvancedServerList implements CommandExecutor{
import java.util.Collections;
public class CmdAdvancedServerList extends Command implements CommandExecutor{
SpigotCore plugin;
BukkitAudiences bukkitAudiences;
private final PluginCore<?> plugin;
private final BukkitAudiences audiences;
public CmdAdvancedServerList(SpigotCore plugin){
public CmdAdvancedServerList(PluginCore<?> plugin){
this(plugin, null);
}
public CmdAdvancedServerList(PluginCore<?> plugin, BukkitAudiences audiences){
super(
"advancedserverlist",
"Main command of the plugin",
"/asl [reload|help|clearCache]",
Collections.singletonList("asl")
);
this.plugin = plugin;
bukkitAudiences = BukkitAudiences.create(plugin);
this.audiences = audiences;
}
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
return true;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(new SpigotCmdSender(sender, bukkitAudiences), args);
plugin.getCore().getCommandHandler().handle(getSender(sender), args);
return true;
}
private CmdSender getSender(CommandSender sender){
return audiences == null ? new PaperCmdSender(sender) : new SpigotCmdSender(sender, audiences);
}
}
@@ -1,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,21 +23,29 @@
*
*/
package ch.andre601.advancedserverlist.spigot.events;
package ch.andre601.advancedserverlist.bukkit.events;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
public class JoinEvent<F> implements Listener{
private final SpigotCore plugin;
private final BukkitCore<F> plugin;
public JoinEvent(SpigotCore plugin){
private JoinEvent(BukkitCore<F> plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public static <F> void init(BukkitCore<F> plugin){
new JoinEvent<>(plugin);
}
@EventHandler
@@ -46,6 +54,7 @@ public class JoinEvent implements Listener{
if(address == null)
return;
plugin.getCore().getPlayerHandler().addPlayer(event.getPlayer().getName(), address.getHostString());
Player player = event.getPlayer();
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
}
}
@@ -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,12 +23,14 @@
*
*/
package ch.andre601.advancedserverlist.core.interfaces.core;
package ch.andre601.advancedserverlist.bukkit.events;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.spigot.events.PreServerListSetEvent;
import java.util.List;
public interface ServerCore<F, P, P2> extends PluginCore<F>{
List<P> createPlayers(List<String> lines, P2 player, Placeholders... placeholders);
public class PreServerListSetEventImpl extends PreServerListSetEvent{
public PreServerListSetEventImpl(ProfileEntry entry){
super(entry);
}
}
@@ -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,18 +23,18 @@
*
*/
package ch.andre601.advancedserverlist.paper.logging;
package ch.andre601.advancedserverlist.bukkit.logging;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PaperLogger implements PluginLogger{
public class BukkitLogger implements PluginLogger{
private final Logger logger;
public PaperLogger(Logger logger){
public BukkitLogger(Logger logger){
this.logger = logger;
}
@@ -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);
}
}
@@ -0,0 +1,61 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit.objects;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.spigot.objects.SpigotPlayer;
public class BukkitPlayerPlaceholders extends PlaceholderProvider{
private BukkitPlayerPlaceholders(){
super("player");
}
public static BukkitPlayerPlaceholders init(){
return new BukkitPlayerPlaceholders();
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
SpigotPlayer bukkitPlayer = (SpigotPlayer)player;
return switch(placeholder){
case "name" -> bukkitPlayer.getName();
case "protocol" -> String.valueOf(bukkitPlayer.getProtocol());
case "uuid" -> bukkitPlayer.getUUID().toString();
case "hasPlayedBefore" -> returnValue(bukkitPlayer, bukkitPlayer.hasPlayedBefore());
case "isBanned" -> returnValue(bukkitPlayer, bukkitPlayer.isBanned());
case "isWhitelisted" -> returnValue(bukkitPlayer, bukkitPlayer.isWhitelisted());
default -> null;
};
}
private String returnValue(SpigotPlayer player, Object value){
return player.getPlayer() == null ? null : String.valueOf(value);
}
}
@@ -0,0 +1,153 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bukkit.objects;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.objects.GenericServerImpl;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.events.ProtocolLibEvents;
import com.comphenix.protocol.ProtocolLibrary;
import com.viaversion.viaversion.api.Via;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.net.InetSocketAddress;
import java.util.*;
public class PAPIPlaceholders<F> extends PlaceholderExpansion{
private final BukkitCore<F> plugin;
private PAPIPlaceholders(BukkitCore<F> plugin){
this.plugin = plugin;
this.register();
}
public static <F> PAPIPlaceholders<F> init(BukkitCore<F> plugin){
return new PAPIPlaceholders<>(plugin);
}
@Override
public @NotNull String getIdentifier(){
return "asl";
}
@Override
public @NotNull String getAuthor(){
return "Andre601";
}
@Override
public @NotNull String getVersion(){
return plugin.getCore().getVersion();
}
@Override
public boolean persist(){
return true;
}
@Override
public String onPlaceholderRequest(Player pl, @NotNull String identifier){
InetSocketAddress address = pl.getAddress();
String host = resolveVirtualHost(pl, address);
CachedPlayer cached = plugin.getCore().getPlayerHandler().getCachedPlayer(pl.getUniqueId());
int protocol = resolveProtocol(pl);
int online = Bukkit.getOnlinePlayers().size();
int max = Bukkit.getMaxPlayers();
GenericServer server = new GenericServerImpl(online, max, host);
GenericPlayer player = new SpigotPlayerImpl(pl, cached, protocol);
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
if(profile == null)
return null;
ProfileEntry entry = ProfileManager.merge(profile);
if(ProfileManager.checkOption(entry.extraPlayersEnabled()))
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
GenericServer finalServer = new GenericServerImpl(online, max, host);
return switch(identifier.toLowerCase(Locale.ROOT)){
case "motd" -> getOption(entry.motd(), pl, player, finalServer);
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer);
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
case "extra_players_max" -> String.valueOf(max);
default -> null;
};
}
private String getOption(String str, Player pl, GenericPlayer player, GenericServer server){
return getOption(Collections.singletonList(str), pl, player, server);
}
private String getOption(List<String> list, Player pl, GenericPlayer player, GenericServer server){
return ComponentParser.list(list)
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
.modifyText(text -> StringReplacer.replace(text, player, server))
.toString();
}
private int resolveProtocol(Player player){
if(Bukkit.getPluginManager().isPluginEnabled("ViaVersion"))
return Via.getAPI().getPlayerVersion(player.getUniqueId());
// Since Spigot version requires ProtocolLib can we use it here safely if the plugin instance is SpigotCore.
if(plugin instanceof SpigotCore)
return ProtocolLibrary.getProtocolManager().getProtocolVersion(player);
// getProtocolVersion is only in Paper, so this is only called when main class isn't SpigotCore
return Bukkit.getUnsafe().getProtocolVersion();
}
private String resolveVirtualHost(Player player, InetSocketAddress address){
try {
// Server is a Paper Server with Player#getVirtualHost()
Class.forName("com.destroystokyo.paper.network.NetworkClient");
return player.getVirtualHost() == null ? null : player.getVirtualHost().getHostString();
}catch(ClassNotFoundException ignored){}
if(address == null)
return null;
return ProtocolLibEvents.getHostAddresses().get(address.getHostString());
}
}
@@ -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,25 +23,53 @@
*
*/
package ch.andre601.advancedserverlist.spigot;
package ch.andre601.advancedserverlist.bukkit.objects;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
import ch.andre601.advancedserverlist.spigot.objects.SpigotPlayer;
import org.bukkit.OfflinePlayer;
public class SpigotPlayer extends GenericPlayer<OfflinePlayer>{
public class SpigotPlayerImpl extends GenericPlayerImpl implements SpigotPlayer{
public SpigotPlayer(OfflinePlayer player, String name, int protocol){
private final OfflinePlayer player;
private boolean playedBefore = false;
private boolean banned = false;
private boolean whitelisted = false;
public SpigotPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
this.player = player;
this.name = player == null ? name : player.getName();
this.name = player == null ? cachedPlayer.getName() : player.getName();
this.protocol = protocol;
this.uuid = player == null ? cachedPlayer.getUuid() : player.getUniqueId();
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
this.uuid = player.getUniqueId();
}
@Override
public OfflinePlayer getPlayer(){
return player;
}
@Override
public boolean hasPlayedBefore(){
return playedBefore;
}
@Override
public boolean isBanned(){
return banned;
}
@Override
public boolean isWhitelisted(){
return whitelisted;
}
}
@@ -0,0 +1,61 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository;
import org.jetbrains.annotations.NotNull;
public class ASLLoader implements PluginLoader{
@Override
public void classloader(@NotNull PluginClasspathBuilder pluginClasspathBuilder){
ComponentLogger logger = pluginClasspathBuilder.getContext().getLogger();
logger.info(Component.text("Loading Libraries for plugin..."));
MavenLibraryResolver resolver = new MavenLibraryResolver();
resolver.addRepository(new RemoteRepository.Builder(
"paper-maven",
"default",
"https://repo.papermc.io/repository/maven-public/"
).build());
logger.info(Component.text("Loading com.squareup.okhttp3:okhttp:4.10.0 from repo.papermc.io..."));
resolver.addDependency(new Dependency(new DefaultArtifact("com.squareup.okhttp3:okhttp:4.10.0"), null));
pluginClasspathBuilder.addLibrary(resolver);
logger.info(Component.text("Loading libraries complete!"));
}
}
@@ -0,0 +1,137 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bukkit.events.JoinEvent;
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
import ch.andre601.advancedserverlist.bukkit.objects.BukkitPlayerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.PAPIPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.paper.events.PaperPingEvent;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.util.CachedServerIcon;
import java.nio.file.Path;
public class PaperCore extends BukkitCore<CachedServerIcon>{
private final PluginLogger logger = new BukkitLogger(getLogger());
private AdvancedServerList<CachedServerIcon> core;
private FaviconHandler<CachedServerIcon> faviconHandler;
private PAPIPlaceholders<CachedServerIcon> papiPlaceholders = null;
@Override
public void onEnable(){
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init());
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
papiPlaceholders = PAPIPlaceholders.init(this);
}
@Override
public void onDisable(){
if(papiPlaceholders != null){
papiPlaceholders.unregister();
papiPlaceholders = null;
}
getCore().disable();
}
@Override
public void loadCommands(){
if(getServer().getCommandMap().register("asl", new CmdAdvancedServerList(this))){
getPluginLogger().info("Registered /advancedserverlist:advancedserverlist");
}else{
getPluginLogger().info("Registered /asl:advancedserverlist");
}
}
@Override
public void loadEvents(){
JoinEvent.init(this);
PaperPingEvent.init(this);
}
@Override
public void loadMetrics(){
new Metrics(this, 15584).addCustomChart(new SimplePie("profiles",
() -> String.valueOf(core.getFileHandler().getProfiles().size())
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList<CachedServerIcon> getCore(){
return core;
}
@Override
public Path getFolderPath(){
return getDataFolder().toPath();
}
@Override
public PluginLogger getPluginLogger(){
return logger;
}
@Override
public FaviconHandler<CachedServerIcon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getServer().getName();
}
@Override
public String getPlatformVersion(){
return getServer().getVersion();
}
@Override
public String getLoader(){
return "paper";
}
}
@@ -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
@@ -25,7 +25,7 @@
package ch.andre601.advancedserverlist.paper.commands;
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import org.bukkit.command.CommandSender;
@@ -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
@@ -25,14 +25,19 @@
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.events.PreServerListSetEventImpl;
import ch.andre601.advancedserverlist.bukkit.objects.SpigotPlayerImpl;
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.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.PaperPlayer;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import com.destroystokyo.paper.profile.PlayerProfile;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
@@ -40,9 +45,11 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.util.CachedServerIcon;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, CachedServerIcon>{
public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon, SpigotPlayerImpl>{
private final PaperCore plugin;
private final PaperServerListPingEvent event;
@@ -52,6 +59,14 @@ public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, Cac
this.event = event;
}
@Override
public GenericServerListEvent callEvent(ProfileEntry entry){
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
plugin.getServer().getPluginManager().callEvent(event);
return event;
}
@Override
public void setMaxPlayers(int maxPlayers){
event.setMaxPlayers(maxPlayers);
@@ -74,12 +89,25 @@ public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, Cac
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
public void setPlayers(List<String> lines, SpigotPlayerImpl player, GenericServer server){
event.getPlayerSample().clear();
List<PlayerProfile> players = new ArrayList<>(lines.size());
event.getPlayerSample().addAll(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
for(String line : lines){
String parsed = ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString();
players.add(Bukkit.createProfile(UUID.randomUUID(), parsed));
}
event.getPlayerSample().addAll(players);
}
@Override
@@ -123,7 +151,7 @@ public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, Cac
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
public String parsePAPIPlaceholders(String text, SpigotPlayerImpl player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
@@ -136,21 +164,15 @@ public class PaperEventWrapper implements GenericEventWrapper<OfflinePlayer, Cac
}
@Override
public PluginCore<CachedServerIcon> getPlugin(){
public BukkitCore<CachedServerIcon> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
public SpigotPlayerImpl createPlayer(CachedPlayer player, int protocol){
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
if(player == null){
player = Bukkit.getOfflinePlayer(name);
return new PaperPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new PaperPlayer(player, name, protocol);
return new SpigotPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
}
@Override
@@ -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
@@ -31,17 +31,21 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class PingEvent implements Listener{
public class PaperPingEvent implements Listener{
private final PaperCore plugin;
public PingEvent(PaperCore plugin){
private PaperPingEvent(PaperCore plugin){
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public static void init(PaperCore plugin){
new PaperPingEvent(plugin);
}
@EventHandler
public void onServerPing(PaperServerListPingEvent event){
public void onPaperServerListPing(PaperServerListPingEvent event){
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
}
}
@@ -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
@@ -25,35 +25,30 @@
package ch.andre601.advancedserverlist.spigot;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bukkit.logging.BukkitLogger;
import ch.andre601.advancedserverlist.bukkit.objects.BukkitPlayerPlaceholders;
import ch.andre601.advancedserverlist.bukkit.objects.PAPIPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
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 net.kyori.adventure.platform.bukkit.BukkitAudiences;
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 ServerCore<WrappedServerPing.CompressedImage, WrappedGameProfile, OfflinePlayer>{
public class SpigotCore extends BukkitCore<WrappedServerPing.CompressedImage>{
private final PluginLogger logger = new SpigotLogger(getLogger());
private final PluginLogger logger = new BukkitLogger(getLogger());
private AdvancedServerList core;
FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
private AdvancedServerList<WrappedServerPing.CompressedImage> core;
private FaviconHandler<WrappedServerPing.CompressedImage> faviconHandler = null;
private PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders = null;
@Override
public void onEnable(){
@@ -70,11 +65,16 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
}catch(ClassNotFoundException ignored){}
}
this.core = new AdvancedServerList(this);
this.core = AdvancedServerList.init(this, BukkitPlayerPlaceholders.init());
}
@Override
public void onDisable(){
if(papiPlaceholders != null){
papiPlaceholders.unregister();
papiPlaceholders = null;
}
getCore().disable();
}
@@ -82,10 +82,10 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
public void loadCommands(){
PluginCommand cmd = getServer().getPluginCommand("advancedserverlist");
if(cmd == null){
getPluginLogger().warn("Could not register command /advancedserverlist");
getPluginLogger().warn("Unable to register command /advancedserverlist");
return;
}
cmd.setExecutor(new CmdAdvancedServerList(this));
cmd.setExecutor(new CmdAdvancedServerList(this, BukkitAudiences.create(this)));
}
@Override
@@ -109,7 +109,7 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
}
@Override
public AdvancedServerList getCore(){
public AdvancedServerList<WrappedServerPing.CompressedImage> getCore(){
return core;
}
@@ -146,26 +146,8 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
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;
public void setPapiPlaceholders(PAPIPlaceholders<WrappedServerPing.CompressedImage> papiPlaceholders){
this.papiPlaceholders = papiPlaceholders;
}
private void printPaperInfo(){
@@ -173,7 +155,7 @@ public class SpigotCore extends JavaPlugin implements ServerCore<WrappedServerPi
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 downloading of external Libraries already provided by Paper (i.e. Adventure).");
getPluginLogger().warn(" - No dependency on ProtocolLib thanks to provided Events.");
getPluginLogger().warn("");
getPluginLogger().warn("AdvancedServerList may work as normal, but consider using the PaperMC version instead!");
@@ -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
@@ -25,7 +25,7 @@
package ch.andre601.advancedserverlist.spigot.commands;
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender;
@@ -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
@@ -25,7 +25,9 @@
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.bukkit.events.JoinEvent;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.bukkit.objects.PAPIPlaceholders;
import com.comphenix.protocol.ProtocolLibrary;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -52,7 +54,10 @@ public class LoadEvent implements Listener{
return;
}
manager.registerEvents(new JoinEvent(plugin), plugin);
manager.registerEvents(new PingEvent(plugin, ProtocolLibrary.getProtocolManager()), plugin);
JoinEvent.init(plugin);
ProtocolLibEvents.init(plugin, ProtocolLibrary.getProtocolManager());
if(manager.isPluginEnabled("PlaceholderAPI"))
plugin.setPapiPlaceholders(PAPIPlaceholders.init(plugin));
}
}
@@ -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
@@ -25,39 +25,50 @@
package ch.andre601.advancedserverlist.spigot.events;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bukkit.BukkitCore;
import ch.andre601.advancedserverlist.bukkit.events.PreServerListSetEventImpl;
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.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.spigot.SpigotCore;
import ch.andre601.advancedserverlist.spigot.SpigotPlayer;
import ch.andre601.advancedserverlist.bukkit.objects.SpigotPlayerImpl;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.AdventureComponentConverter;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlayer, WrappedServerPing.CompressedImage>{
public class ProtocolLibEventWrapper implements GenericEventWrapper<WrappedServerPing.CompressedImage, SpigotPlayerImpl>{
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){
public ProtocolLibEventWrapper(SpigotCore plugin, PacketEvent event){
this.plugin = plugin;
this.event = event;
this.ping = event.getPacket().getServerPings().read(0);
}
@Override
public GenericServerListEvent callEvent(ProfileEntry entry){
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
plugin.getServer().getPluginManager().callEvent(event);
this.hostAddresses = hostAddresses;
return event;
}
@Override
@@ -67,7 +78,7 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlaye
@Override
public void setMotd(Component component){
ping.setMotD(AdventureComponentConverter.fromComponent(component));
ping.setMotD(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)));
}
@Override
@@ -82,10 +93,24 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlaye
}
@Override
public void setPlayers(List<String> players, GenericPlayer<OfflinePlayer> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders){
ping.setPlayers(
plugin.createPlayers(players, player.getPlayer(), playerPlaceholders, serverPlaceholders)
);
public void setPlayers(List<String> lines, SpigotPlayerImpl player, GenericServer server){
List<WrappedGameProfile> players = new ArrayList<>(lines.size());
for(String line : lines){
String parsed = ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> {
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
return text;
})
.toString();
players.add(new WrappedGameProfile(UUID.randomUUID(), parsed));
}
ping.setPlayers(players);
}
@Override
@@ -100,7 +125,9 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlaye
// Not used in ProtocolLib
@Override
public void updateEvent(){}
public void updateEvent(){
event.getPacket().getServerPings().write(0, ping);
}
@Override
public boolean isInvalidProtocol(){
@@ -128,7 +155,7 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlaye
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<OfflinePlayer> player){
public String parsePAPIPlaceholders(String text, SpigotPlayerImpl player){
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
return PlaceholderAPI.setPlaceholders(player.getPlayer(), text);
@@ -141,26 +168,19 @@ public class ProtocolLibEventWrapper implements GenericEventWrapper<OfflinePlaye
if(host == null)
return null;
return hostAddresses.get(host);
return ProtocolLibEvents.getHostAddresses().get(host);
}
@Override
public PluginCore<WrappedServerPing.CompressedImage> getPlugin(){
public BukkitCore<WrappedServerPing.CompressedImage> getPlugin(){
return plugin;
}
@Override
public GenericPlayer<OfflinePlayer> createPlayer(String name, int protocol){
OfflinePlayer player = Bukkit.getPlayerExact(name);
public SpigotPlayerImpl createPlayer(CachedPlayer player, int protocol){
OfflinePlayer pl = Bukkit.getOfflinePlayer(player.getUuid());
if(player == null){
//noinspection deprecation
player = Bukkit.getOfflinePlayer(name);
return new SpigotPlayer(player.hasPlayedBefore() ? player : null, name, protocol);
}
return new SpigotPlayer(player, name, protocol);
return new SpigotPlayerImpl(pl.hasPlayedBefore() ? pl : null, player, protocol);
}
@Override
@@ -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
@@ -32,22 +32,32 @@ import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
public class PingEvent implements Listener{
public class ProtocolLibEvents implements Listener{
private final ProtocolManager protocolManager;
private final Map<String, String> hostAddresses = new HashMap<>();
private static final Map<String, String> hostAddresses = new HashMap<>();
public PingEvent(SpigotCore plugin, ProtocolManager protocolManager){
private ProtocolLibEvents(SpigotCore plugin, ProtocolManager protocolManager){
this.protocolManager = protocolManager;
loadPacketListener(plugin);
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public static void init(SpigotCore plugin, ProtocolManager protocolManager){
new ProtocolLibEvents(plugin, protocolManager);
}
public static Map<String, String> getHostAddresses(){
return hostAddresses;
}
private void loadPacketListener(SpigotCore spigotPlugin){
@@ -67,7 +77,7 @@ public class PingEvent implements Listener{
protocolManager.addPacketListener(new PacketAdapter(spigotPlugin, ListenerPriority.LOW, PacketType.Status.Server.SERVER_INFO){
@Override
public void onPacketSending(PacketEvent event){
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event, hostAddresses));
PingEventHandler.handleEvent(new ProtocolLibEventWrapper(spigotPlugin, event));
}
});
}
@@ -4,16 +4,26 @@ version: '${plugin.version}'
description: '${plugin.description}'
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
loader: 'ch.andre601.advancedserverlist.paper.ASLLoader'
api-version: 1.19
libraries:
- 'com.squareup.okhttp3:okhttp:4.10.0'
dependencies:
- name: PlaceholderAPI
required: false
bootstrap: false
- name: ViaVersion
required: false
bootstrap: false
softdepend:
- 'PlaceholderAPI'
load-after:
- name: PlaceholderAPI
bootstrap: false
- name: ViaVersion
bootstrap: false
commands:
# The below stuff is NOT used by Paper plugin.
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [help|reload]'
@@ -21,11 +31,12 @@ commands:
- 'asl'
permission: 'advancedserverlist.admin'
permissions:
# This is actually supported(?)
permissions:
advancedserverlist.*:
description: 'Grants access to all permissions'
default: op
children:
children:
- 'advancedserverlist.admin'
advancedserverlist.admin:
description: 'Grants access to all permissions'
@@ -7,12 +7,14 @@ main: 'ch.andre601.advancedserverlist.spigot.SpigotCore'
api-version: 1.19
folia-supported: true
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:
@@ -22,7 +24,7 @@ softdepend:
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [help|reload]'
usage: '/<command> [help|reload|clearCache]'
aliases:
- 'asl'
permission: 'advancedserverlist.admin'
@@ -49,4 +51,7 @@ permissions:
default: op
advancedserverlist.command.reload:
description: 'Grants access to /asl reload'
default: op
advancedserverlist.command.clearcache:
description: 'Clears the Player and Favicon cache'
default: op
+33 -7
View File
@@ -2,7 +2,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
@@ -58,6 +58,12 @@
<version>${plugin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bungeecord</artifactId>
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
@@ -72,6 +78,18 @@
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.13.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.13.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
@@ -84,10 +102,22 @@
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}</finalName>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}${project.build.commit}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -98,7 +128,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -119,10 +149,6 @@
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.caffeine</shadedPattern>
</relocation>
<relocation>
<pattern>okhttp3</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.okhttp3</shadedPattern>
@@ -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
@@ -29,32 +29,27 @@ import ch.andre601.advancedserverlist.bungeecord.commands.CmdAdvancedServerList;
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.bungeecord.objects.BungeePlayerPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
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.interfaces.core.PluginCore;
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 ProxyCore<Favicon, ServerPing.PlayerInfo>{
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
private AdvancedServerList core;
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private final PluginLogger logger = new BungeeLogger(getLogger());
@Override
public void onEnable(){
this.core = new AdvancedServerList(this);
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init());
}
@Override
@@ -90,7 +85,7 @@ public class BungeeCordCore extends Plugin implements ProxyCore<Favicon, ServerP
}
@Override
public AdvancedServerList getCore(){
public AdvancedServerList<Favicon> getCore(){
return core;
}
@@ -126,20 +121,4 @@ public class BungeeCordCore extends Plugin implements ProxyCore<Favicon, ServerP
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;
}
}
@@ -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
@@ -25,7 +25,7 @@
package ch.andre601.advancedserverlist.bungeecord.commands;
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
@@ -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
@@ -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
@@ -25,26 +25,29 @@
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.BungeePlayer;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.bungeecord.objects.BungeePlayerImpl;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
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.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import 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;
import java.util.UUID;
public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Favicon>{
public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePlayerImpl>{
private final BungeeCordCore plugin;
private final ProxyPingEvent event;
@@ -58,6 +61,14 @@ public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Fa
this.ping = event.getResponse();
}
@Override
public GenericServerListEvent callEvent(ProfileEntry entry){
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
plugin.getProxy().getPluginManager().callEvent(event);
return event;
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.getPlayers().setMax(maxPlayers);
@@ -80,12 +91,20 @@ public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Fa
}
@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]);
public void setPlayers(List<String> lines, BungeePlayerImpl player, GenericServer server){
ServerPing.PlayerInfo[] players = new ServerPing.PlayerInfo[lines.size()];
if(playerInfos.length > 0)
ping.getPlayers().setSample(playerInfos);
for(int i = 0; i < players.length; i++){
String parsed = ComponentParser.text(lines.get(i))
.modifyText(text -> StringReplacer.replace(text, player, server))
.toString();
ServerPing.PlayerInfo pi = new ServerPing.PlayerInfo(parsed, UUID.randomUUID());
players[i] = pi;
}
if(players.length > 0)
ping.getPlayers().setSample(players);
}
@Override
@@ -130,7 +149,7 @@ public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Fa
}
@Override
public String parsePAPIPlaceholders(String text, GenericPlayer<ProxiedPlayer> player){
public String parsePAPIPlaceholders(String text, BungeePlayerImpl player){
return text;
}
@@ -145,8 +164,8 @@ public class BungeeEventWrapper implements GenericEventWrapper<ProxiedPlayer, Fa
}
@Override
public GenericPlayer<ProxiedPlayer> createPlayer(String name, int protocol){
return new BungeePlayer(name, protocol);
public BungeePlayerImpl createPlayer(CachedPlayer player, int protocol){
return new BungeePlayerImpl(player, protocol);
}
@Override
@@ -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
@@ -26,6 +26,7 @@
package ch.andre601.advancedserverlist.bungeecord.events;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
@@ -44,6 +45,8 @@ public class JoinEvent implements Listener{
@EventHandler
public void onJoin(PostLoginEvent event){
InetSocketAddress address = (InetSocketAddress)event.getPlayer().getPendingConnection().getSocketAddress();
plugin.getCore().getPlayerHandler().addPlayer(event.getPlayer().getName(), address.getHostString());
ProxiedPlayer player = event.getPlayer();
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
}
}
@@ -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
@@ -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,11 +23,13 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
package ch.andre601.advancedserverlist.bungeecord.events;
import java.util.Map;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
public interface Placeholders{
public class PreServerListSetEventImpl extends PreServerListSetEvent{
Map<String, Object> getReplacements();
public PreServerListSetEventImpl(ProfileEntry entry){
super(entry);
}
}
@@ -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
@@ -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);
}
}
@@ -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,15 +23,16 @@
*
*/
package ch.andre601.advancedserverlist.bungeecord;
package ch.andre601.advancedserverlist.bungeecord.objects;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
public class BungeePlayer extends GenericPlayer<ProxiedPlayer>{
public class BungeePlayerImpl extends GenericPlayerImpl{
public BungeePlayer(String name, int protocol){
this.name = name;
public BungeePlayerImpl(CachedPlayer player, int protocol){
this.name = player.getName();
this.protocol = protocol;
this.uuid = player.getUuid();
}
}
@@ -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.bungeecord.objects;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import java.util.Locale;
public class BungeePlayerPlaceholders extends PlaceholderProvider{
private BungeePlayerPlaceholders(){
super("player");
}
public static BungeePlayerPlaceholders init(){
return new BungeePlayerPlaceholders();
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
return switch(placeholder.toLowerCase(Locale.ROOT)){
case "name" -> player.getName();
case "protocol" -> String.valueOf(player.getProtocol());
case "uuid" -> String.valueOf(player.getUUID());
default -> null;
};
}
}
+53 -14
View File
@@ -2,7 +2,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
@@ -43,47 +43,80 @@
<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>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.12.0</version>
<version>4.13.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.12.0</version>
<version>4.13.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.2</version>
<scope>compile</scope>
<version>4.13.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
<version>2.10.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
<version>4.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.unascribed</groupId>
<artifactId>flexver-java</artifactId>
<version>1.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
<scope>provided</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Core-${plugin.version}</finalName>
<finalName>AdvancedServerList-Core-${plugin.version}${project.build.commit}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -94,7 +127,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -111,6 +144,12 @@
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.unascribed</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
@@ -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
@@ -25,10 +25,13 @@
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.objects.ServerPlaceholders;
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
import java.io.IOException;
@@ -36,27 +39,35 @@ import java.io.InputStream;
import java.nio.file.Path;
import java.util.Properties;
public class AdvancedServerList{
public class AdvancedServerList<F>{
private final PluginCore<?> plugin;
private final PluginCore<F> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private UpdateChecker updateChecker;
private String version;
public AdvancedServerList(PluginCore<?> plugin){
private AdvancedServerList(PluginCore<F> plugin, PlaceholderProvider placeholders){
this.plugin = plugin;
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.api.addPlaceholderProvider(placeholders);
this.api.addPlaceholderProvider(new ServerPlaceholders());
load();
}
public PluginCore<?> getPlugin(){
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider placeholders){
return new AdvancedServerList<>(plugin, placeholders);
}
public PluginCore<F> getPlugin(){
return plugin;
}
@@ -76,8 +87,12 @@ public class AdvancedServerList{
return version;
}
public AdvancedServerListAPI getApi(){
return api;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving cache.data file...");
getPlugin().getPluginLogger().info("Saving playercache.json file...");
getPlayerHandler().save();
if(updateChecker != null){
@@ -92,6 +107,10 @@ public class AdvancedServerList{
plugin.clearFaviconCache();
}
public void clearPlayerCache(){
getPlayerHandler().clearCache();
}
private void load(){
printBanner();
resolveVersion();
@@ -125,7 +144,7 @@ public class AdvancedServerList{
plugin.loadEvents();
getPlugin().getPluginLogger().info("Events loaded!");
getPlugin().getPluginLogger().info("Loading cache.data...");
getPlugin().getPluginLogger().info("Loading playercache.json...");
getPlayerHandler().load();
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
@@ -139,7 +158,6 @@ public class AdvancedServerList{
}
private void printBanner(){
getPlugin().getPluginLogger().info("");
getPlugin().getPluginLogger().info(" _____ _");
getPlugin().getPluginLogger().info(" /\\ / ____| |");
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
@@ -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
@@ -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
@@ -31,6 +31,7 @@ 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;
@@ -41,7 +42,10 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class UpdateChecker{
@@ -80,13 +84,12 @@ public class UpdateChecker{
int result = version.compare(core.getVersion());
switch(result){
case -2 -> {
logger.warn("Encountered an exception while comparing versions. Are they valid?");
logger.warn("Own version: %s; New version: %s", core.getVersion(), version.getVersionNumber());
}
case -1 -> logger.info("You seem to run a newer version compared to Modrinth. Are you running a dev build?");
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 -> printUpdateBanner(version.getVersionNumber(), version.getId());
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);
@@ -94,12 +97,19 @@ public class UpdateChecker{
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();
@@ -144,6 +154,7 @@ public class UpdateChecker{
}
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;
@@ -160,13 +171,20 @@ public class UpdateChecker{
});
}
private void printUpdateBanner(String version, String versionId){
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("==================================================================");
@@ -177,10 +195,13 @@ public class UpdateChecker{
private String id;
@SuppressWarnings("FieldMayBeFinal")
private String versionNumber;
@SuppressWarnings("FieldMayBeFinal")
private String versionType;
public ModrinthVersion(String id, String versionNumber){
public ModrinthVersion(String id, String versionNumber, String versionType){
this.id = id;
this.versionNumber = versionNumber;
this.versionType = versionType;
}
public String getId(){
@@ -191,26 +212,12 @@ public class UpdateChecker{
return versionNumber;
}
public boolean isRelease(){
return versionType.equals("release");
}
public int compare(String version){
String[] oldParts = version.split("\\.");
String[] newParts = versionNumber.split("\\.");
int length = Math.max(oldParts.length, newParts.length);
for(int i = 0; i < length; i++){
try{
int oldPart = i < oldParts.length ? Integer.parseInt(oldParts[i]) : 0;
int newPart = i < newParts.length ? Integer.parseInt(newParts[i]) : 0;
if(oldPart < newPart)
return 1;
if(oldPart > newPart)
return -1;
}catch(NumberFormatException ex){
return -2;
}
}
return 0;
return FlexVerComparator.compare(version, versionNumber);
}
}
}
@@ -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
@@ -26,56 +26,121 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.PluginCommand;
import java.util.ArrayList;
import java.util.List;
public class CommandHandler{
private final AdvancedServerList core;
private final List<PluginCommand> subCommands = new ArrayList<>();
public CommandHandler(AdvancedServerList core){
this.core = core;
subCommands.add(new Help());
subCommands.add(new Reload(core));
subCommands.add(new ClearCache(core));
}
public void handle(CmdSender sender, String[] args){
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>]";
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>]";
if(args.length == 0){
sender.sendErrorMsg("<red>Too few arguments! Use <grey>/asl help</grey> for a list of commands.");
return;
}
if(args.length == 0 || args[0].equalsIgnoreCase("help")){
if(sender.hasPermission("advancedserverlist.command.help")){
sender.sendMsg("%s - Commands", prefix);
sender.sendMsg();
sender.sendMsg("<gradient:aqua:white>/asl help</gradient> <grey>- Shows this Help");
sender.sendMsg();
sender.sendMsg("<gradient:aqua:white>/asl reload</gradient> <grey>- Reloads the plugin");
}else{
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
}
}else
if(args[0].equalsIgnoreCase("reload")){
if(sender.hasPermission("advancedserverlist.command.reload")){
sender.sendMsg("%s Reloading plugin...", prefix);
if(core.getFileHandler().reloadConfig()){
sender.sendMsg("%s <green>Reloaded <grey>config.yml</grey>!", prefix);
}else{
sender.sendMsg("%s <red>Error while reloading the <grey>config.yml</grey>!", errorPrefix);
for(PluginCommand subCommand : subCommands){
if(subCommand.getArgument().equalsIgnoreCase(args[0])){
if(!sender.hasPermission(subCommand.getPermission())){
sender.sendErrorMsg(
"<red>You do not have the permission <grey>%s</grey> to execute this command.",
subCommand.getPermission()
);
return;
}
if(core.getFileHandler().reloadProfiles()){
sender.sendMsg("%s <green>Loaded <grey>%d Profile(s)</grey>!", prefix, core.getFileHandler().getProfiles().size());
}else{
sender.sendMsg("%s <red>Cannot load Profiles!", errorPrefix);
}
core.clearFaviconCache();
sender.sendMsg("%s <green>Successfully cleared Favicon cache!", prefix);
sender.sendMsg("%s <green>Reload complete!", prefix);
}else{
sender.sendMsg("%s <red>You do not have permissions to execute this command!", errorPrefix);
subCommand.handle(sender);
return;
}
}else{
sender.sendMsg("%s <red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", prefix, args[0]);
}
sender.sendErrorMsg("<red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", args[0]);
}
private static class Help extends PluginCommand{
public Help(){
super("help");
}
@Override
public void handle(CmdSender sender){
sender.sendPrefixedMsg("- Commands");
sender.sendMsg();
sender.sendMsg("<aqua>/asl <white>help <grey>- Shows this help");
sender.sendMsg();
sender.sendMsg("<aqua>/asl <white>reload <grey>- Reloads the plugin and clears caches");
sender.sendMsg();
sender.sendMsg("<aqua>/asl <white>clearCache <grey>- Clears the Player and Favicon cache");
}
}
private static class Reload extends PluginCommand{
private final AdvancedServerList core;
public Reload(AdvancedServerList core){
super("reload");
this.core = core;
}
@Override
public void handle(CmdSender sender){
sender.sendPrefixedMsg("Reloading plugin...");
if(core.getFileHandler().reloadConfig()){
sender.sendPrefixedMsg("<green>Reloaded <grey>config.yml</grey>!");
}else{
sender.sendErrorMsg("<red>Error while reloading <grey>config.yml</grey>!");
}
if(core.getFileHandler().reloadProfiles()){
sender.sendPrefixedMsg("<green>Loaded <grey>%d profile(s)</grey>!", core.getFileHandler().getProfiles().size());
}else{
sender.sendErrorMsg("<red>Error while loading profile(s)!");
}
core.clearFaviconCache();
sender.sendPrefixedMsg("<green>Successfully cleared Favicon Cache!");
core.clearPlayerCache();
sender.sendPrefixedMsg("<green>Successfully cleared Player Cache!");
sender.sendPrefixedMsg("<green>Reload complete!");
}
}
private static class ClearCache extends PluginCommand{
private final AdvancedServerList core;
public ClearCache(AdvancedServerList core){
super("clearCache");
this.core = core;
}
@Override
public void handle(CmdSender sender){
sender.sendPrefixedMsg("Clearing caches...");
core.clearFaviconCache();
sender.sendPrefixedMsg("<green>Successfully cleared Favicon Cache!");
core.clearPlayerCache();
sender.sendPrefixedMsg("<green>Successfully cleared Player Cache!");
sender.sendPrefixedMsg("<green>Cache clearing complete!");
}
}
}
@@ -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
@@ -25,81 +25,86 @@
package ch.andre601.advancedserverlist.core.events;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.GenericServerImpl;
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.players.GenericPlayer;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
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){
public static <F, P extends GenericPlayer> void handleEvent(GenericEventWrapper<F, P> 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();
P player = event.createPlayer(
plugin.getCore().getPlayerHandler().getCachedPlayer(event.getPlayerIP()),
event.getProtocolVersion()
);
GenericServer server = new GenericServerImpl(online, max, host);
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
if(profile == null)
return;
if(profile.isExtraPlayersEnabled()){
max = online + profile.getExtraPlayers();
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
if(e == null || e.isCancelled())
return;
ProfileEntry entry = e.getEntry();
if(entry.isInvalid())
return;
if(ProfileManager.checkOption(entry.extraPlayersEnabled())){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
event.setMaxPlayers(max);
}
serverPlaceholders = new ServerPlaceholders(online, max, host);
GenericServer finalServer = new GenericServerImpl(online, max, host);
if(!profile.getMotd().isEmpty()){
if(ProfileManager.checkOption(entry.motd())){
event.setMotd(
ComponentParser.list(profile.getMotd())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
ComponentParser.list(entry.motd())
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toComponent()
);
}
if(profile.shouldHidePlayers()){
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
if(hidePlayers){
event.hidePlayers();
}
if(!profile.getPlayerCount().isEmpty() && !profile.shouldHidePlayers()){
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers){
event.setPlayerCount(
ComponentParser.text(profile.getPlayerCount())
.replacements(playerPlaceholders)
.replacements(serverPlaceholders)
ComponentParser.text(entry.playerCountText())
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString()
);
}
if(!profile.getPlayers().isEmpty() && !profile.shouldHidePlayers()){
event.setPlayers(profile.getPlayers(), player, playerPlaceholders, serverPlaceholders);
if(ProfileManager.checkOption(entry.players()) && !hidePlayers){
event.setPlayers(entry.players(), player, server);
}
if(!profile.getFavicon().isEmpty()){
String favicon = StringReplacer.replace(profile.getFavicon(), playerPlaceholders.getReplacements());
if(ProfileManager.checkOption(entry.favicon())){
String favicon = StringReplacer.replace(entry.favicon(), player, server);
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
try{
@@ -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
@@ -28,6 +28,8 @@ 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.ServerListProfile;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
@@ -106,6 +108,7 @@ public class FileHandler{
return false;
}
}
return reloadProfiles();
}
@@ -127,7 +130,7 @@ public class FileHandler{
if(tmp == null)
continue;
profiles.add(new ServerListProfile(tmp, logger));
profiles.add(ServerListProfile.Builder.resolve(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();
@@ -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
@@ -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);
}
@@ -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,25 +23,26 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
package ch.andre601.advancedserverlist.core.interfaces.commands;
import java.util.HashMap;
import java.util.Map;
public class ServerPlaceholders implements Placeholders{
public interface CmdSender{
private final Map<String, Object> replacements = new HashMap<>();
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>] ";
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>] ";
public ServerPlaceholders(int online, int max, String host){
this.replacements.put("${server playersOnline}", online);
this.replacements.put("${server playersMax}", max);
if(host != null)
this.replacements.put("${server host}", host);
boolean hasPermission(String permission);
void sendMsg(String msg, Object... args);
default void sendMsg(){
sendMsg("");
}
@Override
public Map<String, Object> getReplacements(){
return this.replacements;
default void sendPrefixedMsg(String msg, Object... args){
sendMsg(prefix + msg, args);
}
default void sendErrorMsg(String msg, Object... args){
sendMsg(errorPrefix + msg, args);
}
}
@@ -0,0 +1,47 @@
/*
* 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.interfaces.commands;
import java.util.Locale;
public abstract class PluginCommand{
private final String argument;
public PluginCommand(String argument){
this.argument = argument;
}
public String getArgument(){
return argument;
}
public String getPermission(){
return "advancedserverlist.command." + getArgument().toLowerCase(Locale.ROOT);
}
public abstract void handle(CmdSender sender);
}
@@ -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
@@ -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
@@ -25,17 +25,21 @@
package ch.andre601.advancedserverlist.core.interfaces.events;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
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.core.objects.CachedPlayer;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
public interface GenericEventWrapper<P, F>{
public interface GenericEventWrapper<F, P extends GenericPlayer>{
GenericServerListEvent callEvent(ProfileEntry entry);
void setMaxPlayers(int maxPlayers);
@@ -45,7 +49,7 @@ public interface GenericEventWrapper<P, F>{
void setPlayerCount(String name);
void setPlayers(List<String> players, GenericPlayer<P> player, PlayerPlaceholders playerPlaceholders, ServerPlaceholders serverPlaceholders);
void setPlayers(List<String> players, P player, GenericServer server);
void setFavicon(F favicon);
@@ -63,13 +67,13 @@ public interface GenericEventWrapper<P, F>{
String getPlayerIP();
String parsePAPIPlaceholders(String text, GenericPlayer<P> player);
String parsePAPIPlaceholders(String text, P player);
String getVirtualHost();
PluginCore<F> getPlugin();
GenericPlayer<P> createPlayer(String name, int protocol);
P createPlayer(CachedPlayer player, int protocol);
F createFavicon(BufferedImage image) throws Exception;
@@ -0,0 +1,54 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.objects;
import java.util.UUID;
@SuppressWarnings("FieldMayBeFinal")
public class CachedPlayer{
private String ip;
private String name;
private UUID uuid;
public CachedPlayer(String ip, String name, UUID uuid){
this.ip = ip;
this.name = name;
this.uuid = uuid;
}
public String getIp(){
return ip;
}
public String getName(){
return name;
}
public UUID getUuid(){
return uuid;
}
}
@@ -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,33 +23,34 @@
*
*/
package ch.andre601.advancedserverlist.spigot.logging;
package ch.andre601.advancedserverlist.core.objects;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SpigotLogger implements PluginLogger{
public class GenericServerImpl implements GenericServer{
private final Logger logger;
private final int online;
private final int max;
private final String host;
public SpigotLogger(Logger logger){
this.logger = logger;
public GenericServerImpl(int online, int max, String host){
this.online = online;
this.max = max;
this.host = host;
}
@Override
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
public int getPlayersOnline(){
return online;
}
@Override
public void warn(String msg, Object... args){
logger.warning(String.format(msg, args));
public int getPlayersMax(){
return max;
}
@Override
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
public String getHost(){
return host;
}
}
@@ -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,26 +23,25 @@
*
*/
package ch.andre601.advancedserverlist.paper.commands;
package ch.andre601.advancedserverlist.core.objects;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
public class CmdAdvancedServerList implements CommandExecutor{
public class ServerPlaceholders extends PlaceholderProvider{
private final PaperCore plugin;
public CmdAdvancedServerList(PaperCore plugin){
this.plugin = plugin;
public ServerPlaceholders(){
super("server");
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(new PaperCmdSender(sender), args);
return true;
public String parsePlaceholder(String placeholder, GenericPlayer genericPlayer, GenericServer genericServer){
return switch(placeholder){
case "playersOnline" -> String.valueOf(genericServer.getPlayersOnline());
case "playersMax" -> String.valueOf(genericServer.getPlayersMax());
case "host" -> genericServer.getHost();
default -> null;
};
}
}
@@ -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
@@ -25,8 +25,6 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
@@ -58,11 +56,6 @@ public class ComponentParser{
return new ComponentParser(String.join("\n", lines));
}
public ComponentParser replacements(Placeholders placeholders){
text = StringReplacer.replace(text, placeholders.getReplacements());
return this;
}
public ComponentParser modifyText(Function<String, String> function){
this.text = function.apply(text);
return this;
@@ -1,64 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.replacer.placeholders.Placeholders;
import java.util.HashMap;
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.isInvalid())
continue;
if(profile.evalConditions(replacements))
return profile;
}
return null;
}
}
@@ -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
@@ -25,127 +25,166 @@
package ch.andre601.advancedserverlist.core.profiles;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.conditions.Expression;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class ServerListProfile{
private final int priority;
private final List<Expression> expressions;
private final ProfileEntry defaultProfile;
private final List<String> motd;
private final List<String> players;
private final String playerCount;
private final String favicon;
private final boolean hidePlayers;
private final boolean extraPlayersEnabled;
private final int extraPlayers;
private final List<ProfileEntry> profiles;
public ServerListProfile(ConfigurationNode node, PluginLogger logger){
this.priority = node.node("priority").getInt();
this.expressions = createExpressions(getList(node, false, "conditions"), logger);
private final Random random = new Random();
public ServerListProfile(int priority, List<Expression> expressions, ProfileEntry defaultProfile, List<ProfileEntry> profiles){
this.priority = priority;
this.expressions = expressions;
this.defaultProfile = defaultProfile;
this.motd = getList(node, true, "motd");
this.players = getList(node, false, "playerCount", "hover");
this.playerCount = node.node("playerCount", "text").getString("");
this.favicon = node.node("favicon").getString("");
this.hidePlayers = node.node("playerCount", "hidePlayers").getBoolean();
this.extraPlayersEnabled = node.node("playerCount", "extraPlayers", "enabled").getBoolean();
this.extraPlayers = node.node("playerCount", "extraPlayers", "amount").getInt();
this.profiles = profiles;
}
public int getPriority(){
return priority;
}
public List<String> getMotd(){
return motd;
}
public List<String> getPlayers(){
return players;
}
public String getPlayerCount(){
return playerCount;
}
public String getFavicon(){
return favicon;
}
public boolean shouldHidePlayers(){
return hidePlayers;
}
public boolean isExtraPlayersEnabled(){
return extraPlayersEnabled;
}
public int getExtraPlayers(){
return extraPlayers;
}
public boolean evalConditions(Map<String, Object> replacements){
public boolean evalConditions(GenericPlayer player, GenericServer server){
if(expressions.isEmpty())
return true;
for(Expression expression : expressions){
if(!expression.evaluate(replacements)){
if(!expression.evaluate(player, server))
return false;
}
}
return true;
}
public boolean isInvalid(){
return getMotd().isEmpty() &&
getPlayers().isEmpty() &&
(getPlayerCount().isEmpty() && !shouldHidePlayers()) &&
getFavicon().isEmpty();
public ProfileEntry getRandomProfile(){
if(profiles.isEmpty()){
return null;
}
if(profiles.size() == 1)
return profiles.get(0); // No need to run a random for 1 profile.
synchronized(random){
return profiles.get(random.nextInt(profiles.size()));
}
}
private List<Expression> createExpressions(List<String> list, PluginLogger logger) {
if(list.isEmpty())
return Collections.emptyList();
public ProfileEntry getDefaultProfile(){
return defaultProfile;
}
/*
* Returns true if the Profile...
* ...doesn't have any valid MOTD set AND
* ...doesn't have any player hover set AND
* ...doesn't have a player count text set and hidePlayers is false AND
* ...doesn't have a favicon set.
*/
public boolean isInvalidProfile(){
if(profiles.isEmpty())
return defaultProfile.isInvalid();
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());
boolean profilesValid = false;
for(ProfileEntry profile : profiles){
if(profile.isInvalid())
continue;
profilesValid = true;
break;
}
return !profilesValid && defaultProfile.isInvalid();
}
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;
}
public static Builder resolve(String fileName, ConfigurationNode node, PluginLogger logger){
return new Builder(fileName, node, logger)
.resolveExpressions()
.resolveProfiles()
.resolveDefaultProfile();
}
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;
}
expressions.add(expression);
if(temp == null || temp.isEmpty())
return this;
for(String str : temp){
Expression expr = Expression.resolve(str);
if(expr.getResult() != Expression.ExpressionResult.VALID){
logger.warn("Found invalid expression in condition '%s'! Reason: %s", str, expr.getResult().getMessage());
continue;
}
this.expressions.add(expr);
}
return this;
}
return expressions;
}
private List<String> getList(ConfigurationNode node, boolean trim, Object... path){
List<String> list;
try{
list = node.node(path).getList(String.class);
}catch(SerializationException ex){
return Collections.emptyList();
private Builder resolveProfiles(){
try{
this.profiles = node.node("profiles").getList(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the profiles entry for %s", ex, fileName);
}
return this;
}
if(list == null)
return Collections.emptyList();
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;
}
if(trim && list.size() > 2)
return list.subList(0, 2);
return list;
public ServerListProfile build(){
return new ServerListProfile(this.priority, this.expressions, this.defaultProfile, this.profiles);
}
}
}
@@ -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
@@ -25,43 +25,40 @@
package ch.andre601.advancedserverlist.core.profiles.conditions;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import java.util.Map;
public class Expression{
private ExpressionResult result = ExpressionResult.VALID;
private final ExpressionResult result;
private String left;
private Operator operator = Operator.UNKNOWN;
private String right;
private final String left;
private final Operator operator;
private final String right;
public Expression(String expression){
resolveExpression(expression);
private Expression(ExpressionResult result, String left, Operator operator, String right){
this.result = result;
this.left = left;
this.operator = operator;
this.right = right;
}
public boolean evaluate(Map<String, Object> replacements){
String newLeft = StringReplacer.replace(left, replacements).trim();
String newRight = StringReplacer.replace(right, replacements).trim();
public static Expression createInvalid(ExpressionResult result){
return new Expression(result, null, Operator.UNKNOWN, null);
}
public static Expression resolve(String expression){
Operator operator = Operator.UNKNOWN;
return operator.evaluate(newLeft, newRight);
}
public ExpressionResult getResult(){
return result;
}
private void resolveExpression(String expression){
if(expression == null || expression.isEmpty()){
result = ExpressionResult.INVALID_NO_EXPRESSION;
return;
return Expression.createInvalid(ExpressionResult.INVALID_NO_EXPRESSION);
}
char[] chars = expression.toCharArray();
StringBuilder left = new StringBuilder();
StringBuilder right = new StringBuilder();
StringBuilder leftBuilder = new StringBuilder();
StringBuilder rightBuilder = new StringBuilder();
boolean foundOperator = false;
@@ -81,19 +78,28 @@ public class Expression{
}
if(foundOperator){
right.append(c);
rightBuilder.append(c);
}else{
left.append(c);
leftBuilder.append(c);
}
}
if(left.isEmpty() || right.isEmpty()){
result = ExpressionResult.INVALID_EMPTY_PARTS;
return;
if(leftBuilder.isEmpty() || rightBuilder.isEmpty()){
return Expression.createInvalid(ExpressionResult.INVALID_EMPTY_PARTS);
}
this.left = left.toString();
this.right = right.toString();
return new Expression(ExpressionResult.VALID, leftBuilder.toString().trim(), operator, rightBuilder.toString().trim());
}
public boolean evaluate(GenericPlayer player, GenericServer server){
String newLeft = StringReplacer.replace(left, player, server);
String newRight = StringReplacer.replace(right, player, server);
return operator.evaluate(newLeft, newRight);
}
public ExpressionResult getResult(){
return result;
}
public enum Operator{
@@ -192,8 +198,8 @@ public class Expression{
public enum ExpressionResult{
VALID(null),
INVALID_NO_EXPRESSION ("Received empty condition which isn't allowed!"),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
INVALID_NO_EXPRESSION("Received empty condition which isn't allowed!"),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
private final String message;
@@ -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
@@ -26,8 +26,8 @@
package ch.andre601.advancedserverlist.core.profiles.favicon;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import javax.imageio.ImageIO;
import java.awt.*;
@@ -39,12 +39,13 @@ import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class FaviconHandler<F>{
private final Cache<String, F> favicons = Caffeine.newBuilder()
private final Cache<String, F> favicons = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
@@ -55,13 +56,17 @@ public class FaviconHandler<F>{
}
public F getFavicon(String input, Function<BufferedImage, F> function){
return favicons.get(input, k -> {
BufferedImage image = resolveImage(core, input);
if(image == null)
return null;
return function.apply(image);
});
try{
return favicons.get(input, () -> {
BufferedImage image = resolveImage(core, input);
if(image == null)
return null;
return function.apply(image);
});
}catch(ExecutionException ignored){
return null;
}
}
public void clearCache(){
@@ -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
@@ -25,48 +25,28 @@
package ch.andre601.advancedserverlist.core.profiles.players;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import java.util.UUID;
public abstract class GenericPlayer<T>{
public abstract class GenericPlayerImpl implements GenericPlayer{
protected T player = null;
protected String name = null;
protected String version = null;
protected int protocol = -1;
protected boolean playedBefore = false;
protected boolean banned = false;
protected boolean whitelisted = false;
protected int protocol = 0;
protected UUID uuid = null;
public T getPlayer(){
return player;
}
@Override
public String getName(){
return name;
}
@Override
public int getProtocol(){
return protocol;
}
public String getVersion(){
return version;
}
public boolean hasPlayedBefore(){
return playedBefore;
}
public boolean isBanned(){
return banned;
}
public boolean isWhitelisted(){
return whitelisted;
}
public UUID getUniqueId(){
@Override
public UUID getUUID(){
return uuid;
}
}
@@ -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
@@ -26,110 +26,149 @@
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.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import com.google.gson.Gson;
import io.leangen.geantyref.TypeToken;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.UUID;
public class PlayerHandler{
private final AdvancedServerList core;
private final PluginLogger logger;
private final Path cache;
private final EntryList<String, String> players = new EntryList<>();
private List<CachedPlayer> cachedPlayers = new ArrayList<>();
private final Type listType = new TypeToken<ArrayList<CachedPlayer>>(){}.getType();
private final Gson gson = new Gson();
// UUID of MHF_Question
private final String defaultUUID = "606e2ff0-ed77-4842-9d6c-e1d3321c7838";
private CachedPlayer defaultPlayer = null;
public PlayerHandler(AdvancedServerList core){
this.core = core;
this.cache = core.getPlugin().getFolderPath().resolve("cache.data");
this.logger = core.getPlugin().getPluginLogger();
this.cache = core.getPlugin().getFolderPath().resolve("playercache.json");
}
public void load(){
if(!cache.toFile().exists()){
core.getPlugin().getPluginLogger().info("No cache.data present. Skipping...");
logger.info("No playercache.json file present. Skipping...");
return;
}
if(core.getFileHandler().getBoolean("disable_cache")){
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player loading...");
logger.info("'disable_cache' is set to true. Skipping playercache.json loading...");
return;
}
List<String> lines;
try{
lines = Files.readAllLines(cache);
Reader reader = Files.newBufferedReader(cache);
cachedPlayers = gson.fromJson(reader, listType);
reader.close();
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Encountered IOException while trying to read cache.data", ex);
logger.warn("Encountered IOException while reading the playercache.json file!", ex);
return;
}
if(lines.isEmpty()){
core.getPlugin().getPluginLogger().info("cache.data is empty. Skipping...");
return;
}
for(String line : lines){
String[] parts = line.split("=", 2);
if(parts.length < 2 || parts[0].isEmpty() || parts[1].isEmpty())
continue;
if(players.containsKey(parts[0]))
continue;
players.add(parts[0], parts[1]);
}
core.getPlugin().getPluginLogger().info("Loaded " + players.size() + " players into cache!");
logger.info("Loaded %d players into cache!", cachedPlayers.size());
}
public void save(){
if(players.isEmpty()){
core.getPlugin().getPluginLogger().info("No data to save. Skipping...");
if(cachedPlayers.isEmpty()){
logger.info("No players in cache to save. Skipping...");
return;
}
if(core.getFileHandler().getBoolean("disable_cache")){
core.getPlugin().getPluginLogger().info("Cache disabled. Skipping player saving...");
logger.info("'disable_cache' is set to true. Skipping saving of cached players...");
return;
}
StringJoiner joiner = new StringJoiner("\n");
for(Map.Entry<String, String> entry : players){
joiner.add(entry.getKey() + "=" + entry.getValue());
}
try{
BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8);
writer.write(joiner.toString());
writer.close();
core.getPlugin().getPluginLogger().info("Successfully saved cache.data file.");
try(BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8)){
gson.toJson(cachedPlayers, listType, writer);
logger.info("Successfully saved playercache.json file.");
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Cannot save player data to cache.data file!", ex);
logger.warn("Encountered IOException while saving cached players to playercache.json!", ex);
}
}
public void addPlayer(String name, String ip){
if(players.containsKey(name) || core.getFileHandler().getBoolean("disable_cache"))
public void addPlayer(String ip, String name, UUID uuid){
if(contains(ip) || core.getFileHandler().getBoolean("disable_cache"))
return;
players.add(name, ip);
cachedPlayers.add(new CachedPlayer(ip, name, uuid));
}
public String getPlayerByIp(String ip){
if(core.getFileHandler().getBoolean("disable_cache"))
core.getFileHandler().getString("Anonymous", "unknown_player");
public CachedPlayer getCachedPlayer(String key){
if(!contains(key) || core.getFileHandler().getBoolean("disable_cache"))
return getDefaultPlayer();
for(Map.Entry<String, String> entry : players){
if(entry.getValue().equals(ip))
return entry.getKey();
for(CachedPlayer player : cachedPlayers){
if(player.getIp().equals(key))
return player;
}
return core.getFileHandler().getString("Anonymous", "unknown_player");
return getDefaultPlayer();
}
public CachedPlayer getCachedPlayer(UUID uuid){
for(CachedPlayer player : cachedPlayers){
if(player.getUuid().equals(uuid))
return player;
}
return getDefaultPlayer();
}
public void clearCache(){
cachedPlayers.clear();
defaultPlayer = null;
}
private boolean contains(String ip){
for(CachedPlayer player : cachedPlayers){
if(player.getIp().equals(ip))
return true;
}
return false;
}
private CachedPlayer getDefaultPlayer(){
if(defaultPlayer != null)
return defaultPlayer;
return (defaultPlayer = new CachedPlayer(
"0.0.0.0",
core.getFileHandler().getString("Anonymous", "unknown_player"),
convertToUUID(core.getFileHandler().getString(defaultUUID, "unknown_player_uuid"))
));
}
private UUID convertToUUID(String uuid){
try{
return UUID.fromString(uuid);
}catch(IllegalArgumentException ex){
// This is always a valid UUID.
return UUID.fromString(defaultUUID);
}
}
}
@@ -0,0 +1,181 @@
/*
* 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.profiles.profile;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.Collections;
import java.util.List;
public class ProfileManager{
/*
* 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,
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), extraPlayersCount);
}
public static ServerListProfile resolveProfile(AdvancedServerList core, GenericPlayer player, GenericServer server){
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
if(profile.isInvalidProfile())
continue;
if(profile.evalConditions(player, server))
return profile;
}
return null;
}
public static ProfileEntry retrieveProfileEntry(ConfigurationNode node){
List<String> motd = resolveList(node, "motd");
List<String> players = resolveList(node, "playerCount", "hover");
String playerCountText = node.node("playerCount", "text").getString("");
String favicon = node.node("favicon").getString("");
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
Integer extraPlayers = resolveNullableInt(node);
return new ProfileEntry.Builder()
.setMotd(motd)
.setPlayers(players)
.setPlayerCountText(playerCountText)
.setFavicon(favicon)
.setHidePlayersEnabled(hidePlayers)
.setExtraPlayersEnabled(extraPlayersEnabled)
.setExtraPlayerCount(extraPlayers)
.build();
}
public static boolean checkOption(Object obj){
if(obj == null)
return false;
if(obj instanceof List<?> list){
return !list.isEmpty(); // Check if list isn't empty
}else
if(obj instanceof String str){
return !str.isEmpty(); // Check if String is not empty
}else
if(obj instanceof NullBool nb){
return nb.getOrDefault(false); // Return NullBool's value
}
return false;
}
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.motd()))
return defaultProfile.motd();
return profile.motd();
}
private static List<String> resolvePlayers(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.players()))
return defaultProfile.players();
return profile.players();
}
private static String resolvePlayerCountText(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.playerCountText()))
return defaultProfile.playerCountText();
return profile.playerCountText();
}
private static String resolveFavicon(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.favicon()))
return defaultProfile.favicon();
return profile.favicon();
}
private static boolean resolveHidePlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.hidePlayersEnabled()))
return defaultProfile.hidePlayersEnabled().getOrDefault(false);
return profile.hidePlayersEnabled().getOrDefault(false);
}
private static boolean resolveExtraPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.extraPlayersEnabled()))
return defaultProfile.extraPlayersEnabled().getOrDefault(false);
return profile.extraPlayersEnabled().getOrDefault(false);
}
private static Integer resolveExtraPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.extraPlayersCount() == null)
return defaultProfile.extraPlayersCount() == null ? 0 : defaultProfile.extraPlayersCount();
return profile.extraPlayersCount();
}
private static List<String> resolveList(ConfigurationNode node, Object... path){
try{
return node.node(path).getList(String.class);
}catch(SerializationException ex){
return Collections.emptyList();
}
}
private static NullBool resolveNullBool(ConfigurationNode node, Object... path){
if(node.node(path).virtual())
return NullBool.NOT_SET;
return NullBool.resolve(node.node(path).getBoolean());
}
private static Integer resolveNullableInt(ConfigurationNode node){
if(node.node("playerCount", "extraPlayers", "amount").virtual())
return null;
return node.node("playerCount", "extraPlayers", "amount").getInt();
}
}
@@ -0,0 +1,59 @@
/*
* 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.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 ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
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 ProfileManager.retrieveProfileEntry(node);
}
@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.motd());
node.node("playerCount", "hover").set(profile.players());
node.node("playerCount", "text").set(profile.playerCountText());
node.node("favicon").set(profile.favicon());
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled());
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled());
node.node("playerCount", "extraPlayers", "amount").set(profile.extraPlayersCount());
}
}
@@ -1,49 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Map;
/*
* Original by Imo van den Berge (aka Bergerkiller: https://github.com/Bergerkiller)
*
* Original Source: https://github.com/bergerhealer/BKCommonLib/blob/master/src/main/java/com/bergerkiller/bukkit/common/collections/EntryList.java
*/
public class EntryList<K, V> extends ArrayList<Map.Entry<K, V>>{
public void add(K key, V value){
add(new AbstractMap.SimpleEntry<>(key, value));
}
public boolean containsKey(K key){
for(Map.Entry<K, V> entry : this){
if(entry.getKey().equals(key))
return true;
}
return false;
}
}
@@ -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
@@ -25,20 +25,110 @@
package ch.andre601.advancedserverlist.core.profiles.replacer;
import java.util.Map;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
public class StringReplacer{
public static String replace(String input, Map<String, Object> replacements){
StringBuilder output = new StringBuilder(input);
int index;
for(Map.Entry<String, Object> entry : replacements.entrySet()){
index = 0;
while((index = output.indexOf(entry.getKey(), index)) != -1){
output.replace(index, index + entry.getKey().length(), String.valueOf(entry.getValue()));
index += String.valueOf(entry.getValue()).length();
public static String replace(String input, GenericPlayer player, GenericServer server){
if(input == null)
return null;
char[] chars = input.toCharArray();
StringBuilder builder = new StringBuilder(input.length());
StringBuilder identifier = new StringBuilder();
StringBuilder placeholder = new StringBuilder();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(int i = 0; i < chars.length; i++){
char c = chars[i];
char next = (i == (chars.length - 1)) ? '\0' : chars[i + 1];
if(c != '$' || i + 2 >= chars.length){
builder.append(c);
continue;
}
if(next != '{'){
if(next == '\0')
continue;
builder.append(next);
i++;
continue;
}
i++;
boolean identified = false;
boolean invalid = true;
while(++i < chars.length){
final char id = chars[i];
if(id == '}'){
invalid = false;
break;
}
if(id == ' ' && !identified){
identified = true;
continue;
}
if(identified){
placeholder.append(id);
}else{
identifier.append(id);
}
}
String identifierString = identifier.toString();
String placeholderString = placeholder.toString();
identifier.setLength(0);
placeholder.setLength(0);
if(invalid){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
continue;
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierString);
if(provider == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
String replacement = provider.parsePlaceholder(placeholderString, player, server);
if(replacement == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
builder.append(replacement);
}
return output.toString();
return builder.toString();
}
}
@@ -1,57 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.replacer.placeholders;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import java.util.HashMap;
import java.util.Map;
public class PlayerPlaceholders implements Placeholders{
private final Map<String, Object> replacements = new HashMap<>();
public PlayerPlaceholders(GenericPlayer<?> player){
this.replacements.put("${player name}", player.getName());
this.replacements.put("${player protocol}", player.getProtocol());
if(player.getVersion() != null)
this.replacements.put("${player version}", player.getVersion());
if(player.getPlayer() == null)
return;
this.replacements.put("${player hasPlayedBefore}", player.hasPlayedBefore());
this.replacements.put("${player isBanned}", player.isBanned());
this.replacements.put("${player isWhitelisted}", player.isWhitelisted());
this.replacements.put("${player uuid}", player.getUniqueId());
}
@Override
public Map<String, Object> getReplacements(){
return replacements;
}
}
+14
View File
@@ -1,14 +1,26 @@
#
# Used for when AdvancedServerList doesn't have a cached player to use for ${player name}
#
# Defaults to 'Anonymous' when not present.
#
unknown_player: "Anonymous"
#
# UUID used for when AdvancedServerList doesn't have a cached player to use for the ${player uuid}
# placeholder.
#
# Defaults to the UUID of MHF_Question (606e2ff0-ed77-4842-9d6c-e1d3321c7838) when not present.
#
unknown_player_uuid: "606e2ff0-ed77-4842-9d6c-e1d3321c7838"
#
# Should the Caching of players be disabled?
#
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
# Placeholders that rely on the player being cached (such as ${player isWhitelisted}) will not work while this option is enabled.
#
# Defaults to false when not present.
#
disable_cache: false
#
@@ -17,4 +29,6 @@ disable_cache: false
# 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
+38 -5
View File
@@ -16,24 +16,54 @@ priority: 0
# - '{playerVersion} < 759'
#
# Set the MOTD that should be displayed.
# Option that allows you to define multiple profiles to use.
# Each entry supports the same options as the server list profile does. Whenever an option is not present, or set to
# an empty value (If supported) would the option in the file be used (if present).
# This allows you to f.e. randomize the MOTD while keeping other options the same, without copy-pasting the same options.
#
# A profile will be selected randomly.
#
# Remove this option or set it to profiles: [] to use the global options of this file.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#profiles
#
#profiles:
# - motd:
# - '<aqua>Line 1'
# - '<aqua>Line 2'
# favicon: ''
# playerCount:
# hidePlayers: false
# hover:
# - '<green>Line 1'
# - '<green>Line 2'
# - '<green>Line 3'
# text: ''
# extraPlayers:
# enabled: false
# amount: 0
#
# Set the default (Global) MOTD used by this server list profile.
# Supports HEX colors for 1.16+ servers including gradients using MiniMessage's <gradient:color:color> format.
#
# Remove this option or set it to motd: [] to not alter the MOTD.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motd
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#motds
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
#
# Allows you to set a favicon for this server list profile.
# Allows you to set a global (Default) favicon for this server list profile.
# You can use one of three possible options:
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
# 2. A URL pointing to a valid Image
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
#
# Remove this option or set to favicon: '' to not replace the Favicon.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#favicon
#
favicon: ''
@@ -50,12 +80,15 @@ playerCount:
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
# You can set this to 'hover: []' or remove the option to not modify the hover text.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#hover
#
@@ -69,7 +102,7 @@ playerCount:
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
# This is nothing that can be fixed or avoided and would require changes from Mojang.
#
# You can set this to 'count: ''' or remove the option to not modify the player count text.
# Remove this option or set it to text: '' to not modify the player count text.
#
# Read more: https://github.com/Andre601/AdvancedServerList/wiki/Profiles#text
#
+1 -1
View File
@@ -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
@@ -0,0 +1,292 @@
/*
* 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.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);
}
}
+60
View File
@@ -0,0 +1,60 @@
# Changelog
This page lists the recent changes made towards the AdvancedServerListAPI.
They are ordered newest to oldest.
## v2.1.0
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
- Turned `ProfileEntry` class into a record
- Former `getX()` methods are now deprecated in favour of the recor's own `x()` methods (i.e. `getMotd()` -> `motd()`)
## v2.0.0
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v2-breaking }
- `platform-paper` has been removed. It used the same code as `platform-spigot` and was therefore considered duplicate code and useless.
- `core` has been removed. The `CachedPlayer` is no longer needed in the platform-specific APIs.
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v2-added }
- `PreServerListSetEvent` to the different platform-specific APIs.
- Called before AdvancedServerList alters the server list.
- Allows to override the `ProfileEntry` used or even cancel the event.
- `ProfileEntry`
- Used for setting the different values of the server list.
- Own instances can be made using the nested `Builder` class.
- Has methods to create a Builder instance from itself, or make a copy from another ProfileEntry-instance.
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v2-changed }
- Converted `GenericPlayer`, `GenericServer`, `BungeePlayer`, `SpigotPlayer` and `VelocityPlayer` into interfaces.
- `GenericPlayer` no longer has `getVersion()`, `hasPlayedBefore()`, `isBanned()` and `isWhitelisted()`. They have been moved to `VelocityPlayer` (Only `getVersion()`) and `SpigotPlayer` respectively.
- Converted `NullBool` from a class to an enum.
- Contains `TRUE`, `FALSE` and `NOT_SET`.
- `isNull()` is now `isNotSet()`.
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v2-removed }
- `UnsupportedAPIAccessException` as it is no longer used in the API itself.
## v1.0.0
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v1-added }
- `AdvancedServerListAPI`
- Main class used to add your own `PlaceholderProvider` instances.
- `PlaceholderProvider`
- Abstract class used to add your own placeholders to parse in AdvancedServerList.
<!--
Templates for changelog
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v-breaking }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v-added }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v-removed }
-->
+153
View File
@@ -0,0 +1,153 @@
# API
AdvancedServerList v2 introduced a new API that plugins can hook into to use.
It provides a way for your plugin to provide its own placeholders that should be parsed by AdvancedServerList and also an event to modify the server list.
## Add dependency
Add the following to your `build.gradle` or `pom.xml` file to use the API:
=== ":simple-gradle: Gradle"
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
```groovy title="build.gradle"
repositorories {
maven { url = 'https://jitpack.io/' }
}
dependencies {
implementation 'ch.andre601.asl-api:api:{version}'
// Optional platform dependencies
implementation 'ch.andre601.asl-api:platform-bungeecord:{version}'
implementation 'ch.andre601.asl-api:platform-spigot:{version}'
implementation 'ch.andre601.asl-api:platform-velocity:{version}'
}
```
=== ":simple-apachemaven: Maven"
Make sure to replace `{version}` with the latest version available in the [GitHub Repository][api-repo].
```xml title="pom.xml"
<repositories>
<repository>
<id>jitpack</id>
<url>https://jitpack.io/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>{version}</version>
</dependency>
<!-- Optional platform dependencies -->
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bungeecord</artifactId>
<version>{version}</version>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-spigot</artifactId>
<version>{version}</version>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-velocity</artifactId>
<version>{version}</version>
</dependency>
</dependencies>
```
[api-repo]: https://github.com/Andre601/asl-api
## Add own placeholders
To add your own placeholders will you need to do a few steps.
### 1) Get API instance
Use `AdvancedServerListAPI.get()` to retrieve an instance of the currently used AdvancedServerList API.
It will be needed at a later point.
### 2) Create a Placeholder class
Make a new class that you want to use for the placeholders and let it extend the `PlaceholderProvider` class of AdvancedServerList.
Your IDE should now tell you to implement/override some methods. Confirm this action and your class should look something alongside this:
```java title="PlaceholderProvider example"
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders(String identifier) {
super(identifier);
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
return null;
}
}
```
It's recommended to replace your generated constructor with a no-args one and set the identifier directly in the `super()`.
For example:
```java
public MyPlaceholders() {
super("myplaceholders");
}
```
The next step now would be to handle the different placeholders. These are handled in the `parsePlaceholder` method you had to override.
The `placeholder` String is whatever value was provided after the identifier in `${<identifier> <placeholder>}`. It can contain spaces.
Something to note is, that when returning `null` will AdvancedServerList understand it as an invalid placeholder and return it unchanged.
Here is a small example of the final class:
```java title="PlaceholderProvider example"
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders() {
super("myplaceholders");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if(placeholder.equals("hello"))
return "Hi!";
return null;
}
}
```
### 3) Register the placeholder class
All that is left to do now is to register your class as a new PlaceholderProvider instance. To do this, get the API instance you retrieved earlier and use `addPlaceholderProvider` with a new instance of your class.
```java title="Registering PlaceholderProvider class"
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholders());
```
## Events
!!! info "Note"
The mentioned event is only accessible through one of the platform dependencies, as those are used in the platform's respective event handler system.
v2 of the API adds the `PreServerListSetEvent` to the different platform dependencies to use.
It allows you to modify the ProfileEntry used for the player pinging the server/proxy or even cancelling the event altogether.
### ProfileEntry
The ProfileEntry class has been moved to the API in v2 allowing you to create your own versions using the available Builder class.
This class contains values from a Server List Profile file. The values can either be from a `profiles` list entry, one of the global options in the file, or a mix of both, depending on what options are present.
You can create a new entry or copy an existing one (i.e. from the [`PreServerListSetEvent`](#events)) to modify and use in the server list by setting it in the aforementioned `PreServerListSetEvent`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+43
View File
@@ -0,0 +1,43 @@
.md-header__button.md-logo img {
height: 2.5rem;
}
.md-header__button.md-logo {
padding-right: unset;
padding-left: unset;
}
.changelog-added {
color: #2ea043;
}
.changelog-removed {
color: #f85149;
}
.changelog-changed {
color: #1f6feb;
}
.changelog-breaking {
color: #9e6a03
}
.md-banner--warning__icon {
color: #d29922;
}
.result {
border: .05rem solid var(--md-code-bg-color);
border-bottom-left-radius: .1rem;
border-bottom-right-radius: .1rem;
border-top-width: .1rem;
margin-top: -1.125em;
overflow: visible;
padding: 0 1em;
}
/* Override mkdocs-material styling */
.md-banner--warning {
background: rgba(187,128,9,0.15);
}
+28
View File
@@ -0,0 +1,28 @@
# Commands
The plugin adds commands to use for various things related to the plugin itself.
The main command is `/advancedserverlist` but an alias called `/asl` is also registered to use.
## Permissions
The main permission is `advancedserverlist.admin` for all commands, but you can also grant access to specific commands using `advancedserverlist.command.<subcommand>` instead (i.e. `advancedserverlist.command.help` to grant access to [`/asl help`](#help)).
## Subcommands
The following subcommands are available (Subcommands are case-insensitive):
- [`help`](#help)
- [`reload`](#reload)
- [`clearCache`](#clearcache)
### help
Shows a list of all available [subcommands](#subcommands) for AdvancedServerList.
### reload
Reloads the plugin's `config.yml`, all available YAML files in the `profiles` folder and also clears the currently cached favicons and Players.
### clearCache
Clears the currently cached favicons and Players.
+150
View File
@@ -0,0 +1,150 @@
## About
!!! warning "The below examples may only work in v1.10.0 or newer!"
This page lists some examples you may want to use for your proxy or server.
Feel free to suggest additional examples on my [Discord Server](https://discord.gg/6dazXp6) in the `#advancedserverlist` channel.
## Table of Contents
- [Versions](#versions)
- [Different List for outdated Clients](#different-list-for-outdated-clients)
- [Different MOTD for < 1.16](#different-motd-for-116)
- [Spigot/PaperMC](#spigotpapermc)
- [Different profile for banned Player](#different-profile-for-banned-player)
- [Other](#other)
- [Different profile for different host](#different-profile-for-different-host)
- [Different profile for known player](#different-profile-for-known-player)
- [Random MOTD but same hover](#random-motd-but-same-hover)
----
## Versions
Some examples about version-related things.
### Different List for outdated Clients
You may want to display a separate MOTD or text for incompatible client versions.
This example here shows a separate MOTD and player count message for when the player's client version is older than what the server supports.
```yaml title="outdated-client.yml"
priority: 1
# Display this profile, if the version of the player is below 760 (1.19.1)
conditions:
- '${player protocol} < 760'
motd:
- <red>You are using an outdated client!
- <red>Please update to 1.19.1 to join.
playerCount:
text: '<red>Outdated Client!'
```
### Different MOTD for < 1.16
This profile would display a MOTD without HEX colours if the player's version is below 735 (1.16).
```yaml title="pre-1_16.yml"
priority: 1
# Display this profile, if the version of the player is below 735 (1.16)
conditions:
- '${player protocol} < 735'
motd:
- <grey>Welcome to <aqua>YourServer.com</aqua>!
- <grey>Enjoy your stay.
```
----
## Spigot/PaperMC
Examples that can be used with the Spigot or PaperMC version.
### Different profile for banned Player
!!! warning "Requires a cached player to work reliably."
Displays a separate profile for when the player has been banned from the server.
```yaml title="banned.yml"
priority: 1
conditions:
- '${player isBanned} = true'
motd:
- <red>You have been <bold>BANNED</bold>!
- <red>Go away.
# Don't show the player count to the banned player.
playerCount:
hidePlayers: true
```
----
## Other
Some misc examples.
### Different profile for different host
Display a different profile when the playing pings a specific domain/IP.
```yaml title="specific-host.yml"
priority: 1
conditions:
- '${server host} = other.example.com'
motd:
- <grey>Please use <aqua>mc.example.com
- <grey>to join our server.
```
### Different profile for known player
Display a different profile, if the player pinging the server is "known" by AdvancedServerList (Has joined before with the same IP).
```yaml title="personalized.yml"
priority: 1
conditions:
- `${player name} != Anonymous` # "Anonymous" should be replaced with whatever you use in 'unknown_player'
motd:
- <grey>Hello there <aqua>${player name}</aqua>!
- <grey>It's nice to see you again.
playerCount:
hover:
- '<grey>Welcome back <aqua>${player name}</aqua>!'
- '<grey>'
- '<grey>Come and join <aqua>${server playersOnline}'
- '<aqua>other players</aqua> <grey>on the Server!'
```
### Random MOTD but same hover
v1.10.0 of AdvancedServerList introduced an option called `profiles`. It allows you to create multiple variants of an MOTD, playercount, etc. while also supporting the normal (global) options as a fallback.
The following example will create a profile that has a randomized MOTD, but the same hover for both:
```yaml title="random-motd.yml"
priority: 1
profiles:
- motd:
- 'A randomized MOTD.'
- 'Lines change, but hover is the same.'
- motd: ['Different Syntax.', 'May be more readable.']
playerCount:
hover:
- 'This player count hover always'
- 'stays the same, no matter what'
- 'MOTD is being used here.'
```
+41
View File
@@ -0,0 +1,41 @@
# AdvancedServerList Wiki
Welcome to the Wiki of AdvancedServerList!
On this site can you find the latest documentation for the plugin, including some useful examples.
If you're new to the plugin is it recommended to check out the [Profiles page](./profiles) for a quick start on how to use this plugin.
## Platforms
AdvancedServerList supports the following platforms:
[![spigot-img](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/spigot_vector.svg "Tested on Spigot"){ width=64 }][spigot]
[![paper-img](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/paper_vector.svg "Tested on Paper"){ width=64 }][paper]
[![bungeecord-img](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/bungeecord_vector.svg "Tested on BungeeCord"){ width=64 }][spigot]
[![waterfall](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/waterfall_vector.svg "Tested on Waterfall"){ width=64 }][paper]
[![velocity](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/velocity_vector.svg "Tested on Velocity"){ width=64 }][velocity]
## Dependencies
| Dependency | Platforms | Required? |
|------------------|---------------|-----------|
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
| [ViaVersion] | Spigot, Paper | No |
## Pages
- [Profiles](./profiles)
- [Formatting](./profiles/formatting)
- [Placeholders](./profiles/placeholders)
- [API](./api)
- [Examples](./examples)
- [PlaceholderAPI placeholders](./placeholderapi.md)
[spigot]: https://www.spigotmc.org
[paper]: https://papermc.io
[velocity]: https://velocitypowered.com
[protocollib]: https://www.spigotmc.org/resources/1997/
[placeholderapi]: https://www.spigotmc.org/resources/6245/
[viaversion]: https://www.spigotmc.org/resources/19254/
+18
View File
@@ -0,0 +1,18 @@
# PlaceholderAPI Placeholders
The Spigot and Paper version of AdvancedServerList provide their own set of placeholders to use through [PlaceholderAPI].
## Placeholders
!!! note
AdvancedServerList will try to find a matching Profile for the player similar to when they ping the server when using any of the below placeholders.
| Placeholder | Description |
|---------------------------|-------------------------------------------------------------------------------|
| `%asl_favicon%` | Gives the value of `favicon` from a matching Profile. |
| `%asl_extra_players_max%` | Gives the value of `playerCount.extraPlayers.amount` from a matching Profile. |
| `%asl_motd%` | Gives the value of `motd` in the matching Profile. |
| `%asl_playercount_hover%` | Gives the value of `playerCount.hover` from a matching Profile. |
| `%asl_playercount_text%` | Gives the value of `playerCount.text` from a matching Profile. |
[placeholderapi]: https://www.spigotmc.org/resources/6245/
+37
View File
@@ -0,0 +1,37 @@
# Formatting
All text options with exception of [`Conditions`](../#conditions) allow the usage of formatting options using [MiniMessage].
!!! warning "IMPORTANT"
Whenever your text starts with a colour or formatting code (`<aqua>`, `<blue>`, `<bold>`, `<italic>`, etc.) should it be surrounded with single or double quotes.
Not doing so will cause the YAML parses used - Configurate - to not see the value as a String, but something else, causing exceptions to appear.
```yaml title="Wrong formatting"
motd:
- <red>This will cause
- <red>Errors
```
```yaml title="Right formatting"
motd:
- '<green>This will be formatted'
- '<green>properly.'
```
## Unsupported options
The following options are **not** supported, no matter what option they are used in:
- Hover Actions (Show text, Show Advancement, etc)
- Click Actions (Run command, Suggest command, etc.)
- Custom Fonts (May work if player already has the resource pack loaded)
## Colors
Normal text colours such as `<aqua>` or `<red>` can be used in all text options.
## HEX Colours
24-Bit HEX colours such as `<#ffffff>` can be used in the [`Motd`](../#motd) option on 1.16+ servers/proxies.
[MiniMessage]: https://docs.adventure.kyori.net/minimessage/index.html
+251
View File
@@ -0,0 +1,251 @@
# Profiles
AdvancedServerList allows the creation of multiple profiles.
A profile is a single YAML file located in the plugin's `profiles` directory containing multiple settings including [Conditions](#conditions) and [Priority](#priority).
!!! info "Important"
In order for a profile to be considered "valid" by AdvancedServerList will it need to meet the following conditions:
- Have a [`Priority`](#priority) set to a valid, whole number (i.e. `1`)
- Have **at least one** of the following options set:
- [`Profiles`](#profiles) with at least one entry containing one of the below option
- [`Motd`](#motd) set with at least one line of text
- [`Favicon`](#favicon) set with a non-empty String
- [`HidePlayers`](#hideplayers) set to `true`
- [`Hover`](#hover) set with at least one line of text
- [`Text`](#text) set with a non-empty String
## Priority
The priority option determines the order in which the profiles are checked by AdvancedServerList, starting with the highest number.
It will go through each file until it finds one with [`conditions`](#conditions) returning true (Default if no conditions are set).
This means that a profile with no conditions and a priority of `1` will be used before a profile with a condition and priority `0` even if the player is meeting the condition.
## Conditions
A list of conditions can be set that need to be met in order to have this profile shown to the player.
[Placeholders](./formatting#placeholders) can be used to further customize the conditions (PlaceholderAPI placeholders are **not** supported).
Only when **all** conditions defined return true will the profile be displayed.
You can remove this option, or set it to an empty list (`conditions: []`) to always return true.
### Operants
The following operants are available and can be used in the conditions.
!!! warning "Only one operant can be used per condition!"
| Operant | Description |
| ------- | ------------------------------------------------------------------ |
| `<` | Checks if the left value is less than the right one.\* |
| `<=` | Checks if the left value is less than or equal to the right one.\* |
| `>` | Checks if the left value is more than the right one.\* |
| `>=` | Checks if the left value is more than or equal to the right one.\* |
| `=` | Checks if the left value is equal to the right one. |
| `!=` | Checks if the left value is not equal to the right one. |
\* In the case of the provided value not being a number will the plugin instead use the text length to compare with.
## Profiles
The profiles option allows you to add multiple combinations of all the other options (With the exception of [`Priority`](#priority) and [`Conditions`](#conditions)) to have randomized MOTDs, player counts, etc.
If an option is not present in an entry will AdvancedServerList try to use one defined in the file or use whatever default value would be for that option.
??? example "Example"
```yaml title="YAML file"
priority: 0
profiles:
- motd:
- '<rainbow>Line 1</rainbow>'
- '<rainbow:!>Line 2</rainbow>'
playerCount:
text: '<green><bold>Awesome!'
- playerCount:
text: '<yellow><bold>Also Awesome!'
motd:
- '<rainbow:2>Line A</rainbow>'
- '<rainbow:!2>Line B</rainbow>'
```
<div class="result">
![profiles-example-1](../assets/images/examples/profiles-example-1.jpg)
![profiles-example-2](../assets/images/examples/profiles-example-2.jpg)
</div>
## Motd
The motd option allows to set up to two lines to be displayed in an MOTD.
Normal colour and formatting codes such as `<aqua>` or `<bold>` are supported. On 1.16 and newer can you also use HEX colours using either `<#rrggbb>` or `<color:#rrggbb>`.
If you want to display multiple MOTDs will you need to use the [`Profiles` option](#profiles)
??? example "Example"
```yaml title="YAML file"
priority: 0
motd:
- '<rainbow:2>Rainbow Gradients</rainbow>'
- '<rainbow:!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
<div class="result">
![motd-example](../assets/images/examples/motd-example.jpg)
</div>
## Favicon
The favicon option allows you to customize the favicon and display one or multiple different images.
This option currently supports the following values:
- A URL pointing to a `64x64` PNG image.
- A name with `.png` extension that matches a PNG file in the `favicons` folder.
- `${player uuid}` (or alternatively `${player name}`) to display the head of the player. The UUID/Name resolving is handled by https://mc-heads.net
Please note that AdvancedServerList will rescale the image to be 64x64 pixels, so be sure to provide images at that particular scale.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
# Player is Andre_601
favicon: ${player uuid}
```
<div class="result">
![hideplayers-example](../assets/images/examples/favicon-example.jpg)
</div>
## PlayerCount
The `playerCount` option contains multiple different options all about the Player count itself.
### HidePlayers
Boolean option to set whether AdvancedServerList should hide the player count or not. When set to `true` will the player count be replaced with `???`.
Additionally will the [`Text`](#text) and [`Hover`](#hover) option be ignored.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayers: true
```
<div class="result">
![hideplayers-example](../assets/images/examples/hideplayers-example.jpg)
</div>
### Hover
This option allows to override the hover text usually displaying the players on the server when hovering over the player count.
You can either remove this option or set to an empty list (`hover: []`) to not override the hover.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
hover:
- '<grey>Line 1'
- '<aqua>Line 2'
- '<gold>Line 3'
```
<div class="result">
![hover-example](../assets/images/examples/hover-example.jpg)
</div>
### Text
This option allows to override the text usually displaying the online players and total players that can join.
Note that AdvancedServerList will not add the `<online>/<max>` text to the player count. Instead will you need to use [`${server playersOnline}`](./placeholders#server) and [`${server playersMax}`](./placeholders#server) respectively.
!!! info "Note"
This feature works by changing the "outdated server" message followed by altering the protocol version of the server.
Due to this will your server appear as "outdated" to the client (Have the ping icon crossed out). This is nothing that can be changed unfortunately.
To not override the player count, remove this option or set it to an empty String (`text: ''`).
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
text: '<yellow><bold>Cool text!'
```
<div class="result">
![hover-example](../assets/images/examples/text-example.jpg)
</div>
### ExtraPlayers
Contains options to modify how the `<max>` number in the player count should look like.
!!! warning "Using this option will modify the `${server playersMax}` placeholder (Except in conditions)"
#### Enabled
Boolean option to set whether the extra players feature should be used or not.
When set to `true` will the max amount of players be modified by taking the current amount of online players, add [`Amount`](#amount) more to it and use it.
#### Amount
Sets the number to add to the current online players to then use as the new max players count.
As an example, setting this to `1` while `10` players are online will display `11`, while `-1` would display `9`.
??? example "Example"
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
motd:
- '<grey>'
- '<grey>'
playerCount:
extraPlayers:
enabled: true
amount: 1
```
<div class="result">
![hover-example](../assets/images/examples/extraplayers-example.jpg)
</div>
+52
View File
@@ -0,0 +1,52 @@
# Placeholders
AdvancedServerList provides a set of pre-made placeholders using the `${<identifier> <placeholder>}` format adobted from BungeeTabListPlus.
It also has built-in [PlaceholderAPI support](#placeholderapi) for Spigot and Paper Servers and since v2 can even allow you to [add your own placeholders](#custom-placeholders) by using its [API](../../api).
## Built-in Placeholders
The following placeholders are available in AdvancedServerList itself. Please note that not all placeholders are available on all platforms.
### Player Placeholders
These placeholders use the player who pinged the server, to return values. They may require the player to be cached in order to work.
| Placeholder | Description | Platforms | Cached Player required?\* |
|-----------------------------|-----------------------------------------------------------------|--------------|---------------------------|
| `${player name}` | The name of the player. | All | Yes\*\* |
| `${player protocol}` | The protocol version of the player. | All | No |
| `${player uuid}` | The UUID of the player. | All | Yes\*\*\* |
| `${player version}` | The protocol version of the player as readable MC version. | Velocity | No |
| `${player hasPlayedBefore}` | Boolean for whether the player has played on the server before. | Spigot/Paper | Yes |
| `${player isBanned}` | Boolean for whether the player has been banned from the server. | Spigot/Paper | Yes |
| `${player isWhitelisted}` | Boolean for whether the player is whitelisted on the server. | Spigot/Paper | Yes |
\*Whether this placeholder requires the player to have joined before while AdvancedServerList was running. When `disable_cache` is enabled will these placeholders not work.
\*\*Will default to whatever name has been provided in the config.yml's `unknown_player` option, when the player isn't cached yet.
\*\*\*Will default to whatever name has been provided in the config.yml's `unknown_player_uuid` option, when the player isn't cached yet.
### Server
These placeholders use values given by the server/proxy AdvancedServerList runs on.
| Placeholder | Description |
|---------------------------|----------------------------------------------------------|
| `${server playersOnline}` | The number of players online on this server. |
| `${server playersMax}` | The total number of players that can join this server.\* |
| `${server host}` | The domain/IP the player pinged. |
\*This placeholder is affected by the [`Amount` option](../#amount) in a server list profile, with the exception being when used in [`Conditions`](../#conditions).
## PlaceholderAPI
The Spigot and Paper version of AdvancedServerList allow the usage of *any* placeholders provided by PlaceholderAPI by using the `%<identifier>_<values>%` placeholder format.
Depending on the placeholder used is a cached player required (i.e. `%player_name%`). AdvancedServerList will try to get a OfflinePlayer instance based on the cached UUID from the server to manage this.
!!! warning "PlaceholderAPI placeholders can NOT be used in Conditions!"
## Custom Placeholders
Since version 2 of AdvancedServerList are developers able to provide their own placeholders to be used in a server list profile.
The format follows the same one as the [built-in placeholders](#built-in-placeholders), meaning it is `${<identifier> <placeholder>}`.
If you're a developer and want to integrate your own placeholders into AdvancedServerList, read about it [here](../../api).
+32 -65
View File
@@ -2,7 +2,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
@@ -27,106 +27,73 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>ch.andre601.advancedserverlist</groupId>
<artifactId>parent</artifactId>
<version>parent</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>paper</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
<artifactId>hangar-uploader</artifactId>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public</url>
</repository>
<repository>
<id>placeholderapi-repo</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.advancedserverlist</groupId>
<artifactId>core</artifactId>
<version>${plugin.version}</version>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.2</version>
<scope>provided</scope>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Paper-${plugin.version}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<finalName>HangarUploader</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.0</version>
<configuration>
<release>16</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>ch.andre601.advancedserverlist.hangaruploader.HangarUploader</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.spongepowered.configurate</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.configurate</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.caffeine</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
@@ -0,0 +1,209 @@
/*
* 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.hangaruploader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.FileBody;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.entity.mime.StringBody;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpMessage;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class HangarUploader{
private static final Logger LOGGER = LoggerFactory.getLogger(HangarUploader.class);
private static final String API_URL = "https://hangar.papermc.io/api/v1/";
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private final String apiKey;
private ActiveJWT activeJWT;
public HangarUploader(String apiKey){
this.apiKey = apiKey;
}
public static void main(String[] args) throws IOException{
LOGGER.info("Starting Jar file...");
final VersionUpload.Namespace project = new VersionUpload.Namespace("Andre_601", "AdvancedServerList");
if(args.length < 3){
throw new IllegalStateException("Application requires HANGAR_TOKEN, RELEASE_TAG, PRERELEASE and RELEASE_BODY to work");
}
String apiToken = args[0];
String version = args[1].startsWith("v") ? args[1].substring(1) : args[1];
boolean isPreRelease = args[2].equalsIgnoreCase("true");
String body = System.getenv("GITHUB_RELEASE_BODY");
LOGGER.info("Version: {}", version);
LOGGER.info("Is Prerelease: {}", isPreRelease);
LOGGER.info("Release Message: {}", body);
final List<Path> filePaths = List.of(
new File("bukkit/target/AdvancedServerList-Bukkit-" + version + ".jar").toPath(),
new File("bungeecord/target/AdvancedServerList-BungeeCord-" + version + ".jar").toPath(),
new File("velocity/target/AdvancedServerList-Velocity-" + version + ".jar").toPath()
);
final List<VersionUpload.PluginDependency> paperDependencies = List.of(
VersionUpload.PluginDependency.createWithHangarNamespace(
"ViaVersion",
false,
new VersionUpload.Namespace("ViaVersion", "ViaVersion")
),
VersionUpload.PluginDependency.createWithExternalUrl(
"PlaceholderAPI",
false,
"https://www.spigotmc.org/resources/6245/"
)
);
final List<VersionUpload.MultipartFileOrUrl> fileInfo = List.of(
new VersionUpload.MultipartFileOrUrl(List.of(VersionUpload.Platform.PAPER), null),
new VersionUpload.MultipartFileOrUrl(List.of(VersionUpload.Platform.WATERFALL), null),
new VersionUpload.MultipartFileOrUrl(List.of(VersionUpload.Platform.VELOCITY), null)
);
final VersionUpload versionUpload = new VersionUpload(
version,
Map.of(
VersionUpload.Platform.PAPER, paperDependencies,
VersionUpload.Platform.WATERFALL, List.of(),
VersionUpload.Platform.VELOCITY, List.of()
),
Map.of(
VersionUpload.Platform.PAPER, List.of("1.19.x"),
VersionUpload.Platform.WATERFALL, List.of("1.19.x"),
VersionUpload.Platform.VELOCITY, List.of("3.1")
),
body,
fileInfo,
isPreRelease ? "Beta" : "Release"
);
HangarUploader uploader = new HangarUploader(apiToken);
try(CloseableHttpClient client = HttpClients.createDefault()){
uploader.uploadVersion(client, project, versionUpload, filePaths);
}catch(ParseException ex){
LOGGER.error("Encountered ParseException while performing a request.", ex);
}
}
public void uploadVersion(HttpClient client, VersionUpload.Namespace namespace, VersionUpload versionUpload,
List<Path> filePaths) throws IOException, ParseException{
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("versionUpload", new StringBody(GSON.toJson(versionUpload), ContentType.APPLICATION_JSON));
for(Path path : filePaths){
builder.addPart("files", new FileBody(path.toFile(), ContentType.DEFAULT_BINARY));
}
HttpPost post = new HttpPost(API_URL + "projects/" + namespace + "/upload");
post.setEntity(builder.build());
this.addAuthHeader(client, post);
LOGGER.info("Uploading release...");
final boolean success = client.execute(post, response -> {
if(response.getCode() != 200){
LOGGER.error("Error while uploading version. Received response code {}: {}", response.getCode(), response.getReasonPhrase());
LOGGER.error("Body: {}", EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
return false;
}
return true;
});
if(!success){
throw new RuntimeException("Error uploading version!");
}
LOGGER.info("Upload complete!");
System.exit(0);
}
private synchronized void addAuthHeader(HttpClient client, HttpMessage message) throws IOException{
LOGGER.info("Applying Authorization Header...");
if(this.activeJWT != null && !this.activeJWT.hasExpired()){
message.addHeader("Authorization", this.activeJWT.jwt());
LOGGER.info("Authorization Header applied. Expires at {}", getDate(this.activeJWT.expiresAt()));
return;
}
LOGGER.info("Current JWT expired. Requesting new one...");
ActiveJWT jwt = client.execute(new HttpPost(API_URL + "authenticate?apiKey=" + this.apiKey), response -> {
if(response.getCode() == 400){
LOGGER.error("Bad JWT request; is the API-token valid?");
return null;
}else
if(response.getCode() != 200){
LOGGER.error("Received non-successful response code {}: {}", response.getCode(), response.getReasonPhrase());
return null;
}
final String json = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
final JsonObject jsonObject = GSON.fromJson(json, JsonObject.class);
final String token = jsonObject.getAsJsonPrimitive("token").getAsString();
final long expiresIn = jsonObject.getAsJsonPrimitive("expiresIn").getAsLong();
LOGGER.info("Received new JWT!");
return new ActiveJWT(token, System.currentTimeMillis() + expiresIn);
});
if(jwt == null){
throw new RuntimeException("Error getting JWT.");
}
this.activeJWT = jwt;
LOGGER.info("Authorization Header applied. Expires at {}", getDate(this.activeJWT.expiresAt()));
message.addHeader("Authorization", jwt.jwt());
}
private synchronized String getDate(long timestamp){
return timestamp + " (" + new Date(timestamp) + ")";
}
private record ActiveJWT(String jwt, long expiresAt){
public boolean hasExpired(){
return System.currentTimeMillis() < this.expiresAt + TimeUnit.SECONDS.toMillis(3);
}
}
}
@@ -0,0 +1,66 @@
/*
* 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.hangaruploader;
import java.util.List;
import java.util.Map;
public record VersionUpload(String version, Map<Platform, List<PluginDependency>> pluginDependencies,
Map<Platform, List<String>> platformDependencies, String description,
List<MultipartFileOrUrl> files, String channel){
public record Namespace(String owner, String slug){
@Override
public String toString(){
return this.owner + "/" + this.slug;
}
}
public record PluginDependency(String name, boolean required, Namespace namespace, String externalUrl){
public PluginDependency{
if(namespace == null && externalUrl == null)
throw new IllegalStateException("Either a Hangar Namespace or an external URL needs to be defined.");
}
public static PluginDependency createWithHangarNamespace(String name, boolean required, Namespace namespace){
return new PluginDependency(name, required, namespace, null);
}
public static PluginDependency createWithExternalUrl(String name, boolean required, String externalUrl){
return new PluginDependency(name, required, null, externalUrl);
}
}
public record MultipartFileOrUrl(List<Platform> platforms, String externalUrl){}
public enum Platform{
PAPER,
WATERFALL,
VELOCITY
}
}
@@ -0,0 +1,60 @@
<!--
~ 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.
~
-->
<configuration debug="false">
<property name="DEV_HOME" value="./logs"/>
<!--CONSOLE -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%highlight([) %boldWhite(%d{dd.MM.yyyy HH:mm:ss}) %highlight(%-5level) %highlight(]) %cyan([%t]) %boldWhite([%logger{0}]) %boldRed(-) %white(%msg) %n</pattern>
</encoder>
</appender>
<!--FILE OUT-->
<appender name="FILE-AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<file>${DEV_HOME}/Purr.log</file>
<encoder>
<pattern>%d{dd.MM.yyyy HH:mm:ss} [%thread] [ %-5level] [%logger{0}] %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/archived/purr-%d{dd.MM.yyyy}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
</appender>
<!--Root logger-->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE-AUDIT"/>
</root>
</configuration>
+82
View File
@@ -0,0 +1,82 @@
site_name: AdvancedServerList Wiki
site_description: 'Wiki for the AdvancedServerList plugin'
site_author: 'Andre_601'
site_url: 'https://www.andre601.ch/AdvancedServerList' # Uncomment to set a canonical URL
copyright: |
&copy; Andre_601
docs_dir: docs/
repo_name: Andre601/AdvancedServerList
repo_url: https://github.com/Andre601/AdvancedServerList
nav:
- Home: index.md
- Profiles:
- profiles/index.md
- Formatting: profiles/formatting.md
- Placeholders: profiles/placeholders.md
- API:
- api/index.md
- Changelog: api/changelog.md
- Examples: examples.md
- PlaceholderAPI: placeholderapi.md
theme:
name: 'material'
favicon: 'assets/images/favicon.png'
logo: 'assets/images/favicon.png'
palette:
scheme: 'slate'
primary: 'indigo'
accent: 'indigo'
features:
- navigation.indexes
- navigation.tabs
- navigation.tabs.sticky
- content.code.copy
icon:
repo: 'octicons/mark-github-16'
admonition:
note: 'octicons/tag-16'
abstract: 'octicons/checklist-16'
info: 'octicons/info-16'
tip: 'octicons/squirrel-16'
success: 'octicons/check-16'
question: 'octicons/question-16'
warning: 'octicons/alert-16'
failure: 'octicons/x-circle-16'
danger: 'octicons/zap-16'
bug: 'octicons/bug-16'
example: 'octicons/beaker-16'
quote: 'octicons/quote-16'
extra_css:
- assets/stylesheets/custom.css
extra:
social:
- icon: 'fontawesome/brands/github'
link: 'https://github.com/Andre601/asl-wiki'
version:
provider: 'mike'
default:
- latest
- dev
markdown_extensions:
- markdown.extensions.admonition:
- markdown.extensions.toc:
permalink: true
- markdown.extensions.attr_list:
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.highlight:
- pymdownx.magiclink:
- pymdownx.superfences:
- pymdownx.tabbed:
alternate_style: true
- pymdownx.details:
@@ -1,189 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
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 ServerCore<CachedServerIcon, PlayerProfile, OfflinePlayer>{
private final PluginLogger logger = new PaperLogger(getLogger());
private AdvancedServerList core;
private FaviconHandler<CachedServerIcon> faviconHandler;
@Override
public void onEnable(){
try{
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
enable();
}catch(ClassNotFoundException ex){
try{
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 ========================================");
getServer().getPluginManager().disablePlugin(this);
}
}
}
@Override
public void onDisable(){
if(getCore() == null)
return; // This is always the case when the plugin is used on a Spigot server (See above try-catch blocks).
getCore().disable();
}
@Override
public void loadCommands(){
PluginCommand cmd = getServer().getPluginCommand("advancedserverlist");
if(cmd == null){
getPluginLogger().warn("Could not register command /advancedserverlist");
return;
}
cmd.setExecutor(new CmdAdvancedServerList(this));
}
@Override
public void loadEvents(){
new JoinEvent(this);
new PingEvent(this);
}
@Override
public void loadMetrics(){
new Metrics(this, 15584).addCustomChart(new SimplePie("profiles",
() -> String.valueOf(core.getFileHandler().getProfiles().size())
));
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
}
@Override
public AdvancedServerList getCore(){
return core;
}
@Override
public Path getFolderPath(){
return getDataFolder().toPath();
}
@Override
public PluginLogger getPluginLogger(){
return logger;
}
@Override
public FaviconHandler<CachedServerIcon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformName(){
return getServer().getName();
}
@Override
public String getPlatformVersion(){
return getServer().getVersion();
}
@Override
public String getLoader(){
return "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);
}
}
@@ -1,47 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayer;
import org.bukkit.OfflinePlayer;
public class PaperPlayer extends GenericPlayer<OfflinePlayer>{
public PaperPlayer(OfflinePlayer player, String name, int protocol){
this.player = player;
this.name = player == null ? name : player.getName();
this.protocol = protocol;
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
this.uuid = player.getUniqueId();
}
}
@@ -1,52 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper.events;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
private final PaperCore plugin;
public JoinEvent(PaperCore plugin){
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onJoin(PlayerJoinEvent event){
InetSocketAddress address = event.getPlayer().getAddress();
if(address == null)
return;
plugin.getCore().getPlayerHandler().addPlayer(event.getPlayer().getName(), address.getHostString());
}
}
+54 -6
View File
@@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -11,20 +36,43 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.commit/>
<plugin.version>1.8.0</plugin.version>
<plugin.version>3.0.2</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<api.version>v2.1.0</api.version>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<profiles>
<profile>
<id>gh-actions</id>
<activation>
<property>
<name>env.COMMIT_SHA</name>
</property>
</activation>
<properties>
<project.build.commit>_${env.COMMIT_SHA}</project.build.commit>
</properties>
</profile>
</profiles>
<repositories>
<repository>
<id>jitpack</id>
<url>https://jitpack.io/</url>
</repository>
</repositories>
<modules>
<module>core</module>
<module>velocity</module>
<module>bungeecord</module>
<module>paper</module>
<module>spigot</module>
<module>bukkit</module>
<module>velocity</module>
<module>hangar-uploader</module>
</modules>
</project>
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff. Show more