Compare commits

...
559 Commits
Author SHA1 Message Date
Andre601 2779f565a9 Add config option to ignore maintenance for hidePlayersHover 2025-01-06 17:41:37 +01:00
Andre601 6d3cd0c505 Update getting started 2025-01-06 16:33:16 +00:00
Andre601 cf95f11fdb Remove automerge (Useless under current setup) 2025-01-06 15:07:26 +00:00
Andre601 679dbb8c0b Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.16' (#397) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/397
2025-01-06 15:06:29 +00:00
Andre601's Bot f44e2759b9 Update dependency ch.qos.logback:logback-classic to v1.5.16 2025-01-06 12:01:41 +00:00
Andre601 29239cc4ed Add HidePlayersHover to docs 2025-01-05 22:24:16 +01:00
Andre601 bcd5e77166 Try new Bungeecord version to fix CI 2025-01-05 22:02:30 +01:00
Andre601 5d2fa03601 Upload hover examples 2025-01-05 20:39:54 +00:00
Andre601 8f1a5e5a37 Add option to hide online players list. 2025-01-05 20:19:57 +01:00
Andre601 05fde902a4 Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.0-SNAPSHOT' (#395) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/395
2025-01-04 12:18:43 +00:00
Andre601's Bot d69e70c485 Update dependency space.arim.libertybans:bans-api to v1.1.0-SNAPSHOT 2025-01-04 12:16:35 +00:00
Andre601 fba1e84171 Disable dependency Dashboard 2025-01-04 12:15:36 +00:00
Andre601 530f0fd954 Update renovate.json with some automerge and grouping stuff. 2025-01-03 16:06:13 +00:00
Andre601 8bec42bb91 Fix wrong Paper repo URL for renovate 2025-01-03 02:38:41 +00:00
Andre601 94982ff1e8 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.2.1' (#394) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/394
2025-01-02 13:29:51 +00:00
Andre601's Bot 1f9795ed97 Update dependency com.viaversion:viaversion-api to v5.2.1 2025-01-02 12:01:33 +00:00
Andre601 c6f95cb78a Update formatting.md 2024-12-30 13:48:48 +01:00
Andre601 571f9f6b38 Add support for SayanVanish 2024-12-29 01:24:55 +01:00
Andre601 6d7fbb8c25 Merge pull request 'Update API reference' (#393) from feature/update-api-reference into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/393
2024-12-25 00:58:11 +00:00
Andre601 d3d83e5e11 Update ProfileEntry index page 2024-12-25 00:46:43 +00:00
Andre601 82fb9c90f4 Update API reference 2024-12-25 00:39:03 +00:00
Andre601 6841a5a6e0 Undo componentlogger changes on velocity 2024-12-24 22:27:26 +01:00
Andre601 6f41cd4e3a Use a fallback logger for velocity versions without ComponentLoggers 2024-12-24 22:05:56 +01:00
Andre601 379f36832e Use snippet links 2024-12-24 21:45:01 +01:00
Andre601 5d8a39cd22 Update config example in getting-started 2024-12-24 21:43:39 +01:00
Andre601 9dba820840 Reduce flood of messages on Startup + make ASL banner hidable.
(I really don't get why people get upset about a few lines of text... Won't make the Log file like 10GB bigger or smth...)
2024-12-24 21:41:39 +01:00
Andre601 58712ca5c5 Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0' (#392) from renovate/dependency.adventure-text-serializer-legacy into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/392
2024-12-24 12:04:13 +00:00
Andre601's Bot e19e942799 Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0 2024-12-24 12:01:21 +00:00
Andre601 03434130c4 Update dependency net.kyori:adventure-text-minimessage to v4.18.0 2024-12-23 13:20:48 +01:00
Andre601 99df25551a Merge pull request 'Update dependency net.kyori:adventure-api to v4.18.0' (#390) from renovate/dependency.adventure-api into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/390
2024-12-23 12:14:32 +00:00
Andre601's Bot 4f31e4ce6f Update dependency net.kyori:adventure-api to v4.18.0 2024-12-23 12:01:35 +00:00
Andre601 ba097c538d Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.15' (#389) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/389
2024-12-22 13:03:31 +00:00
Andre601's Bot aa52435591 Update dependency ch.qos.logback:logback-classic to v1.5.15 2024-12-22 12:01:59 +00:00
Andre601 f44194d24f Update docs 2024-12-21 02:21:33 +01:00
Andre601 0e2d760ea6 Upload center_text_example.jpg 2024-12-20 13:31:42 +00:00
Andre601 c1e7e6b3ff Merge pull request 'Add support for centering MOTD lines' (#388) from feature/motd-center-feature into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/388
2024-12-20 13:24:41 +00:00
Andre601 96d383a5a1 Merge branch 'master' into feature/motd-center-feature 2024-12-20 13:24:11 +00:00
Andre601 79ba7877bf Bump version and add docs 2024-12-20 13:46:53 +01:00
Andre601 86b9aaa7c6 Add support for centering MOTD lines 2024-12-20 13:40:11 +01:00
Andre601 0cb3c036af Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.14' (#387) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/387
2024-12-20 12:11:41 +00:00
Andre601's Bot b1f7b75e2d Update dependency ch.qos.logback:logback-classic to v1.5.14 2024-12-20 12:01:15 +00:00
Andre601 e9bc72c165 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.13' (#386) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/386
2024-12-19 12:02:24 +00:00
Andre601's Bot 93203249fe Update dependency ch.qos.logback:logback-classic to v1.5.13 2024-12-19 12:01:11 +00:00
Andre601 2523ccb425 Merge pull request 'Update dependency com.google.guava:guava to v33.4.0-jre' (#384) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/384
2024-12-17 12:04:55 +00:00
Andre601 94972dad31 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4' (#383) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/383
2024-12-17 12:04:39 +00:00
Andre601's Bot f8ac310259 Update dependency com.google.guava:guava to v33.4.0-jre 2024-12-17 12:01:48 +00:00
Andre601's Bot 5d8f5d81ed Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4 2024-12-17 12:01:40 +00:00
Andre601 3111d7933d Merge pull request 'Move Migration pages to sub-pages' (#382) from docs/move-migration-pages into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/382
2024-12-16 21:42:31 +00:00
Andre601 55f7e17d34 Fix typo. 2024-12-16 21:42:14 +00:00
Andre601 0e88a50deb Move Migration pages to sub-pages 2024-12-16 22:38:55 +01:00
Andre601 83f351de6d Try github.run_number variable 2024-12-16 19:42:19 +00:00
Andre601 b96d1cb1a9 Merge pull request 'Update dependency mkdocs-material to v9.5.49' (#381) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/381
2024-12-16 12:04:47 +00:00
Andre601's Bot 517ff1df82 Update dependency mkdocs-material to v9.5.49 2024-12-16 12:01:18 +00:00
Andre601 e8c7c4ee18 Merge pull request 'Update Wiki Announcement' (#380) from feature/wiki-update-announcement into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/380
2024-12-13 14:15:21 +00:00
Andre601 da44eac70e Fix typos 2024-12-13 14:05:41 +00:00
Andre601 e85c121ee4 Add missing .svg 2024-12-13 13:58:10 +00:00
Andre601 0c175999fc Update announcement 2024-12-13 13:57:32 +00:00
Andre601 9c3f237f6d Use ruby for hocon highlighting 2024-12-11 20:42:52 +01:00
Andre601 777545c94f Possible fix for IndexOutOfBoundsException in condition parsing. 2024-12-10 23:22:41 +01:00
Andre601 dd197609e1 Set secrets via ENV (secrets is deprecated) 2024-12-10 13:29:13 +00:00
Andre601 14ee306463 Bump version 2024-12-10 14:09:34 +01:00
Andre601 a635aa8c91 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7.2' (#379) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/379
2024-12-09 12:05:22 +00:00
Andre601 050ac3262a Merge pull request 'Update dependency mkdocs-material to v9.5.48' (#378) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/378
2024-12-09 12:05:12 +00:00
Andre601's Bot 89aa309c90 Update dependency net.william278:papiproxybridge to v1.7.2 2024-12-09 12:02:16 +00:00
Andre601's Bot e9b004c3f2 Update dependency mkdocs-material to v9.5.48 2024-12-09 12:02:05 +00:00
Andre601 3ecca64a3d Allow random to be converted in MiniMOTDConfigMigrator 2024-12-09 03:04:22 +01:00
Andre601 96dcea4e5b Fix admonition box 2024-12-08 13:54:35 +00:00
Andre601 400f4709f5 Add missing ! 2024-12-08 13:52:30 +00:00
Andre601 5d4307128b Use thumbnail + link for better privacy 2024-12-08 13:51:44 +00:00
Andre601 65c96690f6 Use youtube-nocookie domain for iframes 2024-12-08 13:44:04 +00:00
Andre601 483d582cd1 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.2.0' (#377) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/377
2024-12-07 12:02:00 +00:00
Andre601's Bot 6f14e17ae7 Update dependency com.viaversion:viaversion-api to v5.2.0 2024-12-07 12:01:26 +00:00
Andre601 ff32cc1005 Use annotation and (hopefully) improve JS code) 2024-12-07 02:03:29 +01:00
Andre601 bcc18d7738 [Wiki] Add tutorials page 2024-12-05 23:51:20 +01:00
Andre601 629079b438 Remove container image (Is now default) 2024-12-05 01:40:04 +00:00
Andre601 bce03b68a8 Remove container image (Is now default) 2024-12-05 01:39:50 +00:00
Andre601 841c32de0d Update docs and smaller corrections 2024-12-04 23:10:50 +01:00
Andre601 f321ef0162 [Wiki] Add info about favicon creation. 2024-12-04 16:42:51 +00:00
Andre601 eca32d1858 Add video of KasaiSora 2024-12-04 16:26:40 +00:00
Andre601 f2c1f6e491 Update favicons description 2024-12-04 16:19:57 +00:00
Andre601 af31aac07e Merge pull request 'Add support for 'random' in Favicon option' (#376) from feature/add-random-favicon-option into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/376
2024-12-01 19:37:49 +00:00
Andre601 f8db3e7706 Add support for 'random' in Favicon option 2024-12-01 17:31:38 +01:00
Andre601 3d3ea2913c Merge pull request 'Create deploy_wiki.yml' (#375) from feature/deploy-wiki-action into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/375
2024-12-01 15:31:07 +00:00
Andre601 7b7042a856 Merge branch 'master' into feature/deploy-wiki-action 2024-12-01 15:30:06 +00:00
Andre601 c66c4f21f3 Ignore tags (releases) 2024-12-01 15:29:01 +00:00
Andre601 890a3f7b46 Create deploy_wiki.yml 2024-12-01 15:24:54 +00:00
Andre601 73b969bc51 Rename preview-domains to preview_domains 2024-12-01 15:22:52 +00:00
Andre601 55c93d8d59 disable publish_docs for woodpecker 2024-12-01 15:14:33 +00:00
Andre601 e1ed8c1cb2 Disable pr_preview for woodpecker 2024-12-01 15:13:50 +00:00
Andre601 e2a91a461a Create pr_preview.yml 2024-12-01 15:12:34 +00:00
Andre601 8a454004a4 Merge pull request 'Update dependency mkdocs-material to v9.5.47' (#374) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/374
2024-12-01 12:05:13 +00:00
Andre601's Bot 8df862530d Update dependency mkdocs-material to v9.5.47 2024-12-01 12:01:41 +00:00
Andre601 4a1c93fb1b Delete build_wiki.yml 2024-11-29 23:11:30 +00:00
Andre601 e795cf31eb Add Git credentials setup 2024-11-29 13:41:05 +00:00
Andre601 e8d93d064f try ubuntu:act-latest from ghcr.io 2024-11-29 13:35:36 +00:00
Andre601 6a2a90b868 Try node:23-alpine.19 2024-11-29 12:53:43 +00:00
Andre601 9cea1d3841 Try ubuntu 20.04? 2024-11-29 12:48:38 +00:00
Andre601 7453b43d6b Try node:22-bookworm 2024-11-28 23:38:13 +00:00
Andre601 7e30f937bd Try using alpine container image 2024-11-28 23:35:56 +00:00
Andre601 176a8ac42e Use a specific python version 2024-11-28 19:36:17 +00:00
Andre601 f480ff51e1 Try out Forgejo Actions 2024-11-28 19:31:12 +00:00
Andre601 e72b772cb9 Add proper highlighting for mitmotd config 2024-11-28 17:04:11 +01:00
Andre601 c91faa899e Add note about availability of BanPlugins Download 2024-11-27 16:34:14 +00:00
Andre601 e5c6d77e3d Merge pull request 'Update dependency mkdocs-material to v9.5.46' (#372) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/372
2024-11-25 12:14:04 +00:00
Andre601's Bot e8ad2c8266 Update dependency mkdocs-material to v9.5.46 2024-11-25 12:03:01 +00:00
Andre601 d244f2816a Merge pull request 'Update dependency mkdocs-material to v9.5.45' (#371) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/371
2024-11-20 12:06:25 +00:00
Andre601's Bot 73f3172504 Update dependency mkdocs-material to v9.5.45 2024-11-20 12:03:20 +00:00
Andre601 d7c9f73898 Fix typo for code block 2024-11-12 01:33:31 +00:00
Andre601 2b6818180f Merge pull request 'Update dependency mkdocs-material to v9.5.44' (#369) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/369
2024-11-06 12:26:39 +00:00
Andre601's Bot c7c14799e3 Update dependency mkdocs-material to v9.5.44 2024-11-06 12:01:46 +00:00
Andre601 59774347f6 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7.1' (#367) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/367
2024-11-02 12:08:14 +00:00
Andre601 e45f9a1e73 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.1.1' (#368) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/368
2024-11-02 12:07:40 +00:00
Andre601's Bot a44235dc10 Update dependency com.viaversion:viaversion-api to v5.1.1 2024-11-02 12:01:22 +00:00
Andre601's Bot 52569a3588 Update dependency net.william278:papiproxybridge to v1.7.1 2024-11-01 12:01:45 +00:00
Andre601 602a8e27ea Merge pull request 'Update dependency mkdocs-material to v9.5.43' (#366) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/366
2024-10-31 12:14:58 +00:00
Andre601's Bot 81a23953e5 Update dependency mkdocs-material to v9.5.43 2024-10-31 12:01:41 +00:00
Andre601 9daf8f3a3e Delete CHANGELOG.md file 2024-10-30 21:09:21 +00:00
Andre601 3d5b4501e3 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1' (#365) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/365
2024-10-29 12:09:50 +00:00
Andre601's Bot 67047e9877 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1 2024-10-29 12:01:14 +00:00
Andre601 7fcb0e78e3 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.12' (#363) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/363
2024-10-26 12:02:53 +00:00
Andre601 8b8018245e Merge branch 'master' into renovate/ch.qos.logback-logback-classic-1.x 2024-10-26 12:02:40 +00:00
Andre601 b34143d4f5 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.1.0' (#364) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/364
2024-10-26 12:02:25 +00:00
Andre601's Bot a33c096cf4 Update dependency com.viaversion:viaversion-api to v5.1.0 2024-10-26 12:01:27 +00:00
Andre601's Bot 0957edbcd8 Update dependency ch.qos.logback:logback-classic to v1.5.12 2024-10-26 12:01:21 +00:00
Andre601 70adf4e216 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.3' (#361) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/361
2024-10-24 12:10:50 +00:00
Andre601 da42e8c137 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7' (#362) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/362
2024-10-24 12:10:32 +00:00
Andre601's Bot f4eecda209 Update dependency net.william278:papiproxybridge to v1.7 2024-10-24 12:01:26 +00:00
Andre601's Bot b934d1a856 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.3 2024-10-24 12:01:19 +00:00
Andre601 bbec0aa064 Improve AdvancedBanProvider 2024-10-21 16:43:29 +02:00
Andre601 ba1f620eee SECURITY.md aktualisiert 2024-10-20 22:48:03 +00:00
Andre601 f0281adf8a Merge pull request 'Update dependency mkdocs-material to v9.5.42' (#360) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/360
2024-10-20 12:50:09 +00:00
Andre601's Bot c702f61c21 Update dependency mkdocs-material to v9.5.42 2024-10-20 12:02:03 +00:00
Andre601 dec23e0412 Merge pull request 'Update dependency mkdocs-material to v9.5.41' (#359) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/359
2024-10-16 13:03:17 +00:00
Andre601's Bot 782dcb8382 Update dependency mkdocs-material to v9.5.41 2024-10-16 12:01:17 +00:00
Andre601 e401d1f8c1 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.0.5' (#358) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/358
2024-10-15 13:07:25 +00:00
Andre601 5e6654b3ef Merge branch 'master' into renovate/com.viaversion-viaversion-api-5.x 2024-10-15 13:06:30 +00:00
Andre601 25a9e8ef63 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.11' (#357) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/357
2024-10-15 13:06:16 +00:00
Andre601's Bot 558e47a7da Update dependency com.viaversion:viaversion-api to v5.0.5 2024-10-15 12:02:05 +00:00
Andre601's Bot 740896c304 Update dependency ch.qos.logback:logback-classic to v1.5.11 2024-10-15 12:01:56 +00:00
Andre601 62d9aa81a3 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.10' (#356) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/356
2024-10-12 12:03:19 +00:00
Andre601's Bot 7220b633cf Update dependency ch.qos.logback:logback-classic to v1.5.10 2024-10-12 12:01:33 +00:00
Andre601 0908ddad5e Remove unused imports and bump version 2024-10-10 17:01:10 +02:00
Andre601 d1549b1441 delete release-config.ts 2024-10-10 14:58:51 +00:00
Andre601 57f618e7e2 Remove the action (Pointless and confusing to use) 2024-10-10 14:58:29 +00:00
Andre601 911c64f7ad Merge pull request '🎉 Release 5.0.5' (#352) from next-release/master into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/352
2024-10-10 14:50:32 +00:00
oauth fdeeb35fa9 🎉 Release 5.0.5 2024-10-10 12:30:10 +00:00
oauth c2c653e613 Merge branch 'origin/master' into 'next-release/master' 2024-10-10 12:30:10 +00:00
Andre601 8fa7c1593d Merge pull request 'Update dependency mkdocs-material to v9.5.40' (#355) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/355
2024-10-10 12:29:26 +00:00
Andre601's Bot b2dc74951f Update dependency mkdocs-material to v9.5.40 2024-10-10 12:01:17 +00:00
oauth 099c45e4c4 🎉 Release 5.0.5 2024-10-09 12:29:42 +00:00
oauth e38f6648ee Merge branch 'origin/master' into 'next-release/master' 2024-10-09 12:29:42 +00:00
Andre601 2d701aa8a8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.9' (#354) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/354
2024-10-09 12:29:05 +00:00
Andre601's Bot 1f32c22ebf Update dependency ch.qos.logback:logback-classic to v1.5.9 2024-10-09 12:01:45 +00:00
oauth 610d86ad1b 🎉 Release 5.0.5 2024-10-09 11:55:51 +00:00
oauth 658ec8dd74 Merge branch 'origin/master' into 'next-release/master' 2024-10-09 11:55:51 +00:00
Andre601 85b7210e7c Push empty commit to trigger release 2024-10-09 13:55:23 +02:00
Andre601 98b99b37de Merge pull request 'Improve PAPIProxyBridge support' (#353) from feature/improve-papi-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/353
2024-10-09 11:49:41 +00:00
Andre601 bc3aaa4d28 Improve PAPIProxyBridge support 2024-10-09 13:31:34 +02:00
oauth a3d0342f28 🎉 Release 5.0.5 2024-10-09 11:20:46 +00:00
Andre601 6e057422b6 Merge pull request 'Add automatic release action' (#351) from feature/automatic-release-creation into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/351
2024-10-09 11:20:26 +00:00
Andre601 7ee65c6c21 Add useVersionPrefixV to release-config.ts 2024-10-09 13:18:42 +02:00
Andre601 b4b754e483 Update MODRINTH.md 2024-10-08 23:53:00 +00:00
Andre601 b7c0c8a312 Update Mastodon Link 2024-10-08 23:51:52 +00:00
Andre601 cf6006f9d6 Merge branch 'master' into feature/automatic-release-creation 2024-10-06 00:07:49 +02:00
Andre601 6bf44f6208 Fix hover not supporting PlaceholderAPI Placeholders 2024-10-06 00:01:06 +02:00
Andre601 428dd3cd06 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.2' (#350) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/350
2024-10-05 12:12:34 +00:00
Andre601's Bot 871e2efbe2 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.2 2024-10-05 12:01:14 +00:00
Andre601 a5b45e2c82 Add SECURITY.md 2024-10-04 22:54:25 +00:00
Andre601 9feb3dfac6 Bump version 2024-10-02 13:43:45 +02:00
Andre601 5961d0dca0 Don't log errors when fetching servers (+ misc changes) 2024-10-02 13:43:05 +02:00
Andre601 ea0f0f09f4 Add automatic release action 2024-10-02 13:27:46 +02:00
Andre601 3d5d4fcab2 Fix wrong name for AdvancedBan in BanPlugins Addon 2024-10-01 19:58:11 +02:00
Andre601 0763a9b3b4 Fix wrong main class for Paper BanPluginsAddon 2024-10-01 02:26:14 +02:00
Andre601 2d67a89fc2 Merge pull request 'Update dependency mkdocs-material to v9.5.39' (#349) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/349
2024-09-29 12:07:56 +00:00
Andre601's Bot 4207d875f9 Update dependency mkdocs-material to v9.5.39 2024-09-29 12:03:17 +00:00
Andre601 5da420c6c6 Merge pull request 'feature/online-players-setting' (#348) from feature/online-players-setting into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/348
2024-09-27 14:27:47 +00:00
Andre601 1ffa4842c3 Update API docs and bump version to major v5 2024-09-26 16:47:28 +02:00
Andre601 819e194f27 Make Server placeholders return empty String instead of null. 2024-09-26 16:11:38 +02:00
Andre601 269e55b93f Merge branch 'master' into feature/online-players-setting 2024-09-26 15:54:50 +02:00
Andre601 04412f7138 Implement feature to set online player count 2024-09-26 15:54:28 +02:00
Andre601 0fce9d01e1 Merge pull request 'Update dependency mkdocs-material to v9.5.38' (#346) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/346
2024-09-26 13:50:41 +00:00
Andre601's Bot 1c29301635 Update dependency mkdocs-material to v9.5.38 2024-09-26 12:02:06 +00:00
Andre601 8bd7bbb5d7 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.1' (#345) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/345
2024-09-25 12:04:33 +00:00
Andre601 1a99663b59 Merge pull request 'Update dependency mkdocs-material to v9.5.37' (#344) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/344
2024-09-25 12:04:14 +00:00
Andre601's Bot 36e31279b2 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.1 2024-09-25 12:01:31 +00:00
Andre601's Bot 4aa7eba675 Update dependency mkdocs-material to v9.5.37 2024-09-25 12:01:21 +00:00
Andre601 3bbe2d26b8 Merge pull request 'Update dependency com.google.guava:guava to v33.3.1-jre' (#342) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/342
2024-09-24 13:11:35 +00:00
Andre601 782ad838be Merge pull request 'Update dependency org.bstats:bstats-velocity to v3.1.0' (#343) from renovate/org.bstats-bstats-velocity-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/343
2024-09-24 13:11:22 +00:00
Andre601's Bot ceddb26137 Update dependency org.bstats:bstats-velocity to v3.1.0 2024-09-24 12:01:32 +00:00
Andre601's Bot ff044d75c7 Update dependency com.google.guava:guava to v33.3.1-jre 2024-09-24 12:01:25 +00:00
Andre601 8955df695d Merge pull request 'Update dependency org.bstats:bstats-bungeecord to v3.1.0' (#341) from renovate/org.bstats-bstats-bungeecord-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/341
2024-09-23 12:57:03 +00:00
Andre601 8ddcb208f5 Merge pull request 'Update dependency org.bstats:bstats-bukkit to v3.1.0' (#340) from renovate/org.bstats-bstats-bukkit-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/340
2024-09-23 12:56:27 +00:00
Andre601's Bot 95834df89f Update dependency org.bstats:bstats-bungeecord to v3.1.0 2024-09-23 12:01:58 +00:00
Andre601's Bot 2f67f26cbe Update dependency org.bstats:bstats-bukkit to v3.1.0 2024-09-23 12:01:52 +00:00
Andre601 00957f9458 Merge pull request 'Create ${proxy status ...} placeholder.' (#334) from feature/proxy-status-placeholder into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/334
2024-09-22 13:12:42 +00:00
Andre601 2e9e886c48 Merge pull request 'Update dependency mkdocs-material to v9.5.36' (#338) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/338
2024-09-21 12:24:01 +00:00
Andre601's Bot d2d4e48b73 Update dependency mkdocs-material to v9.5.36 2024-09-21 12:01:47 +00:00
Andre601 fe16df27f2 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4' (#337) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/337
2024-09-20 15:51:44 +00:00
Andre601's Bot cc29f70dff Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4 2024-09-20 12:02:38 +00:00
Andre601 e136f7cfaf Merge pull request 'Update dependency mkdocs-material to v9.5.35' (#336) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/336
2024-09-18 12:05:57 +00:00
Andre601's Bot fd52f124fb Update dependency mkdocs-material to v9.5.35 2024-09-18 12:01:38 +00:00
Andre601 5a656cee39 Merge pull request 'Update alpine Docker tag to v3.20.3' (#335) from renovate/alpine-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/335
2024-09-17 14:39:09 +00:00
Andre601's Bot 21a89f9b14 Update alpine Docker tag to v3.20.3 2024-09-17 12:01:40 +00:00
Andre601 9ded4d2d57 Add more placeholders 2024-09-09 14:49:07 +02:00
Andre601 fb64d92879 Create Proxy Placeholder 2024-09-09 02:05:50 +02:00
Andre601 1a4bcae4d1 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.8' (#331) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/331
2024-09-07 12:07:57 +00:00
Andre601's Bot 25ee4da4f4 Update dependency ch.qos.logback:logback-classic to v1.5.8 2024-09-07 12:01:12 +00:00
Andre601 35cb39c35e Merge pull request 'Update dependency mkdocs-material to v9.5.34' (#330) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/330
2024-09-01 14:09:33 +00:00
Andre601's Bot 3a5f232f92 Update dependency mkdocs-material to v9.5.34 2024-09-01 12:03:23 +00:00
Andre601 4ed201fba9 Bump version 2024-08-29 20:31:14 +02:00
Andre601 03835f71d9 Fix local favicon saving using non-lowercased names. 2024-08-29 20:30:44 +02:00
Andre601 480e50e71e .woodpecker/publish_assets.yml aktualisiert 2024-08-29 11:51:38 +00:00
Andre601 39110b2898 Merge pull request 'Update dependency mkdocs-material to v9.5.33' (#329) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/329
2024-08-23 13:08:17 +00:00
Andre601's Bot e8db70e319 Update dependency mkdocs-material to v9.5.33 2024-08-23 12:02:52 +00:00
Andre601 eb907988fb Merge pull request 'Update maven Docker tag to v3.9.9' (#328) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/328
2024-08-21 12:39:31 +00:00
Andre601's Bot 95935022b8 Update maven Docker tag to v3.9.9 2024-08-21 12:10:41 +00:00
Andre601 1e70cb0651 Merge pull request 'Update dependency org.bstats:bstats-velocity to v3.0.3' (#327) from renovate/org.bstats-bstats-velocity-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/327
2024-08-20 13:55:27 +00:00
Andre601 1594d062e5 Merge pull request 'Update dependency org.bstats:bstats-bungeecord to v3.0.3' (#326) from renovate/org.bstats-bstats-bungeecord-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/326
2024-08-20 13:55:11 +00:00
Andre601's Bot 04b266f558 Update dependency org.bstats:bstats-velocity to v3.0.3 2024-08-20 12:03:13 +00:00
Andre601's Bot 9989fec809 Update dependency org.bstats:bstats-bungeecord to v3.0.3 2024-08-20 12:03:06 +00:00
Andre601 ab8eabc348 Merge pull request 'Update dependency org.bstats:bstats-bukkit to v3.0.3' (#325) from renovate/org.bstats-bstats-bukkit-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/325
2024-08-19 13:54:53 +00:00
Andre601 931b8b5c36 Merge pull request 'Update dependency mkdocs-material to v9.5.32' (#324) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/324
2024-08-19 13:53:45 +00:00
Andre601's Bot 64957ba13c Update dependency org.bstats:bstats-bukkit to v3.0.3 2024-08-19 12:04:55 +00:00
Andre601's Bot a03be990ab Update dependency mkdocs-material to v9.5.32 2024-08-19 12:04:46 +00:00
Andre601 44729495f5 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.7' (#322) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/322
2024-08-19 00:59:33 +00:00
Andre601 9e7500f0cd Merge pull request 'Update dependency com.google.guava:guava to v33.3.0-jre' (#323) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/323
2024-08-17 12:06:21 +00:00
Andre601's Bot d10ff8bdbc Update dependency com.google.guava:guava to v33.3.0-jre 2024-08-17 12:04:11 +00:00
Andre601's Bot f91fc36365 Update dependency ch.qos.logback:logback-classic to v1.5.7 2024-08-16 12:02:51 +00:00
Andre601 84ddff07a2 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.0' (#321) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/321
2024-08-14 12:46:12 +00:00
Andre601's Bot 4a89658cf4 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.0 2024-08-14 12:31:56 +00:00
Andre601 5daef41031 Fix renovate.json 2024-08-14 12:22:44 +00:00
Andre601 07cc1e8160 Update registry URL for Libby 2024-08-13 12:45:02 +00:00
Andre601 8b2d763207 Adding Maintenance placeholders 2024-08-12 23:29:53 +02:00
Andre601 fb8c556e24 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.6.2' (#320) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/320
2024-08-12 12:04:15 +00:00
Andre601's Bot 397fa12f12 Update dependency net.william278:papiproxybridge to v1.6.2 2024-08-12 12:03:25 +00:00
Andre601 d86ecf8d8b Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.0.3' (#319) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/319
2024-08-08 12:49:45 +00:00
Andre601's Bot 2882e9ecdf Update dependency com.viaversion:viaversion-api to v5.0.3 2024-08-08 12:03:10 +00:00
Andre601 69a4a05069 Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.3.4' (#318) from renovate/dependency.adventure-platform-bungeecord into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/318
2024-08-07 12:35:00 +00:00
Andre601's Bot 361a340ef1 Update dependency net.kyori:adventure-platform-bungeecord to v4.3.4 2024-08-07 12:03:12 +00:00
Andre601 ee7c0451af Merge pull request 'Update dependency mkdocs-material to v9.5.31' (#316) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/316
2024-08-02 12:11:44 +00:00
Andre601's Bot 200c7cbfea Update dependency mkdocs-material to v9.5.31 2024-08-02 12:03:08 +00:00
Andre601 9a665ddf26 Merge pull request 'Make various improvements to UpdateChecker' (#315) from feat/update-checker-improvements into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/315
2024-07-30 14:08:41 +00:00
Andre601 c4327ac238 Bump version and don't use lenient setting in Gson 2024-07-30 16:07:00 +02:00
Andre601 9f4b798848 Make various improvements to UpdateChecker 2024-07-29 23:42:10 +02:00
Andre601 3cc18f4dc0 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.0.2' (#313) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/313
2024-07-29 12:21:52 +00:00
Andre601's Bot 9637308045 Update dependency com.viaversion:viaversion-api to v5.0.2 2024-07-29 12:02:59 +00:00
Andre601 772603e785 Merge pull request 'Update dependency dev.masecla:Modrinth4J to v2.2.0' (#312) from renovate/dev.masecla-modrinth4j-2.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/312
2024-07-26 14:30:44 +00:00
Andre601's Bot f9417ee2f7 Update dependency dev.masecla:Modrinth4J to v2.2.0 2024-07-26 12:03:04 +00:00
Andre601 2db85bff60 Merge pull request 'Update dependency mkdocs-material to v9.5.30' (#311) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/311
2024-07-23 12:06:48 +00:00
Andre601's Bot 527b5aa25c Update dependency mkdocs-material to v9.5.30 2024-07-23 12:03:04 +00:00
Andre601 5d9bb0dc4a Merge pull request 'Update dependency mkdocs-material to v9.5.29' (#310) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/310
2024-07-14 12:05:50 +00:00
Andre601's Bot cc51756f0d Update dependency mkdocs-material to v9.5.29 2024-07-14 12:01:13 +00:00
Andre601 5ff66adb0c Merge pull request 'Fix Paper PlayerSample deprecation.' (#309) from fix/paper-playersample-deprecation into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/309
2024-07-11 14:59:21 +00:00
Andre601 8e9cc98ded Update registry URLs for Renovate 2024-07-11 13:41:07 +00:00
Andre601 4387e78007 Update VersionUploader to list latest MC release as supported. 2024-07-11 15:33:27 +02:00
Andre601 4fff1e24cc Fix Paper PlayerSample deprecation. 2024-07-11 15:28:14 +02:00
Andre601 9791ed0cee Merge pull request 'Update dependency mkdocs-material to v9.5.28' (#308) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/308
2024-07-02 15:07:08 +00:00
Andre601's Bot e8e6f3a8fd Update dependency mkdocs-material to v9.5.28 2024-07-02 12:01:55 +00:00
Andre601 5e6da9b24e Merge pull request 'Use allorigins.win for fetching stats' (#307) from feat/docs-use-allorigins.win into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/307
2024-07-01 12:28:50 +00:00
Andre601 59bd9239b2 Use raw instead? 2024-07-01 12:24:52 +00:00
Andre601 08436a278c Fix wrong json keys 2024-07-01 12:11:14 +00:00
Andre601 5d512e5e89 Use allorigins.win for fetching stats 2024-07-01 12:02:11 +00:00
Andre601 ec1a367691 Merge pull request 'Update maven Docker tag to v3.9.8' (#306) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/306
2024-06-28 12:16:32 +00:00
Andre601 457450683b Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.3' (#305) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/305
2024-06-28 12:16:21 +00:00
Andre601's Bot a8d76d6b0f Update maven Docker tag to v3.9.8 2024-06-28 12:01:20 +00:00
Andre601's Bot 5036d62824 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.3 2024-06-28 12:01:12 +00:00
Andre601 4f5f6e724f Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.0.1' (#304) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/304
2024-06-23 12:12:00 +00:00
Andre601's Bot 71f7532fe3 Update dependency com.viaversion:viaversion-api to v5.0.1 2024-06-23 12:01:14 +00:00
Andre601 9ea37af603 Merge pull request 'Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.2' (#303) from renovate/org.apache.maven.plugins-maven-jar-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/303
2024-06-20 18:35:21 +00:00
Andre601's Bot 1964a6b4e3 Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.2 2024-06-20 12:01:22 +00:00
Andre601 94a9ea31a0 Merge pull request 'Update dependency mkdocs-material to v9.5.27' (#301) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/301
2024-06-17 12:05:56 +00:00
Andre601 2855d268da Merge pull request 'Update dependency com.viaversion:viaversion-api to v5' (#302) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/302
2024-06-17 12:05:27 +00:00
Andre601's Bot d6d576da20 Update dependency com.viaversion:viaversion-api to v5 2024-06-17 12:01:48 +00:00
Andre601's Bot 34ed832d79 Update dependency mkdocs-material to v9.5.27 2024-06-17 12:01:39 +00:00
Andre601 42ef8c0c39 Update getting-started guide 2024-06-10 13:07:57 +02:00
Andre601 1ce0c2db4e Merge pull request 'Update dependency mkdocs-material to v9.5.26' (#299) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/299
2024-06-06 12:06:19 +00:00
Andre601's Bot 028aaa1cf7 Update dependency mkdocs-material to v9.5.26 2024-06-06 12:03:07 +00:00
Andre601 66937916c4 Bump version 2024-06-06 02:32:46 +02:00
Andre601 82a053095e Display yt video thumbnail 2024-06-03 23:56:41 +00:00
Andre601 f24e62687d Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.3.3' (#298) from renovate/dependency.adventure-platform-bungeecord into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/298
2024-06-02 12:03:11 +00:00
Andre601's Bot 184cf8443c Update dependency net.kyori:adventure-platform-bungeecord to v4.3.3 2024-06-02 12:01:20 +00:00
Andre601 2b06bcc497 Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0' (#297) from renovate/org.apache.maven.plugins-maven-shade-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/297
2024-06-01 12:32:39 +00:00
Andre601 743f4cc5eb Merge branch 'master' into renovate/org.apache.maven.plugins-maven-shade-plugin-3.x 2024-06-01 12:32:31 +00:00
Andre601 45ccb18133 Merge pull request 'Update dependency com.google.guava:guava to v33.2.1-jre' (#296) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/296
2024-06-01 12:32:21 +00:00
Andre601's Bot 3812e11702 Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0 2024-06-01 12:02:46 +00:00
Andre601's Bot c731cd3c87 Update dependency com.google.guava:guava to v33.2.1-jre 2024-06-01 12:02:34 +00:00
Andre601 466a24eea3 Bump ExpressionParser to 1.4.3 2024-05-29 15:05:31 +02:00
Andre601 d747a0c19a Merge pull request 'Update maven Docker tag to v3.9.7' (#295) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/295
2024-05-29 12:21:38 +00:00
Andre601's Bot 59a64620bf Update maven Docker tag to v3.9.7 2024-05-29 12:05:46 +00:00
Andre601 f36b4b4078 Merge pull request 'Update dependency mkdocs-material to v9.5.25' (#292) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/292
2024-05-27 12:03:05 +00:00
Andre601's Bot 9298b0270b Update dependency mkdocs-material to v9.5.25 2024-05-27 12:01:04 +00:00
Andre601 d8dc50ceec Make ProfileEntry nav consistent 2024-05-26 00:30:17 +00:00
Andre601 60be698c61 Upload command hover images 2024-05-25 22:17:57 +00:00
Andre601 0b37e92260 Update docs 2024-05-25 15:51:56 +02:00
Andre601 b7b1b63c4e Bump version 2024-05-25 15:43:54 +02:00
Andre601 98b923aa54 Redo command system and add profiles sub-command 2024-05-25 15:42:57 +02:00
Andre601 b24d7cb849 Simplify folder path retrieval 2024-05-23 14:57:24 +02:00
Andre601 7df7157d5f Fix another wrong folder name and bump version 2024-05-23 14:55:50 +02:00
Andre601 47263746db Merge pull request 'Add MiniMOTD migrator' (#291) from feat/minimotd-migrator into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/291
2024-05-23 12:52:32 +00:00
Andre601 ff06b06966 Fix wrong folder name on Velocity 2024-05-23 14:25:28 +02:00
Andre601 fe42d282d1 Update documentation 2024-05-23 14:19:16 +02:00
Andre601 12df4e49c6 Add serializations 2024-05-22 13:42:20 +02:00
Andre601 06812b2725 Add MiniMOTD migrator 2024-05-21 21:13:04 +02:00
Andre601 93e4ae7ca7 Merge pull request 'Update dependency me.clip:placeholderapi to v2.11.6' (#290) from renovate/me.clip-placeholderapi-2.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/290
2024-05-21 12:04:06 +00:00
Andre601's Bot d57f3f20e3 Update dependency me.clip:placeholderapi to v2.11.6 2024-05-21 12:02:46 +00:00
Andre601 f418fb961b Merge pull request 'Update dependency mkdocs-material to v9.5.24' (#288) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/288
2024-05-20 12:06:14 +00:00
Andre601 267af92ceb Merge pull request 'Update dependency com.google.code.gson:gson to v2.11.0' (#289) from renovate/com.google.code.gson-gson-2.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/289
2024-05-20 12:05:28 +00:00
Andre601's Bot 57448ddaf6 Update dependency com.google.code.gson:gson to v2.11.0 2024-05-20 12:02:53 +00:00
Andre601's Bot 9f40af4553 Update dependency mkdocs-material to v9.5.24 2024-05-20 12:02:42 +00:00
Andre601 e25da2c6c5 Remove unused GitHub Actions label 2024-05-20 11:51:38 +00:00
Andre601 897cccaa86 Update description in renovate.json 2024-05-20 11:50:27 +00:00
Andre601 512efd0efe Merge pull request 'Update dependency eu.kennytv.maintenance:maintenance-api to v4.2.1' (#287) from renovate/eu.kennytv.maintenance-maintenance-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/287
2024-05-19 12:07:28 +00:00
Andre601's Bot b67fa683c6 Update dependency eu.kennytv.maintenance:maintenance-api to v4.2.1 2024-05-19 12:01:19 +00:00
Andre601 34387925b8 Update docker image to temurin 21 2024-05-17 14:15:36 +02:00
Andre601 303dbc5ae9 Bump version 2024-05-17 14:02:50 +02:00
Andre601 ee565ff6f7 Update Paper API to 1.20.6 and use new BuildInfo class 2024-05-17 14:02:11 +02:00
Andre601 98baaab36a Add LiteBansAPI to jitpack lookup 2024-05-16 12:07:28 +00:00
Andre601 92e9d790a4 Merge pull request 'Update dependency mkdocs-material to v9.5.23' (#286) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/286
2024-05-16 12:05:26 +00:00
Andre601's Bot b8f2e2932b Update dependency mkdocs-material to v9.5.23 2024-05-16 12:02:13 +00:00
Andre601 45f9202bdd Use a normal h1 header here 2024-05-16 12:01:18 +00:00
Andre601 ffeffc70c3 Also update readme itself 2024-05-16 12:01:00 +00:00
Andre601 60080a5af6 Improve Modrinth page 2024-05-16 11:52:46 +00:00
Andre601 1191265c8c Fix missing muteDuration and banDuration placeholders in LiteBansPlaceholders
Also, make ban and mute return String instead of boolean.
2024-05-15 18:23:45 +02:00
Andre601 27dfeea12c Improve formatting page a bit 2024-05-15 16:17:18 +00:00
Andre601 e50ec1632d Add LiteBans support for BanPlugins addon 2024-05-15 17:06:09 +02:00
Andre601 a0d4dedc9d Merge pull request 'Update dependency mkdocs-material to v9.5.22' (#285) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/285
2024-05-13 12:07:09 +00:00
Andre601's Bot 9eda026738 Update dependency mkdocs-material to v9.5.22 2024-05-13 12:01:27 +00:00
Andre601 f3b81b7cb6 Fix a typo in the migration page of slp 2024-05-13 11:56:42 +00:00
Andre601 cf766ddd9a Bump version to 4.8.0 2024-05-13 13:38:11 +02:00
Andre601 12cd2f5e6b Use PAPIProxyBridge 1.6.1 2024-05-13 00:32:52 +02:00
Andre601 04ef50ea91 Use a unified Caching util 2024-05-12 14:41:28 +02:00
Andre601 d4c627fa79 Remove outdated info 2024-05-12 12:39:49 +02:00
Andre601 deffc28ab6 Implement workaround for 16 character limit on paper 2024-05-12 12:35:32 +02:00
Andre601 833f8f5dbb Fix PAPIProxyBridge breaking change 2024-05-11 15:30:04 +02:00
Andre601 5bdf2fa301 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.6' (#284) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/284
2024-05-11 12:16:13 +00:00
Andre601's Bot d13607873c Update dependency net.william278:papiproxybridge to v1.6 2024-05-11 12:01:04 +00:00
Andre601 a1f11dac03 Update docs 2024-05-10 20:38:20 +02:00
Andre601 74f1805441 Merge pull request 'Limit character length to 16 for player entries' (#283) from fix/282-profile-name-limit into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/283
2024-05-10 17:48:53 +00:00
Andre601 21046d8eee Fix index out of bounds issue 2024-05-10 19:43:01 +02:00
Andre601 0c37e3bb35 Actually truncate text after serialization [SKIP CI] 2024-05-10 17:42:48 +02:00
Andre601 3f9ea7035f Add info box to docs 2024-05-10 17:35:59 +02:00
Andre601 b55c56af12 Add note to option description. 2024-05-10 17:30:28 +02:00
Andre601 498a948605 Limit character length to 16 for player entries 2024-05-10 17:23:37 +02:00
Andre601 76a1890bba Make the migrator not create a single profiles entry 2024-05-10 15:34:33 +02:00
Andre601 8899770518 Improve SLP Migration page 2024-05-10 15:28:30 +02:00
Andre601 a7d29d292f Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.10.2' (#281) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/281
2024-05-10 12:09:48 +00:00
Andre601's Bot a9ca388f4e Update dependency com.viaversion:viaversion-api to v4.10.2 2024-05-10 12:01:34 +00:00
Andre601 c42a88142c Include names for external dependencies 2024-05-09 15:14:53 +02:00
Andre601 9fe78d3e6e Slightly better error message. 2024-05-09 15:09:38 +02:00
Andre601 816a58493a Include response body in error 2024-05-09 14:47:50 +02:00
Andre601 bc84cd2ec9 Add SLP dependency to Hangar, Update MC version and bump version 2024-05-09 14:36:13 +02:00
Andre601 5f7fda250c Merge branch 'renovate/dependency.adventure-text-serializer-legacy' 2024-05-09 14:21:19 +02:00
Andre601 03b58da260 Improve migration messages 2024-05-09 14:19:20 +02:00
Andre601 238049b58c Merge pull request 'Update dependency net.kyori:adventure-text-minimessage to v4.17.0' (#279) from renovate/dependency.adventure-text-minimessage into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/279
2024-05-09 12:16:19 +00:00
Andre601's Bot 34a701cbe9 Update dependency net.kyori:adventure-text-serializer-legacy to v4.17.0 2024-05-09 12:01:37 +00:00
Andre601's Bot bdf42b3ef1 Update dependency net.kyori:adventure-text-minimessage to v4.17.0 2024-05-09 12:01:32 +00:00
Andre601 7b82fa17d0 Merge pull request 'ServerListPlus migration support' (#276) from feature/slp-migrator into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/276
2024-05-08 15:28:19 +00:00
Andre601 05f1f285d0 Add SLP as softdependency to plugin configurations 2024-05-08 17:23:36 +02:00
Andre601 12813a4a00 Add migration guide for SLP to docs 2024-05-08 15:34:46 +02:00
Andre601 176b02ebe3 Remove unused files 2024-05-08 14:58:36 +02:00
Andre601 bd53bf7eb2 Bump version to 4.8.0-b1 2024-05-08 14:51:56 +02:00
Andre601 ae17d965e6 Merge remote-tracking branch 'origin/feature/slp-migrator' into feature/slp-migrator 2024-05-08 14:49:53 +02:00
Andre601 17b69fd38c Make single method to apply content to builders 2024-05-08 14:49:29 +02:00
Andre601 ee9c6f77ec Merge branch 'refs/heads/master' into feature/slp-migrator 2024-05-08 14:42:19 +02:00
Andre601 ddeb523154 Merge pull request 'Update dependency net.kyori:adventure-api to v4.17.0' (#278) from renovate/net.kyori-adventure-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/278
2024-05-08 12:41:18 +00:00
Andre601 04ec8e1927 Merge pull request 'Update dependency net.kyori:adventure-api to v4.17.0' (#277) from renovate/dependency.adventure-api into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/277
2024-05-08 12:41:07 +00:00
Andre601's Bot f3f3cc7927 Update dependency net.kyori:adventure-api to v4.17.0 2024-05-08 12:01:37 +00:00
Andre601's Bot c7dd3f5344 Update dependency net.kyori:adventure-api to v4.17.0 2024-05-08 12:01:31 +00:00
Andre601 19f534845f Merge branch 'master' into feature/slp-migrator 2024-05-07 23:43:46 +00:00
Andre601 3c3110a3f8 Change command output. 2024-05-08 01:38:48 +02:00
Andre601 2aa551090c Use the SLP Internal API for migration 2024-05-08 01:31:40 +02:00
Andre601 57861e435c Merge pull request 'Update dependency mkdocs-glightbox to v0.4.0' (#275) from renovate/mkdocs-glightbox-0.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/275
2024-05-07 12:05:11 +00:00
Andre601's Bot 205e1e065d Update dependency mkdocs-glightbox to v0.4.0 2024-05-07 12:01:58 +00:00
Andre601 79ee776167 Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.10.1' (#274) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/274
2024-05-06 12:03:26 +00:00
Andre601's Bot 19869084e5 Update dependency com.viaversion:viaversion-api to v4.10.1 2024-05-06 12:01:35 +00:00
Andre601 f1bd608fca Merge branch 'refs/heads/master' into feature/slp-migrator
# Conflicts:
#	.woodpecker/pr_preview.yml
#	bungeecord/src/main/java/ch/andre601/advancedserverlist/bungeecord/BungeeCordCore.java
#	requirements.txt
2024-05-05 22:59:22 +02:00
Andre601 2474e390f7 Update config.yml comments 2024-05-05 01:57:00 +02:00
Andre601 ef737d5566 Revert "First steps on an SLP migrator"
This reverts commit cda72b3b3a.
2024-05-05 00:02:47 +02:00
Andre601 9c64d3521e Remove dependencies.maven file 2024-05-05 00:02:41 +02:00
Andre601 c7c8636720 Use file-based library loading 2024-05-04 23:59:40 +02:00
Andre601 cda72b3b3a First steps on an SLP migrator 2024-05-04 23:57:40 +02:00
Andre601 04a1101045 Merge pull request 'Update dependency mkdocs-material to v9.5.21' (#272) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/272
2024-05-04 12:07:23 +00:00
Andre601 44e3e51bbc Fix missing repo 2024-05-04 12:04:54 +00:00
Andre601 40f2c44b5d Forgot publish_docs.yml 2024-05-04 14:01:27 +02:00
Andre601 16c26af04e Without the {} I guess... 2024-05-04 14:01:26 +02:00
Andre601 85aa30f82c Set git user and name globally 2024-05-04 14:01:26 +02:00
Andre601 0ad119b6e0 Manually re-write all files 2024-05-04 14:01:26 +02:00
Andre601 a612e2216b Revert changes to old file format 2024-05-04 14:01:25 +02:00
Andre601 2c0d3db9f4 This step contained spaces in name 2024-05-04 14:01:25 +02:00
Andre601's Bot 8de820747a Update dependency com.google.guava:guava to v33.2.0-jre 2024-05-04 14:01:25 +02:00
Andre601 6469893b15 Final test 2024-05-04 14:01:24 +02:00
Andre601 a46feb5e03 Maybe this? 2024-05-04 14:01:24 +02:00
Andre601 2e39683687 ...and finally here. 2024-05-04 14:01:23 +02:00
Andre601 78464ac222 Change here too 2024-05-04 14:01:23 +02:00
Andre601 92b12fd612 Try without spaces in name. 2024-05-04 14:01:23 +02:00
Andre601 5e90191aa4 Change workflow file structures. 2024-05-04 14:01:23 +02:00
Andre601 1b4ee54b73 Bump version 2024-05-04 14:01:22 +02:00
Andre601 409c007759 Remove the temp fix from CodebergReleaseFetcher 2024-05-04 14:01:22 +02:00
Andre601 49cd7410cf Use a library loader system 2024-05-04 14:01:22 +02:00
Andre601 978b21360e Use - instead of / 2024-05-04 14:01:21 +02:00
Andre601 0d1fbc15ce Add preview-domains file 2024-05-04 14:01:21 +02:00
Andre601 1cf3ba543d Maybe this works... 2024-05-04 14:01:20 +02:00
Andre601 358830cbfb Remove source command 2024-05-04 14:01:20 +02:00
Andre601 ea193d7bd3 Set target branch env using reusable 2024-05-04 14:01:20 +02:00
Andre601 8e59336833 fixing missing closing brace 2024-05-04 14:01:19 +02:00
Andre601 5083f0a3d2 Comment (Trigger workflow) 2024-05-04 14:01:19 +02:00
Andre601 d20fdd3086 Use preview repository for PR previews. 2024-05-04 14:01:19 +02:00
Andre601's Bot e005d80192 Update dependency ch.andre601:expressionparser to v1.4.2 2024-05-04 14:01:18 +02:00
Andre601 afd791b808 Update e-mail to noreply one by codeberg 2024-05-04 14:01:18 +02:00
Andre601 0acdcba09b Change e-mail to noreply one by codeberg 2024-05-04 14:01:18 +02:00
Andre601 872078ff05 Stupid typo. -_- 2024-05-04 14:01:17 +02:00
Andre601 4bfb1ec29b Apply workaround for broken Tags ENV variable 2024-05-04 14:01:17 +02:00
Andre601 97f073685e Update ExpressionParser 2024-05-04 14:01:16 +02:00
Andre601's Bot 08ab52d7f0 Update dependency mkdocs-material to v9.5.20 2024-05-04 14:01:16 +02:00
Andre601's Bot e7b7c78b11 Update dependency com.viaversion:viaversion-api to v4.10.0 2024-05-04 14:01:16 +02:00
Andre601's Bot 7df02868ad Update dependency mkdocs-material to v9.5.19 2024-05-04 14:01:15 +02:00
Andre601's Bot 063b5f90e9 Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.3 2024-05-04 14:01:15 +02:00
Andre601's Bot dd700f99e2 Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.1 2024-05-04 14:01:10 +02:00
Andre601's Bot 7b9f418b23 Update dependency mkdocs-material to v9.5.21 2024-05-04 12:01:08 +00:00
Andre601 fa163e0593 Forgot publish_docs.yml 2024-05-03 17:39:38 +02:00
Andre601 8ba86bec71 Without the {} I guess... 2024-05-03 17:38:43 +02:00
Andre601 971f404f20 Set git user and name globally 2024-05-03 17:34:46 +02:00
Andre601 f378b1e10a Manually re-write all files 2024-05-03 17:31:43 +02:00
Andre601 13a281ebf7 Revert changes to old file format 2024-05-03 16:53:12 +02:00
Andre601 e7f210739f This step contained spaces in name 2024-05-03 16:50:58 +02:00
Andre601 addca59c39 Merge pull request 'Update dependency com.google.guava:guava to v33.2.0-jre' (#271) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/271
2024-05-03 12:17:55 +00:00
Andre601's Bot f93880a0f5 Update dependency com.google.guava:guava to v33.2.0-jre 2024-05-03 12:01:09 +00:00
Andre601 489e8b60aa Final test 2024-05-02 21:56:09 +00:00
Andre601 bf418d8a9a Maybe this? 2024-05-02 21:55:39 +00:00
Andre601 1e1f11cde9 ...and finally here. 2024-05-02 21:33:34 +00:00
Andre601 34179eb850 Change here too 2024-05-02 21:32:22 +00:00
Andre601 cfcd488d44 Try without spaces in name. 2024-05-02 21:28:23 +00:00
Andre601 a49b838b83 Change workflow file structures. 2024-05-02 23:17:31 +02:00
Andre601 fdeec1e97c Bump version 2024-05-02 21:07:37 +02:00
Andre601 39ba75410e Remove the temp fix from CodebergReleaseFetcher 2024-05-02 21:07:13 +02:00
Andre601 c20d6be447 Use a library loader system 2024-05-02 20:40:31 +02:00
Andre601 d2f7f256d3 Merge pull request 'Use preview repository for PR previews.' (#267) from feature/use-preview-repo into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/267
2024-05-02 12:08:34 +00:00
Andre601 fb6abf7161 Merge pull request 'Update dependency ch.andre601:expressionparser to v1.4.2' (#270) from renovate/ch.andre601-expressionparser-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/270
2024-05-02 12:04:02 +00:00
Andre601's Bot 445bdac8a7 Update dependency ch.andre601:expressionparser to v1.4.2 2024-05-02 12:01:26 +00:00
Andre601 7bdabf93b8 Update e-mail to noreply one by codeberg 2024-05-01 15:03:01 +00:00
Andre601 8d9c0549b7 Change e-mail to noreply one by codeberg 2024-05-01 15:02:25 +00:00
Andre601 4d94a4879b Stupid typo. -_- 2024-04-29 21:11:47 +02:00
Andre601 924a72c537 Apply workaround for broken Tags ENV variable 2024-04-29 21:08:05 +02:00
Andre601 75abdccd06 Update ExpressionParser 2024-04-29 20:46:26 +02:00
Andre601 bb4b92e37e First steps on an SLP migrator 2024-04-29 20:32:47 +02:00
Andre601 880616135f Use - instead of / 2024-04-29 12:55:28 +00:00
Andre601 be72744651 Merge pull request 'Update dependency mkdocs-material to v9.5.20' (#269) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/269
2024-04-29 12:09:31 +00:00
Andre601's Bot c43090bdd8 Update dependency mkdocs-material to v9.5.20 2024-04-29 12:01:16 +00:00
Andre601 50143c2374 Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.10.0' (#268) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/268
2024-04-28 12:32:05 +00:00
Andre601's Bot 951f1853fc Update dependency com.viaversion:viaversion-api to v4.10.0 2024-04-28 12:00:58 +00:00
Andre601 a69962dd86 Add preview-domains file 2024-04-27 15:26:03 +02:00
Andre601 29e0bf8476 Maybe this works... 2024-04-27 13:20:59 +00:00
Andre601 ee41a234e8 Remove source command 2024-04-27 13:18:57 +00:00
Andre601 c8cf01319a Set target branch env using reusable 2024-04-27 13:18:15 +00:00
Andre601 3f4da7884f fixing missing closing brace 2024-04-27 13:11:15 +00:00
Andre601 965df44783 Comment (Trigger workflow) 2024-04-27 13:10:22 +00:00
Andre601 b9b8f8b36d Use preview repository for PR previews. 2024-04-27 13:05:07 +00:00
Andre601 d293cdfb39 Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.3' (#266) from renovate/org.apache.maven.plugins-maven-shade-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/266
2024-04-27 12:41:01 +00:00
Andre601 e3dc3ea548 Merge branch 'master' into renovate/org.apache.maven.plugins-maven-shade-plugin-3.x 2024-04-27 12:40:49 +00:00
Andre601 3037d3a742 Merge pull request 'Update dependency mkdocs-material to v9.5.19' (#265) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/265
2024-04-27 12:40:24 +00:00
Andre601's Bot 2230800deb Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.3 2024-04-27 12:35:30 +00:00
Andre601's Bot 1f0b8f783f Update dependency mkdocs-material to v9.5.19 2024-04-27 12:35:23 +00:00
Andre601 da8d4e93ab Merge pull request 'Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.1' (#264) from renovate/org.apache.maven.plugins-maven-jar-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/264
2024-04-20 12:10:35 +00:00
Andre601's Bot aa38567232 Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.1 2024-04-20 12:01:15 +00:00
Andre601 b6757b9622 Add PremiumVanishAPI to jitpack in packageRules 2024-04-18 12:05:17 +00:00
Andre601 ca288fdf75 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.6' (#263) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/263
2024-04-18 12:03:15 +00:00
Andre601's Bot 8b74c29bbe Update dependency ch.qos.logback:logback-classic to v1.5.6 2024-04-18 12:01:14 +00:00
Andre601 5aae4a17ef Update title for Discord icon 2024-04-18 11:57:41 +00:00
Andre601 778212d48a Improve description of Discord Server 2024-04-17 22:46:26 +02:00
Andre601 8d126436ea Remove api_support.yml file 2024-04-17 22:26:42 +02:00
Andre601 ec40db1b26 Clean up repository files a bit 2024-04-17 22:19:17 +02:00
Andre601 263c197845 Update ExpressionParserTests 2024-04-17 22:16:04 +02:00
Andre601 7bdc14aa30 Merge pull request 'Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.0' (#262) from renovate/org.apache.maven.plugins-maven-jar-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/262
2024-04-16 12:26:38 +00:00
Andre601 7ba5209222 Merge pull request 'Update dependency mkdocs-material to v9.5.18' (#261) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/261
2024-04-16 12:26:13 +00:00
Andre601's Bot 71e62e0bae Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.4.0 2024-04-16 12:06:14 +00:00
Andre601's Bot 4a8029ec31 Update dependency mkdocs-material to v9.5.18 2024-04-16 12:06:07 +00:00
Andre601 382038b9a4 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.5' (#259) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/259
2024-04-15 12:52:28 +00:00
Andre601 7f59851a3b Update ExpressionParser and ProfileConditionParser 2024-04-15 14:51:55 +02:00
Andre601's Bot 0ebcc449f8 Update dependency ch.qos.logback:logback-classic to v1.5.5 2024-04-15 12:05:32 +00:00
Andre601 323614d8c5 Only change cb_token. 2024-04-13 12:16:05 +00:00
Andre601 264dedca34 Remove useless secrets option 2024-04-13 12:13:29 +00:00
Andre601 ce26decb7d Use environment instead of secret 2024-04-13 12:08:50 +00:00
Andre601 37085e82f0 Merge pull request 'Add message on join for new versions' (#258) from feature/update-message-on-join into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/258
2024-04-13 11:58:23 +00:00
Andre601 041430e842 Bump version 2024-04-13 13:57:42 +02:00
Andre601 6762cbc245 Make delay for VersionCache 5 minutes (300k ms) 2024-04-12 22:45:18 +02:00
Andre601 917d3640f0 Add message on join for new versions 2024-04-12 22:37:10 +02:00
Andre601 0cece71f37 Include tag in release webhook message. 2024-04-10 17:30:58 +02:00
Andre601 d9c9f30cea Update invites to M.O.S.S. Discord. 2024-04-10 17:27:11 +02:00
Andre601 dcb119df96 Fix ${player protocol} using the protocol of the proxy. 2024-04-10 14:31:43 +02:00
Andre601 78ae7fbcb2 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.4' (#257) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/257
2024-04-09 23:57:48 +00:00
Andre601's Bot 1545aad32d Update dependency ch.qos.logback:logback-classic to v1.5.4 2024-04-09 12:10:52 +00:00
Andre601 035d485561 Forgot a closing double quote... 2024-04-08 00:48:00 +00:00
Andre601 f34a1ad2e4 Add gap 2024-04-08 00:44:56 +00:00
Andre601 5ceef81927 Add basic condition example 2024-04-08 00:41:24 +00:00
Andre601 6315f74312 Fix wrong link 2024-04-06 23:43:56 +00:00
Andre601 086a45593b Put negate example into admonition box 2024-04-05 22:37:44 +00:00
Andre601 1095166155 Remove unused placeholder 2024-04-04 01:03:52 +00:00
Andre601 bf89a7cb12 Add comment on failure action 2024-04-02 22:56:40 +00:00
Andre601 729b671c5a Add <filename> 2024-04-02 15:50:13 +00:00
Andre601 380791cd45 Merge pull request 'Update dependency mkdocs-material to v9.5.17' (#256) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/256
2024-04-02 12:09:37 +00:00
Andre601's Bot ca80083414 Update dependency mkdocs-material to v9.5.17 2024-04-02 12:01:00 +00:00
Andre601 ee7fa16514 Merge pull request 'Update dependency mkdocs-material to v9.5.16' (#255) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/255
2024-03-31 12:03:36 +00:00
Andre601's Bot c86a3d4101 Update dependency mkdocs-material to v9.5.16 2024-03-31 12:00:58 +00:00
Andre601 6fd6a8fe38 Re-add Hangar badge 2024-03-30 12:14:57 +00:00
Andre601 b05b38e0e8 Merge pull request 'Update actions/configure-pages action to v5' (#254) from renovate/actions-configure-pages-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/254
2024-03-30 12:02:18 +00:00
Andre601's Bot d55298d61b Update actions/configure-pages action to v5 2024-03-30 12:01:09 +00:00
Andre601 37ccf7176c Fix wrong relative link 2024-03-29 00:44:59 +00:00
Andre601 868c93ac09 Update api index about events 2024-03-29 00:42:45 +00:00
Andre601 f927e836f5 Merge pull request 'Update dependency mkdocs-material to v9.5.15' (#253) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/253
2024-03-27 22:49:40 +00:00
Andre601's Bot 2172628985 Update dependency mkdocs-material to v9.5.15 2024-03-27 22:46:32 +00:00
Andre601 628b1763da Merge pull request 'Update docs' (#252) from docs/update-docs into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/252
2024-03-27 15:58:39 +00:00
Andre601 bbe5fea132 Update docs 2024-03-27 16:51:01 +01:00
Andre601 8b555a8f53 .woodpecker/publish_assets.yml aktualisiert 2024-03-27 15:30:53 +00:00
Andre601 a5ca6fb53e Bump version 2024-03-27 16:19:09 +01:00
Andre601 164a4823e8 Fix wrong regex for LibertyBansPlaceholders and limit to 2 results 2024-03-27 16:18:27 +01:00
Andre601 352191695a Merge pull request 'Remove dependencies section' (#251) from docs/remove-dependencies-section into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/251
2024-03-19 20:49:51 +00:00
Andre601 b2235e1d8b Fix formatting 2024-03-19 20:45:47 +00:00
Andre601 324b6d6f82 Try without remote branches 2024-03-19 20:39:29 +00:00
Andre601 fd6e2e736f Merge branch 'master' into docs/remove-dependencies-section 2024-03-19 20:34:26 +00:00
Andre601 efd5164b8e Add attr_list 2024-03-19 20:32:10 +00:00
Andre601 cdb86ae83f Use branch option for git clone 2024-03-19 20:30:11 +00:00
Andre601 90c02da02e Update default.yml and config.yml examples 2024-03-19 20:19:28 +00:00
Andre601 53d56c5891 Different wording 2024-03-19 20:16:07 +00:00
Andre601 7dd02fa0e5 Try without branch option 2024-03-19 20:15:06 +00:00
Andre601 e02b944181 revert 299eff1b0d
revert Try without branch
2024-03-19 20:14:42 +00:00
Andre601 299eff1b0d Try without branch 2024-03-19 20:14:10 +00:00
Andre601 aa24ab336b Remove .pages.yml file 2024-03-19 20:13:39 +00:00
Andre601 a8b9e69e30 Remove dependencies section 2024-03-19 20:11:42 +00:00
Andre601 065c9abf9c Try with just the branch option. 2024-03-19 20:09:49 +00:00
Andre601 bdc9668b29 Merge pull request 'Fix link' (#250) from docs/fix-link into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/250
2024-03-19 20:03:49 +00:00
Andre601 7d1abdd2b2 Fix link 2024-03-19 20:03:28 +00:00
Andre601 667c642708 Merge pull request 'Add "Available on Codeberg" badge' (#248) from docs/available-on-codeberg-badge into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/248
2024-03-19 19:56:12 +00:00
Andre601 79b13ceab6 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-19 19:55:45 +00:00
Andre601 169f560b2c Add mastodon posting 2024-03-19 15:26:56 +00:00
Andre601 7e8c41c27a Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.13.0' (#249) from renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/249
2024-03-19 12:03:54 +00:00
Andre601's Bot 973966c844 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.13.0 2024-03-19 12:01:18 +00:00
Andre601 eee90cc02f Remove not needed content 2024-03-18 22:10:33 +00:00
Andre601 ecf052b955 Remove unused setting 2024-03-18 22:09:43 +00:00
Andre601 a791c86df0 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:06:38 +00:00
Andre601 63d0b0ac62 Fix wrong workflow file target 2024-03-18 22:06:26 +00:00
Andre601 c46bc37818 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:05:13 +00:00
Andre601 268d5b84c9 Add quotes 2024-03-18 22:05:05 +00:00
Andre601 0c63abfac8 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:02:59 +00:00
Andre601 35ca151424 Set default branch directly 2024-03-18 22:02:45 +00:00
Andre601 e28800f72f Add evaluate when check 2024-03-18 21:43:51 +00:00
Andre601 8232357aba Add "Available on Codeberg" badge 2024-03-18 21:35:28 +00:00
Andre601 eae7f1117c Merge pull request 'Create PR-preview' (#247) from feature/pr-preview into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/247
2024-03-18 21:26:11 +00:00
Andre601 d25053b285 Add switch and set-branches git commands 2024-03-18 21:25:54 +00:00
Andre601 57273bd265 Use bot token for docs publish 2024-03-18 20:44:11 +00:00
Andre601 9cf694a7d6 Use bot token 2024-03-18 20:43:38 +00:00
Andre601 5bc0c7b843 Create PR-preview 2024-03-18 20:35:45 +00:00
Andre601 1c48fd61bc Fix wrong target URL 2024-03-18 19:54:15 +00:00
Andre601 8e622b4038 Add woodpecker file to CI run 2024-03-18 19:51:37 +00:00
Andre601 35e37bca2e Move site to dedicated repository 2024-03-18 19:50:47 +00:00
Andre601 cdb508994f Improve default.yml file 2024-03-18 15:53:20 +01:00
Andre601 1113c41379 Merge pull request 'Update dependency mkdocs-material to v9.5.14' (#246) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/246
2024-03-18 12:05:24 +00:00
Andre601's Renovate Bot d186ca82a2 Update dependency mkdocs-material to v9.5.14 2024-03-18 12:01:09 +00:00
Andre601 5cda9e819b Add missing changelog entry 2024-03-17 01:30:19 +00:00
Andre601 fe5a73440b Update API Javadocs URL 2024-03-16 21:39:01 +00:00
158 changed files with 5535 additions and 1891 deletions

No files matched your search

+43
View File
@@ -0,0 +1,43 @@
name: "Deploy Wiki"
on:
push:
branches:
- master
tags-ignore:
- "**"
paths:
- ".forgejo/workflows/deploy_wiki.yml"
- "docs/**"
- "domains"
- "mkdocs.yml"
- "requirements.txt"
jobs:
deployWiki:
runs-on: codeberg-tiny
steps:
- name: "Checkout Source Repository"
uses: https://code.forgejo.org/actions/checkout@v4
with:
token: "${{ secrets.BOT_TOKEN }}"
- name: "Checkout Target Repository"
run: "git clone -b pages https://codeberg.org/Andre601/asl-docs site"
- name: "Setup Python 3.x"
uses: https://code.forgejo.org/actions/setup-python@v5
with:
python-version: 3.x
- name: "Install Dependencies"
run: "pip install -r requirements.txt"
- name: "Build Website"
run: "mkdocs build"
- name: "Commit and Push"
run: |
git config --global user.email "andre_601-bot@noreply.codeberg.org"
git config --global user.name "ASL Wiki Builder"
mv domains site/.domains
cd site
git remote set-url origin https://${{ secrets.BOT_TOKEN }}@codeberg.org/Andre601/asl-docs
git add --all
git commit -m "Update Wiki ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" ))"
git push
+116
View File
@@ -0,0 +1,116 @@
name: Pull Request Preview
on:
pull_request_target:
types:
- opened
- reopened
- synchronize
paths:
- ".forgejo/workflows/pr_preview.yml"
- "docs/**"
- "mkdocs.yml"
- "preview_domains"
- "requirements.txt"
workflow_dispatch:
env:
BRANCH_NAME: "${{ github.event.repository.name }}/${{ github.event.pull_request.number }}"
RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
jobs:
createPreview:
runs-on: codeberg-tiny
steps:
#
# Finding and updating comment in Pull request.
# If not found, have one created instead.
#
- name: "Find Comment"
id: find-comment
uses: https://github.com/peter-evans/find-comment@v3
with:
issue-number: "${{ github.event.pull_request.number }}"
comment-author: "Andre_601-Bot"
- name: "Create or update Comment"
id: comment
uses: https://github.com/peter-evans/create-or-update-comment@v4
with:
body: |-
## Pull request Preview
Creating Preview for Pull request. Please wait...
comment-id: "${{ steps.find-comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
#
# Setup source and target repository.
# Build website and push.
#
- name: "Checkout Source Repository"
uses: https://code.forgejo.org/actions/checkout@v4
with:
token: ${{ secrets.BOT_TOKEN }}
fetch-depth: 0
ref: "${{ github.event.pull_request.head.sha }}"
- name: "Checkout Target Repository"
run: |
git clone https://codeberg.org/Andre601/preview site
cd site
git switch ${{ env.BRANCH_NAME }} 2>/dev/null || git switch -c ${{ env.BRANCH_NAME }}
- name: "Setup Python 3.x"
uses: https://code.forgejo.org/actions/setup-python@v5
with:
python-version: 3.x
- name: "Install Dependencies"
run: "pip install -r requirements.txt"
- name: "Build Website"
run: "mkdocs build"
- name: "Commit and Push"
run: |
git config --global user.email "andre_601-bot@noreply.codeberg.org"
git config --global user.name "PR Docs Preview Builder"
mv preview_domains site/.domains
cd site
git remote add upstream https://${{ secrets.BOT_TOKEN }}@codeberg.org/Andre601/preview.git
git add --all
git commit -m "Update Preview for ${{ env.BRANCH_NAME }} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" ))"
git push --set-upstream upstream ${{ env.BRANCH_NAME }} -f
#
# Update comment on success or failure.
#
- name: "Comment Success"
uses: https://github.com/peter-evans/create-or-update-comment@v4
with:
body: |-
## Pull request Preview
Pull request Preview created successfully!
| Name | Link |
|---------|----------------------------------------------------------------------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Preview | https://preview.andre601.ch/@${{ github.event.repository.name }}~${{ github.event.pull_request.number }} |
| Logs | ${{ env.RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
- name: "Comment Failure"
if: ${{ failure() }}
uses: https://github.com/peter-evans/create-or-update-comment@v4
with:
body: |-
## Pull request Preview
Pull request Preview failed! Check the logs for details.
| Name | Link |
|---------|-------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Logs | ${{ RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
File renamed without changes.
+11
View File
@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: API Support
about: For API support, please create an issue in the `asl-api` repository.
url: https://codeberg.org/Andre601/asl-api
- name: Discord Server
about: Please ask questions in the `#asl-support` channel on the M.O.S.S. Discord Server.
url: https://discord.gg/MyPTjpsgGH
- name: Wiki
about: Check the Wiki for explanations about the features and examples.
url: https://asl.andre601.ch
+103
View File
@@ -0,0 +1,103 @@
<center><strong><u><font size="6">AdvancedServerList</font ></u></strong></center>
AdvancedServerList is a plugin designed to allow the largest possible customization for your server's appearance in a Player's multiplayer screen.
The plugin offers extensive customization including changing the MOTD, player count text, player count hover and favicon of your server. All while also allowing you to create multiple profiles with priorities and conditions to set when a specific profile should be displayed.
## Supported Platforms
<a href="https://papermc.io" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg&h=48" alt="platform-paper" title="Tested on Paper">
</a>
<br>
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/bungeecord_vector.svg&h=48" alt="platform-bungeecord" title="Tested on BungeeCord">
</a>
<br>
<a href="https://www.papermc.io" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/waterfall_vector.svg&h=48" alt="platform-waterfall" title="Tested on Waterfall">
</a>
<br>
<a href="https://velocitypowered.com" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/velocity_vector.svg&h=48" alt="platform-velocity" title="Tested on Velocity">
</a>
## Server List Profiles
A Server List Profile is a single YAML file located in the plugin's `profiles` folder. It contains settings that allow you to modify the server's appearance within a Player's multiplayer screen.
### Priority and Conditions
Each file has a priority and optional condition. The priority is used to determine what file AdvancedServerList should use first - starting from highest number to lowest - with conditions being used to set when the profile should be used.
Once a profile has been found with a condition returning true - which is the default should there be no condition - will AdvancedServerList use said profile.
> *Read more about [Priority](https://asl.andre601.ch/profiles/#priority) and [Conditions](https://asl.andre601.ch/profiles/#condition)*
### Placeholders
AdvancedServerList supports two sets of placeholders. The first one being its own placeholders using the `${<type> <values>}` format adobted from BungeeTabListPlus and the second one being placeholders from PlaceholderAPI using its `%<identifier>_<values>%` placeholder format.
Note that internal placeholders can be used in all text-based options of a profile, while PlaceholderAPI placeholders can be used in all text-based options except the `condition` one.
As a final note can plugins provide their own placeholders to use within AdvancedServerList by using its API.
> *Read more about [Placeholders](https://asl.andre601.ch/profiles/placeholders/)*
### Formatting
AdvancedServerList utilizes the MiniMessage formatting to handle colors and formatting of text. This option was chosen over legacy formatting - using `&` character - for being more clear and readable in its design, not to mention having an easier way for more complex features such as RGB gradients.
> *Read more about [Formatting](https://asl.andre601.ch/profiles/formatting/)*
## Dependencies
AdvancedServerList soft-depends on the following plugins, meaning their inclusion is not required.
| Plugin | Supported Platforms |
|-------------------------------------------------------------------------|----------------------------------------|
| [PlaceholderAPI](https://hangar.papermc.io/HelpChat/PlaceholderAPI) | Paper |
| [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) | Paper |
| [PAPIProxyBridge](https://hangar.papermc.io/William278/PAPIProxyBridge) | BungeeCord, Waterfall, Velocity |
| [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) | Paper, BungeeCord, Waterfall, Velocity |
## Statistics
The plugin sends statistics to [bStats](https://bstats.org) to show.
You can disable the sending of statistics in the global bStats config located inside `/plugins/bstats/`.
You can find the bStats pages of the plugin for the following platforms:
- [Paper](https://bstats.org/plugin/bungeecord/AdvancedServerList/15584)
- [BungeeCord, Waterfall](https://bstats.org/plugin/bungeecord/AdvancedServerList/15585)
- [Velocity](https://bstats.org/plugin/velocity/AdvancedServerList/15587)
## Videos
Below can you find a collection of videos made for my plugin. If you made a video and it isn't shown here, let me know and I'll add it.
<details><summary>Click to show/hide Videos</summary>
<p>
Spanish Video by Ajneb97
<iframe width="560" height="auto" src="https://www.youtube.com/embed/rIbljm_4HVI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</p>
</details>
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/modrinth-gallery_vector.svg&h=48" alt="gallery" title="Check out the Gallery">
</a>
## Support
<a href="https://discord.gg/MyPTjpsgGH" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg&h=48" alt="discord" title="Join the M.O.S.S. Discord Server">
</a>
<br>
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg&h=48" alt="revolt" title="Join my Revolt Server">
</a>
<br>
<a href="https://swiss.social/@andre_601" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg&h=48" alt="revolt" title="Chat with me on Mastodon">
</a>
File renamed without changes.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

+37
View File
@@ -0,0 +1,37 @@
name: Pull Request
description: Create a new Pull request
body:
- type: markdown
attributes:
value: |-
Thank you for creating a Pull request!
Please be sure to fill out this template with all requested information to ensure it being valid and not being closed unmerged.
- type: dropdown
attributes:
label: Type
description: What kind of Pull request is this?
options:
- Enhancement
- Bugfix
- Documentation
validations:
required: true
- type: dropdown
attributes:
label: Breaking Change?
description: |-
Is this a breaking change?
A breaking change means that it becomes incompatible with previous server/proxy versions or plugin versions.
options:
- Yes
- No
validations:
required: true
- type: textarea
attributes:
label: Description
description: Provide a detailed description of what this Pull request is doing. Link any issues this Pull request may fix/close.
validations:
required: true
-2
View File
@@ -1,2 +0,0 @@
patreon: andre_601
ko_fi: andre_601
-41
View File
@@ -1,41 +0,0 @@
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+ 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
-8
View File
@@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Discord Server
about: Ask questions about the plugin in the `#advancedserverlist` channel.
url: https://discord.gg/6dazXp6
- name: Wiki
about: Check the Wiki for explanations about the features and examples.
url: https://docs.andre601.ch/AdvancedServerList
-108
View File
@@ -1,108 +0,0 @@
# AdvancedServerList
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Supported Platforms
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/spigot_vector.svg&w=64 alt="platform-spigot" title="Tested on Spigot">
</a>
<a href="https://papermc.io" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/paper_vector.svg&w=64 alt="platform-paper" title="Tested on Paper">
</a>
<a href="https://www.spigotmc.org" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/bungeecord_vector.svg&w=64 alt="platform-bungeecord" title="Tested on BungeeCord">
</a>
<a href="https://www.papermc.io" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/waterfall_vector.svg&w=64 alt="platform-waterfall" title="Tested on Waterfall">
</a>
<a href="https://velocitypowered.com" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/supported/velocity_vector.svg&w=64 alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
> [*Read More*][profiles]
### Conditions
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
> [*Read More*][conditions]
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option (motd, playerCount and players) to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
When using the SpigotMC/PaperMC version can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
> [*Read More*][placeholders]
### Formatting
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
> [*Read More*][minimessage]
## Dependencies
| Dependency | Platforms | Required? |
|------------------|---------------|-----------|
| [ProtocolLib] | Spigot | Yes |
| [PlaceholderAPI] | Spigot, Paper | No |
| [ViaVersion] | Spigot, Paper | No |
## Statistics
This plugin sends statistics to [bStats] to display.
You can disable this in the global bStats config file located in `/plugins/bstats/`
- [BungeeCord][bstats-bungee]
- [Paper/Spigot][bstats-spigot]
- [Velocity][bstats-velocity]
## Videos
Do you have your own video to share? Contact me and I will add it to this section.
<details><summary>Click to Show/Hide Videos</summary>
Spanish Video by Ajneb97
<iframe width="560" height="auto" src="https://www.youtube.com/embed/rIbljm_4HVI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</details>
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/modrinth-gallery_vector.svg&w=208" alt="gallery" title="Check out the Gallery">
</a>
## Support
<a href="https://discord.gg/6dazXp6" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/discord-singular_vector.svg&w=64" alt="discord" title="Join my Discord Server">
</a>
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/revolt-singular_vector.svg&w=64" alt="revolt" title="Join my Revolt Server">
</a>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact-minimal/social/mastodon-singular_vector.svg&w=64" alt="revolt" title="Chat with me on Mastodon">
</a>
<!-- Links -->
[profiles]: https://docs.andre601.ch/AdvancedServerList/latest/profiles
[conditions]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/#conditions
[placeholders]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/placeholders
[minimessage]: https://docs.andre601.ch/AdvancedServerList/latest/profiles/formatting
[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
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
-14
View File
@@ -1,14 +0,0 @@
"Target: All":
- all: ["bukkit/**", "bungeecord/**", "core/**", "velocity/**"]
"Target: Bukkit":
- all: ["bukkit/**", "!bungeecord/**", "!core/**", "!velocity/**"]
"Target: BungeeCord":
- all: ["!bukkit/**", "bungeecord/**", "!core/**", "!velocity/**"]
"Target: Core":
- all: ["!bukkit/**", "!bungeecord/**", "core/**", "!velocity/**"]
"Target: Velocity":
- all: ["!bukkit/**", "!bungeecord/**", "!core/**", "velocity/**"]
-49
View File
@@ -1,49 +0,0 @@
name: 'Deploy Site (Push)'
on:
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
env:
GITHUB_REPO_INSTANCE: true
jobs:
build:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.7
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Create/Get Cache
uses: actions/cache@v4
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: Build docs
run: mkdocs build
- name: Configure GitHub Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'site/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+64
View File
@@ -0,0 +1,64 @@
when:
- event: pull_request
path:
include: [".woodpecker/pr_preview.yml", "docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "andre_601-bot@noreply.codeberg.org"
- git config --global user.name "PR Docs Preview Builder"
steps:
- name: "Clone Preview Repository"
image: alpine:3.20.3
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone https://codeberg.org/Andre601/preview.git site
- chmod -R a+w site
- cd site
- git switch ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST} 2>/dev/null || git switch -c ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST}
- name: "Build Docs"
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
- name: "Commit and Push"
image: alpine:3.20.3
secrets:
- bot_token
commands:
- <<: *setup_git
- mv preview-domains site/.domains
- cd site
- git remote add upstream https://$BOT_TOKEN@codeberg.org/Andre601/preview.git
- git add --all
- git commit -m "Update Preview for ${CI_REPO_NAME}/${CI_COMMIT_PULL_REQUEST} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push --set-upstream upstream ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST} -f
- name: "Comment on Success"
image: mcs94/gitea-comment
when:
- status: ["success"]
settings:
gitea_address: https://codeberg.org
gitea_token:
from_secret: BOT_TOKEN
comment: |-
Pull request Preview Ready!
| Name | Value |
|--------|--------------------------------------------------------------------------|
| Commit | ${CI_COMMIT_SHA} |
| Link | https://preview.andre601.ch/@${CI_REPO_NAME,,}~${CI_COMMIT_PULL_REQUEST} |
- name: "Comment on Failure"
image: mcs94/gitea-comment
when:
- status: ["failure"]
settings:
gitea_address: https://codeberg.org
gitea_token:
from_secret: BOT_TOKEN
comment: |-
Pull request Preview **failed**!
Please check the CI logs for details: ${CI_PIPELINE_URL}
+30 -18
View File
@@ -1,29 +1,26 @@
when:
- event: tag
branch: master
branch: ${CI_REPO_DEFAULT_BRANCH}
steps:
createFiles:
image: maven:3.9.6-eclipse-temurin-17
secrets:
- source: cb_token
target: codeberg_api_token
- source: modrinth_api_token
target: modrinth_api_token
- source: hangar_api_token
target: hangar_api_token
- source: discord_webhook_url
target: discord_webhook_url
- name: "Build Jar and Upload"
image: maven:3.9.9-eclipse-temurin-21
environment:
CODEBERG_API_TOKEN:
from_secret: cb_token
MODRINTH_API_TOKEN:
from_secret: modrinth_api_token
HANGAR_API_TOKEN:
from_secret: hangar_api_token
DISCORD_WEBHOOK_URL:
from_secret: discord_webhook_url
commands:
# Create the jar files.
- mvn clean install
# Move VersionUploader jar file
- cd version-uploader/target/
- cd version-uploader/target
- mv VersionUploader.jar ../../
- cd ../../
# Execute Jar file
- java -jar VersionUploader.jar --all
uploadToCodeberg:
- name: "Upload Jars to Codeberg"
image: woodpeckerci/plugin-gitea-release
settings:
base_url: https://codeberg.org
@@ -33,4 +30,19 @@ steps:
- "velocity/target/AdvancedServerList-*.jar"
- "addons/banplugins/target/AdvancedServerList-*.jar"
api_key:
from_secret: CB_TOKEN
from_secret: cb_token
- name: "Create Post on Mastodon"
image: woodpeckerci/plugin-mastodon-post
when:
- status: ["success"]
settings:
server_url: https://swiss.social
access_token:
from_secret: mastodon_token
status: |-
#AdvancedServerList was updated to ${CI_COMMIT_TAG} and can be downloaded from #Modrinth, #Hangar and #Codeberg!
Modrinth - https://modrinth.com/plugin/advancedserverlist
Hangar - https://hangar.papermc.io/Andre_601/AdvancedServerList
Codeberg - https://codeberg.org/Andre601/AdvancedServerList
visibility: public
@@ -1,36 +1,36 @@
when:
- branch: master
event: push
- event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
path:
include: ['requirements.txt', 'mkdocs.yml', 'docs/**']
include: [".woodpecker/publish_docs.yml", "docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "github@andre601.ch"
- git config --global user.email "andre_601-bot@noreply.codeberg.org"
- git config --global user.name "ASL Docs Builder"
steps:
cloneTargetRepo:
image: alpine:3.18.4
- name: "Clone target Repository"
image: alpine:3.20.3
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
- git clone -b pages https://codeberg.org/Andre601/asl-docs.git site
- chmod -R a+w site
buildDocs:
- name: "Build Docs"
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
commitAndPush:
image: alpine:3.18.4
- name: "Commit and Push"
image: alpine:3.20.3
secrets:
- cb_token
- bot_token
commands:
- <<: *setup_git
- mv domains site/.domains
- cd site
- git remote set-url origin https://$CB_TOKEN@codeberg.org/Andre601/AdvancedServerList.git
- git remote set-url origin https://$BOT_TOKEN@codeberg.org/Andre601/asl-docs.git
- git add --all
- git commit -m "Update AdvancedServerList Docs ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
+62 -67
View File
@@ -1,121 +1,116 @@
# AdvancedServerList
AdvancedServerList is a plugin that allows 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.
AdvancedServerList is a plugin designed to allow the largest possible customization for your server's appearance in a Player's multiplayer screen.
The plugin offers extensive customization including changing the MOTD, player count text, player count hover and favicon of your server. All while also allowing you to create multiple profiles with priorities and conditions to set when a specific profile should be displayed.
## 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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg" height="48" 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">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg" height="48" alt="hangar" title="Available on Hangar">
</a>
-->
## Supported Platforms
<a href="https://papermc.io" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/supported/paper_vector.svg" height="64" alt="platform-paper" title="Tested on Paper">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/paper_vector.svg" height="48" alt="platform-paper" title="Tested on Paper">
</a>
<br>
<a href="https://www.spigotmc.org" target="_blank">
<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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/bungeecord_vector.svg" height="48" alt="platform-bungeecord" title="Tested on BungeeCord">
</a>
<br>
<a href="https://www.papermc.io" target="_blank">
<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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/waterfall_vector.svg" height="48" alt="platform-waterfall" title="Tested on Waterfall">
</a>
<br>
<a href="https://velocitypowered.com" target="_blank">
<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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/supported/velocity_vector.svg" height="48" alt="platform-velocity" title="Tested on Velocity">
</a>
## What is a Server List Profile?
## Server List Profiles
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
A Server List Profile is a single YAML file located in the plugin's `profiles` folder. It contains settings that allow you to modify the server's appearance within a Player's multiplayer screen.
> [*Read More*][profiles]
### Priority and Conditions
### Conditions
Each file has a priority and optional condition. The priority is used to determine what file AdvancedServerList should use first - starting from highest number to lowest - with conditions being used to set when the profile should be used.
Once a profile has been found with a condition returning true - which is the default should there be no condition - will AdvancedServerList use said profile.
Thanks to conditions can you determine when a profile should be displayed in the player's server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes it automatically true.
> [*Read More*][conditions]
> *Read more about [Priority](https://asl.andre601.ch/profiles/#priority) and [Conditions](https://asl.andre601.ch/profiles/#condition)*
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
AdvancedServerList supports two sets of placeholders. The first one being its own placeholders using the `${<type> <values>}` format adobted from BungeeTabListPlus and the second one being placeholders from PlaceholderAPI using its `%<identifier>_<values>%` placeholder format.
When using the SpigotMC/PaperMC version, or while [PAPIProxyBridge][papiproxybridge] is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed on the server (not proxy) for that.
Note that internal placeholders can be used in all text-based options of a profile, while PlaceholderAPI placeholders can be used in all text-based options except the `condition` one.
As a final note can plugins provide their own placeholders to use within AdvancedServerList by using its API.
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
> [*Read More*][placeholders]
> *Read more about [Placeholders](https://asl.andre601.ch/profiles/placeholders/)*
### Formatting
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
AdvancedServerList utilizes the MiniMessage formatting to handle colors and formatting of text. This option was chosen over legacy formatting - using `&` character - for being more clear and readable in its design, not to mention having an easier way for more complex features such as RGB gradients.
> [*Read More*][minimessage]
> *Read more about [Formatting](https://asl.andre601.ch/profiles/formatting/)*
## Dependencies
All listed dependencies are optional.
AdvancedServerList soft-depends on the following plugins, meaning their inclusion is not required.
| Dependency | Platforms |
|-------------------|----------------------|
| [PlaceholderAPI] | Paper |
| [ViaVersion] | Paper |
| [PAPIProxyBridge] | BungeeCord, Velocity |
| [Maintenance] | All |
| Plugin | Supported Platforms |
|-------------------------------------------------------------------------|----------------------------------------|
| [PlaceholderAPI](https://hangar.papermc.io/HelpChat/PlaceholderAPI) | Paper |
| [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) | Paper |
| [PAPIProxyBridge](https://hangar.papermc.io/William278/PAPIProxyBridge) | BungeeCord, Waterfall, Velocity |
| [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) | Paper, BungeeCord, Waterfall, Velocity |
## Statistics
This plugin sends statistics to [bStats] to display.
You can disable this in the global bStats config file located in `/plugins/bstats/`
The plugin sends statistics to [bStats](https://bstats.org) to show.
You can disable the sending of statistics in the global bStats config located inside `/plugins/bstats/`.
- [BungeeCord][bstats-bungee]
- [Paper/Spigot][bstats-spigot]
- [Velocity][bstats-velocity]
You can find the bStats pages of the plugin for the following platforms:
- [Paper](https://bstats.org/plugin/bungeecord/AdvancedServerList/15584)
- [BungeeCord, Waterfall](https://bstats.org/plugin/bungeecord/AdvancedServerList/15585)
- [Velocity](https://bstats.org/plugin/velocity/AdvancedServerList/15587)
## Videos
Below can you find a collection of videos made for my plugin. If you made a video and it isn't shown here, let me know and I'll add it.
<details><summary>Click to show/hide Videos</summary>
<p>
English Video by KasaiSora
[![video thumbnail](https://img.youtube.com/vi/9cU0uUWHOO0/0.jpg)](https://youtube.com/watch?v=9cU0uUWHOO0)
Spanish Video by Ajneb97
[![video thumbnail](https://img.youtube.com/vi/rIbljm_4HVI/0.jpg)](https://youtube.com/watch?v=rIbljm_4HVI)
</p>
</details>
## Screenshots
<a href="https://modrinth.com/plugin/advancedserverlist/gallery" target="_blank">
<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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/modrinth-gallery_vector.svg" height="48" alt="gallery" title="Check out the Gallery">
</a>
## Support
<a href="https://discord.gg/6dazXp6" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact-minimal/social/discord-singular_vector.svg" height="64" alt="discord" title="Join my Discord Server">
<a href="https://discord.gg/MyPTjpsgGH" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-singular_vector.svg" height="48" alt="discord" title="Join the M.O.S.S. Discord Server">
</a>
<br>
<a href="https://app.revolt.chat/invite/74TpERXA" target="_blank">
<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">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg" height="48" alt="revolt" title="Join my Revolt Server">
</a>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<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://asl.andre601.ch/profiles/
[conditions]: https://asl.andre601.ch/profiles/#condition
[placeholders]: https://asl.andre601.ch/profiles/placeholders/
[minimessage]: https://asl.andre601.ch/profiles/formatting/
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
[bstats]: https://bstats.org
[bstats-bungee]: https://bstats.org/plugin/bungeecord/AdvancedServerList/15585
[bstats-spigot]: https://bstats.org/plugin/bukkit/AdvancedServerList/15584
[bstats-velocity]: https://bstats.org/plugin/velocity/AdvancedServerList/15587
[gallery]: https://modrinth.com/mod/advancedserverlist/gallery
<br>
<a href="https://swiss.social/@andre_601" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg" height="48" alt="revolt" title="Chat with me on Mastodon">
</a>
+60
View File
@@ -0,0 +1,60 @@
# Supported Versions
To ensure proper safety and support are only certain versions and Platforms of AdvancedServerList maintained and supported.
## Supported Plugin Versions
| Major Version | Supported |
|---------------|-----------|
| v5 | Yes |
| v4 | Yes* |
| v3 | Yes** |
| v2 | No |
| v1 | No |
\*Only receives support but no updates or bug fixes.
\*\*Support ends at the end of 2024.
## Supported Server/Proxy Versions
| Server/Proxy Version* | Supported |
|-----------------------|-----------|
| 1.21.x | Yes |
| 1.20.x | Yes |
| 1.19.x | No |
| 1.18.x | No |
| 1.17.x | No |
| 1.16.x | No |
| 1.15.x | No |
| 1.14.x | No |
| 1.13.x | No |
| 1.12.x | No |
| 1.11.x | No |
| 1.10.x | No |
| 1.19.x | No |
| 1.8.x | No |
\*Only the latest patch version is actively supported should "Supported" have "Yes".
## Supported Platforms
### Servers
| Server | Supported |
|--------|-----------|
| Spigot | No |
| Paper | Yes |
| Purpur | Yes* |
| Mohist | No |
\*Support hasn't actively been tested, but should work without issues.
### Proxies
| Proxy | Supported |
|------------|-----------|
| BungeeCord | Yes** |
| Waterfall | Yes** |
| Velocity | Yes |
\*\*Platform version of this plugin is maintenance only, not receiving any bug fixes for major breaking changes anymore.
+10 -4
View File
@@ -52,7 +52,7 @@
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>libertybans</id>
@@ -79,7 +79,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.20-R0.1-SNAPSHOT</version>
<version>1.21-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -99,7 +99,13 @@
<dependency>
<groupId>space.arim.libertybans</groupId>
<artifactId>bans-api</artifactId>
<version>1.1.0-RC1</version>
<version>1.1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gitlab.ruany</groupId>
<artifactId>LiteBansAPI</artifactId>
<version>0.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -122,7 +128,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
@@ -23,35 +23,48 @@
*
*/
package ch.andre601.advancedserverlist.banplugins.bungeecord;
package ch.andre601.advancedserverlist.banplugins;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.placeholders.AdvancedBanPlaceholders;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import ch.andre601.advancedserverlist.banplugins.placeholders.LiteBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum BungeeCordBanPlugins{
public enum BanPluginsList{
ADVANCED_BAN("AdvancedBan", new AdvancedBanPlaceholders()),
LIBERTY_BANS("LibertyBans", new LibertyBansPlaceholders());
ADVANCED_BAN("AdvancedBan", new AdvancedBanPlaceholders(), true, true, false),
LIBERTY_BANS("LibertyBans", new LibertyBansPlaceholders(), true, true, true),
LITE_BANS("LiteBans", new LiteBansPlaceholders(), true, true, true);
private final String plugin;
private final String name;
private final PlaceholderProvider placeholderProvider;
private final boolean paper, bungeecord, velocity;
BungeeCordBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
BanPluginsList(String name, PlaceholderProvider placeholderProvider, boolean paper, boolean bungeecord, boolean velocity){
this.name = name;
this.placeholderProvider = placeholderProvider;
this.paper = paper;
this.bungeecord = bungeecord;
this.velocity = velocity;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(BungeeCordBanPlugins bungeeCordBanPlugins : BungeeCordBanPlugins.values()){
content.put(bungeeCordBanPlugins.plugin, bungeeCordBanPlugins.placeholderProvider);
}
return content;
public String getName(){
return name;
}
public PlaceholderProvider getPlaceholderProvider(){
return placeholderProvider;
}
public boolean supportsPaper(){
return paper;
}
public boolean supportsBungeeCord(){
return bungeecord;
}
public boolean supportsVelocity(){
return velocity;
}
}
@@ -26,11 +26,9 @@
package ch.andre601.advancedserverlist.banplugins.bungeecord;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.BanPluginsList;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.Map;
public class BungeeCordBanPluginsAddon extends Plugin{
@Override
@@ -50,14 +48,16 @@ public class BungeeCordBanPluginsAddon extends Plugin{
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = BungeeCordBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(getProxy().getPluginManager().getPlugin(entry.getKey()) != null){
getLogger().info("Registering Placeholders for " + entry.getKey() + "...");
api.addPlaceholderProvider(entry.getValue());
getLogger().info("Placeholder successfully registered!");
for(BanPluginsList entry : BanPluginsList.values()){
if(!entry.supportsBungeeCord())
continue;
if(getProxy().getPluginManager().getPlugin(entry.getName()) != null){
getLogger().info("Registering Placeholders for " + entry.getName() + "...");
api.addPlaceholderProvider(entry.getPlaceholderProvider());
getLogger().info("Placeholders successfully registered!");
loaded++;
}
@@ -1,57 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.banplugins.paper;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.placeholders.AdvancedBanPlaceholders;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum PaperBanPlugins{
ADVANCED_BAN("AdvancedBan", new AdvancedBanPlaceholders()),
LIBERTY_BANS("LibertyBans", new LibertyBansPlaceholders());
private final String plugin;
private final PlaceholderProvider placeholderProvider;
PaperBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
this.placeholderProvider = placeholderProvider;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(PaperBanPlugins paperBanPlugins : PaperBanPlugins.values()){
content.put(paperBanPlugins.plugin, paperBanPlugins.placeholderProvider);
}
return content;
}
}
@@ -26,11 +26,9 @@
package ch.andre601.advancedserverlist.banplugins.paper;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.BanPluginsList;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Map;
public class PaperBanPluginsAddon extends JavaPlugin{
@Override
@@ -53,14 +51,16 @@ public class PaperBanPluginsAddon extends JavaPlugin{
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = PaperBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(getServer().getPluginManager().isPluginEnabled(entry.getKey())){
getLogger().info("Registering Placeholders for " + entry.getKey() + "...");
api.addPlaceholderProvider(entry.getValue());
getLogger().info("Placeholder successfully registered!");
for(BanPluginsList entry : BanPluginsList.values()){
if(!entry.supportsPaper())
continue;
if(getServer().getPluginManager().isPluginEnabled(entry.getName())){
getLogger().info("Registering Placeholders for " + entry.getName() + "...");
api.addPlaceholderProvider(entry.getPlaceholderProvider());
getLogger().info("Placeholders successfully registered!");
loaded++;
}
@@ -30,11 +30,9 @@ import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.banplugins.providers.AdvancedBanProvider;
import java.util.Arrays;
public class AdvancedBanPlaceholders extends PlaceholderProvider{
private final AdvancedBanProvider provider = new AdvancedBanProvider();
private AdvancedBanProvider provider = null;
public AdvancedBanPlaceholders(){
super("advancedban");
@@ -42,19 +40,19 @@ public class AdvancedBanPlaceholders extends PlaceholderProvider{
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
String[] args = placeholder.split("\\s");
if(provider == null)
provider = new AdvancedBanProvider();
String[] args = placeholder.split("\\s", 2);
return switch(args[0]) {
// Mute-related placeholders
case "isMuted" -> String.valueOf(provider.muted(player));
case "isMuted" -> provider.muted(player);
case "muteReason" -> provider.muteReason(player);
case "muteDuration" -> {
if(args.length == 1)
yield provider.muteDuration(player);
if(args.length > 2)
yield null;
boolean fromStart = Boolean.getBoolean(args[1]);
yield provider.muteDuration(player, fromStart);
}
@@ -62,21 +60,16 @@ public class AdvancedBanPlaceholders extends PlaceholderProvider{
if(args.length == 1)
yield provider.muteExpirationDate(player);
String pattern = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
yield provider.banExpirationDate(player, pattern);
yield provider.banExpirationDate(player, args[1]);
}
// Ban-related placeholders
case "isBanned" -> String.valueOf(provider.banned(player));
case "isBanned" -> provider.banned(player);
case "banReason" -> provider.banReason(player);
case "banDuration" -> {
if(args.length == 1)
yield provider.banDuration(player);
if(args.length > 2)
yield null;
boolean fromStart = Boolean.getBoolean(args[1]);
yield provider.banDuration(player, fromStart);
}
@@ -84,9 +77,7 @@ public class AdvancedBanPlaceholders extends PlaceholderProvider{
if(args.length == 1)
yield provider.banExpirationDate(player);
String pattern = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
yield provider.banExpirationDate(player, pattern);
yield provider.banExpirationDate(player, args[1]);
}
// Unknown/Invalid placeholder.
@@ -30,11 +30,9 @@ import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.banplugins.providers.LibertyBansProvider;
import java.util.Arrays;
public class LibertyBansPlaceholders extends PlaceholderProvider{
private final LibertyBansProvider provider = LibertyBansProvider.create();
private LibertyBansProvider provider = null;
public LibertyBansPlaceholders(){
super("libertybans");
@@ -42,31 +40,30 @@ public class LibertyBansPlaceholders extends PlaceholderProvider{
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
String[] args = placeholder.split("\\.");
if(provider == null)
provider = LibertyBansProvider.create();
String[] args = placeholder.split("\\s", 2);
return switch(args[0]){
// Mute-related placeholders
case "isMuted" -> String.valueOf(provider.muted(player));
case "isMuted" -> provider.muted(player);
case "muteReason" -> provider.muteReason(player);
case "muteExpiration" -> {
if(args.length == 1)
yield provider.muteExpirationDate(player);
String pattern = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
yield provider.muteExpirationDate(player, pattern);
yield provider.muteExpirationDate(player, args[1]);
}
// Ban-related placeholders
case "isBanned" -> String.valueOf(provider.banned(player));
case "isBanned" -> provider.banned(player);
case "banReason" -> provider.banReason(player);
case "banExpiration" -> {
if(args.length == 1)
yield provider.banExpirationDate(player);
String pattern = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
yield provider.banExpirationDate(player, pattern);
yield provider.banExpirationDate(player, args[1]);
}
// Unknown/Invalid placeholder
@@ -0,0 +1,87 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.banplugins.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.banplugins.providers.LiteBansProvider;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class LiteBansPlaceholders extends PlaceholderProvider{
private LiteBansProvider provider = null;
public LiteBansPlaceholders(){
super("litebans");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(provider == null)
provider = new LiteBansProvider();
String[] args = placeholder.split("\\s", 2);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() ->
switch(args[0]){
// Mute-related placeholders
case "isMuted" -> provider.muted(player);
case "muteReason" -> provider.muteReason(player);
case "muteDuration" -> provider.muteDuration(player);
case "muteExpiration" -> {
if(args.length == 1)
yield provider.muteExpirationDate(player);
yield provider.muteExpirationDate(player, args[1]);
}
// Ban-related placeholders
case "isBanned" -> provider.banned(player);
case "banReason" -> provider.banReason(player);
case "banDuration" -> provider.banDuration(player);
case "banExpiration" -> {
if(args.length == 1)
yield provider.banExpirationDate(player);
yield provider.banExpirationDate(player, args[1]);
}
//Unknown/Invalid placeholder
default -> null;
}
);
try{
return future.join();
}catch(CancellationException | CompletionException ex){
return null;
}
}
}
@@ -31,40 +31,18 @@ import com.google.common.primitives.UnsignedLongs;
import me.leoko.advancedban.manager.PunishmentManager;
import me.leoko.advancedban.utils.Punishment;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class AdvancedBanProvider implements PunishmentProvider{
private static PunishmentManager getAPI(){
return PunishmentManager.get();
}
private static String noDashesUUID(UUID uuid){
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
}
private static Punishment mute(GenericPlayer player){
return getAPI().getMute(noDashesUUID(player.getUUID()));
}
private static Punishment ban(GenericPlayer player){
return getAPI().getBan(noDashesUUID(player.getUUID()));
}
private static String hexString(long unsigned){
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
@Override
public String muted(GenericPlayer player){
return String.valueOf(getAPI().isMuted(noDashesUUID(player.getUUID())));
}
@Override
public boolean muted(GenericPlayer player){
return getAPI().isMuted(noDashesUUID(player.getUUID()));
}
@Override
public boolean banned(GenericPlayer player){
return getAPI().isBanned(noDashesUUID(player.getUUID()));
public String banned(GenericPlayer player){
return String.valueOf(getAPI().isBanned(noDashesUUID(player.getUUID())));
}
@Override
@@ -136,4 +114,24 @@ public class AdvancedBanProvider implements PunishmentProvider{
return ban.getDuration(fromStart);
}
private PunishmentManager getAPI(){
return PunishmentManager.get();
}
private String noDashesUUID(UUID uuid){
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
}
private Punishment mute(GenericPlayer player){
return getAPI().getMute(noDashesUUID(player.getUUID()));
}
private Punishment ban(GenericPlayer player){
return getAPI().getBan(noDashesUUID(player.getUUID()));
}
private String hexString(long unsigned){
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
}
}
@@ -53,13 +53,13 @@ public class LibertyBansProvider implements PunishmentProvider{
}
@Override
public boolean muted(GenericPlayer player){
return punishment(player.getUUID(), PunishmentType.MUTE) != null;
public String muted(GenericPlayer player){
return String.valueOf(punishment(player.getUUID(), PunishmentType.MUTE) != null);
}
@Override
public boolean banned(GenericPlayer player){
return punishment(player.getUUID(), PunishmentType.BAN) != null;
public String banned(GenericPlayer player){
return String.valueOf(punishment(player.getUUID(), PunishmentType.BAN) != null);
}
@Override
@@ -0,0 +1,103 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.banplugins.providers;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import litebans.api.Database;
import litebans.api.Entry;
public class LiteBansProvider implements PunishmentProvider{
@Override
public String muted(GenericPlayer player){
return String.valueOf(Database.get().isPlayerMuted(player.getUUID(), null));
}
@Override
public String banned(GenericPlayer player){
return String.valueOf(Database.get().isPlayerBanned(player.getUUID(), null));
}
@Override
public String muteReason(GenericPlayer player){
Entry mute = Database.get().getMute(player.getUUID(), null, null);
if(mute == null)
return null;
return mute.getReason();
}
@Override
public String banReason(GenericPlayer player){
Entry ban = Database.get().getBan(player.getUUID(), null, null);
if(ban == null)
return null;
return ban.getReason();
}
@Override
public String muteDuration(GenericPlayer player){
Entry mute = Database.get().getMute(player.getUUID(), null, null);
if(mute == null)
return null;
return mute.getDurationString();
}
@Override
public String banDuration(GenericPlayer player){
Entry ban = Database.get().getBan(player.getUUID(), null, null);
if(ban == null)
return null;
return ban.getDurationString();
}
@Override
public String muteExpirationDate(GenericPlayer player, String pattern){
Entry mute = Database.get().getMute(player.getUUID(), null, null);
if(mute == null)
return null;
if(mute.isPermanent())
return "never";
return this.returnDate(pattern, mute.getDateEnd());
}
@Override
public String banExpirationDate(GenericPlayer player, String pattern){
Entry ban = Database.get().getBan(player.getUUID(), null, null);
if(ban == null)
return null;
if(ban.isPermanent())
return "never";
return this.returnDate(pattern, ban.getDateEnd());
}
}
@@ -32,9 +32,9 @@ import java.util.Date;
public interface PunishmentProvider{
boolean muted(GenericPlayer player);
String muted(GenericPlayer player);
boolean banned(GenericPlayer player);
String banned(GenericPlayer player);
String muteReason(GenericPlayer player);
@@ -1,56 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.banplugins.velocity;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.paper.PaperBanPlugins;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum VelocityBanPlugins{
LIBERTY_BANS("libertybans", new LibertyBansPlaceholders());
private final String plugin;
private final PlaceholderProvider placeholderProvider;
VelocityBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
this.placeholderProvider = placeholderProvider;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(VelocityBanPlugins velocityBanPlugins : VelocityBanPlugins.values()){
content.put(velocityBanPlugins.plugin, velocityBanPlugins.placeholderProvider);
}
return content;
}
}
@@ -26,15 +26,15 @@
package ch.andre601.advancedserverlist.banplugins.velocity;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.BanPluginsList;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import net.md_5.bungee.api.ProxyServer;
import com.velocitypowered.api.proxy.ProxyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Locale;
public class VelocityBanPluginsAddon{
@@ -49,7 +49,7 @@ public class VelocityBanPluginsAddon{
@Subscribe
public void init(ProxyInitializeEvent event){
if(proxy.getPluginManager().getPlugin("advancedserverlist") == null){
if(!proxy.getPluginManager().isLoaded("advancedserverlist")){
logger.warn("AdvancedServerList is not enabled. This plugin requires it to function!");
return;
}
@@ -64,14 +64,16 @@ public class VelocityBanPluginsAddon{
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = VelocityBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(proxy.getPluginManager().getPlugin(entry.getKey()) != null){
logger.info("Registering placeholders for {}...", entry.getKey());
api.addPlaceholderProvider(entry.getValue());
logger.info("Placeholder successfully registered!");
for(BanPluginsList entry : BanPluginsList.values()){
if(!entry.supportsVelocity())
continue;
if(proxy.getPluginManager().isLoaded(entry.getName().toLowerCase(Locale.ROOT))){
logger.info("Registering Placeholders for " + entry.getName() + "...");
api.addPlaceholderProvider(entry.getPlaceholderProvider());
logger.info("Placeholders successfully registered!");
loaded++;
}
@@ -7,5 +7,6 @@ softDepends:
- AdvancedServerList
- AdvancedBan
- LibertyBans
- LiteBans
main: 'ch.andre601.advancedserverlist.banplugins.bungeecord.BungeeCordBanPluginsAddon'
@@ -2,7 +2,7 @@ name: 'ASLBanPluginsAddon'
author: 'Andre_601'
version: '${plugin.version}'
main: 'ch.andre601.advancedserverlist.banplugins.paper.AdvancedBanPlaceholders'
main: 'ch.andre601.advancedserverlist.banplugins.paper.PaperBanPluginsAddon'
api-version: '1.19'
@@ -11,9 +11,12 @@ dependencies:
AdvancedServerList:
required: false
load: BEFORE
AdvancedBans:
AdvancedBan:
required: false
load: BEFORE
LibertyBans:
required: false
load: BEFORE
LiteBans:
required: false
load: BEFORE
@@ -14,6 +14,10 @@
{
"id": "libertybans",
"optional": true
},
{
"id": "litebans",
"optional": true
}
],
"main": "ch.andre601.advancedserverlist.banplugins.velocity.VelocityBanPluginsAddon"
+43 -22
View File
@@ -49,6 +49,10 @@
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
</repository>
</repositories>
<dependencies>
@@ -69,43 +73,43 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2</version>
<version>1.21-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2</version>
<version>1.21-R0.1-SNAPSHOT</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<!-- Adventure Library. Needs to be shaded in -->
<!-- Adventure Library -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.16.0</version>
<scope>compile</scope>
<version>${dependency.adventure-api}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.16.0</version>
<scope>compile</scope>
<version>${dependency.adventure-text-minimessage}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.3.2</version>
<scope>compile</scope>
<version>${dependency.adventure-platform-bungeecord}</version>
<scope>provided</scope>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bungeecord</artifactId>
<version>3.0.2</version>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
@@ -113,8 +117,8 @@
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
<version>${dependency.configurate-yaml}</version>
<scope>provided</scope>
</dependency>
<!-- Plugins -->
@@ -124,6 +128,26 @@
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-bungeecord</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<!-- Other -->
<dependency>
<groupId>com.alessiodp.libby</groupId>
<artifactId>libby-bungee</artifactId>
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
@@ -138,33 +162,30 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</version>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.spongepowered.configurate</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.configurate</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.kyori</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>net.byteflux.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.libby</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
@@ -30,43 +30,83 @@ import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeePlayerPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeProxyPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeServerPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import com.alessiodp.libby.BungeeLibraryManager;
import com.alessiodp.libby.Library;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import org.sayandev.sayanvanish.bungeecord.api.SayanVanishBungeeAPI;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
private final PluginLogger logger = new BungeeLogger(this);
private final Map<String, ServerPing> fetchedServers = new ConcurrentHashMap<>();
private boolean successfulLoad = false;
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private final PluginLogger logger = new BungeeLogger(this);
private BungeeAudiences audiences = null;
private BungeeLibraryManager libraryManager = null;
@Override
public void onLoad(){
// Using getLogger() here, because PluginLogger requires MiniMessage, which isn't loaded at this stage.
getLogger().info("Loading libraries. This may take a while...");
successfulLoad = loadLibs();
if(successfulLoad){
getLogger().info("Library loading completed successfully!");
}else{
getLogger().warning("Library loading completed with errors!");
}
}
@Override
public void onEnable(){
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
if(!successfulLoad){
logger.warn("There were issues during the plugins Loading-phase! Please see the console for possible reasons.");
logger.warn("Aborting further enabling of the plugin to avoid errors.");
return;
}
this.audiences = BungeeAudiences.create(this);
this.core = AdvancedServerList.init(this,
BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this), BungeeProxyPlaceholders.init(this));
}
@Override
public void onDisable(){
core.disable();
getProxy().getScheduler().cancel(this);
audiences.close();
}
@Override
public void loadCommands(){
getProxy().getPluginManager().registerCommand(this, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
@@ -96,6 +136,28 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
faviconHandler.cleanCache();
}
@Override
public void downloadLibrary(String groupId, String artifactId, String version){
if(libraryManager == null){
libraryManager = new BungeeLibraryManager(this);
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
}
Library lib = Library.builder()
.groupId(groupId)
.artifactId(artifactId)
.version(version)
.resolveTransitiveDependencies(true)
.build();
libraryManager.loadLibrary(lib);
}
@Override
public void startScheduler(){
getProxy().getScheduler().schedule(this, this::fetchServers, 0, 10, TimeUnit.SECONDS);
}
@Override
public AdvancedServerList<Favicon> getCore(){
return core;
@@ -120,13 +182,8 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
}
@Override
public String getPlatformName(){
return getProxy().getName();
}
@Override
public String getPlatformVersion(){
return getProxy().getVersion();
public String getPlatformInfo(){
return getProxy().getName() + " " + getProxy().getVersion();
}
@Override
@@ -134,19 +191,61 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
return "bungeecord";
}
@Override
public boolean isPluginEnabled(String plugin){
return getProxy().getPluginManager().getPlugin(plugin) != null;
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
public BungeeAudiences getAudiences(){
return audiences;
}
public int getOnlinePlayers(ServerInfo server){
List<ProxiedPlayer> players = new ArrayList<>(server == null ? getProxy().getPlayers() : server.getPlayers());
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().getPlugin("PremiumVanish") != null){
players.removeIf(BungeeVanishAPI::isInvisible);
}else // Do the same if SayanVanish is enabled.
if(getProxy().getPluginManager().getPlugin("SayanVanish") != null){
players.removeIf(player -> SayanVanishBungeeAPI.getInstance().isVanished(player.getUniqueId()));
}
return players.size();
}
public Map<String, ServerPing> getFetchedServers(){
return fetchedServers;
}
private boolean loadLibs(){
try{
if(libraryManager == null){
libraryManager = new BungeeLibraryManager(this);
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
}
libraryManager.configureFromJSON("dependencies.json");
return true;
}catch(Exception ex){
getLogger().log(Level.WARNING, "Encountered an Exception while trying to load dependencies.", ex);
return false;
}
}
private void fetchServers(){
fetchedServers.clear();
getProxy().getServers().forEach((name, server) -> server.ping((ping, throwable) -> {
if(throwable != null)
return;
fetchedServers.put(name, ping);
}));
}
}
@@ -33,16 +33,14 @@ import net.md_5.bungee.api.plugin.Command;
public class CmdAdvancedServerList extends Command{
private final BungeeCordCore plugin;
private final BungeeAudiences audiences;
public CmdAdvancedServerList(BungeeCordCore plugin){
super("advancedserverlist", "advancedserverlist.command.asl", "asl");
this.plugin = plugin;
this.audiences = BungeeAudiences.create(plugin);
}
@Override
public void execute(CommandSender sender, String[] args){
plugin.getCore().getCommandHandler().handle(new BungeeCmdSender(sender, audiences), args);
plugin.getCore().getCommandHandler().handle(new BungeeCmdSender(sender, plugin.getAudiences()), args);
}
}
@@ -31,7 +31,8 @@ import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeePlayerImpl;
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeeProxyImpl;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
@@ -78,6 +79,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
ping.getPlayers().setMax(maxPlayers);
}
@Override
public void setOnlinePlayers(int onlinePlayers){
ping.getPlayers().setOnline(onlinePlayers);
}
@Override
public void setMotd(Component component){
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
@@ -101,8 +107,9 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
for(int i = 0; i < players.length; i++){
String parsed = ComponentParser.text(lines.get(i))
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> parsePAPIPlaceholders(text, player))
.toString();
ServerPing.PlayerInfo pi = new ServerPing.PlayerInfo(parsed, UUID.randomUUID());
players[i] = pi;
}
@@ -111,6 +118,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
ping.getPlayers().setSample(players);
}
@Override
public void setPlayersHidden(){
ping.getPlayers().setSample(new ServerPing.PlayerInfo[0]);
}
@Override
public void setFavicon(Favicon favicon){
ping.setFavicon(favicon);
@@ -137,12 +149,12 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
if(plugin.getProxy().getPluginManager().getPlugin("Maintenance") == null)
return false;
return PingEventHandler.getMaintenanceUtil().isMaintenanceEnabled();
return MaintenanceUtil.get().isMaintenanceEnabled();
}
@Override
public int getProtocolVersion(){
return this.protocol.getProtocol();
return event.getConnection().getVersion();
}
@Override
@@ -165,10 +177,10 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
if(plugin.getProxy().getPluginManager().getPlugin("PAPIProxyBridge") == null)
return text;
if(!PingEventHandler.getPAPIUtil().isCompatible())
if(!PAPIUtil.get().isCompatible())
return text;
String server = PingEventHandler.getPAPIUtil().getServer();
String server = PAPIUtil.get().getServer();
if(server == null || server.isEmpty())
return text;
@@ -176,11 +188,11 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
if(serverInfo == null || serverInfo.getPlayers().isEmpty())
return text;
ProxiedPlayer carrier = PingEventHandler.getPAPIUtil().getPlayer(serverInfo.getPlayers());
ProxiedPlayer carrier = PAPIUtil.get().getPlayer(serverInfo.getPlayers());
if(carrier == null)
return text;
return PingEventHandler.getPAPIUtil().parse(text, carrier.getUniqueId(), player.getUUID());
return PAPIUtil.get().parse(text, carrier.getUniqueId(), player.getUUID());
}
@Override
@@ -26,6 +26,7 @@
package ch.andre601.advancedserverlist.bungeecord.listeners;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.commands.BungeeCmdSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
@@ -34,7 +35,6 @@ import net.md_5.bungee.event.EventHandler;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
private final BungeeCordCore plugin;
public JoinEvent(BungeeCordCore plugin){
@@ -48,5 +48,14 @@ public class JoinEvent implements Listener{
ProxiedPlayer player = event.getPlayer();
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
if(player.hasPermission("advancedserverlist.admin") || player.hasPermission("advancedserverlist.updatecheck")){
if(plugin.getAudiences() == null || plugin.getCore().getUpdateChecker() == null)
return;
BungeeCmdSender sender = new BungeeCmdSender(player, plugin.getAudiences());
plugin.getCore().getUpdateChecker().performCachedUpdateCheck(sender);
}
}
}
@@ -27,6 +27,7 @@ package ch.andre601.advancedserverlist.bungeecord.logging;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -55,21 +56,21 @@ public class BungeeLogger implements PluginLogger{
@Override
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
logger.info(ComponentParser.textFormatted(msg, args).toStringStriped());
}
@Override
public void warn(String msg, Object... args){
logger.warning(String.format(msg, args));
logger.warning(ComponentParser.textFormatted(msg, args).toStringStriped());
}
@Override
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
logger.log(Level.WARNING, ComponentParser.text(msg).toStringStriped(), throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
logger.log(Level.WARNING, ComponentParser.textFormatted(msg, args).toStringStriped(), throwable);
}
}
@@ -25,14 +25,35 @@
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeePlayer;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
public class BungeePlayerImpl extends GenericPlayerImpl{
import java.util.UUID;
public class BungeePlayerImpl implements BungeePlayer{
private final String name;
private final int protocol;
private final UUID uuid;
public BungeePlayerImpl(CachedPlayer player, int protocol){
this.name = player.name();
this.protocol = protocol;
this.uuid = player.uuid();
}
@Override
public String getName(){
return name;
}
@Override
public int getProtocol(){
return protocol;
}
@Override
public UUID getUUID(){
return uuid;
}
}
@@ -0,0 +1,61 @@
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.BaseComponent;
public class BungeeProxyPlaceholders extends PlaceholderProvider{
private final BungeeCordCore plugin;
private BungeeProxyPlaceholders(BungeeCordCore plugin){
super("proxy");
this.plugin = plugin;
}
public static BungeeProxyPlaceholders init(BungeeCordCore plugin){
return new BungeeProxyPlaceholders(plugin);
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
String[] args = placeholder.split("\\s", 2);
if(args.length < 2)
return null;
ServerPing ping = plugin.getFetchedServers().get(args[1]);
return switch(args[0]){
case "status" -> ping == null ? "offline" : "online";
case "motd" -> {
if(ping == null)
yield "none";
BaseComponent[] components = new BaseComponent[]{ping.getDescriptionComponent()};
Component component = BungeeComponentSerializer.get().deserialize(components);
yield ComponentParser.toMMString(component);
}
case "players" -> {
if(ping == null)
yield "0";
yield String.valueOf(ping.getPlayers().getOnline());
}
case "maxPlayers" -> {
if(ping == null)
yield "0";
yield String.valueOf(ping.getPlayers().getMax());
}
default -> null;
};
}
}
@@ -79,18 +79,18 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
case "playersMax" -> {
// ServerInfo doesn't provide the max players that could join, so we won't allow an extra argument
if(args.length >= 2)
yield null;
yield "";
yield String.valueOf(proxy.getPlayersMax());
}
case "host" -> {
if(args.length > 2)
yield null;
yield "";
if(args.length == 2){
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
ServerInfo info = proxy.getServers().get(args[1]);
if(info == null)
yield null;
yield "";
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
}
+1
View File
@@ -6,5 +6,6 @@ description: '${plugin.description}'
softDepends:
- PAPIProxyBridge
- Maintenance
- ServerListPlus
main: 'ch.andre601.advancedserverlist.bungeecord.BungeeCordCore'
@@ -0,0 +1,28 @@
{
"libraries": [
{
"groupId": "net{}kyori",
"artifactId": "adventure-api",
"version": "${dependency.adventure-api}",
"resolveTransitiveDependencies": true
},
{
"groupId": "net{}kyori",
"artifactId": "adventure-text-minimessage",
"version": "${dependency.adventure-text-minimessage}",
"resolveTransitiveDependencies": true
},
{
"groupId": "net{}kyori",
"artifactId": "adventure-platform-bungeecord",
"version": "${dependency.adventure-platform-bungeecord}",
"resolveTransitiveDependencies": true
},
{
"groupId": "org{}spongepowered",
"artifactId": "configurate-yaml",
"version": "${dependency.configurate-yaml}",
"resolveTransitiveDependencies": true
}
]
}
+41 -12
View File
@@ -41,7 +41,7 @@
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>5</plugin.config.version>
<plugin.config.version>8</plugin.config.version>
</properties>
<repositories>
@@ -61,6 +61,10 @@
<id>codeberg</id>
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
</repository>
<repository>
<id>codemc</id>
<url>https://repo.codemc.io/repository/maven-releases/</url>
</repository>
</repositories>
<dependencies>
@@ -73,12 +77,20 @@
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>1.3.0</version>
<version>1.5.0</version>
<scope>compile</scope>
</dependency>
<!-- Configuration -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>${dependency.configurate-yaml}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-hocon</artifactId>
<version>4.1.2</version>
<scope>provided</scope>
</dependency>
@@ -87,19 +99,19 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.16.0</version>
<version>${dependency.adventure-api}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.16.0</version>
<version>${dependency.adventure-text-minimessage}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.16.0</version>
<version>${dependency.adventure-text-serializer-legacy}</version>
<scope>provided</scope>
</dependency>
@@ -107,7 +119,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -119,7 +131,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.1.0-jre</version>
<version>33.4.0-jre</version>
<scope>provided</scope>
</dependency>
@@ -127,13 +139,19 @@
<dependency>
<groupId>net.william278</groupId>
<artifactId>papiproxybridge</artifactId>
<version>1.5</version>
<version>1.7.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-api</artifactId>
<version>4.2.0-SNAPSHOT</version>
<version>4.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.minecrell</groupId>
<artifactId>ServerListPlus</artifactId>
<version>3.5.0</version>
<scope>provided</scope>
</dependency>
@@ -141,7 +159,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -152,18 +170,28 @@
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/src/main/resources</directory>
<excludes>
<exclude>char-widths.json.gz</exclude>
</excludes>
</resource>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>char-widths.json.gz</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</version>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
@@ -171,6 +199,7 @@
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
@@ -29,10 +29,12 @@ 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.compat.maintenance.MaintenancePlaceholder;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
import java.io.IOException;
import java.io.InputStream;
@@ -46,6 +48,8 @@ public class AdvancedServerList<F>{
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final TextCenterUtil textCenterUtil;
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private final ProfileConditionParser parser = ProfileConditionParser.create();
@@ -58,9 +62,18 @@ public class AdvancedServerList<F>{
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.textCenterUtil = new TextCenterUtil(this);
placeholders.forEach(AdvancedServerList.getApi()::addPlaceholderProvider);
plugin.getPluginLogger().info("Registering internal Placeholders...");
placeholders.forEach(this::addPlaceholder);
if(plugin.isPluginEnabled("Maintenance")){
addPlaceholder(new MaintenancePlaceholder(this));
}
resolveVersion();
getPlugin().getPluginLogger().info("Starting <white>AdvancedServerList v%s</white>...", version);
load();
}
@@ -68,6 +81,10 @@ public class AdvancedServerList<F>{
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
public static AdvancedServerListAPI getApi(){
return api;
}
public PluginCore<F> getPlugin(){
return plugin;
}
@@ -88,24 +105,28 @@ public class AdvancedServerList<F>{
return version;
}
public static AdvancedServerListAPI getApi(){
return api;
}
public ProfileConditionParser getParser(){
return parser;
}
public UpdateChecker getUpdateChecker(){
return updateChecker;
}
public TextCenterUtil getTextCenterUtil(){
return textCenterUtil;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving playercache.json file...");
getPlugin().getPluginLogger().info("[-] Saving <white>playercache.json</white> file...");
getPlayerHandler().save();
if(updateChecker != null){
getPlugin().getPluginLogger().info("Disabling Update Checker...");
getPlugin().getPluginLogger().info("[-] Disabling Update Checker...");
updateChecker.disable();
}
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
getPlugin().getPluginLogger().success("AdvancedServerList disabled!");
}
public void clearFaviconCache(){
@@ -117,66 +138,56 @@ public class AdvancedServerList<F>{
}
private void load(){
printBanner();
resolveVersion();
getPlugin().getPluginLogger().info("Starting AdvancedServerList v%s...", version);
getPlugin().getPluginLogger().info("Platform: " + plugin.getPlatformName() + " " + plugin.getPlatformVersion());
if(getFileHandler().loadConfig()){
getPlugin().getPluginLogger().info("Successfully loaded config.yml!");
}else{
getPlugin().getPluginLogger().warn("Unable to load config.yml! Check previous lines for errors.");
if(!getFileHandler().loadConfig()){
getPlugin().getPluginLogger().failure("Unable to load <white>config.yml</white>! Check previous lines for errors.");
return;
}
if(getFileHandler().isOldConfig()){
getPlugin().getPluginLogger().info("Detected old config.yml. Attempting to migrate...");
getPlugin().getPluginLogger().info("[-] Detected old <white>config.yml</white>. Attempting to migrate...");
if(getFileHandler().migrateConfig()){
getPlugin().getPluginLogger().info("Migration completed successfully!");
getPlugin().getPluginLogger().success("Migration completed successfully!");
}else{
getPlugin().getPluginLogger().warn("Couldn't migrate config.yml! Check previous lines for errors.");
getPlugin().getPluginLogger().failure("Couldn't migrate <white>config.yml</white>! Check previous lines for errors.");
return;
}
}
if(getFileHandler().getBool(true, "printBanner")){
printBanner();
}
getPlugin().getPluginLogger().info("Platform: <white>%s</white>", plugin.getPlatformInfo());
getPlugin().getPluginLogger().info("");
if(getFileHandler().loadProfiles()){
getPlugin().getPluginLogger().info("Successfully loaded %d profile(s)!", getFileHandler().getProfiles().size());
getPlugin().getPluginLogger().success("Successfully loaded <white>%d</white> profile(s)!", getFileHandler().getProfiles().size());
}else{
getPlugin().getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
getPlugin().getPluginLogger().failure("Unable to load profiles! Check previous lines for errors.");
return;
}
getPlugin().loadFaviconHandler(this);
getPlugin().getPluginLogger().info("Loading Commands...");
plugin.loadCommands();
getPlugin().getPluginLogger().info("Commands loaded!");
getPlugin().getPluginLogger().info("Loading events...");
plugin.loadEvents();
getPlugin().getPluginLogger().info("Events loaded!");
getPlugin().getPluginLogger().info("Loading playercache.json...");
getPlayerHandler().load();
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
plugin.loadMetrics();
getPlugin().getPluginLogger().info("Metrics loaded!");
plugin.startScheduler();
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
getPlugin().getPluginLogger().success("<green>AdvancedServerList is ready!");
if(getFileHandler().getBoolean("checkUpdates"))
this.updateChecker = new UpdateChecker(this);
}
private void printBanner(){
getPlugin().getPluginLogger().info(" _____ _");
getPlugin().getPluginLogger().info(" /\\ / ____| |");
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
getPlugin().getPluginLogger().info(" / /\\ \\ \\___ \\| |");
getPlugin().getPluginLogger().info(" / ____ \\ ____) | |____");
getPlugin().getPluginLogger().info("/_/ \\_\\_____/|______|");
getPlugin().getPluginLogger().info("<#3b90ff> __ _______ ___");
getPlugin().getPluginLogger().info("<#3b90ff> /\\ \\ / ____|_| | |");
getPlugin().getPluginLogger().info("<#3b90ff> / \\ \\ | (_(___ | | |");
getPlugin().getPluginLogger().info("<#3b90ff> / /\\ \\ \\ \\___ \\ \\| | |");
getPlugin().getPluginLogger().info("<#3b90ff> / ____ \\ \\ ____) | | |_|____");
getPlugin().getPluginLogger().info("<#3b90ff>/_/_/ \\_\\_\\_____/_/|______|_|");
getPlugin().getPluginLogger().info("");
}
@@ -191,4 +202,8 @@ public class AdvancedServerList<F>{
version = "UNKNOWN";
}
}
private void addPlaceholder(PlaceholderProvider placeholderProvider){
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
}
}
@@ -27,6 +27,8 @@ package ch.andre601.advancedserverlist.core.check;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.objects.ValueCache;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -40,6 +42,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
@@ -48,32 +51,62 @@ import java.util.concurrent.TimeUnit;
public class UpdateChecker{
@SuppressWarnings("FieldCanBeLocal")
// 'https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=["%s"]' URL encoded.
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=%%5B%%22%s%%22%%5D";
private final HttpClient client = HttpClient.newHttpClient();
private final Type listType = new TypeToken<ArrayList<ModrinthVersion>>(){}.getType();
private final Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setPrettyPrinting()
.setLenient()
.create();
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
private final ValueCache<CompletableFuture<ModrinthVersion>> cache = new ValueCache<>(Duration.ofMinutes(5));
private final AdvancedServerList<?> core;
private final PluginLogger logger;
private final String loader;
private final HttpClient client;
public UpdateChecker(AdvancedServerList<?> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.loader = core.getPlugin().getLoader();
this.client = HttpClient.newBuilder().executor(Executors.newSingleThreadExecutor(new UpdateCheckThread())).build();
startUpdateChecker();
}
public void performCachedUpdateCheck(CmdSender sender){
CompletableFuture<ModrinthVersion> modrinthVersion = cache.get(this::performUpdateCheck);
modrinthVersion.whenComplete((version, throwable) -> {
if(throwable != null){
logger.warn("Encountered an Exception while checking for an update!", throwable);
sender.sendErrorMsg("There was an exception while checking for an update. Please check the console for details.");
return;
}
if(version == null)
return;
int result = version.compare(core.getVersion());
if(result == -1){
sender.sendPrefixedMsg("<green>A new Version of AdvancedServerList is available!");
sender.sendPrefixedMsg("<green>Your version: <white>%s", core.getVersion());
sender.sendPrefixedMsg("<green>Version on Modrinth: <white>%s", version.versionNumber());
sender.sendPrefixedMsg(
"<click:open_url:'https://modrinth.com/plugin/advancedserverlist/version/%s'>" +
"<green>[<white>Download Page</white>]" +
"</click>",
version.id()
);
}else
if(result == 1){
sender.sendPrefixedMsg("You seem to run a newer Version (<white>%</white>) than what is available on Modrinth (<white>%s</white>).", core.getVersion(), version.versionNumber());
sender.sendPrefixedMsg("Are you running a development build?");
}
});
}
public void disable(){
executor.shutdown();
try{
@@ -90,11 +123,11 @@ public class UpdateChecker{
private void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Looking for an update...");
logger.info("[-] Looking for an update...");
performUpdateCheck().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. Check previous messages for causes.");
logger.failure("Failed to look for any updates. Check previous messages for causes.");
return;
}
@@ -103,9 +136,9 @@ public class UpdateChecker{
int result = version.compare(core.getVersion());
switch(result){
case -1 -> printUpdateBanner(version);
case 0 -> logger.info("You are running the latest version!");
case 0 -> logger.success("You are running the latest version!");
case 1 -> logger.info(
"Your version (%s) seems to be newer than the latest release (%s). Are you running a dev build?",
"[?] Your version (<white>%s</white>) seems to be newer than the latest release (<white>%s</white>). Are you running a dev build?",
core.getVersion(), version.versionNumber()
);
}
@@ -114,7 +147,11 @@ public class UpdateChecker{
}
private CompletableFuture<ModrinthVersion> performUpdateCheck(){
String finalUrl = String.format(url, loader);
String finalUrl = String.format(
// 'https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=["%s"]' URL encoded.
"https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=%%5B%%22%s%%22%%5D",
loader
);
logger.debug(UpdateChecker.class, "Checking '%s' for updates...", finalUrl);
@@ -127,6 +164,7 @@ public class UpdateChecker{
try{
request = HttpRequest.newBuilder()
.uri(new URI(finalUrl))
.timeout(Duration.ofSeconds(5))
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
.build();
}catch(URISyntaxException ex){
@@ -144,22 +182,22 @@ public class UpdateChecker{
}
private void printUpdateBanner(ModrinthVersion version){
logger.info("==================================================================");
logger.info("You are running an outdated version of AdvancedServerList!");
logger.info("");
logger.info("Your version: %s", core.getVersion());
logger.info("Modrinth: %s", version.versionNumber());
logger.info("");
logger.warn("=======================================================================");
logger.warn("You are running an outdated version of AdvancedServerList!");
logger.warn("");
logger.warn("Your version: <white>%s</white>", core.getVersion());
logger.warn("Modrinth: <white>%s</white>", version.versionNumber());
logger.warn("");
if(!version.isRelease()){
logger.info("WARNING!");
logger.info("This is a %s version and may contain breaking changes and/or bugs!", version.versionType());
logger.info("");
logger.warn("<bold>WARNING!</bold>");
logger.warn("This is a %s version and may contain breaking changes and/or bugs!", version.versionType());
logger.warn("");
}
logger.info("Download the latest version from here:");
logger.info("https://modrinth.com/plugin/advancedserverlist/version/%s", version.id());
logger.info("==================================================================");
logger.warn("Download the latest version from here:");
logger.warn("<white>https://modrinth.com/plugin/advancedserverlist/version/%s</white>", version.id());
logger.warn("=======================================================================");
}
public record ModrinthVersion(String id, String versionNumber, String versionType){
@@ -171,10 +209,5 @@ public class UpdateChecker{
public int compare(String version){
return FlexVerComparator.compare(version, versionNumber());
}
@Override
public String toString(){
return String.format("ModrinthVersion{id=%s,versionNumber=%s,versionType=%s}", id, versionNumber, versionType);
}
}
}
@@ -25,21 +25,43 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.PluginCommand;
import ch.andre601.advancedserverlist.core.migration.minimotd.MiniMOTDConfigMigrator;
import ch.andre601.advancedserverlist.core.migration.serverlistplus.SLPConfigMigrator;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.util.ArrayList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
public class CommandHandler{
private final List<PluginCommand> subCommands = new ArrayList<>();
private final List<PluginCommand> subCommands;
public CommandHandler(AdvancedServerList<?> core){
subCommands.add(new Help());
subCommands.add(new Reload(core));
subCommands.add(new ClearCache(core));
subCommands = List.of(
new Help(core),
new Reload(core),
new ClearCache(core),
new Migrate(core),
new Profiles(core)
);
}
public List<PluginCommand> getSubCommands(){
return subCommands;
}
public void handle(CmdSender sender, String[] args){
@@ -49,16 +71,16 @@ public class CommandHandler{
}
for(PluginCommand subCommand : subCommands){
if(subCommand.getArgument().equalsIgnoreCase(args[0])){
if(!sender.hasPermission(subCommand.getPermission())){
if(subCommand.name().equalsIgnoreCase(args[0])){
if(!sender.hasPermission(subCommand.permission())){
sender.sendErrorMsg(
"<red>You do not have the permission <grey>%s</grey> to execute this command.",
subCommand.getPermission()
subCommand.permission()
);
return;
}
subCommand.handle(sender);
subCommand.handle(sender, Arrays.copyOfRange(args, 1, args.length));
return;
}
}
@@ -68,19 +90,38 @@ public class CommandHandler{
private static class Help extends PluginCommand{
public Help(){
private final AdvancedServerList<?> core;
public Help(AdvancedServerList<?> core){
super("help");
this.core = core;
}
@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 config.yml and profiles");
sender.sendMsg();
sender.sendMsg("<aqua>/asl <white>clearCache <grey>- Clears the Player and Favicon cache");
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("- Commands. Hover for details.");
for(PluginCommand command : core.getCommandHandler().getSubCommands()){
sender.sendMsg();
sender.sendMsg(
"<click:suggest_command:/asl %s>" +
command.usage() +
"</click>",
command.name()
);
sender.sendMsg("<grey>[<hover:show_text:\"%s\"><white>Permission</white></hover>]</grey>", command.permission());
}
}
@Override
public String usage(){
return new CommandStringBuilder("help", description())
.build();
}
@Override
public String description(){
return "Shows all available commands.";
}
}
@@ -95,7 +136,7 @@ public class CommandHandler{
}
@Override
public void handle(CmdSender sender){
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("Reloading plugin...");
if(core.getFileHandler().reloadConfig()){
@@ -112,6 +153,17 @@ public class CommandHandler{
sender.sendPrefixedMsg("<green>Reload complete!");
}
@Override
public String usage(){
return new CommandStringBuilder("reload", description())
.build();
}
@Override
public String description(){
return "Reloads the main config and all profiles.";
}
}
private static class ClearCache extends PluginCommand{
@@ -119,13 +171,13 @@ public class CommandHandler{
private final AdvancedServerList<?> core;
public ClearCache(AdvancedServerList<?> core){
super("clearCache");
super("clearcache");
this.core = core;
}
@Override
public void handle(CmdSender sender){
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("Clearing caches...");
core.clearFaviconCache();
@@ -136,5 +188,288 @@ public class CommandHandler{
sender.sendPrefixedMsg("<green>Cache clearing complete!");
}
@Override
public String usage(){
return new CommandStringBuilder("clearcache", description())
.build();
}
@Override
public String description(){
return "Clears the Favicon and Player Cache.";
}
}
private static class Migrate extends PluginCommand{
private final AdvancedServerList<?> core;
public Migrate(AdvancedServerList<?> core){
super("migrate");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
if(args.length == 0){
sender.sendErrorMsg("<red>Insufficient arguments! Please provide a plugin to migrate from.");
sender.sendErrorMsg("<red>Available options:");
sender.sendErrorMsg(" - ServerListPlus");
sender.sendErrorMsg(" - MiniMOTD");
return;
}
if(args[0].equalsIgnoreCase("serverlistplus")){
if(!core.getPlugin().isPluginEnabled("ServerListPlus")){
sender.sendErrorMsg("<red>Plugin ServerListPlus is not enabled.");
sender.sendErrorMsg("<red>It needs to be active for the migration to work!");
return;
}
sender.sendPrefixedMsg("Migrating ServerListPlus configuration file...");
int migrated = SLPConfigMigrator.migrate(core, sender);
if(migrated == 0){
sender.sendErrorMsg("<red>Unable to migrate any ServerListPlus configuration. Check console for details!");
}else{
sender.sendPrefixedMsg("<green>Migration complete!");
}
}else
if(args[0].equalsIgnoreCase("minimotd")){
sender.sendPrefixedMsg("Migrating MiniMOTD configuration file...");
if(MiniMOTDConfigMigrator.migrate(core, sender)){
sender.sendPrefixedMsg("<green>Migration complete!");
}else{
sender.sendErrorMsg("<red>Unable to migrate MiniMOTD configuration. Check console for details!");
}
}else{
sender.sendErrorMsg("<red>Unknown plugin <grey>%s</grey>. Available Options:", args[0]);
sender.sendErrorMsg(" - ServerListPlus");
sender.sendErrorMsg(" - MiniMOTD");
}
}
@Override
public String usage(){
return new CommandStringBuilder("migrate", description())
.appendSpace()
.appendArgument(new CommandStringBuilder.ArgumentBuilder("Plugin").description(
"""
The Plugin to migrate from.
Supported options:
- <white>ServerListPlus</white>
- <white>MiniMOTD</white>
"""
).build())
.build();
}
@Override
public String description(){
return "Migrates the configuration from supported Plugins to AdvancedServerList.";
}
}
private static class Profiles extends PluginCommand{
private final AdvancedServerList<?> core;
public Profiles(AdvancedServerList<?> core){
super("profiles");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
if(args.length == 0){
sender.sendErrorMsg("<red>Invalid command usage.");
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
return;
}
switch(args[0].toLowerCase(Locale.ROOT)){
case "list" -> {
sender.sendPrefixedMsg("Available Profiles:");
core.getFileHandler().getProfiles().stream()
.sorted(Comparator.comparingInt(ServerListProfile::priority).reversed())
.forEach(
profile -> sender.sendPrefixedMsg("- <white><hover:show_text:\"%s\">%s</hover></white>", getHover(profile), profile.file())
);
}
case "add" -> {
if(args.length == 1){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>Usage:</red> /asl profiles add <name>");
return;
}
String name = getProfileName(args[1]);
if(core.getFileHandler().getProfiles().stream().anyMatch(profile -> profile.file().equalsIgnoreCase(name))){
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", name);
return;
}
if(core.getFileHandler().createFile(name)){
sender.sendPrefixedMsg("<green>Successfully created</green> %s<green>!", name);
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
}else{
sender.sendErrorMsg("<red>Error while trying to create</red> %s<red>!", name);
sender.sendErrorMsg("<red>Check console for further details.");
}
}
case "copy" -> {
if(args.length < 3){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>Usage:</red> /asl profiles copy <profile> <name>");
return;
}
String name = getProfileName(args[1]);
String copy = getProfileName(args[2]);
ServerListProfile targetProfile = core.getFileHandler().getProfiles().stream()
.filter(file -> file.file().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
boolean copyExists = core.getFileHandler().getProfiles().stream()
.anyMatch(profile -> profile.file().equals(copy));
if(targetProfile == null){
sender.sendErrorMsg("<red>There is no file with name</red> %s<red>!", name);
return;
}
if(copyExists){
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", copy);
return;
}
Path profilePath = core.getPlugin().getFolderPath().resolve("profiles").resolve(copy);
try{
Files.createFile(profilePath);
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an error while creating the file</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for further details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while creating file <white>%s</white>", ex, copy);
return;
}
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.path(profilePath)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(options -> options.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.build();
ConfigurationNode node;
try{
node = loader.load();
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an error while loading the file</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for further details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while loading file <white>%s</white>", ex, copy);
return;
}
if(node == null){
sender.sendErrorMsg("Cannot copy</red> %s <red>to</red> %s<red>. ConfigurationNode was null.", name, copy);
return;
}
try{
node.node("priority").set(targetProfile.priority());
node.node("condition").set(targetProfile.condition());
node.node("profiles").setList(ProfileEntry.class, targetProfile.profiles());
node.set(ProfileEntry.class, targetProfile.defaultProfile());
}catch(SerializationException ex){
sender.sendErrorMsg("<red>There was an Error while copying values from</red> %s <red>to</red> %s<red>.", name, copy);
sender.sendErrorMsg("<red>Check console for details.");
core.getPlugin().getPluginLogger().warn("Encountered SerializationException while set values for <white>%s</white>!", ex, copy);
return;
}
try{
loader.save(node);
sender.sendPrefixedMsg("<green>Successfully created copy of</green> %s <green>as</green> %s<green>!", name, copy);
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an Error while trying to save</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while saving ConfigurationNode for <white>%s</white>!", ex, copy);
}
}
default -> {
sender.sendErrorMsg("<red>Unknown argument</red> %s<red>!", args[0]);
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
}
}
}
@Override
public String usage(){
return new CommandStringBuilder("profiles", "Creates a new profile, copies one from an existing file, or lists all available profiles.")
.appendSpace()
.appendText("<grey>\\<")
// add <name>
.appendLiteralArgument("add", "Adds a new profile using the default values.")
.appendSpace()
.appendArgument(new CommandStringBuilder.ArgumentBuilder("name").description("Name of the new profile").required().build())
// Divider
.appendSpace()
.appendText("|")
.appendSpace()
// copy <profile> <name>
.appendLiteralArgument("copy", "Creates a copy of the provided profile.")
.appendSpace()
.appendArgument(new CommandStringBuilder.ArgumentBuilder("profile").description("The profile to copy.").required().build())
.appendSpace()
.appendArgument(new CommandStringBuilder.ArgumentBuilder("name").description("Name of the copy.").required().build())
// Divider
.appendSpace()
.appendText("|")
.appendSpace()
// list
.appendLiteralArgument("list", "Lists all currently know profiles and wether they are valid or not.")
// Closing bracket
.appendText("></grey>")
.build();
}
@Override
public String description(){
return "Creates a new profile, copies one from an existing file, or lists all available profiles.";
}
private String getHover(ServerListProfile profile){
return String.format(
"""
<grey>Priority: <white>%s</white>
Condition: <white>%s</white>
Valid profile: %s
""",
profile.priority(),
profile.condition() == null || profile.condition().isEmpty() ? "<i>None</i>" : profile.condition(),
profile.isInvalidProfile() ? "<red>No</red>" : "<green>Yes</green>"
);
}
private String getProfileName(String name){
String fileName = name.toLowerCase(Locale.ROOT);
return fileName.endsWith(".yml") ? fileName : fileName + ".yml";
}
}
}
@@ -0,0 +1,110 @@
/*
* MIT License
*
* Copyright (c) 2022-2025 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.commands;
import java.util.ArrayList;
import java.util.List;
public class CommandStringBuilder{
private final List<CommandPart> commandParts = new ArrayList<>();
public CommandStringBuilder(String subcommand, String description){
appendText("<hover:show_text:\"<grey>" + description + "</grey>\"><white>" + subcommand + "</white></hover>");
}
public CommandStringBuilder appendArgument(Argument argument){
this.commandParts.add(argument);
return this;
}
public CommandStringBuilder appendText(String text){
this.commandParts.add(new Text(text));
return this;
}
public CommandStringBuilder appendLiteralArgument(String name, String description){
return appendText("<hover:show_text:\"<grey>" + description + "</grey>\"><white>" + name + "</white></hover>");
}
public CommandStringBuilder appendSpace(){
return appendText(" ");
}
public String build(){
StringBuilder builder = new StringBuilder("<aqua>/asl ");
for(CommandPart part : commandParts){
builder.append(part.build());
}
builder.append("</aqua>"); // Closing the first color tag.
return builder.toString();
}
public static class ArgumentBuilder{
private final String name;
private String description = "No description provided.";
private boolean required = false;
public ArgumentBuilder(String name){
this.name = name;
}
public ArgumentBuilder description(String description){
this.description = description;
return this;
}
public ArgumentBuilder required(){
this.required = true;
return this;
}
public Argument build(){
return new Argument(name, description, required);
}
}
private record Text(String text) implements CommandPart{
@Override
public String build(){
return text();
}
}
private record Argument(String name, String description, boolean required) implements CommandPart{
@Override
public String build(){
return "<hover:show_text:\"<grey>" + description() + "</grey>\">" +
"<grey>" + (required() ? "\\<" : "[") + "<white>" + name() + "</white>" + (required() ? ">" : "]") +
"</grey></hover>";
}
}
private interface CommandPart{
String build();
}
}
@@ -0,0 +1,24 @@
package ch.andre601.advancedserverlist.core.compat.maintenance;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
public class MaintenancePlaceholder extends PlaceholderProvider{
private final AdvancedServerList<?> plugin;
public MaintenancePlaceholder(AdvancedServerList<?> plugin){
super("maintenance");
this.plugin = plugin;
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!placeholder.equals("maintenanceEnabled") || !plugin.getPlugin().isPluginEnabled("Maintenance"))
return null;
return String.valueOf(MaintenanceUtil.get().isMaintenanceEnabled());
}
}
@@ -30,12 +30,21 @@ import eu.kennytv.maintenance.api.MaintenanceProvider;
public class MaintenanceUtil{
private static MaintenanceUtil instance;
private final Maintenance api;
public MaintenanceUtil(){
private MaintenanceUtil(){
this.api = MaintenanceProvider.get();
}
public static MaintenanceUtil get(){
if(instance != null)
return instance;
return (instance = new MaintenanceUtil());
}
public boolean isMaintenanceEnabled(){
return api.isMaintenance();
}
@@ -25,31 +25,42 @@
package ch.andre601.advancedserverlist.core.compat.papi;
import ch.andre601.advancedserverlist.core.objects.ValueCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.william278.papiproxybridge.api.PlaceholderAPI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
public class PAPIUtil{
private static PAPIUtil instance;
private final ValueCache<CompletableFuture<Set<String>>> serversCache = new ValueCache<>(Duration.ofSeconds(10));
private final Cache<UUID, CompletableFuture<String>> textCache = CacheBuilder.newBuilder()
.expireAfterWrite(Duration.ofSeconds(10))
.build();
private final PlaceholderAPI papi;
private final PAPICache cache = new PAPICache();
public PAPIUtil(){
private PAPIUtil(){
this.papi = PlaceholderAPI.createInstance();
}
public static PAPIUtil get(){
if(instance != null)
return instance;
return (instance = new PAPIUtil());
}
// Make sure the version of PAPIProxyBridge we get has the required methods we need...
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isCompatible(){
try{
papi.getClass().getMethod("findServers");
papi.getClass().getMethod("getServers");
return true;
}catch(NoSuchMethodException ex){
return false;
@@ -57,19 +68,11 @@ public class PAPIUtil{
}
public String getServer(){
return cache.get(() -> {
List<String> servers;
try{
servers = papi.findServers().getNow(Collections.emptyList());
}catch(CancellationException | CompletionException ex){
return null;
}
if(servers == null || servers.isEmpty())
return null;
return servers.get(0);
});
Set<String> values = serversCache.get(papi::getServers).getNow(Collections.emptySet());
if(values.isEmpty())
return null;
return List.copyOf(values).get(0);
}
public <P> P getPlayer(Collection<P> players){
@@ -81,9 +84,8 @@ public class PAPIUtil{
public String parse(String text, UUID carrier, UUID player){
try{
CompletableFuture<String> future = papi.formatPlaceholders(text, carrier, player);
return future.getNow(text);
}catch(IllegalArgumentException | CancellationException | CompletionException ex){
return textCache.get(player, () -> papi.formatPlaceholders(text, carrier, player)).getNow(text);
}catch(ExecutionException ex){
return text;
}
}
@@ -29,8 +29,6 @@ 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.compat.maintenance.MaintenanceUtil;
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
@@ -38,12 +36,13 @@ import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import java.util.List;
public class PingEventHandler{
private static PAPIUtil papiUtil = null;
private static MaintenanceUtil maintenanceUtil = null;
public static <F, P extends GenericPlayer> ProfileEntry handleEvent(GenericEventWrapper<F, P> event){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
if(event.isInvalidProtocol()){
@@ -75,61 +74,98 @@ public class PingEventHandler{
logger.debug(PingEventHandler.class, "Received valid Server List Profile. Calling PreServerListSetEvent...");
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
if(e == null || e.isCancelled()){
GenericServerListEvent slEvent = event.callEvent(ProfileManager.merge(profile));
if(slEvent == null || slEvent.isCancelled()){
logger.debug(PingEventHandler.class, "PreServerListSetEvent was cancelled. Stopping ping handling...");
return null;
}
logger.debug(PingEventHandler.class, "PreServerListSetEvent completed. Proceeding with ping handling...");
ProfileEntry entry = e.getEntry();
ProfileEntry entry = slEvent.getEntry();
if(entry.isInvalid()){
logger.debugWarn(PingEventHandler.class, "No valid ProfileEntry retrieved. Cancelling ping handling...");
return null;
}
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
if(ProfileManager.checkOption(entry.onlinePlayersEnabled()) && ignoreMaintenance(event, "onlinePlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> onlinePlayers -> enabled' option is true. Trying to apply '%s'...", entry.onlinePlayersCount());
String onlinePlayers = ComponentParser.text(entry.onlinePlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString();
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
event.setMaxPlayers(max);
try{
online = onlinePlayers == null ? online : Integer.parseInt(onlinePlayers);
event.setOnlinePlayers(online);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> onlinePlayers -> amount' is not a valid Number!");
}
}
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
boolean extraPlayersEnabled = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayersEnabled && ignoreMaintenance(event, "extraPlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> enabled' option is true. Trying to apply '%s'...", entry.extraPlayersCount());
String extraPlayers = ComponentParser.text(entry.extraPlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString();
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
try{
max = online + (extraPlayers == null ? 0 : Integer.parseInt(extraPlayers));
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> amount' is a valid number. Applying it...");
event.setMaxPlayers(max);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> extraPlayers -> amount' is not a valid Number!");
}
}
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayersEnabled && ignoreMaintenance(event, "maxPlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> enabled' option is true. Trying to apply '%s'...", entry.maxPlayersCount());
String maxPlayers = ComponentParser.text(entry.maxPlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.toString();
event.setMaxPlayers(max);
try{
max = maxPlayers == null ? 0 : Integer.parseInt(maxPlayers);
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> amount' is a valid number. Applying it...");
event.setMaxPlayers(max);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> maxPlayers -> amount' is not a valid Number!");
}
}
GenericServer finalServer = event.createGenericServer(online, max, host);
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
logger.debug(PingEventHandler.class, "'motd' option present. Applying ['%s']...", String.join("', '", entry.motd()));
event.setMotd(
ComponentParser.list(entry.motd())
List<Component> motd = entry.motd().stream()
.map(line -> ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.modifyText(text -> plugin.getCore().getTextCenterUtil().getCenteredText(text))
.toComponent()
);
)
.toList();
event.setMotd(Component.join(JoinConfiguration.separator(Component.newline()), motd));
}
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
if(hidePlayers && ignoreMaintenance(event, "hidePlayers") && ignoreMaintenance(event, "hidePlayersHover")){
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayers' enabled. Hiding player count...");
event.hidePlayers();
}
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
logger.debug(PingEventHandler.class, "'playerCount -> text' option set. Applying '%s'...", entry.playerCountText());
event.setPlayerCount(
ComponentParser.text(entry.playerCountText())
@@ -139,14 +175,20 @@ public class PingEventHandler{
);
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
boolean hidePlayersHover = ProfileManager.checkOption(entry.hidePlayersHoverEnabled());
if(hidePlayersHover){
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayersHover' option set. Hiding Player Hover...");
event.setPlayersHidden();
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && !hidePlayersHover && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying ['%s']...", String.join("', '", entry.players()));
event.setPlayers(entry.players(), player, server);
}
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
logger.debug(PingEventHandler.class, "'favicon' option set. Resolving '%s'...", entry.favicon());
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
@@ -169,20 +211,6 @@ public class PingEventHandler{
return entry;
}
public static PAPIUtil getPAPIUtil(){
if(papiUtil != null)
return papiUtil;
return (papiUtil = new PAPIUtil());
}
public static MaintenanceUtil getMaintenanceUtil(){
if(maintenanceUtil != null)
return maintenanceUtil;
return (maintenanceUtil = new MaintenanceUtil());
}
private static <F, P extends GenericPlayer> boolean ignoreMaintenance(GenericEventWrapper<F, P> event, String option){
if(!event.isMaintenanceModeActive())
return true;
@@ -46,13 +46,46 @@ public class ConfigMigrator{
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, fourToFive())
.addVersion(LATEST, sevenToEight())
.addVersion(7, sixToSeven())
.addVersion(6, fiveToSix())
.addVersion(5, fourToFive())
.addVersion(4, threeToFour())
.addVersion(3, twoToThree())
.addVersion(2, oneToTwo())
.build();
}
public static ConfigurationTransformation sevenToEight(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
value.node("hidePlayersHover").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation sixToSeven(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("printBanner").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation fiveToSix(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
value.node("onlinePlayers").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation fourToFive(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
@@ -111,7 +144,7 @@ public class ConfigMigrator{
versioned.apply(node);
final int endVersion = versioned.version(node);
if(startVersion < endVersion)
logger.info("Migrated config.yml from v" + startVersion + " to v" + endVersion);
logger.success("Successfully migrated config from <white>v%d</white> to <white>v%d</white>", startVersion, endVersion);
}
return node;
@@ -72,7 +72,6 @@ public class FileHandler{
}
public boolean loadConfig(){
logger.info("Loading config.yml...");
File folder = plugin.getPlugin().getFolderPath().toFile();
if(!folder.exists() && !folder.mkdirs()){
logger.warn("Couldn't create folder for plugin. Is it missing Write permissions?");
@@ -87,7 +86,7 @@ public class FileHandler{
}
Files.copy(stream, config);
logger.info("Created new config.yml!");
logger.success("Created new config.yml!");
}catch(IOException ex){
logger.warn("Cannot create config.yml for plugin.", ex);
return false;
@@ -98,24 +97,37 @@ public class FileHandler{
}
public boolean loadProfiles(){
logger.info("Loading profiles...");
if(!profilesFolder.toFile().exists() && profilesFolder.toFile().mkdirs()){
logger.info("Successfully created profiles folder.");
try(InputStream stream = plugin.getClass().getResourceAsStream("/profiles/default.yml")){
if(stream == null){
logger.warn("Cannot retrieve default.yml from Plugin.");
return false;
}
Files.copy(stream, profilesFolder.resolve("default.yml"));
}catch(IOException ex){
logger.warn("Cannot create default.yml for plugin.", ex);
return false;
}
logger.info("[-] Loading profiles...");
if(createFile("default.yml")){
return reloadProfiles();
}else{
return false;
}
}
public boolean createFile(String name){
if(Files.notExists(profilesFolder) && profilesFolder.toFile().mkdirs()){
logger.debugSuccess(FileHandler.class, "Successfully created profiles folder.");
}
return reloadProfiles();
File file = new File(profilesFolder.toFile(), name);
if(file.exists()){
return true;
}
try(InputStream stream = plugin.getClass().getResourceAsStream("/profiles/default.yml")){
if(stream == null){
logger.warn("Cannot retrieve content of internal default.yml file.");
return false;
}
Files.copy(stream, profilesFolder.resolve(name));
return true;
}catch(IOException ex){
logger.warn("Encountered IOException while trying to create file <white>%s</white>", ex, name);
return false;
}
}
public boolean migrateConfig(){
@@ -147,7 +159,7 @@ public class FileHandler{
File[] files = profilesFolder.toFile().listFiles(((dir, name) -> name.endsWith(".yml")));
if(files == null || files.length == 0){
logger.warn("Cannot load files from profiles folder! No valid YAML files present.");
logger.failure("Cannot load files from profiles folder! No valid YAML files present.");
return false;
}
@@ -157,11 +169,11 @@ public class FileHandler{
continue;
profiles.add(ServerListProfile.Builder.resolve(file.getName(), tmp, logger).build());
logger.info("Loaded '%s'!", file.getName());
logger.debugSuccess(FileHandler.class, "Loaded '<white>%s</white>'!", file.getName());
}
if(profiles.isEmpty()){
logger.warn("Couldn't load any profile from profiles folder!");
logger.failure("Couldn't load any profile from profiles folder!");
return false;
}
@@ -178,7 +190,7 @@ public class FileHandler{
try{
return loader.load();
}catch(IOException ex){
logger.warn("Cannot load '%s' due to an IOException!", ex, path.toFile().getName());
logger.warn("Cannot load '<white>%s</white>' due to an IOException!", ex, path.toFile().getName());
return null;
}
}
@@ -205,11 +217,11 @@ public class FileHandler{
}
private boolean makeBackup(){
logger.info("Making backup of old config.yml...");
logger.info("[-] Making backup of old config.yml...");
File backups = plugin.getPlugin().getFolderPath().resolve("backups").toFile();
if(!backups.exists() && !backups.mkdirs()){
logger.warn("Cannot create backups folder for migration!");
logger.failure("Cannot create backups folder for migration!");
return false;
}
@@ -218,16 +230,16 @@ public class FileHandler{
File configBackup = new File(backups, "config_" + date.replace(":", "_") + ".yml");
try{
if(!configBackup.exists() && !configBackup.createNewFile()){
logger.warn("Cannot create backup file for config.yml!");
logger.failure("Cannot create backup file for config.yml!");
return false;
}
Files.copy(config, configBackup.toPath(), StandardCopyOption.REPLACE_EXISTING);
logger.info("Saved backup as '%s'!", configBackup.getName());
logger.success("Saved backup as '<white>%s</white>'!", configBackup.getName());
return true;
}catch(IOException ex){
logger.warn("Encountered IOException while trying to create a backup.", ex);
logger.failure("Encountered IOException while trying to create a backup.", ex);
return false;
}
}
@@ -27,10 +27,18 @@ package ch.andre601.advancedserverlist.core.interfaces;
public interface PluginLogger{
default void debugSuccess(Class<?> clazz, String msg, Object... args){
debug(clazz, "[<green>✓</green>] " + msg, args);
}
void debug(Class<?> clazz, String msg, Object... args);
void debugWarn(Class<?> clazz, String msg, Object... args);
default void success(String msg, Object... args){
info("[<green>✓</green>] " + msg, args);
}
void info(String msg, Object... args);
void warn(String msg, Object... args);
@@ -38,4 +46,8 @@ public interface PluginLogger{
void warn(String msg, Throwable throwable);
void warn(String msg, Throwable throwable, Object... args);
default void failure(String msg, Object... args){
warn("[<red>x</red>] " + msg, args);
}
}
@@ -29,19 +29,23 @@ import java.util.Locale;
public abstract class PluginCommand{
private final String argument;
private final String name;
public PluginCommand(String argument){
this.argument = argument;
public PluginCommand(String name){
this.name = name;
}
public String getArgument(){
return argument;
public String name(){
return name;
}
public String getPermission(){
return "advancedserverlist.command." + getArgument().toLowerCase(Locale.ROOT);
public String permission(){
return "advancedserverlist.command." + name().toLowerCase(Locale.ROOT);
}
public abstract void handle(CmdSender sender);
public abstract void handle(CmdSender sender, String[] args);
public abstract String usage();
public abstract String description();
}
@@ -27,7 +27,7 @@ package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
@@ -44,6 +44,10 @@ public interface PluginCore<F>{
void clearFaviconCache();
void downloadLibrary(String groupId, String artifactId, String version);
void startScheduler();
AdvancedServerList<F> getCore();
Path getFolderPath();
@@ -52,12 +56,12 @@ public interface PluginCore<F>{
FaviconHandler<F> getFaviconHandler();
String getPlatformName();
String getPlatformVersion();
String getPlatformInfo();
String getLoader();
boolean isPluginEnabled(String plugin);
F createFavicon(BufferedImage image) throws Exception;
default boolean isDebugEnabled(){
@@ -42,6 +42,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
void setMaxPlayers(int maxPlayers);
void setOnlinePlayers(int onlinePlayers);
void setMotd(Component component);
void hidePlayers();
@@ -50,6 +52,8 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
void setPlayers(List<String> players, P player, GenericServer server);
void setPlayersHidden();
void setFavicon(F favicon);
void setDefaultFavicon();
@@ -0,0 +1,235 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.migration.minimotd;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.migration.minimotd.serializing.MiniMOTDConfig;
import ch.andre601.advancedserverlist.core.migration.minimotd.serializing.MiniMOTDSerializer;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MiniMOTDConfigMigrator{
public static boolean migrate(AdvancedServerList<?> core, CmdSender sender){
core.getPlugin().downloadLibrary("org.spongepowered", "configurate-hocon", "4.1.2");
PluginLogger logger = core.getPlugin().getPluginLogger();
String folder = core.getPlugin().getLoader().equals("velocity") ? "minimotd-velocity" : "MiniMOTD";
Path mainConf = core.getPlugin().getFolderPath().getParent().resolve(folder).resolve("main.conf");
if(!Files.exists(mainConf)){
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot find a main.conf file in <white>/plugins/%s/</white> folder.", folder);
sender.sendErrorMsg(" -> <red>No main.conf file found.");
return false;
}
HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
.path(mainConf)
.defaultOptions(options -> options.serializers(builder ->
builder.register(MiniMOTDConfig.class, MiniMOTDSerializer.MINI_MOTD_SERIALIZER)
.register(MiniMOTDConfig.Motd.class, MiniMOTDSerializer.MOTD_SERIALIZER)
.register(MiniMOTDConfig.PlayerCount.class, MiniMOTDSerializer.PLAYER_COUNT_SERIALIZER)
))
.build();
MiniMOTDConfig config;
try{
ConfigurationNode node = loader.load();
config = node.get(MiniMOTDConfig.class);
}catch(IOException ex){
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered IOException while loading main.conf file.", ex);
sender.sendErrorMsg(" -> <red>IOException while loading</red> main.conf <red>file.");
return false;
}
if(config == null){
logger.warn("[<white>Migrator - MiniMOTD</white>] Retrieved main.conf file returned null.");
sender.sendErrorMsg(" -> <red>Received invalid</red> main.conf <red>file.");
return false;
}
ProfileEntry.Builder profileBuilder = ProfileEntry.empty().builder();
List<ProfileEntry.Builder> profilesBuilders = new ArrayList<>();
if(config.motdEnabled() && config.motds().size() > 1){
for(int i = 0; i < config.motds().size(); i++){
profilesBuilders.add(ProfileEntry.empty().builder());
}
}
if(config.motdEnabled()){
if(config.motds().size() == 1){
applyMotd(profileBuilder, config.motds().get(0));
}else
if(config.motds().size() > 1){
for(int i = 0; i < config.motds().size(); i++){
applyMotd(profilesBuilders.get(i), config.motds().get(i));
}
}
}
if(config.iconEnabled()){
if(config.motds().size() == 1){
MiniMOTDConfig.Motd motd = config.motds().get(0);
if(!motd.icon().isEmpty()){
profileBuilder.favicon(motd.icon());
}
}else
if(config.motds().size() > 1){
for(int i = 0; i < config.motds().size(); i++){
MiniMOTDConfig.Motd motd = config.motds().get(i);
if(!motd.icon().isEmpty()){
profilesBuilders.get(i).favicon(motd.icon());
}
}
}
}
if(config.playerCount() != null){
MiniMOTDConfig.PlayerCount playerCount = config.playerCount();
NullBool hidePlayers = NullBool.resolve(playerCount.hidePlayers());
NullBool xMoreEnabled = NullBool.resolve(playerCount.xMoreEnabled());
int xMore = playerCount.xMore();
NullBool maxPlayersEnabled = NullBool.resolve(playerCount.maxPlayersEnabled());
int maxPlayers = playerCount.maxPlayers();
profileBuilder.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(xMoreEnabled)
.extraPlayersCount(String.valueOf(xMore))
.maxPlayersEnabled(maxPlayersEnabled)
.maxPlayersCount(String.valueOf(maxPlayers));
}
ProfileEntry entry = profileBuilder.build();
List<ProfileEntry> profiles = profilesBuilders.stream()
.map(ProfileEntry.Builder::build)
.toList();
boolean profilesInvalid = profiles.isEmpty() || profiles.stream().allMatch(ProfileEntry::isInvalid);
if(entry.isInvalid() && profilesInvalid){
logger.warn("[<white>Migrator - MiniMOTD</white>] Main ProfileEntry was invalid and profiles were empty.");
sender.sendErrorMsg(" -> <red>Received invalid configuration.");
return false;
}
Path profile = core.getPlugin().getFolderPath().resolve("profiles").resolve("minimotd_migrated.yml");
if(Files.exists(profile)){
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot create new file minimotd_migrated.yml. One with the same name is already present.");
sender.sendErrorMsg(" -> <red>File</red> minimotd_migrated.yml <red>already present.");
return false;
}
try{
Files.createFile(profile);
}catch(IOException ex){
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to create file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File creation error.");
return false;
}
YamlConfigurationLoader yamlLoader = YamlConfigurationLoader.builder()
.path(profile)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(option -> option.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.build();
ConfigurationNode migrated;
try{
migrated = yamlLoader.load();
}catch(IOException ex){
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to load file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File loading error.");
return false;
}
if(migrated == null){
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot migrate Configuration. ConfigurationNode was null.");
sender.sendErrorMsg(" -> <red>File loading error.");
return false;
}
try{
migrated.node("priority").set(0);
if(!profiles.isEmpty()){
migrated.node("profiles").setList(ProfileEntry.class, profiles);
}
migrated.set(entry);
}catch(SerializationException ex){
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered a SerializationException while setting values.", ex);
sender.sendErrorMsg(" -> <red>Error while updating file</red> minimotd_migrated.yml<red>.");
return false;
}
try{
yamlLoader.save(migrated);
sender.sendPrefixedMsg(" -> <green>Completed!");
return true;
}catch(IOException ex){
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to save new file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File saving error.");
return false;
}
}
private static void applyMotd(ProfileEntry.Builder builder, MiniMOTDConfig.Motd motd){
if(motd.line1().isEmpty() && !motd.line2().isEmpty()){
builder.motd(List.of("<grey>", motd.line2()));
}else
if(!motd.line1().isEmpty() && motd.line2().isEmpty()){
builder.motd(Collections.singletonList(motd.line1()));
}else
if(!motd.line1().isEmpty()){ // Line2 is by logic not empty here. So this check is not required.
builder.motd(List.of(motd.line1(), motd.line2()));
}
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 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,30 +23,13 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.players;
package ch.andre601.advancedserverlist.core.migration.minimotd.serializing;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import java.util.List;
import java.util.UUID;
public abstract class GenericPlayerImpl implements GenericPlayer{
public record MiniMOTDConfig(boolean iconEnabled, boolean motdEnabled, List<Motd> motds, PlayerCount playerCount){
protected String name = null;
protected int protocol = 0;
protected UUID uuid = null;
public record Motd(String icon, String line1, String line2){}
@Override
public String getName(){
return name;
}
@Override
public int getProtocol(){
return protocol;
}
@Override
public UUID getUUID(){
return uuid;
}
public record PlayerCount(boolean hidePlayers, boolean xMoreEnabled, int xMore, boolean maxPlayersEnabled, int maxPlayers){}
}
@@ -0,0 +1,129 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.migration.minimotd.serializing;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
public class MiniMOTDSerializer implements TypeSerializer<MiniMOTDConfig>{
public static final MiniMOTDSerializer MINI_MOTD_SERIALIZER = new MiniMOTDSerializer();
public static final MotdSerializer MOTD_SERIALIZER = new MotdSerializer();
public static final PlayerCountSerializer PLAYER_COUNT_SERIALIZER = new PlayerCountSerializer();
@Override
public MiniMOTDConfig deserialize(Type type, ConfigurationNode node) throws SerializationException{
boolean iconsEnabled = node.node("icon-enabled").getBoolean();
boolean motdEnabled = node.node("motd-enabled").getBoolean();
List<MiniMOTDConfig.Motd> motds = node.node("motds").getList(MiniMOTDConfig.Motd.class);
MiniMOTDConfig.PlayerCount playerCount = node.node("player-count-settings").get(MiniMOTDConfig.PlayerCount.class);
return new MiniMOTDConfig(iconsEnabled, motdEnabled, motds, playerCount);
}
@Override
public void serialize(Type type, @Nullable MiniMOTDConfig obj, ConfigurationNode node) throws SerializationException{
if(obj == null){
node.raw(null);
return;
}
node.node("icon-enabled").set(obj.iconEnabled());
node.node("motd-enable").set(obj.motdEnabled());
node.node("motds").setList(MiniMOTDConfig.Motd.class, obj.motds());
node.node("player-count-settings").set(MiniMOTDConfig.PlayerCount.class, obj.playerCount());
}
public static class MotdSerializer implements TypeSerializer<MiniMOTDConfig.Motd>{
@Override
public MiniMOTDConfig.Motd deserialize(Type type, ConfigurationNode node) throws SerializationException{
String icon = node.node("icon").getString("");
String line1 = node.node("line1").getString("");
String line2 = node.node("line2").getString("");
return new MiniMOTDConfig.Motd(icon, line1, line2);
}
@Override
public void serialize(Type type, MiniMOTDConfig.@Nullable Motd obj, ConfigurationNode node) throws SerializationException{
if(obj == null){
node.raw(null);
return;
}
node.node("icon").set(obj.icon());
node.node("line1").set(obj.line1());
node.node("line2").set(obj.line2());
}
}
public static class PlayerCountSerializer implements TypeSerializer<MiniMOTDConfig.PlayerCount>{
@Override
public MiniMOTDConfig.PlayerCount deserialize(Type type, ConfigurationNode node) throws SerializationException{
boolean hidePlayerCount = node.node("hide-player-count").getBoolean();
boolean xMoreEnabled = node.node("just-x-more-settings", "just-x-more-enabled").getBoolean();
int xMore = node.node("just-x-more-settings", "x-value").getInt();
boolean maxPlayersEnabled = node.node("max-players-enabled").getBoolean();
int maxPlayers = node.node("max-players").getInt();
return new MiniMOTDConfig.PlayerCount(hidePlayerCount, xMoreEnabled, xMore, maxPlayersEnabled, maxPlayers);
}
@Override
public void serialize(Type type, MiniMOTDConfig.@Nullable PlayerCount obj, ConfigurationNode node) throws SerializationException{
if(obj == null){
node.raw(null);
return;
}
node.node("allow-exceeding-maximum").set(false);
node.node("disable-player-list-hover").set(false);
node.node("fake-players", "fake-players").set("25%");
node.node("fake-players", "fake-players-enabled").set(false);
node.node("hide-player-count").set(obj.hidePlayers());
node.node("just-x-more-settings", "just-x-more-enabled").set(obj.xMoreEnabled());
node.node("just-x-more-settings", "x-value").set(obj.xMore());
node.node("max-players").set(obj.maxPlayers());
node.node("max-players-enabled").set(obj.maxPlayersEnabled());
node.node("servers").setList(String.class, Collections.emptyList());
}
}
}
@@ -0,0 +1,467 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 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.migration.serverlistplus;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import net.minecrell.serverlistplus.core.ServerListPlusCore;
import net.minecrell.serverlistplus.core.config.PersonalizedStatusConf;
import net.minecrell.serverlistplus.core.config.ServerStatusConf;
import net.minecrell.serverlistplus.core.util.BooleanOrList;
import net.minecrell.serverlistplus.core.util.IntegerRange;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SLPConfigMigrator{
private static final Pattern RGB_COLOR_PATTERN = Pattern.compile("&(?<color>#[a-fA-F0-9]{6})");
private static final Pattern COLOR_CODE_PATTERN = Pattern.compile("&(?<color>[abcdefklmnorABCDEFKLMNOR0123456789])");
private static final Pattern RGB_GRADIENT_PATTERN = Pattern.compile(
"%gradient" +
"(?<start>#[a-fA-F0-9]{6})" + // Starting color
"(?<end>#[a-fA-F0-9]{6})" + // Ending color
"%" +
"(?<text>.+?)" + // Text
"%gradient%"
);
private static final Map<String, String> STATIC_REPLACEMENTS = Map.of(
"%player%", "${player name}",
"%uuid%", "${player uuid}",
"%_uuid_%", "${player uuid}",
"%online%", "${server playersOnline}",
"%max%", "${server playersMax}"
);
private static final Map<String, String> COLOR_TO_MINIMESSAGE_TAG = new HashMap<>(){{
// Color Codes.
put("a", "<green>");
put("b", "<aqua>");
put("c", "<red>");
put("d", "<light_purple>");
put("e", "<yellow>");
put("f", "<white>");
put("0", "<black>");
put("1", "<dark_blue>");
put("2", "<dark_green>");
put("3", "<dark_aqua>");
put("4", "<dark_red>");
put("5", "<dark_purple>");
put("6", "<gold>");
put("7", "<grey>");
put("8", "<dark_grey>");
put("9", "<blue>");
// Formatting Codes
put("k", "<obfuscated>");
put("l", "<bold>");
put("m", "<strikethrough>");
put("n", "<underlined>");
put("o", "<italic>");
put("r", "<reset>");
}};
public static int migrate(AdvancedServerList<?> core, CmdSender sender){
ServerListPlusCore slpCore = ServerListPlusCore.getInstance();
PluginLogger logger = core.getPlugin().getPluginLogger();
if(slpCore == null){
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate ServerListPlus config. ServerListPlus is not active!");
return 0;
}
ServerStatusConf conf = slpCore.getConf(ServerStatusConf.class);
if(conf == null){
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate ServerListPlus configuration. Received configuration was null.");
return 0;
}
PersonalizedStatusConf.StatusConf defConf = conf.Default;
PersonalizedStatusConf.StatusConf personalizedConf = conf.Personalized;
PersonalizedStatusConf.StatusConf banned = conf.Banned;
sender.sendPrefixedMsg("Migrating <white>Default</white>...");
int defConfParsed = parseConf(core, sender, defConf, Type.DEFAULT);
sender.sendPrefixedMsg("Migrating <white>Personalized</white>...");
int personalizedParsed = parseConf(core, sender, personalizedConf, Type.PERSONALIZED);
sender.sendPrefixedMsg("Migrating <white>Banned</white>...");
int bannedParsed = parseConf(core, sender, banned, Type.BANNED);
return defConfParsed + personalizedParsed + bannedParsed;
}
private static int parseConf(AdvancedServerList<?> core, CmdSender sender, PersonalizedStatusConf.StatusConf conf, Type type){
PluginLogger logger = core.getPlugin().getPluginLogger();
if(conf == null){
logger.info("[<white>Migrator - ServerListPlus</white>] No StatusConf found for type <white>%s</white>. Skipping...", type.getName());
sender.sendPrefixedMsg(" -> Not found! Skipping...");
return 0;
}
ProfileEntry.Builder builder = ProfileEntry.empty().builder();
List<ProfileEntry.Builder> profiles = new ArrayList<>();
List<List<String>> motds = resolveMotds(conf.Description);
List<String> favicons = resolveFavicons(conf.Favicon);
List<List<String>> hovers = resolveHover(conf.Players);
NullBool hidePlayers = conf.Players != null ? NullBool.resolve(conf.Players.Hidden) : NullBool.NOT_SET;
List<Integer> maxPlayers = resolveMaxPlayers(conf.Players);
List<String> playerCount = resolvePlayerCounts(conf.Players);
int size = getMaxListSize(motds, favicons, hovers, maxPlayers, playerCount);
// Only add profiles entries when there are more than 2 entries of an option.
// Avoids a profiles option with a single entry that has no options whatsoever.
if(size > 1){
for(int i = 0; i < size; i++){
profiles.add(ProfileEntry.empty().builder());
}
}
apply(motds, builder, profiles, ProfileEntry.Builder::motd);
apply(favicons, builder, profiles, ProfileEntry.Builder::favicon);
apply(hovers, builder, profiles, ProfileEntry.Builder::players);
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(String.valueOf(count)));
apply(playerCount, builder, profiles, ProfileEntry.Builder::playerCountText);
builder.hidePlayersEnabled(hidePlayers);
ProfileEntry entry = builder.build();
List<ProfileEntry> profileEntries = profiles.stream()
.map(ProfileEntry.Builder::build)
.toList();
boolean profilesInvalid = profileEntries.isEmpty() || profileEntries.stream().anyMatch(ProfileEntry::isInvalid);
if(entry.isInvalid() && profilesInvalid){
logger.warn("[<white>Migrator - ServerListPlus</white>] Unable to parse ServerListPlus configuration of type <white>%s</white>. Generated ProfileEntry was invalid.", type.getName());
sender.sendErrorMsg(" -> <red>Received invalid Configuration.");
return 0;
}
Path profile = core.getPlugin().getFolderPath().resolve("profiles").resolve(type.getFile());
if(Files.exists(profile)){
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot create new file <white>%s</white>. One with the same name is already present", type.getFile());
sender.sendErrorMsg(" -> <red>File</red> %s <red>already present.", type.getFile());
return 0;
}
try{
Files.createFile(profile);
}catch(IOException ex){
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to create file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File creation error.");
return 0;
}
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.path(profile)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(opt -> opt.serializers(build -> build.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.build();
ConfigurationNode node;
try{
node = loader.load();
}catch(IOException ex){
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to load file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File loading error.");
return 0;
}
if(node == null){
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate Configuration of type <white>%s</white>. ConfigurationNode was null.", type.getName());
sender.sendErrorMsg(" -> <red>File loading error.");
return 0;
}
try{
node.node("priority")
.set(type != Type.DEFAULT ? 1 : 0);
if(type == Type.PERSONALIZED){
node.node("condition")
.set("${player name} != \"" + core.getFileHandler().getString("Anonymous", "unknownPlayer", "name") + "\"");
}else
if(type == Type.BANNED){
node.node("condition")
.set("${player isBanned}");
}
if(!profiles.isEmpty()){
node.node("profiles").setList(ProfileEntry.class, profileEntries);
}
node.set(entry);
}catch(SerializationException ex){
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered a SerializationException while setting values.", ex);
sender.sendErrorMsg(" -> <red>Error while updating file</red> %s<red>.", type.getFile());
return 0;
}
try{
loader.save(node);
sender.sendPrefixedMsg(" -> <green>Completed!");
return 1;
}catch(IOException ex){
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to save new file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File saving error.");
return 0;
}
}
private static int getMaxListSize(List<?>... lists){
int size = 0;
for(List<?> list : lists){
if(list.size() > size)
size = list.size();
}
return size;
}
private static List<List<String>> resolveMotds(List<String> descriptions){
if(descriptions == null || descriptions.isEmpty())
return Collections.emptyList();
List<List<String>> motds = new ArrayList<>();
for(String line : descriptions){
motds.add(getList(line));
}
return motds;
}
private static List<String> resolveFavicons(PersonalizedStatusConf.StatusConf.FaviconConf faviconConf){
if(faviconConf == null || faviconConf.Disabled != null && faviconConf.Disabled)
return Collections.emptyList();
List<String> list = new ArrayList<>();
if(faviconConf.Heads != null){
for(String head : faviconConf.Heads){
list.add(
"https://mc-heads.net/avatar/" +
replacePlaceholders(head) +
"/64/nohelm"
);
}
}
if(faviconConf.Helms != null){
for(String helm : faviconConf.Helms){
list.add(replacePlaceholders(helm));
}
}
if(faviconConf.Files != null){
for(String file : faviconConf.Files){
if(!file.toLowerCase(Locale.ROOT).endsWith(".png"))
continue;
list.add(replacePlaceholders(file));
}
}
return list;
}
private static List<List<String>> resolveHover(PersonalizedStatusConf.StatusConf.PlayersConf playersConf){
if(playersConf == null)
return Collections.emptyList();
BooleanOrList<String> booleanOrList = playersConf.Hover;
if(booleanOrList == null)
return Collections.emptyList();
if(booleanOrList.getList() != null){
List<List<String>> hovers = new ArrayList<>();
for(String line : booleanOrList.getList()){
if(line == null)
continue;
hovers.add(getList(line));
}
return hovers;
}
return Collections.emptyList();
}
private static List<Integer> resolveMaxPlayers(PersonalizedStatusConf.StatusConf.PlayersConf playersConf){
if(playersConf == null)
return Collections.emptyList();
List<IntegerRange> maxPlayers = playersConf.Max;
if(maxPlayers == null)
return Collections.emptyList();
List<Integer> values = new ArrayList<>();
for(IntegerRange range : maxPlayers){
if(range == null)
continue;
values.add(range.to());
}
return values;
}
private static List<String> resolvePlayerCounts(PersonalizedStatusConf.StatusConf.PlayersConf playersConf){
if(playersConf == null)
return Collections.emptyList();
if(playersConf.Slots == null)
return Collections.emptyList();
return playersConf.Slots.stream()
.map(SLPConfigMigrator::replacePlaceholders)
.toList();
}
private static <T> void apply(List<T> list, ProfileEntry.Builder builder, List<ProfileEntry.Builder> profiles,
BiConsumer<ProfileEntry.Builder, T> builderConsumer){
if(list.size() == 1){
builderConsumer.accept(builder, list.get(0));
}else
if(list.size() > 1){
for(int i = 0; i < list.size(); i++){
builderConsumer.accept(profiles.get(i), list.get(i));
}
}
}
private static List<String> getList(String line){
return Arrays.asList(replacePlaceholders(line).split("\n"));
}
private static String replacePlaceholders(String input){
StringBuilder parsed = new StringBuilder(input);
StringBuilder builder = new StringBuilder();
Matcher rgbColorMatcher = RGB_COLOR_PATTERN.matcher(parsed.toString());
if(rgbColorMatcher.find()){
do{
rgbColorMatcher.appendReplacement(builder, "<" + rgbColorMatcher.group("color") + ">");
}while(rgbColorMatcher.find());
rgbColorMatcher.appendTail(builder);
parsed = builder;
}
Matcher colorCodeMatcher = COLOR_CODE_PATTERN.matcher(parsed.toString());
if(colorCodeMatcher.find()){
builder.setLength(0);
do{
for(Map.Entry<String, String> colorCodes : COLOR_TO_MINIMESSAGE_TAG.entrySet()){
if(!colorCodeMatcher.group("color").equalsIgnoreCase(colorCodes.getKey()))
continue;
colorCodeMatcher.appendReplacement(builder, colorCodes.getValue());
}
}while(colorCodeMatcher.find());
colorCodeMatcher.appendTail(builder);
parsed = builder;
}
Matcher rgbGradientMatcher = RGB_GRADIENT_PATTERN.matcher(parsed.toString());
if(rgbGradientMatcher.find()){
builder.setLength(0);
do{
String start = rgbGradientMatcher.group("start");
String end = rgbGradientMatcher.group("end");
String text = rgbGradientMatcher.group("text");
rgbGradientMatcher.appendReplacement(builder, "<gradient:" + start + ":" + end + ">" + text + "</gradient>");
}while(rgbGradientMatcher.find());
rgbGradientMatcher.appendTail(builder);
parsed = builder;
}
return replaceStaticPlaceholders(parsed);
}
private static String replaceStaticPlaceholders(StringBuilder input){
if(input.isEmpty())
return "";
for(Map.Entry<String, String> entry : STATIC_REPLACEMENTS.entrySet()){
int index = 0;
while((index = input.indexOf(entry.getKey(), index)) != -1){
input.replace(index, index + entry.getKey().length(), entry.getValue());
index += entry.getValue().length();
}
}
return input.toString();
}
private enum Type{
DEFAULT("Default", "slp_default.yml"),
PERSONALIZED("Personalized", "slp_personalized.yml"),
BANNED("Banned", "slp_banned.yml");
private final String name, file;
Type(String name, String file){
this.name = name;
this.file = file;
}
public String getName(){
return name;
}
public String getFile(){
return file;
}
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 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,27 +23,30 @@
*
*/
package ch.andre601.advancedserverlist.core.compat.papi;
package ch.andre601.advancedserverlist.core.objects;
import java.time.Duration;
import java.util.function.Supplier;
public class PAPICache{
public class ValueCache<T>{
private CacheValue cache = null;
private final Duration duration;
private CacheValue<T> cache = null;
public PAPICache(){}
public String get(Supplier<String> supplier){
if(cache == null || cache.isExpired())
cache = new CacheValue(supplier.get(), System.currentTimeMillis());
return cache.server();
public ValueCache(Duration duration){
this.duration = duration;
}
private record CacheValue(String server, long timestamp){
// Consider the cache expired if it is older than 5 seconds.
public boolean isExpired(){
return (timestamp < 0L) || System.currentTimeMillis() - timestamp >= 5000L;
public T get(Supplier<T> supplier){
if(cache == null || cache.expired())
cache = new CacheValue<>(System.currentTimeMillis(), duration, supplier.get());
return cache.value();
}
private record CacheValue<T>(long timestamp, Duration duration, T value){
public boolean expired(){
return (timestamp < 0L) || System.currentTimeMillis() - timestamp >= duration.toMillis();
}
}
}
@@ -29,7 +29,6 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.List;
import java.util.function.Function;
public class ComponentParser{
@@ -52,12 +51,13 @@ public class ComponentParser{
return new ComponentParser(text);
}
public static ComponentParser list(List<String> lines){
return new ComponentParser(String.join("\n", lines));
public static ComponentParser textFormatted(String text, Object... args){
return text(String.format(text, args));
}
public ComponentParser modifyText(Function<String, String> function){
this.text = function.apply(text);
return this;
}
@@ -65,8 +65,16 @@ public class ComponentParser{
return mm.deserialize(text);
}
public static String toMMString(Component component){
return mm.serialize(component);
}
@Override
public String toString(){
return legacy.serialize(toComponent());
}
public String toStringStriped(){
return mm.stripTags(text);
}
}
@@ -0,0 +1,136 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.flattener.FlattenerListener;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;
public class TextCenterUtil{
private final ComponentFlattener COMPONENT_FLATTENER = ComponentFlattener.textOnly();
private final double MAX_WIDTH = 270.0; // Max width of the MOTD
private final int SPACE_WIDTH = 4;
private final Map<String, FontInfo> charWidths;
public TextCenterUtil(AdvancedServerList<?> plugin){
charWidths = loadFontWidths(plugin);
}
public String getCenteredText(String text){
if(!text.toLowerCase(Locale.ROOT).startsWith("<center>"))
return text;
if(getDefault() == null)
return text;
text = text.substring("<center>".length());
TextFlattenerListener listener = new TextFlattenerListener(this);
COMPONENT_FLATTENER.flatten(ComponentParser.text(text).toComponent(), listener);
double width = listener.getWidth();
if(width >= MAX_WIDTH)
return text;
return createSpaces(width) + text;
}
private double getCharWidth(int codePoint, boolean isBold, String fontName){
FontInfo font = charWidths.getOrDefault(fontName, getDefault());
if(font == null)
return -1.0;
int index = Arrays.binarySearch(font.codePoints, codePoint);
if(index < 0){
return isBold ? 7.0 : 6.0;
}else{
return isBold ? font.advanceBf[index] : font.advance[index];
}
}
private FontInfo getDefault(){
return charWidths.get("minecraft:default");
}
private String createSpaces(double length){
double remainder = MAX_WIDTH - length;
int padding = (int)Math.max(0, Math.floor(remainder / 2.0) - 1);
return " ".repeat(Math.floorDiv(padding, SPACE_WIDTH));
}
private Map<String, FontInfo> loadFontWidths(AdvancedServerList<?> plugin){
try(InputStream stream = plugin.getClass().getResourceAsStream("/char-widths.json.gz")){
if(stream == null){
plugin.getPlugin().getPluginLogger().warn("Internal char-widths.json.gz couldn't be retrieved.");
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
return new HashMap<>();
}
GZIPInputStream gzipStream = new GZIPInputStream(stream);
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipStream));
return new Gson().fromJson(reader, new TypeToken<Map<String, FontInfo>>(){}.getType());
}catch(IOException ex){
plugin.getPlugin().getPluginLogger().warn("Encountered IOException while loading font widths.");
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
plugin.getPlugin().getPluginLogger().warn("Cause: <white>%s</white>", ex.getMessage());
return new HashMap<>();
}
}
private static class TextFlattenerListener implements FlattenerListener{
private double width = 0.0;
private boolean isBold = false;
private String font = "minecraft:default";
private final TextCenterUtil instance;
public TextFlattenerListener(TextCenterUtil instance){
this.instance = instance;
}
@Override
public void pushStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = true;
if(style.font() != null)
font = style.font().asString();
}
@Override
public void component(@NotNull String text){
for(int i = 0; i < text.length(); i++){
width += instance.getCharWidth(text.codePointAt(i), isBold, font);
}
}
@Override
public void popStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = false;
}
public double getWidth(){
return width;
}
}
private record FontInfo(int[] codePoints, float[] advance, float[] advanceBf){}
}
@@ -28,10 +28,9 @@ 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.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -42,33 +41,27 @@ import java.util.Random;
public record ServerListProfile(int priority, String condition, ProfileEntry defaultProfile, List<ProfileEntry> profiles, String file){
private static final Random random = new Random();
public boolean evalConditions(ProfileConditionParser parser, PluginLogger logger, GenericPlayer player, GenericServer server){
public boolean evalConditions(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
if(condition == null || condition.isEmpty())
return true;
ParseWarnCollector collector = new ParseWarnCollector(condition);
ExpressionTemplate template = parser.compile(condition, player, server, collector);
PluginLogger logger = core.getPlugin().getPluginLogger();
boolean result = core.getParser().evaluate(condition, player, server, collector);
if(collector.hasWarnings()){
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
logger.warn("Encountered <white>%d</white> Error(s) while parsing condition for file '<white>%s</white>':", collector.getWarnings().size(), file);
for(ParseWarnCollector.Context context : collector.getWarnings()){
if(context.position() <= -1){
logger.warn(" - %s", condition);
logger.warn(" -> %s", context.message());
}else{
logger.warn(" - At position %d:", context.position());
logger.warn(" %s", condition);
logger.warn(" ".repeat(context.position() + 5) + "^");
logger.warn(" -> %s", context.message());
}
logger.warn(" - At position <white>%s</white>:", context.position() == -1 ? "<italic>Unknown</italic>" : context.position());
logger.warn(" <white>%s</white>", condition);
logger.warn(" ".repeat(context.position() + 3) + "<red>^</red>");
logger.warn(" <grey>-></grey> %s", context.message());
}
}
if(template == null)
return false;
return template.returnBooleanExpression().evaluate();
return result;
}
public ProfileEntry getRandomProfile(){
@@ -135,6 +128,9 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
}
private Builder resolveCondition(){
if(node == null)
throw new IllegalStateException("ConfigurationNode was null!");
String condition = node.node("condition").getString();
if(condition == null || condition.isEmpty())
return this;
@@ -144,20 +140,26 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
}
private Builder resolveProfiles(){
if(node == null)
throw new IllegalStateException("ConfigurationNode was null!");
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);
logger.warn("Encountered a SerializationException while resolving the profiles entry for <white>%s</white>", ex, fileName);
}
return this;
}
private Builder resolveDefaultProfile(){
if(node == null)
throw new IllegalStateException("ConfigurationNode was null!");
try{
this.defaultProfile = node.get(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the global profile for %s", ex, fileName);
logger.warn("Encountered a SerializationException while resolving the global profile for <white>%s</white>", ex, fileName);
}
return this;
}
@@ -60,8 +60,12 @@ public class ProfileConditionParser implements ExpressionParserEngine{
.build();
}
public ExpressionTemplate compile(String text, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
return parser.parse(tokenizer.parse(text, player, server, collector), collector);
public boolean evaluate(String text, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
ExpressionTemplate result = parser.parse(tokenizer.parse(text, player, server, collector), collector);
if(result == null)
return false;
return result.returnBooleanExpression().evaluate();
}
@Override
@@ -76,7 +76,14 @@ public class CustomExpressionTokenizer{
}
}
collector.appendWarningFormatted(position.getIndex(), "Illegal Token '%c'.", text.charAt(position.getIndex()));
if(position.getIndex() >= text.length()){
collector.appendWarningFormatted(
"Current index position (%d) is larger or equal to Text length (%d) for condition '%s'",
position.getIndex(), text.length(), text
);
}else{
collector.appendWarningFormatted(position.getIndex(), "Illegal Token '%c'.", text.charAt(position.getIndex()));
}
break;
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.favicon;
package ch.andre601.advancedserverlist.core.profiles.handlers;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
@@ -42,9 +42,8 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.List;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Stream;
@@ -57,6 +56,7 @@ public class FaviconHandler<F>{
private final Map<String, F> localFavicons = new HashMap<>();
private final HttpClient client = HttpClient.newHttpClient();
private final Random random = new Random();
public FaviconHandler(AdvancedServerList<F> core){
this.core = core;
@@ -70,14 +70,28 @@ public class FaviconHandler<F>{
}
public F getFavicon(String input){
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT).split("\\.")[0])){
return localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]);
if(localFavicons.size() > 0){
logger.debug(FaviconHandler.class, "Current Local Favicons:");
for(String key : localFavicons.keySet()){
logger.debug(FaviconHandler.class, " - %s", key);
}
}
if(input.equalsIgnoreCase("random")){
logger.debug(FaviconHandler.class, "Input matches 'random'. Returning random Favicon...");
return getRandomized();
}
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT))){
logger.debug(FaviconHandler.class, "Input matches local favicon Image. Returning it...");
return localFavicons.get(input.toLowerCase(Locale.ROOT));
}
try{
logger.debug(FaviconHandler.class, "Getting Favicon image from cache...");
return faviconCache.get(input, () -> getFuture(input)).getNow(null);
}catch(ExecutionException ex){
logger.warn("Received ExecutionException while retrieving Favicon for '%s'.", ex, input);
logger.warn("Received ExecutionException while retrieving Favicon for '<white>%s</white>'.", ex, input);
return null;
}
}
@@ -92,27 +106,46 @@ public class FaviconHandler<F>{
logger.debug(FaviconHandler.class, "Resolving URL '%s'...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, input), this.faviconThreadPool);
}else
if(input.equalsIgnoreCase("random")){
return CompletableFuture.completedFuture(getRandomized());
}else
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
logger.debug(FaviconHandler.class, "Resolving image file '%s'...", input);
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]));
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT)));
}else{
logger.debug(FaviconHandler.class, "Resolving Name/UUID as https://mc-heads.net/avatar/%s/64...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, "https://mc-heads.net/avatar/" + input + "/64"), this.faviconThreadPool);
}
}
private F getRandomized(){
logger.debug(FaviconHandler.class, "Obtaining random Favicon...");
if(localFavicons.isEmpty())
return null;
List<F> faviconList = List.copyOf(localFavicons.values());
// Don't use Random for just one entry.
if(faviconList.size() == 1)
return faviconList.get(0);
synchronized(random){
return faviconList.get(random.nextInt(faviconList.size()));
}
}
private void loadLocalFavicons(){
this.localFavicons.clear();
logger.info("Loading local image files as Favicons...");
logger.info("[-] Loading local image files as Favicons...");
Path folder = core.getPlugin().getFolderPath().resolve("favicons");
if(!Files.exists(folder)){
try{
Files.createDirectories(folder);
logger.info("Created favicons folder.");
logger.debugSuccess(FaviconHandler.class, "Created favicons folder.");
}catch(IOException ex){
logger.warn("Cannot create favicons folder. Encountered an IOException.", ex);
logger.failure("Cannot create favicons folder. Encountered an IOException.", ex);
return;
}
}
@@ -121,8 +154,10 @@ public class FaviconHandler<F>{
pathStream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
logger.success("Loaded <white>%d</white> local Favicons.", localFavicons.size());
}catch(IOException ex){
logger.warn("Cannot load files from Favicons folder.", ex);
logger.failure("Cannot load files from favicons folder.", ex);
}
}
@@ -130,14 +165,14 @@ public class FaviconHandler<F>{
try(InputStream stream = Files.newInputStream(path)){
F favicon = createFavicon(stream);
if(favicon == null){
logger.warn("Cannot create Favicon from file '%s'. Received Favicon was null.", path.getFileName().toString());
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Received Favicon was null.", path.getFileName().toString());
return;
}
localFavicons.put(path.getFileName().toString().split("\\.")[0], favicon);
logger.info("Loaded file '%s' as Favicon.", path.getFileName().toString());
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), favicon);
logger.debugSuccess(FaviconHandler.class, "Loaded file '<white>%s</white>' as Favicon.", path.getFileName().toString());
}catch(IOException ex){
logger.warn("Cannot create Favicon from file '%s'. Encountered IOException.", ex);
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Encountered IOException.", ex);
}
}
@@ -152,11 +187,11 @@ public class FaviconHandler<F>{
try(InputStream stream = client.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()){
return createFavicon(stream);
}catch(InterruptedException | IOException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an Exception.", ex, url);
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered an Exception.", ex, url);
return null;
}
}catch(URISyntaxException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an IOException.", ex, url);
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered a URISyntaxException.", ex, url);
return null;
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.players;
package ch.andre601.advancedserverlist.core.profiles.handlers;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
@@ -66,7 +66,7 @@ public class PlayerHandler{
}
public void load(){
if(!cache.toFile().exists()){
if(!Files.exists(cache)){
logger.info("No playercache.json file present. Skipping...");
return;
}
@@ -79,43 +79,41 @@ public class PlayerHandler{
try(BufferedReader reader = Files.newBufferedReader(cache)){
cachedPlayers = gson.fromJson(reader, listType);
}catch(IOException ex){
logger.warn("Encountered IOException while reading the playercache.json file!", ex);
logger.warn("Encountered IOException while reading the <white>playercache.json</white> file!", ex);
return;
}catch(JsonIOException | JsonSyntaxException ex){
logger.warn("Encountered Json exception while parsing playercache.json file!", ex);
logger.warn("Encountered JsonSyntaxException while parsing <white>playercache.json</white> file!", ex);
return;
}
// In case Gson messes up... I guess.
if(cachedPlayers == null){
logger.warn("Couldn't load players from playercache.json file. Is the JSON valid?");
logger.warn("Couldn't load players from <white>playercache.json</white> file. Is the JSON valid?");
// Create new ArrayList instance to avoid further issues.
cachedPlayers = new ArrayList<>();
return;
}
logger.info("Loaded %d players into cache!", cachedPlayers.size());
logger.success("Loaded <white>%d</white> players into cache!", cachedPlayers.size());
}
public void save(){
if(cachedPlayers.isEmpty()){
logger.info("No players in cache to save. Skipping...");
logger.debug(PlayerHandler.class, "No players in cache to save. Skipping...");
return;
}
if(core.getFileHandler().getBoolean("disableCache")){
logger.info("'disable_cache' is set to true. Skipping saving of cached players...");
logger.debug(PlayerHandler.class, "[-] 'disable_cache' is set to true. Not saving cached players.");
return;
}
try(BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8)){
gson.toJson(cachedPlayers, listType, writer);
logger.info("Successfully saved playercache.json file.");
logger.success("Successfully saved <white>playercache.json</white> file.");
}catch(IOException ex){
logger.warn("Encountered IOException while saving cached players to playercache.json!", ex);
logger.failure("Encountered IOException while saving cached players to <white>playercache.json</white>!", ex);
}
}
public void addPlayer(String ip, String name, UUID uuid){
@@ -36,6 +36,7 @@ import org.spongepowered.configurate.serialize.SerializationException;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
public class ProfileManager{
@@ -44,22 +45,36 @@ public class ProfileManager{
* 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.defaultProfile();
ProfileEntry entry = profile.getRandomProfile();
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);
boolean isMaxPlayersEnabled = resolveMaxPlayersEnabled(entry, defEntry);
Integer extraPlayersCount = resolveExtraPlayersCount(entry, defEntry);
Integer maxPlayersCount = resolveMaxPlayersCount(entry, defEntry);
List<String> motd = resolve(defEntry, entry, ProfileEntry::motd);
List<String> players = resolve(defEntry, entry, ProfileEntry::players);
String playerCountText = resolve(defEntry, entry, ProfileEntry::playerCountText);
String favicon = resolve(defEntry, entry, ProfileEntry::favicon);
NullBool hidePlayersEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersEnabled);
NullBool extraPlayersEnabled = resolve(defEntry, entry, ProfileEntry::extraPlayersEnabled);
NullBool maxPlayersEnabled = resolve(defEntry, entry, ProfileEntry::maxPlayersEnabled);
NullBool onlinePlayersEnabled = resolve(defEntry, entry, ProfileEntry::onlinePlayersEnabled);
NullBool hidePlayersHoverEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersHoverEnabled);
String extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
String maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
String onlinePlayersCount = resolve(defEntry, entry, ProfileEntry::onlinePlayersCount);
return new ProfileEntry(motd, players, playerCountText, favicon,
NullBool.resolve(isHidePlayersEnabled), NullBool.resolve(isExtraPlayersEnabled), NullBool.resolve(isMaxPlayersEnabled),
extraPlayersCount, maxPlayersCount);
return new ProfileEntry.Builder()
.motd(motd)
.players(players)
.playerCountText(playerCountText)
.favicon(favicon)
.hidePlayersEnabled(hidePlayersEnabled)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.onlinePlayersEnabled(onlinePlayersEnabled)
.hidePlayersHoverEnabled(hidePlayersHoverEnabled)
.extraPlayersCount(extraPlayersCount)
.maxPlayersCount(maxPlayersCount)
.onlinePlayersCount(onlinePlayersCount)
.build();
}
public static ServerListProfile resolveProfile(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
@@ -67,7 +82,7 @@ public class ProfileManager{
if(profile.isInvalidProfile())
continue;
if(profile.evalConditions(core.getParser(), core.getPlugin().getPluginLogger(), player, server))
if(profile.evalConditions(core, player, server))
return profile;
}
@@ -82,8 +97,11 @@ public class ProfileManager{
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
NullBool maxPlayersEnabled = resolveNullBool(node, "playerCount", "maxPlayers", "enabled");
Integer extraPlayers = resolveNullableInt(node, "playerCount", "extraPlayers", "amount");
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
NullBool onlinePlayersEnabled = resolveNullBool(node, "playerCount", "onlinePlayers", "enabled");
NullBool hidePlayersHoverEnabled = resolveNullBool(node, "playerCount", "hidePlayersHover");
String extraPlayers = resolveNullableString(node, "playerCount", "extraPlayers", "amount");
String maxPlayers = resolveNullableString(node, "playerCount", "maxPlayers", "amount");
String onlinePlayers = resolveNullableString(node, "playerCount", "onlinePlayers", "amount");
return new ProfileEntry.Builder()
.motd(motd)
@@ -93,8 +111,11 @@ public class ProfileManager{
.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.onlinePlayersEnabled(onlinePlayersEnabled)
.hidePlayersHoverEnabled(hidePlayersHoverEnabled)
.extraPlayersCount(extraPlayers)
.maxPlayersCount(maxPlayers)
.onlinePlayersCount(onlinePlayers)
.build();
}
@@ -115,67 +136,11 @@ public class ProfileManager{
return false;
}
private static List<String> resolveMOTD(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.motd()))
return defaultProfile.motd();
private static <T> T resolve(ProfileEntry defProfile, ProfileEntry profile, Function<ProfileEntry, T> function){
if(profile == null || !checkOption(function.apply(profile)))
return function.apply(defProfile);
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 boolean resolveMaxPlayersEnabled(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || !checkOption(profile.maxPlayersEnabled()))
return defaultProfile.maxPlayersEnabled().getOrDefault(false);
return profile.maxPlayersEnabled().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 Integer resolveMaxPlayersCount(ProfileEntry profile, ProfileEntry defaultProfile){
if(profile == null || profile.maxPlayersCount() == null)
return defaultProfile.maxPlayersCount() == null ? 0 : defaultProfile.maxPlayersCount();
return profile.maxPlayersCount();
return function.apply(profile);
}
private static List<String> resolveList(ConfigurationNode node, Object... path){
@@ -193,10 +158,10 @@ public class ProfileManager{
return NullBool.resolve(node.node(path).getBoolean());
}
private static Integer resolveNullableInt(ConfigurationNode node, Object... path){
private static String resolveNullableString(ConfigurationNode node, Object... path){
if(node.node(path).virtual())
return null;
return node.node(path).getInt();
return node.node(path).getString();
}
}
@@ -53,9 +53,12 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
node.node("playerCount", "text").set(profile.playerCountText());
node.node("favicon").set(profile.favicon());
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled().getOrDefault(false));
node.node("playerCount", "hidePlayersHover").set(profile.hidePlayersHoverEnabled().getOrDefault(false));
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled().getOrDefault(false));
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? 0 : profile.extraPlayersCount());
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? "0" : profile.extraPlayersCount());
node.node("playerCount", "maxPlayers", "enabled").set(profile.maxPlayersEnabled().getOrDefault(false));
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? 0 : profile.maxPlayersCount());
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? "0" : profile.maxPlayersCount());
node.node("playerCount", "onlinePlayers", "enabled").set(profile.onlinePlayersEnabled().getOrDefault(false));
node.node("playerCount", "onlinePlayers", "amount").set(profile.onlinePlayersCount() == null ? "0" : profile.onlinePlayersCount());
}
}
@@ -64,8 +64,6 @@ public class StringReplacer{
private static String parsePlaceholder0(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
AdvancedServerListAPI api = AdvancedServerList.getApi();
int placeholderStart = position.getIndex() - 2;
int index = position.getIndex();
StringBuilder identifier = new StringBuilder();
@@ -74,6 +72,9 @@ public class StringReplacer{
boolean identified = false;
boolean invalid = true;
int placeholderStart = position.getIndex() - 1;
int valueStart = position.getIndex() - 1;
char[] chars = input.substring(index).toCharArray();
for(final char c : chars){
index++;
@@ -85,6 +86,7 @@ public class StringReplacer{
if(c == ' ' && !identified){
identified = true;
valueStart = index + 1;
continue;
}
@@ -100,10 +102,6 @@ public class StringReplacer{
StringBuilder raw = new StringBuilder();
// Condition parsing needs one extra increase of index... for some reason
if(collector != null)
index++;
position.setIndex(index);
if(invalid){
@@ -113,7 +111,7 @@ public class StringReplacer{
raw.append(' ').append(valuesStr);
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
collector.appendWarningFormatted(index, "Placeholder '<white>%s</white>' does not have a closing bracket (})", raw.toString());
return raw.toString();
}
@@ -128,7 +126,7 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
collector.appendWarningFormatted(placeholderStart, "Placeholder '<white>%s</white>' does not have any available PlaceholderProvider", raw.toString());
return raw.toString();
}
@@ -143,7 +141,7 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
collector.appendWarningFormatted(valueStart, "Placeholder '<white>%s</white>' has an invalid value String '<white>%s</white>'", raw.toString(), valuesStr);
return raw.toString();
}
Binary file not shown.
+68 -26
View File
@@ -3,88 +3,130 @@
#
unknownPlayer:
#
# The name to use. Defaults to Anonymous.
# The name to use.
#
# Default: Anonymous
#
name: "Anonymous"
#
# The UUID to use. Defaults to 606e2ff0-ed77-4842-9d6c-e1d3321c7838 (UUID of MHF_Question).
# The UUID to use.
#
# Default: 606e2ff0-ed77-4842-9d6c-e1d3321c7838 (UUID of MHF_Question).
#
uuid: "606e2ff0-ed77-4842-9d6c-e1d3321c7838"
#
# Should the Caching of players be disabled?
#
# When set to true will AdvancedServerList not load any players from the cache.data file (if present) nor save any to it.
# Placeholders that rely on the player being cached (such as ${player name}) will not work while this option is enabled.
# When set to true will no player joining the server be cached and saved to the playercache.json file.
# This will also cause placeholders using a cached player such as ${player name} to no longer work.
#
# Defaults to false when not present.
# Default: false
#
disableCache: false
#
# Should AdvancedServerList check for new versions?
#
# When set to true will AdvancedServerList check for a new version on modrinth.com every 12 hours and inform you in the
# console about whether it found any new update or not.
# When set to true will AdvancedServerList look for a new update on startup and repeat that check
# every 12 hours after that.
# It uses Modrinth to check for updates.
#
# Defaults to false when not present.
# Default: true
#
checkUpdates: true
#
# Should debug mode be enabled?
#
# When set to true will AdvancedServerList print additional messages to the console prefixed with "[DEBUG]".
# It is recommended to only enable this when having problems or when being told to by the plugin dev, as it could
# otherwise cause significant spam in your console.
# Additional messages prefixed with [DEBUG] will be printed in the console when this option is set
# to true.
# Enabling this option is only recommended for when you have problems, or have been told to enable
# it by the plugin developer, as it can otherwise spam your console.
#
# Defaults to false when not present.
# Default: false
#
debug: false
#
# Sets the time in minutes for favicons to be cached.
# The number cannot be less than 1.
# Should the "ASL" ASCI art be displayed on plugin startup?
# Setting this to false will hide the banner.
#
# Defaults to 1 if not set.
# Default: true
#
printBanner: true
#
# Sets how long Favicons should be cached. Value is in minutes with the lowest possible value being 1.
#
# This option only affects dynamic favicons created from a placeholder or URL. Local favicons will
# not be affected.
#
# Default: 1
#
faviconCacheTime: 1
#
# List of options that should be disabled while the Maintenance Mode of the plugin Maintenance is active.
# Any option not listed here will NOT be disabled, meaning AdvancedServerList will continue to handle it.
# Options to disable while the Maintenance Plugin is present and Maintenance Mode is active.
#
# Each option defaults to true when not present, disabling said option while Maintenance is active.
# Should an option be removed from this section will AdvancedServerList continue to set it, as if
# the Maintenance plugin isn't active.
#
disableDuringMaintenance:
#
# When true (Default), disables handling of MOTD while Maintenance is enabled.
# Whether MOTD changing should be disabled while Maintenance mode is active.
#
# Default: true
#
motd: true
#
# When true (Default), disables handling of Favicon while Maintenance is enabled.
# Whether favicon changing should be disabled while Maintenance mode is active.
#
# Default: true
#
favicon: true
#
# When true (Default), disables hiding of player count while Maintenance is enabled.
# Whether player hiding should be disabled while Maintenance mode is active.
#
# Default: true
#
hidePlayers: true
#
# When true (Default), disables handling of player count text while Maintenance is enabled.
# Whether hiding player list on hover should be disabled while Maintenance mode is active.
#
# Default: true
#
hidePlayersHover: true
#
# Whether player count text changing should be disabled while Maintenance mode is active.
#
# Default: true
#
playerCountText: true
#
# When true (Default), disables handling of player count hover while Maintenance is enabled.
# Whether player count hover changing should be disabled while Maintenance mode is active.
#
# Default: true
#
playerCountHover: true
#
# When true (Default), disables use of extra players feature while Maintenance is enabled.
# Whether the extra players feature should be disabled while Maintenance mode is active.
#
# Default: true
#
extraPlayers: true
#
# When true (Default), disables use of max players feature while Maintenance is enabled.
# Whether the max players feature should be disabled while Maintenance mode is active.
#
# Default: true
#
maxPlayers: true
#
# Whether the online players feature should be disabled while Maintenance mode is active.
#
# Default: true
#
onlinePlayers: true
#
# DO NOT EDIT!
@@ -92,4 +134,4 @@ disableDuringMaintenance:
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
config-version: ${plugin.config.version}
configVersion: ${plugin.config.version}
+119 -86
View File
@@ -1,177 +1,210 @@
#
# Set the priority of this profile.
# Higher number = Higher priority.
# If there are multiple profiles (files) will they be sorted by priority, starting with highest.
#
# Read more: https://asl.andre601.ch/profiles/#priority
#
priority: 0
#
# Set conditions that need to me met to show this profile.
# You can use keywords 'and' or 'or' (Or alternatively '&&' or `||`) to make more complex condition sets.
# Set condition(s) that should return true to display this profile.
# This allows you to create profiles to only show for specific scenarios (i.e. player is banned).
#
# Multiple conditions can be chaing with the keywords 'and', 'or', or their counterparts '&&' and '||'.
#
# No condition or an empty condition will be treated as true by default.
#
# Read more: https://asl.andre601.ch/profiles/#condition
#
# condition: '${player protocol} < 759'
#
condition: ''
#
# Set conditions that needs to be met.
# Only when all conditions return true will the profile be shown (Given no profile with higher priority is used).
# Set one or multiple profiles.
#
# Read more: https://asl.andre601.ch/profiles/#conditions
# A profile can contain the same options as used in the file itself, except for priority and condition.
# If multiple entries are present, a random one will be selected. Any options set in the selected profile will override
# any existing option in the file.
#
#conditions:
# - '{playerVersion} < 759'
# Example: The below profile configuration will randomly change the MOTD between two types, but keep the Hover text
# the same.
#
# 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.
# When not present or empty (profiles: []), no profiles will be used and global options from the file will be used instead.
#
# Read more: https://asl.andre601.ch/profiles/#profiles
#
#profiles:
# - motd:
# - '<aqua>Line 1'
# - '<aqua>Line 2'
# favicon: ''
# playerCount:
# hidePlayers: false
# hover:
# - '<green>Line 1'
# - '<green>Line 2'
# - '<green>Line 3'
# text: ''
# extraPlayers:
# enabled: false
# amount: 0
profiles:
- motd: ['<aqua>Line A', '<gold>Line B']
- motd:
- '<aqua>Line 1'
- '<gold>Line 2'
#
# 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.
# Set the "Message of the day" to display.
# This option supports RGB colors for 1.16+ Servers and clients, including gradients using MiniMessage's <gradient>
# option.
#
# Only the first two lines will be considered and any additional one is ignored.
#
# When not present or empty (motd: []), no MOTD will be set.
#
# Read more: https://asl.andre601.ch/profiles/#motd
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>First Line'
- '<grey>Second Line'
#
# 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
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
#
# Remove this option or set to favicon: '' to not replace the Favicon.
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
# 2. "random" to display a random PNG from the favicons folder.
# 3. URL pointing to an image.
# 4. Player name, UUID or placeholders returning one of these.
# https://mc-heads.net will be used to retrieve an image of the provided name/UUID.
#
# Note on favicons not showing:
# AdvancedServerList has to create a Favicon object for the Proxy/Server to use which takes time to do so.
# To not delay the Proxy/Server from being displayed (increase the loading time on the player end) is this creation
# done asynchronously for URL/Player name/UUID. This has the downside that the Proxy/Server may be done handling the
# ping before the Favicon is created, causing none to be displayed.
# Note that this won't happen with local favicons, as those are created during the plugin's startup.
#
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
#
# If not present or empty (favicon: ''), defaults to not modifying the favicon.
#
# Read more: https://asl.andre601.ch/profiles/#favicon
#
favicon: ''
#
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
# Contains options for modifying the player count (Text displaying <online>/<max>).
#
# Read more: https://asl.andre601.ch/profiles/#playercount
#
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
# Set whether the Player count should be hidden.
# When set to true, the player count will be displayed as '???' instead of the usual '<online>/<max>' and all other
# playerCount options, except for extraPlayers and maxPlayers, will be ignored.
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
# Set whether the List of players is shown when hovering over the player count.
# Setting this to true will also make the plugin ignore the hover option below.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayershover
#
hidePlayersHover: false
#
# Set the lines shown when the player hovers over the player count.
# Unlike the MOTD option does this one only support basic color and formatting codes. Any RGB colors will be
# downsampled to the nearest matching color.
#
# If not present or empty (hover: []), defaults to not modifying the hover.
#
# Read more: https://asl.andre601.ch/profiles/#hover
#
hover:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
- '<aqua>Line 1'
- '<yellow>Line 2'
- '<green>Line 3'
#
# Modifies the text that usually displays '<online>/<max>'
#
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
# This is nothing that can be fixed or avoided and would require changes from Mojang.
# Set the text that should be displayed instead of the default '<online>/<max>' text.
#
# Remove this option or set it to text: '' to not modify the player count text.
# Using this option will show the server as "outdated" to the client (Have the ping icon crossed out).
# This cannot be fixed and would require Mojang to change stuff.
#
# If not present or empty (text: ''), defaults to not modifying the text.
#
# Read more: https://asl.andre601.ch/profiles/#text
#
text: ''
#
# Allows you to modify the max player count displayed.
# Note that this will affect ${server playersMax} (Except for when used in conditions).
# The extraPlayers feature allows to set a number that should be added to the current online players and then be
# used as the "max" player count.
#
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers
#
extraPlayers:
#
# Enables/Disables the extraPlayers option.
# When enabled will the total amount of players allowed to join be modified to the current
# number of online players + 'amount'
# Set whether the extraPlayers feature should be enabled or not.
# When set to true, the max players count will be modified to be the number of online players with the 'amount'
# value added to it.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
#
enabled: false
#
# Sets how much should be added/subtracted from the current number of online players
# to then use for the max player count.
# Set the number that should be added to the online player count to then use as the new max player count.
# Placeholders resolving to numbers can be used here.
#
# Example:
# When set to 1 while 10 players are online would the player count - if unmodified -
# display '10/11'. When -1 is used will it display '10/9'
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
# 9 when 8 are online and so on.
#
# Defaults to 0 when not present.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
#
amount: 0
#
# Allows you to set the max players that could join your server.
# Note that this option influences the '${server playersMax}' placeholder.
# The maxPlayers feature allows to set a number to use as the max player count to display.
#
# The settings of this option have no effect should 'extraPlayers' be enabled
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers
#
maxPlayers:
#
# Enables/Disables the maxPlayers option.
# When enabled will the total amount of players allowed to join be changed to what 'amount' is set to.
# Set whether the maxPlayers feature should be enabled or not.
# When set to true, the max player count will be set to the 'amount' value.
#
# If not present, defaults to false.
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
#
enabled: false
#
# Sets the number to display for the max number of players allowed to join your server.
# Set the number that should be used as the new max players count.
# Placeholders resolving to numbers can be used here.
#
# Example:
# Setting this option to 0 (Default) while 1 player is online would display '1/0'
#
# Defaults to 0 if not set.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
#
amount: 0
#
# The onlinePlayers feature allows to set a number to use as the online player count to display.
#
# Read more: https://asl.andre601.ch/profiles/#onlineplayers
#
onlinePlayers:
#
# Set whether the onlinePlayers feature should be enabled or not.
# When set to true, the max player count will be set to the 'amount' value.
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-enabled
#
enabled: false
#
# Set the number that should be used as the new online players count.
# Placeholders resolving to numbers can be used here.
#
# If not present, defaults to current online player count.
#
# Read more: https://asl.andre601.ch/profiles/#onlineplayers-amount
#
amount: 0
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
@@ -23,11 +23,10 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import org.junit.jupiter.api.Test;
import java.util.Map;
@@ -46,15 +45,9 @@ public class ExpressionParserTests{
logger.info("TEST[expression=\"%s\", expected=%b]", values.getKey(), values.getValue());
ParseWarnCollector collector = new ParseWarnCollector(values.getKey());
ExpressionTemplate template = parser.compile(values.getKey(), null, null, collector);
boolean result;
if(template == null){
result = false;
}else{
result = template.returnBooleanExpression().evaluate();
}
boolean result = parser.evaluate(values.getKey(), null, null, collector);
logger.info("Result (output, isExpected): " + result + ", " + (result == values.getValue()));
logger.info("Result (Output, Expected?): %b, %b", result, (result == values.getValue()));
assertEquals(result, values.getValue());
}
}
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import com.unascribed.flexver.FlexVerComparator;
import org.junit.jupiter.api.Test;
+1 -1
View File
@@ -17,7 +17,7 @@
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
def on_page_markdown(
+7
View File
@@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block announce %}
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
Celebrating <a href="https://andre601.ch/blog/2024/12-13-history-of-asl/" target="_blank" rel="nofollow"><b>25,000 downloads!</b></a> Thank you!
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
{% endblock %}
-10
View File
@@ -6,16 +6,6 @@
<!-- Actions -->
{% include "partials/actions.html" %}
{% if config.extra.github_repository %}
<div class="admonition info">
<p class="admonition-title">Moved</p>
<p>
The documenation has been moved and can now be found at <a href="https://asl.andre601.ch" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch</strong></a>.<br>
This page in particular can be found at <a href="https://asl.andre601.ch/{{ page.url }}" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch/{{ page.url }}</strong></a>.
</p>
</div>
{% endif %}
<!--
Hack: check whether the content contains a h1 headline. If it doesn't, the
page title (or respectively site name) is used as the main headline.
+10
View File
@@ -0,0 +1,10 @@
[discord]: https://discord.gg/MyPTjpsgGH
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[hangar]: https://hangar.papermc.io/Andre_601/AdvancedServerList
[codeberg]: https://codeberg.org/Andre601/AdvancedServerList
+109 -43
View File
@@ -1,58 +1,44 @@
---
icon: octicons/stop-24
---
# BanPlugins Addon
The BanPlugins Addon was made to provide placeholders for different punishment plugins to use in AdvancedServerList.
/// info
The BanPlugins Addon is available in downloads of AdvancedServerList on [:simple-modrinth: Modrinth](https://modrinth.com/plugin/advancedserverlist) and in [Releases on :simple-codeberg: Codeberg](https://codeberg.org/Andre601/AdvancedServerList/releases).
///
## Placeholders
### AdvancedBan
/// tab | AdvancedBan
[Plugin Page](https://www.spigotmc.org/resources/8695/){ target="_blank" rel="nofollow" }
Placeholders for the plugin [AdvancedBan](https://www.spigotmc.org/resources/8695/){ target="_blank" rel="nofollow" } are available to use.
**Supported Platforms:**
| Placeholder | Description |
|---------------------------------|-------------------------------------------------------------------------------------------|
| `${advancedban isMuted}` | Whether the player is muted or not. |
| `${advancedban muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${advancedban muteDuration}` | Relative time until the mute expires.[^1] Returns invalid placeholder if no mute was set. |
| `${advancedban muteExpiration}` | Date on when the mute will expire.[^2] |
| `${advancedban isBanned}` | Whether the player is banned or not. |
| `${advancedban banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${advancedban banDuration}` | Relative time until the ban expires.[^3] Returns invalid placeholder if no ban was set. |
| `${advancedban banExpiration}` | Date on when the ban will expire.[^4] |
[^1]:
An optional boolean can be added to set whether the duration should be from the start or not. `false` is the default.
Example: `${advancedban muteDuration true}`
[^2]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${advancedban muteExpiration yyyy-MM-dd HH:mm:ss}`
[^3]:
An optional boolean can be added to set whether the duration should be from the start or not. `false` is the default.
Example: `${advancedban banDuration true}`
[^4]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${advancedban banExpiration yyyy-MM-dd HH:mm:ss}`
### LibertyBans
Placeholders for the plugin [LibertyBans](https://modrinth.com/plugin/libertybans/){ target="_blank" rel="nofollow" } are available to use.
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
| Placeholder | Description |
|---------------------------------|------------------------------------------------------------------------------------------|
| `${libertybans isMuted}` | Whether the player is muted or not. |
| `${libertybans muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${libertybans muteExpiration}` | Date on when the mute will expire.[^5] |
| `${libertybans isBanned}` | Whether the player is banned or not. |
| `${libertybans banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${libertybans banExpiration}` | Date on when the ban will expire.[^6] |
| `${advancedban isMuted}` | Whether the player is muted or not. |
| `${advancedban muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${advancedban muteDuration}` | Relative time until the mute expires. Returns invalid placeholder if no mute was set. |
| `${advancedban muteExpiration}` | Date on when the mute will expire- |
| `${advancedban isBanned}` | Whether the player is banned or not. |
| `${advancedban banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${advancedban banDuration}` | Relative time until the ban expires. Returns invalid placeholder if no ban was set. |
| `${advancedban banExpiration}` | Date on when the ban will expire. |
[^5]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${libertybans muteExpiration yyyy-MM-dd HH:mm:ss}`
[^6]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${libertybans banExpiration yyyy-MM-dd HH:mm:ss}`
//// note | Notes
- `${advancedban muteDuration}` and `${advancedban banDuration}` accept an optional boolean to set, whether the mute/ban duration should be from the start.
Default is `false`.
- `${advancedban muteExpiration}` and `${advancedban banExpiration}` accept an optional Date and Time pattern to format the time into.
Default is `dd, MMM yyyy HH:mm:ss`.
////
## Example
//// details | Example
type: example
```yaml title="banned.yml"
priority: 1
@@ -61,4 +47,84 @@ condition: '${advancedban isBanned}'
motd:
- '<red>You were <bold>BANNED</bold>!'
- '<red>Expires: <grey>${advancedban banExpiration}'
```
```
////
///
/// tab | LibertyBans
[Plugin Page](https://modrinth.com/plugin/libertybans/){ target="_blank" rel="nofollow" }
**Supported Platforms:**
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
| Placeholder | Description |
|---------------------------------|------------------------------------------------------------------------------------------|
| `${libertybans isMuted}` | Whether the player is muted or not. |
| `${libertybans muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${libertybans muteExpiration}` | Date on when the mute will expire. |
| `${libertybans isBanned}` | Whether the player is banned or not. |
| `${libertybans banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${libertybans banExpiration}` | Date on when the ban will expire. |
//// note | Notes
- `${libertybans muteExpiration}` and `${libertybans banExpiration}` accept an optional Date and Time pattern to format the time into.
Default is `dd, MMM yyyy HH:mm:ss`.
////
//// details | Example
type: example
```yaml title="banned.yml"
priority: 1
condition: '${libertybans isBanned}'
motd:
- '<red>You were <bold>BANNED</bold>!'
- '<red>Expires: <grey>${libertybans banExpiration}'
```
////
///
/// tab | LiteBans
[Plugin Page](https://www.spigotmc.org/resources/3715/){ target="_blank" rel="nofollow" }
**Supported Platforms:**
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
| Placeholder | Description |
|------------------------------|------------------------------------------------------------------------------------------|
| `${litebans isMuted}` | Whether the player is muted or not. |
| `${litebans muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${litebans muteDuration}` | Relative time until the mute expires. Returns invalid placeholder if no mute was set. |
| `${litebans muteExpiration}` | Date on when the mute will expire- |
| `${litebans isBanned}` | Whether the player is banned or not. |
| `${litebans banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${litebans banDuration}` | Relative time until the ban expires. Returns invalid placeholder if no ban was set. |
| `${litebans banExpiration}` | Date on when the ban will expire. |
//// note | Notes
- `${litebans muteExpiration}` and `${litebans banExpiration}` accept an optional Date and Time pattern to format the time into.
Default is `dd, MMM yyyy HH:mm:ss`.
////
//// details | Example
type: example
```yaml title="banned.yml"
priority: 1
condition: '${litebans isBanned}'
motd:
- '<red>You were <bold>BANNED</bold>!'
- '<red>Expires: <grey>${litebans banExpiration}'
```
////
///
+39 -8
View File
@@ -7,6 +7,40 @@ icon: octicons/log-24
This page lists the recent changes made towards the AdvancedServerListAPI.
They are ordered newest to oldest.
## v4.1.0 { #v4.1.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v-added }
- New setter method added to [`ProfileEntry.Builder`][profileentry.builder] class:
- [`hidePlayersHoverEnabled(NullBool)`][hidePlayersHoverEnabled]
[hidePlayersHoverEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayershoverenabled(nullbool)
## v4.0.0 { #v4.0.0 }
### :octicons-alert-24:{ .changelog-breaking title="Breaking Changes" } Breaking Changes { #v4.0.0-breaking }
- Changed `extraPlayersCount()` and `maxPlayersCount()` from using an Integer to using a String instead.
- This also affects their corresponding `ProfileEntry.Builder` methods.
- Removed all previously deprecated methods.
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v4.0.0-added }
- New setter methods added to [`ProfileEntry.Builder`][profileentry.builder] class:
- [`onlinePlayersCount(String)`][onlinePlayersCount]
- [`onlinePlayersEnabled(NullBool)`][onlinePlayersEnabled]
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount(string)
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled(nullbool)
## v3.3.0 { #v3.3.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.3.0-added }
- Added `PostServerListSetEvent` to the different platform APIs.
- Fired **after** AdvancedServerList is done with handling the PingEvent.
- Allows to retrieve the [`ProfileEntry`][profileentry] used for the PingEvent.
## v3.2.1 { #v3.2.1 }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.1-changed }
@@ -28,11 +62,11 @@ They are ordered newest to oldest.
- [`playerCountText(String)`][playercounttext]
- [`players(List<String>)`][players]
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount(integer)
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount(string)
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled(nullbool)
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon(string)
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled(nullbool)
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount(integer)
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount(string)
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayersenabled(nullbool)
[motd]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#motd(list<string>)
[playercounttext]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#playercounttext(string)
@@ -94,9 +128,9 @@ They are ordered newest to oldest.
- [`maxPlayersEnabled()`][maxplayersenabled] - Returns the value for `playerCount -> maxPlayers -> enabled` as `NullBool`
- [`maxPlayersCount()`][maxplayerscount] - Returns the value of `playerCount -> maxPlayers -> amount` as nullable `Integer`
- New setters in [`ProfileEntry.Builder`][profileentry.builder]:
- [`setMaxPlayersEnabled(NullBool)`][setmaxplayersenabled] - Sets whether the max players feature is enabled or not.
- [`setMaxPlayersCount(Integer)`][setmaxplayerscount] - Sets the number to use for the max players count.
- [`setExtraPlayersCount(Integer)`][setextraplayersecount] - Replacement for [deprecated `setExtraPlayerCount(Integer)` method](#v3.1.0-deprecated).
- `setMaxPlayersEnabled(NullBool)`- Sets whether the max players feature is enabled or not.
- `setMaxPlayersCount(Integer)` - Sets the number to use for the max players count.
- `setExtraPlayersCount(Integer)` - Replacement for [deprecated `setExtraPlayerCount(Integer)` method](#v3.1.0-deprecated).
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v3.1.0-deprecated }
@@ -107,9 +141,6 @@ They are ordered newest to oldest.
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount()
[profileentry.builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
[setmaxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayersenabled(nullbool)
[setmaxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setmaxplayerscount(integer)
[setextraplayersecount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#setextraplayerscount(integer)
----
Loaded 100 of 158 files, more files were not shown because too many files have changed in this diff. Show more