Compare commits

...
191 Commits
Author SHA1 Message Date
Andre601 0c36667116 Version 5.6.0 2025-06-25 20:44:01 +02:00
Andre601 3417d7c0be Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.2' (#456) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/456
2025-06-25 14:05:24 +02:00
Andre601's Bot 96fa871204 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.2 2025-06-25 12:02:49 +00:00
Andre601 aaacd9944f Merge pull request 'Update maven Docker tag to v3.9.10' (#455) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/455
2025-06-24 14:35:21 +02:00
Andre601's Bot af44324cf1 Update maven Docker tag to v3.9.10 2025-06-24 12:02:49 +00:00
Andre601 77b6897bd4 Add note about favicon resizing 2025-06-23 23:21:02 +02:00
Andre601 9d963199ae Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.4.0' (#454) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/454
2025-06-21 14:03:06 +02:00
Andre601's Bot 580b87ebb5 Update dependency com.viaversion:viaversion-api to v5.4.0 2025-06-21 12:02:16 +00:00
Andre601 efd5762162 Update README 2025-06-19 23:55:08 +02:00
Andre601 62261ae6ed Update config.yml example in getting-started 2025-06-19 21:29:06 +02:00
Andre601 e52bfdf60b Add faviconStrategy config option 2025-06-19 21:18:41 +02:00
Andre601 0152ba3e1a Update default.yml in getting-started.md 2025-06-19 17:04:55 +02:00
Andre601 090787e292 Add german tutorial 2025-06-19 16:40:55 +02:00
Andre601 25d14eeaae Add indonesian tutorial 2025-06-19 16:32:57 +02:00
Andre601 386d490596 Merge pull request 'Update all non-major dependencies to v4.23.0' (#453) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/453
2025-06-18 20:56:11 +02:00
Andre601's Bot 207ce12452 Update all non-major dependencies to v4.23.0 2025-06-18 18:48:21 +00:00
Andre601 b87703c36c Merge pull request 'Update dependency net.md-5:bungeecord-api to v1.21-R0.3' (#452) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/452
2025-06-16 14:05:20 +02:00
Andre601's Bot 41677d0635 Update dependency net.md-5:bungeecord-api to v1.21-R0.3 2025-06-16 12:02:50 +00:00
Andre601 dfdb2aa767 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.1' (#451) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/451
2025-06-07 14:58:29 +02:00
Andre601's Bot d14c5f80e8 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.1 2025-06-07 12:02:12 +00:00
Andre601 bd9e376d08 Merge pull request 'Implement support for merging images' (#450) from feature/favicon-merging into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/450
2025-06-03 14:54:15 +02:00
Andre601 578242078b Move local and random Favicon handling to the start 2025-06-03 14:33:36 +02:00
Andre601 f84842729d Update documentation 2025-06-03 01:04:39 +02:00
Andre601 1daeecbbcf Create proper Favicon merging system 2025-06-03 00:56:37 +02:00
Andre601 5dcab6c37c Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.0' (#449) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/449
2025-05-30 14:02:34 +02:00
Andre601's Bot a146a10d53 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.0 2025-05-30 12:02:12 +00:00
Andre601 75db0d5e96 Add Favicon Merging 2025-05-28 20:17:40 +02:00
Andre601 644dd401d4 Update profiles option page 2025-05-28 19:58:14 +02:00
Andre601 32d85c6be1 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5' (#448) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/448
2025-05-23 14:04:19 +02:00
Andre601's Bot 1b47af6714 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5 2025-05-23 12:03:00 +00:00
Andre601 4544696a54 Merge pull request 'Update dependency mkdocs-material to v9.6.14' (#447) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/447
2025-05-14 12:23:10 +00:00
Andre601's Bot a84848daee Update dependency mkdocs-material to v9.6.14 2025-05-14 12:03:01 +00:00
Andre601 3f8dd90e28 Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.4.0' (#446) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/446
2025-05-11 15:40:33 +00:00
Andre601's Bot f633741988 Update dependency net.kyori:adventure-platform-bungeecord to v4.4.0 2025-05-11 12:02:21 +00:00
Andre601 7e9ea9f470 Merge pull request 'Update dependency mkdocs-material to v9.6.13' (#445) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/445
2025-05-10 12:14:35 +00:00
Andre601's Bot c2c00dc47f Update dependency mkdocs-material to v9.6.13 2025-05-10 12:02:52 +00:00
Andre601 027503efab Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8.1' (#444) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/444
2025-05-06 12:31:54 +00:00
Andre601's Bot 7dd78cbbfc Update dependency net.william278:papiproxybridge to v1.8.1 2025-05-06 12:03:06 +00:00
Andre601 b27b8e78bd Merge pull request 'Update all non-major dependencies to v4.21.0' (#443) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/443
2025-04-30 12:13:12 +00:00
Andre601's Bot ad5b07feda Update all non-major dependencies to v4.21.0 2025-04-30 12:03:04 +00:00
Andre601 d79784d1c0 Merge pull request 'Update all non-major dependencies to v4.1.1' (#442) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/442
2025-04-29 12:06:11 +00:00
Andre601's Bot ef84e85426 Update all non-major dependencies to v4.1.1 2025-04-29 12:02:50 +00:00
Andre601 35782809ac Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.4' (#441) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/441
2025-04-25 12:08:42 +00:00
Andre601's Bot 3e3c4903e4 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.4 2025-04-25 12:02:49 +00:00
Andre601 79b45fb29d Merge pull request 'Update dependency com.google.code.gson:gson to v2.13.1' (#440) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/440
2025-04-24 14:20:27 +00:00
Andre601's Bot 46f40294e2 Update dependency com.google.code.gson:gson to v2.13.1 2025-04-24 14:08:23 +00:00
Andre601 ca5ab5d221 Merge pull request 'Update dependency mkdocs-material to v9.6.12' (#439) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/439
2025-04-17 12:04:54 +00:00
Andre601's Bot b2e5d7ae28 Update dependency mkdocs-material to v9.6.12 2025-04-17 12:02:51 +00:00
Andre601 649e9f07ef Merge pull request 'Update all non-major dependencies' (#438) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/438
2025-04-15 12:04:27 +00:00
Andre601's Bot eaa86aa93b Update all non-major dependencies 2025-04-15 12:02:50 +00:00
Andre601 8a90619810 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.2' (#437) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/437
2025-04-14 12:38:48 +00:00
Andre601's Bot 351db260ce Update dependency com.viaversion:viaversion-api to v5.3.2 2025-04-14 12:21:57 +00:00
Andre601 bcc9d88e8c Update appearance of playercount options in docs 2025-04-12 23:41:08 +00:00
Andre601 9c849157d3 Merge pull request 'Update all non-major dependencies' (#436) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/436
2025-04-12 12:12:05 +00:00
Andre601's Bot f171c951e7 Update all non-major dependencies 2025-04-12 12:02:23 +00:00
Andre601 cae808e3fc Add example for priority 2025-04-10 22:06:15 +02:00
Andre601 ae8e6304f9 Merge pull request 'Update dependency com.google.guava:guava to v33.4.7-jre' (#435) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/435
2025-04-09 12:26:44 +00:00
Andre601's Bot c975ba79b3 Update dependency com.google.guava:guava to v33.4.7-jre 2025-04-09 12:03:17 +00:00
Andre601 83fb13e1f2 Update wiki links 2025-04-07 23:49:05 +00:00
Andre601 586351e277 Update announcement banner 2025-04-08 01:46:40 +02:00
Andre601 098b6be0f4 Refactor profiles page 2025-04-08 01:40:36 +02:00
Andre601 1c881d2832 Update API Docs 2025-04-07 23:40:42 +02:00
Andre601 e6f3d122c7 Merge pull request 'Migrate renovate config' (#434) from renovate/migrate-config into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/434
2025-04-06 01:54:03 +00:00
Andre601's Bot 759474b344 Migrate config renovate.json 2025-04-06 01:52:21 +00:00
Andre601 6aef4c2de9 Enable config migration 2025-04-06 01:51:29 +00:00
Andre601 64d7c81c58 Merge pull request 'Update all non-major dependencies to v4.20.0' (#433) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/433
2025-04-06 01:30:06 +00:00
Andre601's Bot a070708323 Update all non-major dependencies to v4.20.0 2025-04-06 01:29:09 +00:00
Andre601 e9ba86508c Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.0' (#432) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/432
2025-04-05 12:36:42 +00:00
Andre601's Bot c1e3638534 Update dependency space.arim.libertybans:bans-api to v1.1.0 2025-04-05 12:02:18 +00:00
Andre601 f5260f3be1 Merge pull request 'Update dependency mkdocs-material to v9.6.11' (#431) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/431
2025-04-01 12:04:58 +00:00
Andre601's Bot 51372aa8f4 Update dependency mkdocs-material to v9.6.11 2025-04-01 12:02:14 +00:00
Andre601 025c9f4423 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.1' (#430) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/430
2025-03-31 12:25:08 +00:00
Andre601's Bot 99c34dd343 Update dependency com.viaversion:viaversion-api to v5.3.1 2025-03-31 12:02:53 +00:00
Andre601 cd91b799d6 Merge pull request 'Update dependency mkdocs-material to v9.6.10' (#429) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/429
2025-03-30 13:04:23 +00:00
Andre601's Bot 5b7eb014a3 Update dependency mkdocs-material to v9.6.10 2025-03-30 12:03:16 +00:00
Andre601 ad32952b97 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.0' (#428) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/428
2025-03-29 12:03:56 +00:00
Andre601's Bot 4a1e552d5d Update dependency com.viaversion:viaversion-api to v5.3.0 2025-03-29 12:02:13 +00:00
Andre601 ea1394dce9 Merge pull request 'Update all non-major dependencies' (#427) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/427
2025-03-28 12:10:16 +00:00
Andre601's Bot 317fa631e9 Update all non-major dependencies 2025-03-28 12:02:24 +00:00
Andre601 5dd26f6ab8 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.3' (#426) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/426
2025-03-27 12:05:14 +00:00
Andre601's Bot ba82df45ef Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.3 2025-03-27 12:03:35 +00:00
Andre601 d76339188d Merge pull request 'Update all non-major dependencies' (#425) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/425
2025-03-26 12:21:12 +00:00
Andre601's Bot a9fb8f3ed6 Update all non-major dependencies 2025-03-26 12:02:54 +00:00
Andre601 18291a6865 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8' (#424) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/424
2025-03-23 13:12:05 +00:00
Andre601's Bot 83a1808ebc Update dependency net.william278:papiproxybridge to v1.8 2025-03-23 12:02:03 +00:00
Andre601 197967dea9 Use jspecify for (Non)Null annotations 2025-03-20 13:51:05 +01:00
Andre601 b25b65faba Merge pull request 'Update dependency com.google.guava:guava to v33.4.5-jre' (#423) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/423
2025-03-20 12:27:21 +00:00
Andre601's Bot fafcd3ae18 Update dependency com.google.guava:guava to v33.4.5-jre 2025-03-20 12:21:06 +00:00
Andre601 daae88074f Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.18' (#422) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/422
2025-03-19 12:02:45 +00:00
Andre601's Bot fbe019214d Update dependency ch.qos.logback:logback-classic to v1.5.18 2025-03-19 12:01:59 +00:00
Andre601 3e380342a7 Merge pull request 'Update dependency mkdocs-material to v9.6.9' (#421) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/421
2025-03-17 12:42:58 +00:00
Andre601's Bot fd2dbd2edb Update dependency mkdocs-material to v9.6.9 2025-03-17 12:02:33 +00:00
Andre601 e969208ae9 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.1' (#420) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/420
2025-03-16 12:20:14 +00:00
Andre601's Bot 77aa404e06 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.1 2025-03-16 12:10:40 +00:00
Andre601 a6c1840858 Merge pull request 'Update dependency mkdocs-material to v9.6.8' (#419) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/419
2025-03-13 12:35:37 +00:00
Andre601's Bot 762bd1d0fd Update dependency mkdocs-material to v9.6.8 2025-03-13 12:02:56 +00:00
Andre601 02ce580433 Merge pull request 'Update dependency com.github.LeonMangler:PremiumVanishAPI to v2.9.18-2' (#418) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/418
2025-03-09 12:19:41 +00:00
Andre601's Bot c7b7feb476 Update dependency com.github.LeonMangler:PremiumVanishAPI to v2.9.18-2 2025-03-09 12:06:02 +00:00
Andre601 0e145def83 Merge pull request 'Update dependency mkdocs-material to v9.6.7' (#417) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/417
2025-03-03 12:14:54 +00:00
Andre601's Bot 03e32feb1d Update dependency mkdocs-material to v9.6.7 2025-03-03 12:04:14 +00:00
Andre601 dbab282901 Merge pull request 'Update dependency mkdocs-material to v9.6.6' (#416) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/416
2025-03-01 12:10:43 +00:00
Andre601's Bot bd6b599267 Update dependency mkdocs-material to v9.6.6 2025-03-01 12:02:02 +00:00
Andre601 1a63430c1e Merge pull request 'Update all non-major dependencies' (#415) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/415
2025-02-26 12:14:58 +00:00
Andre601's Bot 661f9e6ad4 Update all non-major dependencies 2025-02-26 12:03:25 +00:00
Andre601 6bd8d40ff4 Remove temporary SVG Icon 2025-02-24 03:40:32 +01:00
Andre601 16b74433ff Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.0' (#414) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/414
2025-02-22 12:17:18 +00:00
Andre601's Bot 1aaafe474f Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.0 2025-02-22 12:03:51 +00:00
Andre601 26a7697b0f Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0' (#413) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/413
2025-02-21 12:05:52 +00:00
Andre601's Bot ec6b653988 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 2025-02-21 12:04:18 +00:00
Andre601 854eb67c54 Further API Doc updates 2025-02-20 14:56:29 +01:00
Andre601 00511f6e97 Update API doc page 2025-02-20 14:42:00 +01:00
Andre601 16eebb23a5 Update docs 2025-02-20 14:38:04 +01:00
Andre601 faae641c32 Merge pull request 'Update dependency mkdocs-material to v9.6.5' (#412) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/412
2025-02-20 12:57:14 +00:00
Andre601's Bot 4fa542a242 Update dependency mkdocs-material to v9.6.5 2025-02-20 12:02:25 +00:00
Andre601 2dc1f7ccc1 Update icon used for velocity + other stuff 2025-02-19 00:58:20 +01:00
Andre601 dd7b1a7392 Improve Expressions page 2025-02-17 20:21:20 +01:00
Andre601 a90d241cd2 Merge pull request 'Update all non-major dependencies to v4.19.0' (#411) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/411
2025-02-17 12:06:41 +00:00
Andre601's Bot 452ac00ee7 Update all non-major dependencies to v4.19.0 2025-02-17 12:03:06 +00:00
Andre601 f139270f0e Use inlinehilite 2025-02-16 21:50:38 +01:00
Andre601 b212b2af0f Add MiniMessage Pygments lexer to requirements.txt 2025-02-16 21:23:35 +01:00
Andre601 0d506379cf Add MiniMessage Pygment lexer 2025-02-16 21:22:21 +01:00
Andre601 995793e66d Update api-version and add safety-check to PaperCore 2025-02-16 21:20:54 +01:00
Andre601 f9ebc60d64 Add new SayanVanish placeholders 2025-02-13 19:18:39 +00:00
Andre601 1d531a32e3 Merge pull request 'Update all non-major dependencies to v1.6.5' (#410) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/410
2025-02-13 19:10:12 +00:00
Andre601's Bot 36340d9b9d Update all non-major dependencies to v1.6.5 2025-02-13 19:03:39 +00:00
Andre601 d023e22934 Merge pull request 'Update dependency mkdocs-material to v9.6.4' (#409) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/409
2025-02-12 13:52:19 +00:00
Andre601's Bot 260a0b4835 Update dependency mkdocs-material to v9.6.4 2025-02-12 12:02:41 +00:00
Andre601 3f18aaaf5b renovate.json aktualisiert 2025-02-11 19:56:22 +00:00
Andre601 3f0e7897d4 No longer use allorigins.win
Codeberg apparently no longer causes CORS issues for JS fetched requests.
2025-02-10 12:11:23 +00:00
Andre601 4bd35c810b Add subcommand permissions for profiles commands. 2025-02-09 02:58:52 +01:00
Andre601 b081be8f53 Improve Command docs 2025-02-09 02:40:58 +01:00
Andre601 eb474d061b Merge pull request 'Update dependency mkdocs-material to v9.6.3' (#407) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/407
2025-02-07 12:42:35 +00:00
Andre601 edbc893c65 Ignore 2.0.0-SNAPSHOT for cloud 2025-02-07 12:36:37 +00:00
Andre601's Bot d03dce9b29 Update all non-major dependencies 2025-02-07 12:02:26 +00:00
Andre601 de7d011216 Fix cloud-paper not being compiled into project 2025-02-06 13:45:21 +01:00
Andre601 4a2cb2078d Compile the bungee cloud dependency and make enum public. 2025-02-05 21:28:56 +01:00
Andre601 05381bd538 Rename CommandHandler to CommandManagerInterface 2025-02-04 23:17:05 +01:00
Andre601 51e561f2ba Use records instead of classes for Player implementations 2025-02-04 23:11:30 +01:00
Andre601 71a3bddc62 Remove no longer existing overrides and update docs 2025-02-04 22:16:09 +01:00
Andre601 3eeffd5520 Merge pull request 'Use Cloud for Command handling' (#400) from feature/cloud-command-system into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/400
2025-02-04 20:40:40 +00:00
Andre601 3590e4fa12 Merge pull request 'Update dependency mkdocs-material to v9.6.2' (#405) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/405
2025-02-04 12:54:04 +00:00
Andre601's Bot e1e7907d0f Update dependency mkdocs-material to v9.6.2 2025-02-04 12:02:22 +00:00
Andre601 1e8f71092c Update ExpressionParser 2025-02-04 02:33:47 +01:00
Andre601 1c12180fe3 Merge branch 'master' into feature/cloud-command-system 2025-02-03 17:54:42 +01:00
Andre601 7a41e27788 Merge pull request 'Use MkDocs macros plugin for API reference generation' (#398) from feature/docs/better-autogen-apidocs into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/398
2025-02-03 16:48:20 +00:00
Andre601 ddfc8763c4 Bump Sayanvanish to 1.6.4 and add it as addon to wiki 2025-02-03 14:28:38 +01:00
Andre601 086905ad53 Upate dependencies and saynvanish Repo URL 2025-02-03 14:09:49 +01:00
Andre601 4526e91e0f Add SayanVanish as third-party addon to the docs 2025-02-03 01:19:06 +01:00
Andre601 cfb74b277e Revert updating SayanVanishAPI to 1.6.3 to fix it being fully broken... 2025-02-02 14:40:43 +01:00
Andre601 d7c3a7d756 Merge pull request 'Update all non-major dependencies' (#403) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/403
2025-02-02 12:46:28 +00:00
Andre601's Bot 36c6af0a43 Update all non-major dependencies 2025-02-02 12:03:48 +00:00
Andre601 f9df11c9f8 Add Build ID on Jenkins Builds. 2025-02-01 23:09:38 +01:00
Andre601 8f42b63733 Merge pull request 'Update all non-major dependencies' (#402) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/402
2025-01-31 12:06:35 +00:00
Andre601's Bot 10604f4064 Update all non-major dependencies 2025-01-31 12:03:20 +00:00
Andre601 7a574513af Merge pull request 'Update dependency com.google.code.gson:gson to v2.12.0' (#401) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/401
2025-01-30 12:10:52 +00:00
Andre601's Bot deeea1578d Update dependency com.google.code.gson:gson to v2.12.0 2025-01-30 12:02:28 +00:00
Andre601 ac379b1668 Refactor some stuff 2025-01-30 02:12:04 +01:00
Andre601 c636764f4b Update default config in getting-started.md 2025-01-28 16:13:33 +00:00
Andre601 a823aebafd Exclude kyori in minecraft-extras dependency 2025-01-27 22:37:47 +01:00
Andre601 dd4c3c0eb3 Improve shading of dependencies 2025-01-27 22:32:37 +01:00
Andre601 23afe54e29 No need to use sublist (Is truncated in API) 2025-01-26 02:05:02 +01:00
Andre601 fab3731cf4 Update value change hover 2025-01-26 01:57:01 +01:00
Andre601 49a782d560 Fix broken inherits list for docs 2025-01-25 15:35:00 +00:00
Andre601 cdac325e71 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-25 15:24:16 +00:00
Andre601 88f4278f3f Implement different value types per option 2025-01-25 15:14:06 +01:00
Andre601 de4617e450 Display old and new value on setting 2025-01-24 23:52:41 +01:00
Andre601 4c4573b1e0 Add class to create Options list + /asl profiles set command 2025-01-23 23:39:11 +01:00
Andre601 f74f3ef766 Small restructure 2025-01-22 13:38:51 +01:00
Andre601 806a920d32 Update commands.md 2025-01-22 13:34:38 +01:00
Andre601 c9db8cbc97 Improve info structure a bit 2025-01-22 13:25:06 +01:00
Andre601 3e3cd112ec Change PlayerOnly to CommandType and use enum values 2025-01-22 03:05:53 +01:00
Andre601 fcc7d7c6b6 A loooooooot of work...
Yes, this was absolute pain to make, thanks for asking.
2025-01-22 02:51:15 +01:00
Andre601 cb31fc6f5a Use markdown for entries 2025-01-20 22:11:49 +01:00
Andre601 b26a614f87 Fix issues with Annotationa + add /asl profiles info {profile} 2025-01-20 17:21:35 +01:00
Andre601 eb6f4180bf Implement BungeeCord and Paper Command Handler 2025-01-19 21:13:02 +01:00
Andre601 02d6b1958b Add command alias + remove requiredSender declaration 2025-01-19 19:36:18 +01:00
Andre601 bf3c979819 Use Annotations for commands 2025-01-19 16:49:05 +01:00
Andre601 b5af4b9c47 Use Cloud for Command handling 2025-01-18 23:12:10 +01:00
Andre601 6b9cff2945 Merge pull request 'Update dependency mkdocs-material to v9.5.50' (#399) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/399
2025-01-18 12:16:39 +00:00
Andre601's Bot d17549ee68 Update dependency mkdocs-material to v9.5.50 2025-01-18 12:01:47 +00:00
Andre601 8b73eb3c8c Change PAPI Placeholder behaviour + new placeholders 2025-01-16 02:27:31 +01:00
Andre601 1ee9ae473d Remove api-doc.html 2025-01-13 23:40:04 +01:00
Andre601 37006063cf Add macros plugin to requirements.txt 2025-01-13 23:37:53 +01:00
Andre601 76d97de029 Update API reference pages 2025-01-13 23:36:27 +01:00
Andre601 cd8f6f4c22 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-13 22:32:13 +01:00
Andre601 ce14274e4c Remove PlaceholderAPI page link 2025-01-12 15:34:31 +01:00
Andre601 a5d777f4f1 Restructure Wiki 2025-01-12 15:32:09 +01:00
Andre601 f94e578694 Update formatting.md 2025-01-10 15:28:57 +01:00
Andre601 4ff55ddf28 First work on some templates 2025-01-08 02:13:35 +01:00
Andre601 7c441e6ab5 Update SECURITY.md 2025-01-07 13:36:47 +00:00
Andre601 17d0802e41 Add MkDocs Macros Plugin 2024-12-28 16:14:10 +01:00
131 changed files with 4184 additions and 2615 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ when:
steps:
- name: "Build Jar and Upload"
image: maven:3.9.9-eclipse-temurin-21
image: maven:3.9.10-eclipse-temurin-21
environment:
CODEBERG_API_TOKEN:
from_secret: cb_token
+7 -1
View File
@@ -40,7 +40,7 @@ A Server List Profile is a single YAML file located in the plugin's `profiles` f
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)*
> *Read more about [Priority](https://asl.andre601.ch/profiles/options/priority) and [Conditions](https://asl.andre601.ch/profiles/options/condition)*
### Placeholders
@@ -92,6 +92,12 @@ English Video by KasaiSora
Spanish Video by Ajneb97
[![video thumbnail](https://img.youtube.com/vi/rIbljm_4HVI/0.jpg)](https://youtube.com/watch?v=rIbljm_4HVI)
Indonesian Video by faajrikha
[![video thumbnail](https://img.youtube.com/vi/-p938rOmqy4/0.jpg)](https://www.youtube.com/watch?v=-p938rOmqy4)
German Video by Finni Gamer
[![video thumbnail](https://img.youtube.com/vi/1Kh3cPMDd0c/0.jpg)](https://www.youtube.com/watch?v=1Kh3cPMDd0c)
</p>
</details>
+2 -2
View File
@@ -8,12 +8,12 @@ To ensure proper safety and support are only certain versions and Platforms of A
|---------------|-----------|
| v5 | Yes |
| v4 | Yes* |
| v3 | Yes** |
| v3 | No** |
| v2 | No |
| v1 | No |
\*Only receives support but no updates or bug fixes.
\*\*Support ends at the end of 2024.
\*\*Support ended on December 31st, 2024.
## Supported Server/Proxy Versions
+7 -14
View File
@@ -40,8 +40,8 @@
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@@ -65,14 +65,14 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2</version>
<version>1.21-R0.3</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.3</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
@@ -99,13 +99,13 @@
<dependency>
<groupId>space.arim.libertybans</groupId>
<artifactId>bans-api</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>1.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gitlab.ruany</groupId>
<artifactId>LiteBansAPI</artifactId>
<version>0.5.0</version>
<version>0.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -117,19 +117,12 @@
</dependencies>
<build>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}</finalName>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
</project>
+51 -37
View File
@@ -40,8 +40,9 @@
<description>${plugin.description}</description>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
@@ -51,7 +52,7 @@
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
<url>https://repo.sayandev.org/releases/</url>
</repository>
</repositories>
@@ -73,14 +74,14 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<version>1.21-R0.3</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<version>1.21-R0.3</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
@@ -125,19 +126,19 @@
<dependency>
<groupId>com.github.LeonMangler</groupId>
<artifactId>PremiumVanishAPI</artifactId>
<version>2.9.0-4</version>
<version>2.9.18-2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<version>1.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-bungeecord</artifactId>
<version>1.6.1</version>
<version>1.6.5</version>
<scope>provided</scope>
</dependency>
@@ -148,10 +149,16 @@
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-bungee</artifactId>
<version>${dependency.cloud-bungee}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}</finalName>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -159,44 +166,51 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<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>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.libby</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.expressionparser</shadedPattern>
</relocation>
<relocation>
<pattern>com.unascribed.flexver</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>org.incendo.cloud</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.cloud</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>
</filters>
</configuration>
</execution>
</executions>
</plugin>
@@ -25,15 +25,16 @@
package ch.andre601.advancedserverlist.bungeecord;
import ch.andre601.advancedserverlist.bungeecord.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
import ch.andre601.advancedserverlist.bungeecord.commands.BungeeCommandManagerInterface;
import ch.andre601.advancedserverlist.bungeecord.listeners.PlayerJoinEventListener;
import ch.andre601.advancedserverlist.bungeecord.listeners.ProxyPingEventListener;
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.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import com.alessiodp.libby.BungeeLibraryManager;
@@ -47,6 +48,7 @@ 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.incendo.cloud.CommandManager;
import org.sayandev.sayanvanish.bungeecord.api.SayanVanishBungeeAPI;
import java.awt.image.BufferedImage;
@@ -68,6 +70,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private BungeeAudiences audiences = null;
private BungeeCommandManagerInterface handler;
private BungeeLibraryManager libraryManager = null;
@@ -92,6 +95,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
}
this.audiences = BungeeAudiences.create(this);
this.handler = new BungeeCommandManagerInterface(this);
this.core = AdvancedServerList.init(this,
BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this), BungeeProxyPlaceholders.init(this));
}
@@ -103,16 +107,10 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
audiences.close();
}
@Override
public void loadCommands(){
getProxy().getPluginManager().registerCommand(this, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
public void loadEvents(){
new JoinEvent(this);
new PingEvent(this);
new PlayerJoinEventListener(this);
new ProxyPingEventListener(this);
}
@Override
@@ -181,6 +179,11 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
return faviconHandler;
}
@Override
public CommandManager<CmdSender> getCommandManager(){
return handler.commandHandler();
}
@Override
public String getPlatformInfo(){
return getProxy().getName() + " " + getProxy().getVersion();
@@ -27,8 +27,10 @@ package ch.andre601.advancedserverlist.bungeecord.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeeCmdSender implements CmdSender{
@@ -40,13 +42,22 @@ public class BungeeCmdSender implements CmdSender{
this.bungeeAudiences = bungeeAudiences;
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
}
@Override
public void sendMsg(String msg, Object... args){
bungeeAudiences.sender(sender).sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
@Override
public Audience audience(){
return bungeeAudiences.sender(sender);
}
@Override
public boolean isPlayer(){
return sender instanceof ProxiedPlayer;
}
public CommandSender sender(){
return sender;
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* 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
@@ -20,27 +20,41 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.commands;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandManagerInterface;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.bungee.BungeeCommandManager;
import org.incendo.cloud.execution.ExecutionCoordinator;
public class CmdAdvancedServerList extends Command{
public class BungeeCommandManagerInterface implements CommandManagerInterface<CommandSender>{
private final BungeeCordCore plugin;
public CmdAdvancedServerList(BungeeCordCore plugin){
super("advancedserverlist", "advancedserverlist.command.asl", "asl");
public BungeeCommandManagerInterface(BungeeCordCore plugin){
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args){
plugin.getCore().getCommandHandler().handle(new BungeeCmdSender(sender, plugin.getAudiences()), args);
public CommandManager<CmdSender> commandHandler(){
return new BungeeCommandManager<>(
plugin,
ExecutionCoordinator.asyncCoordinator(),
senderMapper()
);
}
@Override
public SenderMapper<CommandSender, CmdSender> senderMapper(){
return SenderMapper.create(
cmdSender -> new BungeeCmdSender(cmdSender, plugin.getAudiences()),
sender -> ((BungeeCmdSender)sender).sender()
);
}
}
@@ -34,10 +34,10 @@ import net.md_5.bungee.event.EventHandler;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
public class PlayerJoinEventListener implements Listener{
private final BungeeCordCore plugin;
public JoinEvent(BungeeCordCore plugin){
public PlayerJoinEventListener(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@@ -33,11 +33,11 @@ import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public class PingEvent implements Listener{
public class ProxyPingEventListener implements Listener{
private final BungeeCordCore plugin;
public PingEvent(BungeeCordCore plugin){
public ProxyPingEventListener(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@@ -30,21 +30,11 @@ import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
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();
}
public record BungeePlayerImpl(CachedPlayer player, int protocol) implements BungeePlayer{
@Override
public String getName(){
return name;
return player.name();
}
@Override
@@ -54,6 +44,6 @@ public class BungeePlayerImpl implements BungeePlayer{
@Override
public UUID getUUID(){
return uuid;
return player.uuid();
}
}
+43 -45
View File
@@ -39,9 +39,11 @@
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>8</plugin.config.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.config.version>9</plugin.config.version>
</properties>
<repositories>
@@ -77,7 +79,7 @@
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>1.5.0</version>
<version>1.6.0</version>
<scope>compile</scope>
</dependency>
@@ -91,7 +93,7 @@
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-hocon</artifactId>
<version>4.1.2</version>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
@@ -119,7 +121,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.13.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -131,15 +133,42 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.0-jre</version>
<version>33.4.8-jre</version>
<scope>provided</scope>
</dependency>
<!-- Command Framework -->
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-annotations</artifactId>
<version>${dependency.cloud-annotations}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-minecraft-extras</artifactId>
<version>${dependency.cloud-minecraft-extras}</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>net.kyori</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Annotations -->
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>net.william278</groupId>
<artifactId>papiproxybridge</artifactId>
<version>1.7.2</version>
<version>1.8.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -159,13 +188,13 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.4</version>
<version>5.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Core-${plugin.version}</finalName>
<finalName>AdvancedServerList-Core-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -186,43 +215,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<version>3.14.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.unascribed</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.expressionparser</shadedPattern>
</relocation>
</relocations>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -31,22 +31,40 @@ 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.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.annotations.AnnotationParser;
import org.incendo.cloud.description.Description;
import org.incendo.cloud.injection.ParameterInjector;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.parser.standard.BooleanParser;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.permission.Permission;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
public class AdvancedServerList<F>{
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
private final PluginCore<F> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final TextCenterUtil textCenterUtil;
@@ -60,7 +78,6 @@ public class AdvancedServerList<F>{
private AdvancedServerList(PluginCore<F> plugin, List<PlaceholderProvider> placeholders){
this.plugin = plugin;
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.textCenterUtil = new TextCenterUtil(this);
@@ -77,10 +94,6 @@ public class AdvancedServerList<F>{
load();
}
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
public static AdvancedServerListAPI getApi(){
return api;
}
@@ -93,10 +106,6 @@ public class AdvancedServerList<F>{
return fileHandler;
}
public CommandHandler getCommandHandler(){
return commandHandler;
}
public PlayerHandler getPlayerHandler(){
return playerHandler;
}
@@ -167,9 +176,8 @@ public class AdvancedServerList<F>{
return;
}
getPlugin().loadFaviconHandler(this);
plugin.loadCommands();
loadCommands();
plugin.loadEvents();
getPlayerHandler().load();
plugin.loadMetrics();
@@ -189,6 +197,8 @@ public class AdvancedServerList<F>{
getPlugin().getPluginLogger().info("<#3b90ff> / ____ \\ \\ ____) | | |_|____");
getPlugin().getPluginLogger().info("<#3b90ff>/_/_/ \\_\\_\\_____/_/|______|_|");
getPlugin().getPluginLogger().info("");
seasonalText();
}
private void resolveVersion(){
@@ -206,4 +216,115 @@ public class AdvancedServerList<F>{
private void addPlaceholder(PlaceholderProvider placeholderProvider){
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
}
private void loadCommands(){
getPlugin().loadFaviconHandler(this);
CommandManager<CmdSender> commandManager = plugin.getCommandManager();
commandManager.parameterInjectorRegistry().registerInjector(AdvancedServerList.class, ParameterInjector.constantInjector(this));
AnnotationParser<CmdSender> annotationParser = new AnnotationParser<>(commandManager, CmdSender.class);
annotationParser.registerBuilderModifier(
CommandType.class,
(annotation, builder) -> builder.meta(CommandHandler.COMMAND_TYPE, annotation.value())
);
annotationParser.parse(new CommandHandler(commandManager));
for(String option : CommandHandler.PROFILE_OPTIONS){
commandManager.command(
commandManager.commandBuilder("advancedserverlist", "asl")
.literal("profiles")
.literal("set")
.required(
"profile",
StringParser.stringParser(),
Description.of("The profile to edit."),
SuggestionProvider.suggesting(
getFileHandler().getProfiles().stream()
.map(ServerListProfile::file)
.map(Suggestion::suggestion)
.toList()
)
)
.literal(option)
.optional("value", descriptor(option), description(option))
.commandDescription(Description.of("Sets or resets profile values."))
.handler(context -> CommandHandler.handleSet(this, context))
.meta(CommandHandler.OPTION, option)
.permission(
Permission.anyOf(
Permission.permission("advancedserverlist.admin"),
Permission.permission("advancedserverlist.command.profiles"),
Permission.permission("advancedserverlist.command.profiles.set")
)
)
);
}
getPlugin().getPluginLogger().success("Loaded Command <white>/advancedserverlist</white>!");
}
private ParserDescriptor<CmdSender, ?> descriptor(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> BooleanParser.booleanParser();
case "priority" -> IntegerParser.integerParser();
default -> StringParser.greedyStringParser();
};
}
private Description description(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> Description.of(
"Whether this option should be enabled or not. Leave empty to unset it."
);
case "priority" -> Description.of("Priority this Profile should have. Leave empty to reset.");
case "motd", "playercount.hover" -> Description.of(
"Lines to set. Use \\n or <newline> to set a linebreak. Leave empty to reset."
);
default -> Description.of("The Value to use for this option. Leave empty to reset.");
};
}
// Adding some seasonal messages
private void seasonalText(){
LocalDate date = LocalDate.now();
switch(date.getMonth()){
case JANUARY -> {
if(date.getDayOfMonth() == 1){
getPlugin().getPluginLogger().info("Happy new Year!");
getPlugin().getPluginLogger().info("");
}
}
case JUNE -> {
getPlugin().getPluginLogger().info("Happy Pride Month!");
getPlugin().getPluginLogger().info("");
}
case AUGUST -> {
if(date.getDayOfMonth() == 1){
getPlugin().getPluginLogger().info("Happy Birthday Switzerland!");
getPlugin().getPluginLogger().info("");
}
}
case OCTOBER -> {
if(date.getDayOfMonth() == 31){
getPlugin().getPluginLogger().info("Happy Halloween!");
getPlugin().getPluginLogger().info("");
}
}
case DECEMBER -> {
if(date.getDayOfMonth() == 13){
getPlugin().getPluginLogger().info("Happy Birthday Andre_601!");
getPlugin().getPluginLogger().info("");
}else
if(date.getDayOfMonth() > 23 && date.getDayOfMonth() < 27){
getPlugin().getPluginLogger().info("Merry Christmas!");
getPlugin().getPluginLogger().info("");
}
}
}
}
}
@@ -101,8 +101,12 @@ public class UpdateChecker{
);
}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?");
sender.sendPrefixedMsg(
"Your version (<white>%</white>) is newer than what is available on Modrinth (<white>%s</white>).",
core.getVersion(),
version.versionNumber()
);
sender.sendPrefixedMsg("Are you using a Development Version?");
}
});
}
@@ -137,10 +141,14 @@ public class UpdateChecker{
switch(result){
case -1 -> printUpdateBanner(version);
case 0 -> logger.success("You are running the latest version!");
case 1 -> logger.info(
"[?] 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()
);
case 1 -> {
logger.info(
"[?] Your version (<white>%s</white>) is newer than what is available on Modrint (<white>%s</white>).",
core.getVersion(),
version.versionNumber()
);
logger.info(" Are you using a Development Version?");
}
}
});
}, 0L, 12L, TimeUnit.HOURS);
File diff suppressed because it is too large. Load diff
@@ -1,110 +0,0 @@
/*
* 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,172 @@
/*
* 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 ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ProfileOptionsSender{
private final List<OptionStringBuilder> builders = new ArrayList<>();
private final String file;
public ProfileOptionsSender(String file){
this.file = file;
}
public ProfileOptionsSender append(OptionStringBuilder builder){
this.builders.add(builder.file(file));
return this;
}
public void send(CmdSender sender){
sender.sendMsg();
sender.sendPrefixedMsg("Profile Info [<white>%s</white>]", file);
for(OptionStringBuilder builder : builders){
sender.sendMsg(builder.build());
}
sender.sendMsg();
sender.sendMsg("[<grey>Hover for info, click for command</grey>]");
sender.sendMsg();
}
public static class OptionStringBuilder{
public static OptionStringBuilder of(String displayName, String hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : hover)
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, List<String> hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : String.join("\n<reset>", hover))
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, NullBool hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || !hover.getOrDefault(false) ? "<red>Disabled</red>" : "<green>Enabled</green>")
.color(hover == null || !hover.getOrDefault(false) ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, int hover){
return new OptionStringBuilder(displayName)
.hover(String.valueOf(hover));
}
public static OptionStringBuilder of(String displayName){
return new OptionStringBuilder(displayName).hover(null);
}
private final String displayName;
private String file = null;
private String prefix = "├─";
private ColorName color = ColorName.AQUA;
private String hover = "<i>Not set</i>";
private String option = null;
private OptionStringBuilder(String displayName){
this.displayName = displayName;
}
public OptionStringBuilder file(String file){
this.file = file;
return this;
}
public OptionStringBuilder prefix(String prefix){
this.prefix = prefix;
return this;
}
public OptionStringBuilder color(ColorName color){
this.color = color;
return this;
}
public OptionStringBuilder hover(String hover){
this.hover = hover;
return this;
}
public OptionStringBuilder option(String option){
this.option = option;
return this;
}
public String build(){
StringBuilder builder = new StringBuilder("<grey>")
.append(prefix)
.append(" <white>[")
.append('<')
.append(color)
.append('>');
if(hover != null && !hover.isEmpty()){
builder.append("<hover:show_text:\"")
.append(hover)
.append("\">");
}
if(option != null && !option.isEmpty() && file != null && !file.isEmpty()){
builder.append("<click:suggest_command:/asl profiles set ")
.append(file)
.append(" ")
.append(option)
.append(" >");
}
builder.append(displayName);
if(option != null && !option.isEmpty())
builder.append("</click>");
if(hover != null && !hover.isEmpty())
builder.append("</hover>");
builder.append("</")
.append(color)
.append(">]</white></grey>");
return builder.toString();
}
}
enum ColorName{
RED,
GREEN,
AQUA;
@Override
public String toString(){
return this.name().toLowerCase(Locale.ROOT);
}
}
}
@@ -190,9 +190,12 @@ public class PingEventHandler{
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
logger.debug(PingEventHandler.class, "'favicon' option set. Resolving '%s'...", entry.favicon());
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
String faviconString = StringReplacer.modifier(entry.favicon())
.modify(text -> StringReplacer.replace(text, player, server))
.modify(text -> event.parsePAPIPlaceholders(text, player))
.asString();
F favicon = plugin.getFaviconHandler().getFavicon(faviconString);
F favicon = plugin.getFaviconHandler().favicon(faviconString);
if(favicon == null){
logger.debugWarn(PingEventHandler.class, "Favicon was invalid or not yet resolved! Using default favicon of Server/Proxy...");
@@ -46,7 +46,8 @@ public class ConfigMigrator{
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, sevenToEight())
.addVersion(LATEST, eightToNine())
.addVersion(8, sevenToEight())
.addVersion(7, sixToSeven())
.addVersion(6, fiveToSix())
.addVersion(5, fourToFive())
@@ -56,6 +57,16 @@ public class ConfigMigrator{
.build();
}
public static ConfigurationTransformation eightToNine(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("faviconStrategy").set("resize");
return null;
})
.build();
}
public static ConfigurationTransformation sevenToEight(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
@@ -25,12 +25,12 @@
package ch.andre601.advancedserverlist.core.interfaces.commands;
import net.kyori.adventure.audience.Audience;
public interface CmdSender{
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>] ";
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>] ";
boolean hasPermission(String permission);
String prefix = "<grey>[<aqua>ASL</aqua>] ";
String errorPrefix = "<grey>[<red>ASL</red>] ";
void sendMsg(String msg, Object... args);
@@ -45,4 +45,8 @@ public interface CmdSender{
default void sendErrorMsg(String msg, Object... args){
sendMsg(errorPrefix + msg, args);
}
Audience audience();
boolean isPlayer();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* 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
@@ -20,24 +20,15 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.velocity.commands;
package ch.andre601.advancedserverlist.core.interfaces.commands;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import com.velocitypowered.api.command.SimpleCommand;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
public class CmdAdvancedServerList implements SimpleCommand{
public interface CommandManagerInterface<S>{
CommandManager<CmdSender> commandHandler();
private final VelocityCore plugin;
public CmdAdvancedServerList(VelocityCore plugin){
this.plugin = plugin;
}
@Override
public void execute(Invocation invocation){
plugin.getCore().getCommandHandler().handle(new VelocityCmdSender(invocation.source()), invocation.arguments());
}
SenderMapper<S, CmdSender> senderMapper();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* 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
@@ -20,32 +20,22 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.commands;
import java.util.Locale;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public abstract class PluginCommand{
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface CommandType{
Type value();
private final String name;
public PluginCommand(String name){
this.name = name;
enum Type{
ALL,
PLAYER_ONLY
}
public String name(){
return name;
}
public String permission(){
return "advancedserverlist.command." + name().toLowerCase(Locale.ROOT);
}
public abstract void handle(CmdSender sender, String[] args);
public abstract String usage();
public abstract String description();
}
@@ -27,15 +27,15 @@ 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.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import org.incendo.cloud.CommandManager;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
public interface PluginCore<F>{
void loadCommands();
void loadEvents();
void loadMetrics();
@@ -56,6 +56,8 @@ public interface PluginCore<F>{
FaviconHandler<F> getFaviconHandler();
CommandManager<CmdSender> getCommandManager();
String getPlatformInfo();
String getLoader();
@@ -1,28 +1,3 @@
/*
* 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.profiles.handlers;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
@@ -42,9 +17,12 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.*;
import java.util.concurrent.*;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
public class FaviconHandler<F>{
@@ -54,183 +32,305 @@ public class FaviconHandler<F>{
private final ThreadPoolExecutor faviconThreadPool;
private final Cache<String, CompletableFuture<F>> faviconCache;
private final Map<String, F> localFavicons = new HashMap<>();
private final HttpClient client = HttpClient.newHttpClient();
private final Random random = new Random();
private final HttpClient client = HttpClient.newHttpClient();
private final Map<String, FaviconPair<F>> localFavicons = new HashMap<>();
public FaviconHandler(AdvancedServerList<F> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.faviconThreadPool = createFaviconThreadPool();
this.faviconThreadPool = createThreadPool();
this.faviconCache = CacheBuilder.newBuilder()
.expireAfterWrite(core.getFileHandler().getLong(1, 1, "faviconCacheTime"), TimeUnit.MINUTES)
.build();
.expireAfterWrite(core.getFileHandler().getLong(1, 1, "faviconCacheTime"), TimeUnit.MINUTES)
.build();
loadLocalFavicons();
}
public F getFavicon(String input){
if(localFavicons.size() > 0){
logger.debug(FaviconHandler.class, "Current Local Favicons:");
for(String key : localFavicons.keySet()){
logger.debug(FaviconHandler.class, " - %s", key);
}
public F favicon(String input){
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT))){
logger.debug(FaviconHandler.class, "Returning local Favicon '%s'.", input);
return localFavicons.get(input.toLowerCase(Locale.ROOT)).favicon();
}
if(input.equalsIgnoreCase("random")){
logger.debug(FaviconHandler.class, "Input matches 'random'. Returning random Favicon...");
return getRandomized();
logger.debug(FaviconHandler.class, "Returning random local Favicon.");
FaviconPair<F> pair = randomFavicon();
if(pair == null){
logger.warn("Cannot return random Favicon. Make sure PNGs are available in the Favicons folder!");
return null;
}
return pair.favicon();
}
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));
CompletableFuture<F> favicon = faviconCache.getIfPresent(input);
if(favicon != null)
return favicon.getNow(null);
logger.debug(FaviconHandler.class, "Processing '%s'", input);
if(input.contains(";")){
String[] parts = input.split(";");
logger.debug(FaviconHandler.class, "Handling multi-part Favicon: ['%s']", String.join("', '", parts));
favicon = CompletableFuture.supplyAsync(() -> {
List<BufferedImage> images = new ArrayList<>();
Arrays.stream(parts).forEach(part -> {
logger.debug(FaviconHandler.class, "Creating BufferedImage for part '%s'...", part);
images.add(create(part));
});
if(images.isEmpty()){
logger.debugWarn(FaviconHandler.class, "Unable to create Multi-part Favicon. List was empty.");
return null;
}
return composeFavicon(images);
}, faviconThreadPool);
}else{
logger.debug(FaviconHandler.class, "Handling Favicon input '%s'...", input);
favicon = CompletableFuture.supplyAsync(() -> {
logger.debug(FaviconHandler.class, "Creating BufferedImage for '%s'...", input);
BufferedImage image = create(input);
if(image == null){
logger.warn("Cannot create Favicon for '%s'. BufferedImage was null!", input);
return null;
}
return createFavicon(image);
}, faviconThreadPool);
}
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 '<white>%s</white>'.", ex, input);
return null;
}
faviconCache.put(input, favicon);
return favicon.getNow(null);
}
public void cleanCache(){
faviconCache.invalidateAll();
localFavicons.clear();
loadLocalFavicons();
}
private CompletableFuture<F> getFuture(String input){
private F composeFavicon(List<BufferedImage> images){
logger.debug(FaviconHandler.class, "Composing Favicon out of %d part(s)...", images.size());
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
String strategy = core.getFileHandler().getString("resize", "faviconStrategy");
int layer = 0;
for(BufferedImage img : images){
layer++;
logger.debug(FaviconHandler.class, "Applying layer %d...", layer);
if(img == null){
logger.debugWarn(FaviconHandler.class, "Layer %d was null! Skipping...", layer);
continue;
}
switch(strategy.toLowerCase(Locale.ROOT)){
case "center" -> {
int height = img.getHeight();
int width = img.getWidth();
int posHeight = 0;
int posWidth = 0;
if(height != 64){
posHeight = (64 - height) / 2;
}
// 64 - 128 = -64
if(width != 64){
posWidth = (64 - width) / 2;
}
graphics.drawImage(img, posWidth, posHeight, img.getWidth(), img.getHeight(), null);
}
case "none" -> graphics.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);
default -> graphics.drawImage(img, 0, 0, 64, 64, null);
}
logger.debug(FaviconHandler.class, "Applied layer %d!", layer);
}
graphics.dispose();
logger.debug(FaviconHandler.class, "Image Composing complete! Creating Favicon instance...");
return createFavicon(image);
}
private BufferedImage create(String input){
if(input.toLowerCase(Locale.ROOT).startsWith("https://")){
logger.debug(FaviconHandler.class, "Resolving URL '%s'...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, input), this.faviconThreadPool);
logger.debug(FaviconHandler.class, "Handling URL '%s'...", input);
return fromURL(input);
}else
if(input.equalsIgnoreCase("random")){
return CompletableFuture.completedFuture(getRandomized());
logger.debug(FaviconHandler.class, "Returning random local Favicon...");
FaviconPair<F> pair = randomFavicon();
return pair == null ? null : pair.image();
}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)));
logger.debug(FaviconHandler.class, "Returning local Favicon '%s'...", input);
return localFavicons.get(input.toLowerCase(Locale.ROOT)).image();
}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);
logger.debug(FaviconHandler.class, "Handling Player Name/UUID '%s'...", input);
return fromURL("https://mc-heads.net/avatar/" + input + "/64");
}
}
private F getRandomized(){
logger.debug(FaviconHandler.class, "Obtaining random Favicon...");
private FaviconPair<F> randomFavicon(){
if(localFavicons.isEmpty())
return null;
List<F> faviconList = List.copyOf(localFavicons.values());
List<FaviconPair<F>> favicons = new ArrayList<>(localFavicons.values());
if(favicons.isEmpty())
return null;
// Don't use Random for just one entry.
if(faviconList.size() == 1)
return faviconList.get(0);
if(favicons.size() == 1)
return favicons.getFirst();
synchronized(random){
return faviconList.get(random.nextInt(faviconList.size()));
return favicons.get(random.nextInt(favicons.size()));
}
}
private void loadLocalFavicons(){
this.localFavicons.clear();
logger.info("[-] Loading local image files as Favicons...");
logger.info("[-] Loading local images as Favicons...");
Path folder = core.getPlugin().getFolderPath().resolve("favicons");
if(!Files.exists(folder)){
try{
Files.createDirectories(folder);
logger.debugSuccess(FaviconHandler.class, "Created favicons folder.");
logger.debugSuccess(FaviconHandler.class, "Created favicons folder");
}catch(IOException ex){
logger.failure("Cannot create favicons folder. Encountered an IOException.", ex);
logger.warn("Encountered IOException while creating favicons folder.", ex);
return;
}
}
try(Stream<Path> pathStream = Files.list(folder)){
pathStream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
try(Stream<Path> stream = Files.list(folder)){
stream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
logger.success("Loaded <white>%d</white> local Favicons.", localFavicons.size());
logger.success("Loaded <white>%s</white> local Favicon(s).", localFavicons.size());
}catch(IOException ex){
logger.failure("Cannot load files from favicons folder.", ex);
logger.warn("Encountered IOException while loading local favicons.", ex);
}
}
private void loadFile(Path path){
try(InputStream stream = Files.newInputStream(path)){
F favicon = createFavicon(stream);
if(favicon == null){
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Received Favicon was null.", path.getFileName().toString());
BufferedImage image = createBufferedImage(stream);
if(image == null)
return;
}
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), favicon);
logger.debugSuccess(FaviconHandler.class, "Loaded file '<white>%s</white>' as Favicon.", path.getFileName().toString());
F favicon = core.getPlugin().createFavicon(image);
if(favicon == null)
return;
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), new FaviconPair<>(image, favicon));
}catch(IOException ex){
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Encountered IOException.", ex);
logger.warn("Encountered IOException while creating a Favicon from '%s'.", ex, path.getFileName().toString());
}catch(Exception ex){
logger.warn("Encountered an Exceotion while creating a Favicon from '%s'.", ex, path.getFileName().toString());
}
}
private F fromURL(AdvancedServerList<F> core, String url){
private BufferedImage fromURL(String url){
try{
logger.debug(FaviconHandler.class, "Creating Request for URL '%s'...", url);
logger.debug(FaviconHandler.class, "Creating request for URL '%s'...", url);
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(url))
.header("User-Agent", "AdvancedServerList-" + core.getPlugin().getLoader() + "/" + core.getVersion())
.build();
.uri(new URI(url))
.header("User-Agent", "AdvancedServerList-" + core.getPlugin().getLoader() + "/" + core.getVersion())
.build();
try(InputStream stream = client.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()){
return createFavicon(stream);
}catch(InterruptedException | IOException ex){
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered an Exception.", ex, url);
return createBufferedImage(stream);
}catch(IOException ex){
logger.warn("Encountered IOException while performing a web request for '%s'.", ex, url);
return null;
}catch(InterruptedException ex){
logger.warn("Encountered an InterruptedException while performing a web request for '%s'.", ex, url);
return null;
}
}catch(URISyntaxException ex){
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered a URISyntaxException.", ex, url);
logger.warn("Received URISyntaxException for URL '%s'", ex, url);
return null;
}
}
private F createFavicon(InputStream stream){
private BufferedImage createBufferedImage(InputStream stream){
logger.debug(FaviconHandler.class, "Creating BufferedImage from InputStream...");
try{
logger.debug(FaviconHandler.class, "Creating BufferedImage from InputStream...");
BufferedImage original = ImageIO.read(stream);
if(original == null){
logger.warn("Cannot create Favicon. Received null BufferedImage.");
logger.warn("Cannot create Favicon. Received a null BufferedImage!");
return null;
}
// Don't waste resources resizing images already having right size.
if(original.getWidth() == 64 && original.getHeight() == 64){
logger.debug(FaviconHandler.class, "BufferedImage is 64x64 pixels. No resizing needed.");
return core.getPlugin().createFavicon(original);
logger.debug(FaviconHandler.class, "Check image size for possible resizing...");
if(original.getHeight() == 64 && original.getWidth() == 64){
logger.debug(FaviconHandler.class, "Image is 64x64. No resizing needed!");
return original;
}
logger.debug(FaviconHandler.class, "Resizing image to 64x64 pixels...");
logger.debug(FaviconHandler.class, "Applying Favicon resize strategy...");
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = image.createGraphics();
Graphics2D graphics = image.createGraphics();
graphics2D.drawImage(original, 0, 0, 64, 64, null);
graphics2D.dispose();
String resizeMode = core.getFileHandler().getString("resize", "faviconStrategy");
switch(resizeMode.toLowerCase(Locale.ROOT)){
case "center" -> {
int height = original.getHeight();
int width = original.getWidth();
int posHeight = 0;
int posWidth = 0;
if(height != 64){
posHeight = (64 - height) / 2;
}
if(width != 64){
posWidth = (64 - width) / 2;
}
graphics.drawImage(original, posWidth, posHeight, original.getWidth(), original.getHeight(), null);
}
case "none" -> graphics.drawImage(original, 0, 0, original.getWidth(), original.getHeight(), null);
default -> graphics.drawImage(original, 0, 0, 64, 64, null);
}
logger.debug(FaviconHandler.class, "Image resized! Returning Favicon...");
return core.getPlugin().createFavicon(image);
}catch(Exception ex){
logger.warn("Unable to create Favicon. Received Exception.", ex);
graphics.dispose();
logger.debug(FaviconHandler.class, "Image resized. Returning it...");
return image;
}catch(IOException ex){
logger.warn("Encountered an IOException while processing Favicon!", ex);
return null;
}
}
private ThreadPoolExecutor createFaviconThreadPool(){
private F createFavicon(BufferedImage image){
try{
return core.getPlugin().createFavicon(image);
}catch(Exception ex){
logger.warn("Encountered an Exception while trying to create a Favicon instance.", ex);
return null;
}
}
private ThreadPoolExecutor createThreadPool(){
return new ThreadPoolExecutor(3, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024), r -> {
Thread t = new Thread(r, "AdvancedServerList-FaviconThread");
t.setDaemon(true);
return t;
});
}
private record FaviconPair<F>(BufferedImage image, F favicon){}
}
@@ -120,20 +120,13 @@ public class ProfileManager{
}
public static boolean checkOption(Object obj){
if(obj == null)
return false;
return switch(obj){
case List<?> list -> !list.isEmpty(); // Check if list isn't empty
case String str -> !str.isEmpty(); // Check if String is not empty
case NullBool nb -> nb.getOrDefault(false); // Return NullBool's value
case null, default -> false;
};
if(obj instanceof List<?> list){
return !list.isEmpty(); // Check if list isn't empty
}else
if(obj instanceof String str){
return !str.isEmpty(); // Check if String is not empty
}else
if(obj instanceof NullBool nb){
return nb.getOrDefault(false); // Return NullBool's value
}
return false;
}
private static <T> T resolve(ProfileEntry defProfile, ProfileEntry profile, Function<ProfileEntry, T> function){
@@ -34,9 +34,14 @@ import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.toke
import ch.andre601.expressionparser.ParseWarnCollector;
import java.text.ParsePosition;
import java.util.function.Function;
public class StringReplacer{
public static StringModifier modifier(String text){
return new StringModifier(text);
}
public static String replace(String input, GenericPlayer player, GenericServer server){
if(input == null)
return null;
@@ -148,4 +153,22 @@ public class StringReplacer{
return replacement;
}
public static class StringModifier{
private String value;
public StringModifier(String value){
this.value = value;
}
public StringModifier modify(Function<String, String> function){
this.value = function.apply(value);
return this;
}
public String asString(){
return value;
}
}
}
+13
View File
@@ -66,6 +66,19 @@ printBanner: true
#
faviconCacheTime: 1
#
# Sets how AdvancedServerList should handle the size and positioning of images for favicons.
#
# Available options:
#
# - resize: Resizes the image to 64x64 pixels if it isn't these dimensions already.
# - center: Doesn't resize the image, but instead tries to center it as good as possible in a 64x64 area.
# - none: Doesn't resize the image and leaves it positioned at x 0 and y 0 (top-left) of the 64x64 area.
#
# Setting any not listed option or leaving this blank/removing it sets the option to resize.
#
faviconStrategy: 'resize'
#
# Options to disable while the Maintenance Plugin is present and Maintenance Mode is active.
#
+24 -18
View File
@@ -10,9 +10,9 @@ priority: 0
# 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 '||'.
# 'AND'/'&&' and 'OR'/'||' can be used to chain together multiple conditions.
#
# No condition or an empty condition will be treated as true by default.
# Removing the condition option or setting it to an empty String will be treated as a true condition being returned.
#
# Read more: https://asl.andre601.ch/profiles/#condition
#
@@ -40,8 +40,11 @@ profiles:
#
# 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.
# This option supports RGB colors for 1.16+ Servers and clients. More advanced MiniMessage features such as <gradient>
# can be used for further styling the text.
#
# <center> can be put at the start of a line to have AdvancedServerList automatically center the text as good as
# possible.
#
# Only the first two lines will be considered and any additional one is ignored.
#
@@ -55,27 +58,30 @@ motd:
#
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
# This option supports three types of input:
#
# 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.
# 1. Filename, including the .png extension, matching a filename in the favicons folder of the plugin.
# - 'random' can be used to have AdvancedServerList select a random image from the favicons folder every time
# the server is pinged.
# 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.
# 4. Player name, UUID or a placeholder that returns either.
# - 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.
# Any image below or above 64x64 pixels will be resized according to the faviconResizeMode option in the config.yml.
#
# If not present or empty (favicon: ''), defaults to not modifying the favicon.
#
# Read more: https://asl.andre601.ch/profiles/#favicon
#
# "The favicon isn't showing!"
# This is a side effect of using either URLs or player names/UUIDs for the favicon.
# These types require AdvancedServerList to create a new favicon object from scratch. This action takes a significant
# amount of time, which can cause the server to show with a huge ping.
# To avoid this is this action performed asynchronously. This means that the plugin doesn't wait for the favicon to
# be created before continuing, which can result in no favicon being available when it is done handling the ping.
# This should only happen for the first ping of a player and subsequent pings should display the favicon, if the
# pings are done within the configured cache time (See 'faviconCacheTime' in the config.yml).
#
favicon: ''
#
@@ -106,7 +112,7 @@ playerCount:
#
# 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.
# down-sampled to the nearest matching color.
#
# If not present or empty (hover: []), defaults to not modifying the hover.
#
+15
View File
@@ -0,0 +1,15 @@
def on_pre_page_macros(env):
footer = """
{% if page.meta and page.meta.api %}
{% include 'api_docs/constructor_summaries.md' %}
{% include 'api_docs/nested_class_summaries.md' %}
{% include 'api_docs/enum_summaries.md' %}
{% include 'api_docs/method_summaries.md' %}
{% include 'api_docs/constructor_details.md' %}
{% include 'api_docs/enum_details.md' %}
{% include 'api_docs/method_details.md' %}
{% endif %}
"""
env.markdown += footer
+23
View File
@@ -0,0 +1,23 @@
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
from re import Match
def on_page_markdown(
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
):
def replace(match: Match):
platform = match.group(1)
if platform == "paper": return "[:fontawesome-solid-paper-plane:](https://papermc.io){ .md-button .md-button--icon title=\"PaperMC\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "bungee": return "[:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "velocity": return "[:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "proxies": return "[:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" } [:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "all": return "[:fontawesome-solid-paper-plane:](https://papermc.io){ .md-button .md-button--icon title=\"PaperMC\" target=\"_blank\" rel=\"noopener\" } [:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" } [:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
else: return platform
return re.sub(
r"<!-- icon:(paper|bungee|velocity|proxies|all) -->",
replace, markdown, flags = re.I | re.M
)
-35
View File
@@ -1,35 +0,0 @@
{% extends "base.html" %}
{% import "api-objects/info-template.html" as info %}
{% block content %}
{% include "partials/content.html" %}
{% if page.meta %}
<!--
Object summaries
-->
{% if page.meta.constructors %}
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.classes %}
{{ info.summary('Class Summary', page.meta.classes, details_type='class', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.summary('Enum Constant Summary', page.meta.enums, details_type='enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods or page.meta.inherits %}
{{ info.summary('Method Summary', page.meta.methods, page.meta.inherits, details_type='method', defaults=page.meta.defaults) }}
{% endif %}
<!--
Detailed object info
-->
{% if page.meta.constructors %}
{{ info.info('Constructor Detail', page.meta.constructors, 'constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.info('Enum Constant Detail', page.meta.enums, 'enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods %}
{{ info.info('Method Detail', page.meta.methods, 'method', defaults=page.meta.defaults)}}
{% endif %}
{% endif %}
{% endblock %}
@@ -1,228 +0,0 @@
{% macro summary(title, summaries, inherits, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
{% if summaries %}
<table>
<thead>
<tr>
{% if details_type and details_type == "method" %}
<th>Modifier and Type</th>
{% endif %}
<th>{{ details_type | capitalize() }}</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for summary in summaries %}
<tr>
{% set modifiers = namespace(name = "") %}
{% for attribute in summary.attributes %}
{% set modifiers.name = modifiers.name ~ attribute %}
{% if loop.revindex > 0 %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
{% endfor %}
{% if modifiers.name %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
{% if summary.type and summary.type.name %}
{% set modifiers.name = modifiers.name ~ summary.type.name %}
{% elif defaults and defaults.type and defaults.type.name %}
{% set modifiers.name = modifiers.name ~ defaults.type.name %}
{% else %}
{% set modifiers.name = modifiers.name ~ "void" %}
{% endif %}
{% set desc = "" %}
{% if summary.deprecated %}
{% set desc = "<api__deprecated></api__deprecated><br>" ~ summary.deprecated.split("<br>")[0] %}
{% elif summary.description %}
{% set desc = summary.description.split("<br>")[0] %}
{% endif %}
{% set final_name = namespace(name = "") %}
{% if details_type and details_type == "enum" %}
{% set final_name.name = summary.name | upper() %}
{% else %}
{% set final_name.name = summary.name ~ "(" %}
{% endif %}
{% for parameter in summary.parameters %}
{% set final_name.name = final_name.name ~ parameter.type %}
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
{% if details_type and details_type == "method" %}
{% if modifiers.name %}
<td><code>{{ modifiers.name }}</code></td>
{% else %}
<td></td>
{% endif %}
{% endif %}
<td>
{% if summary.link %}
<a href="{{ summary.link }}"><code>{{ final_name.name | e}}</code></a>
{% else %}
<a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}"><code>{{ final_name.name | e}}</code></a>
{% endif %}
</td>
<td>{{ desc }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if inherits %}
{% for classpath, inherit in inherits.items() %}
<table>
<thead>
<tr>
<th>Methods inherited from <a href="{{ inherit.link }}"><code>{{ classpath }}</code></a></th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% for inh in inherit.list %}
<a href="{{ inherit.link }}#{{ inh | lower() | replace(' ', '-') | e }}">
<code>{{- inh | e -}}</code>
</a>
{%- if loop.revindex > 1 %}, {% endif -%}
{% endfor %}
</td>
</tr>
</tbody>
</table>
{% endfor %}
{% endif %}
</div>
</div>
{%- endmacro %}
{% macro info(title, details, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
{% for detail in details %}
<div class="api-detail">
{% set final_name = namespace(name = "") %}
{% if details_type == "enum" %}
{% set final_name.name = detail.name | upper() %}
{% else %}
{% set final_name.name = detail.name ~ "(" %}
{% endif %}
{% for parameter in detail.parameters %}
{% set final_name.name = final_name.name ~ parameter.type %}
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
<h3 id="{{ final_name.name | lower() | replace(' ', '-') | e }}">
{% if detail.deprecated %}
<api__deprecated></api__deprecated>
{% endif %}
{% for attribute in detail.attributes %}
<api__{{- attribute -}}></api__{{- attribute -}}>
{% endfor %}
{% if enum %}
<api__static></api__static> <api__final></api__final>
{% endif %}
{% if detail.type and details_type == "method" %}
{% if detail.type.link %}
<a href="{{ detail.type.link }}" class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</span>
{% endif %}
{% elif defaults and defaults.type and details_type == "method" %}
{% if defaults.type.link %}
<a href="{{ defaults.type.link }}" class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') }}</span>
{% endif %}
{% elif details_type == "method" %}
<span class="api-type__primitive">void</span>
{% endif %}
<code>{{ final_name.name | e }}</code><a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}" class="headerlink" title="Permanent link"></a>
</h3>
{% if detail.deprecated %}
<div class="admonition deprecated">
<div class="admonition-title">Deprecation Warning</div>
<p>
{{ detail.deprecated }}
</p>
</div>
{% endif %}
{% if detail.description %}
<p class="api-detail__description">
{{ detail.description }}
</p>
{% endif %}
{% if detail.parameters %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-parameters">
Parameters:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-parameters" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for parameter in detail.parameters %}
<li>
{% for attribute in parameter.attribute %}
<api__{{- attribute -}}></api__{{- attribute -}}>
{% endfor %}
<code>{{ parameter.type | e }}: {{ parameter.name }}</code>{% if parameter.description %} - {{ parameter.description }}{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% if detail.returns %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-returns">
Returns:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-returns" class="headerlink" title="Permanent link"></a>
</h4>
<p class="api-detail__description">
{{ detail.returns }}
</p>
{% endif %}
{% if detail.throws %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-throws">
Throws:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-throws" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for throw in detail.throws %}
<li>
<code>{{ throw.name }}</code>{% if throw.description %} - {{ throw.description }}{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% if seealso %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-see-also">
See also:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-see-also" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for see in detail.seealso %}
<li>
<a href="{{ see.link }}"><code>{{ see.name }}</code></a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
{%- endmacro %}
@@ -0,0 +1,61 @@
{% if page.meta.constructors %}
## Constructor Details
{% for constructor in page.meta.constructors %}
<div class="api-detail" markdown>
{% set name = namespace(text = constructor.name ~ "(") %}
{% for parameter in constructor.parameters %}
{% set name.text = name.text ~ parameter.type %}
{% if loop.revindex > 1 %}{% set name.text = name.text ~ ", " %}{% endif %}
{% endfor %}
{% set name.text = name.text ~ ")" %}
{% if constructor.deprecated %}
{% set name.text = "<api__deprecated></api__deprecated> " ~ name.text %}
{% endif %}
{% for attribute in constructor.attributes %}
{% set name.text = "<api__{{- attribute -}}></api__{{- attribute -}}> " ~ name.text %}
{% endfor %}
### {{ name.text | e }} { #{{ constructor.name | lower() | replace(' ', '-') | e }} }
{% if constructor.deprecated %}
/// deprecated | Deprecation Warning
{{ constructor.deprecated }}
///
{% endif %}
{% if constructor.description %}
<p class="api-detail__description">
{{ constructor.description }}
</p>
{% endif %}
{% if constructor.parameters %}
#### Parameters: { #{{ constructor.name | lower() | replace(' ', '-') | e }}-parameters }
{% for parameter in constructor.parameters %}
- {% for attribute in parameter.attributes %}<api__{{- attribute -}}></api__{{- attribute -}}>{% endfor %} `{{ parameter.type | e}}: {{ parameter.name }}`{% if parameter.description %} - {{ parameter.description }}{% endif %}
{% endfor %}
{% endif %}
{% if constructor.seealso %}
#### See also: { #{{ constructor.name | lower() | replace(' ', '-') | e }}-see-also }
<div class="api-detail__description" markdown>
{% for see in constructor.seealso %}
- [`{{ see.name }}`]({{ see.link }})
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,14 @@
{% if page.meta.constructors %}
## Constructor Summary
| Constructor | Description |
|-------------|-------------|{% for constructor in page.meta.constructors %}
| [`{{ constructor.name }}({% for parameter in constructor.parameters -%}
{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}
{%- endfor %})`](#{{ constructor.name | lower() }}) | {% if constructor.deprecated -%}
<api__deprecated></api__deprecated> {{ constructor.deprecated.split("\n")[0] }}
{%- elif constructor.description -%}
{{ constructor.description.split("\n")[0] }}
{%- endif %} |
{%- endfor %}
{% endif %}
+32
View File
@@ -0,0 +1,32 @@
{% if page.meta.enums %}
## Enum Constant Details
{% for enum in page.meta.enums %}
<div class="api-detail" markdown>
{% set modifiers = namespace(text = "<api__static></api__static> <api__final></api__final> ") %}
{% if enum.deprecated %}
{% set modifiers.text = "<api__deprecated></api__deprecated> " ~ modifiers.text %}
{% endif %}
### {{ modifiers.text }} `{{ enum.name | upper() }}` { #{{ enum.name | lower() | replace(' ', '-') | e }} }
{% if enum.deprecated %}
/// deprecated | Deprecation Warning
{{ enum.deprecated }}
///
{% endif %}
{% if enum.description %}
<div class="api-detail__description" markdown>
{{ enum.description }}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,8 @@
{% if page.meta.enums %}
## Enum Constant Summary
| Enum | Description |
|------|-------------|{% for enum in page.meta.enums %}
| [`{{ enum.name | upper() }}`](#{{ enum.name | lower() }}) | {{ enum.description.split("\n")[0] }} |
{%- endfor %}
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
{% macro render_name(method) -%}
{{ method.name }}({% for parameter in method.parameters %}{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}{% endfor %})
{%- endmacro %}
+109
View File
@@ -0,0 +1,109 @@
{% if page.meta.methods %}
## Method Details
{% for method in page.meta.methods %}
<div class="api-detail" markdown>
{% set modifiers = namespace(text = "") %}
{% if method.deprecated %}
{% set modifiers.text = "<api__deprecated></api__deprecated> " %}
{% endif %}
{% for attribute in method.attributes %}
{% set modifiers.text = modifiers.text ~ "<api__" ~ attribute ~ "></api__" ~ attribute ~ ">" %}
{% if loop.revindex > 0 %}{% set modifiers.text = modifiers.text ~ " " %}{% endif %}
{% endfor %}
{% if modifiers.text %}{% set modifiers.text = modifiers.text ~ " " %}{% endif %}
{% set method_type = "" %}
{% if method.type %}
{% if method.type.link %}
{% set method_type = '[' ~ method.type.name|default('void')|e ~ '](' ~ method.type.link ~ '){ .api-type__' ~ method.type.type|default('primitive') ~ '} ' %}
{% else %}
{% set method_type = '<span class="api-type__' ~ method.type.type|default('primitive') ~ '">' ~ method.type.name|default('void')|e ~ '</span> ' %}
{% endif %}
{% elif page.meta.defaults and page.meta.defaults.type %}
{% if page.meta.defaults.type.link %}
{% set method_type = '[' ~ page.meta.defaults.type.name|default('void')|e ~ '](' ~ page.meta.defaults.type.link ~ '){ .api-type__' ~ page.meta.defaults.type.type|default('primitive') ~ '} ' %}
{% else %}
{% set method_type = '<span class="api-type__' ~ page.meta.defaults.type.type|default('primitive') ~ '">' ~ page.meta.defaults.type.name|default('void')|e ~ '</span> ' %}
{% endif %}
{% else %}
{% set method_type = '<span class="api-type__primitive">void</span> ' %}
{% endif %}
{% set name = namespace(text = method.name ~ "(") %}
{% for parameter in method.parameters %}
{% set name.text = name.text ~ parameter.type %}
{% if loop.revindex > 1 %}{% set name.text = name.text ~ ", " %}{% endif %}
{% endfor %}
{% set name.text = name.text ~ ")" %}
### {{ modifiers.text }} {{ method_type }} `{{ name.text }}` { #{{ method.name | lower() | replace(' ', '-') | e }} }
{% if method.deprecated %}
/// deprecated | Deprecation Warning
{{ method.deprecated }}
///
{% endif %}
{% if method.description %}
<div class="api-detail__description" markdown>
{{ method.description }}
</div>
{% endif %}
{% if method.parameters %}
#### Parameters: { #{{ method.name | lower() | replace(' ', '-') | e }}-parameters }
<div class="api-detail__description" markdown>
{% for parameter in method.parameters %}
- {% for attribute in parameter.attributes %}<api__{{- attribute -}}></api__{{- attribute -}}>{% endfor %} `{{ parameter.type | e}}: {{ parameter.name }}`{% if parameter.description %} - {{ parameter.description }}{% endif %}
{% endfor %}
</div>
{% endif %}
{% if method.returns %}
#### Returns: { #{{ method.name | lower() | replace(' ', '-') | e }}-returns }
<div class="api-detail__description" markdown>
{{ method.returns }}
</div>
{% endif %}
{% if method.throws %}
#### Throws: { #{{ method.name | lower() | replace(' ', '-') | e }}-throws }
<div class="api-detail__description" markdown>
{% for throw in method.throws %}
- `{{ throw.name }}`{% if throw.description %} - {{ throw.description }}{% endif %}
{% endfor %}
</div>
{% endif %}
{% if method.seealso %}
#### See also: { #{{ method.name | lower() | replace(' ', '-') | e }}-see-also }
<div class="api-detail__description" markdown>
{% for see in method.seealso %}
- [`{{ see.name }}`]({{ see.link }})
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,31 @@
{% if page.meta.methods or page.meta.inherits %}
## Method Summary
{% if page.meta.methods %}
| Modifier and Type | Method | Description |
|-------------------|--------|-------------|{% for method in page.meta.methods %}
| `{% if method.attributes -%}
{% for attribute in method.attributes -%}
{{ attribute }}{% if loop.revindex > 0 %} {% endif %}
{%- endfor %} {%- endif %}{% if method.type and method.type.name -%}
{{ method.type.name }}
{%- elif page.meta.defaults and page.meta.defaults.type and page.meta.defaults.type.name -%}
{{ page.meta.defaults.type.name }}
{%- else -%}void{%- endif %}` | [`{{ method.name }}({% for parameter in method.parameters -%}
{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}
{%- endfor %})`](#{{ method.name | lower() }}) | {% if method.deprecated -%}
<api__deprecated></api__deprecated> {{ method.deprecated.split("\n")[0] }}
{%- elif method.description -%}
{{ method.description.split("\n")[0] }}
{%- endif %} |
{%- endfor %}
{% endif %}
{% if page.meta.inherits %}
{% for classpath, inherit in page.meta.inherits.items() %}
| Methods inherited from [`{{ classpath }}`]({{ inherit.link }}) |
|----------------------------------------------------------------|
| {% for entry in inherit.list -%}[`{{ entry.name | e }}`]({{ inherit.link }}#{{ entry.link | lower() | replace(' ', '-') | e }}){% if loop.revindex > 1 %}, {% endif %}{% endfor %} |
{% endfor %}
{% endif %}
{% endif %}
@@ -0,0 +1,11 @@
{% if page.meta.classes %}
## Nested Class Summary
| Modifier and Type | Class | Description |
|-------------------|-------|-------------|{% for class in page.meta.classes %}
| `{% if class.attributes -%}
{% for attribute in class.attributes -%}
{{ attribute }}{% if loop.revindex > 1 %} {% endif %}
{%- endfor %} {%- endif %}{{ class.type }}` | [`{{ class.name }}`]({{ class.link }}) | {{ class.description.split("\n")[0] }} |
{%- endfor %}
{% endif %}
+2 -3
View File
@@ -1,7 +1,6 @@
{% 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>
<span class="twemoji">{% include ".icons/octicons/paintbrush-24.svg" %}</span>
The <a href="/profiles">Profiles page</a> received a huge restructuring!
{% endblock %}
@@ -16,8 +16,7 @@ The BanPlugins Addon is available in downloads of AdvancedServerList on [:simple
**Supported Platforms:**
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
<!-- icon:paper --> <!-- icon:bungee -->
| Placeholder | Description |
|---------------------------------|------------------------------------------------------------------------------------------|
@@ -57,9 +56,7 @@ motd:
**Supported Platforms:**
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
<!-- icon:all -->
| Placeholder | Description |
|---------------------------------|------------------------------------------------------------------------------------------|
@@ -95,9 +92,7 @@ motd:
**Supported Platforms:**
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
<!-- icon:all -->
| Placeholder | Description |
|------------------------------|------------------------------------------------------------------------------------------|
+10 -2
View File
@@ -13,7 +13,7 @@ These Addons are made by Andre601 and available together with the plugin downloa
<div class="grid cards" markdown>
- [**BanPlugins**](banplugins.md)
- [**BanPlugins**](first-party/banplugins.md)
----
@@ -25,4 +25,12 @@ These Addons are made by Andre601 and available together with the plugin downloa
Third-party addons made by other people not working on AdvancedServerList.
*Currently no entries*
<div class="grid cards" markdown>
- [**SayanVanish**](third-party/sayanvanish.md)
----
SayanVanish adds additional placeholders to the Velocity version of AdvancedServerList to use.
</div>
+43
View File
@@ -0,0 +1,43 @@
---
icon: octicons/eye-closed-24
---
# SayanVanish
The plugin [SayanVanish]{ target="_blank" rel="nofollow" } is hooking into AdvancedServerList to provide placeholders of its own to be used in conditions and text options.
## Placeholders
/// tab | :fontawesome-solid-paper-plane: Paper
[:octicons-file-code-24: Source][source-paper]
| Placeholder | Description |
|----------------------------------|--------------------------------------------------------------------------------------------|
| `${sayanvanish vanished}` | Returns true or false based on if the player is vanished. |
| `${sayanvanish level}` | Returns the vanish level of the player. |
| `${sayanvanish count}` | Returns the number of online players that are vanished. |
| `${sayanvanish online_here}` | Returns the number of online players on the same server that aren't vanished. |
| `${sayanvanish online_total}` | Returns the number of online players on the entire network that aren't vanished.^[1](#n1)^ |
| `${sayanvanish online_<server>}` | Returns the number of online players on `<server>` that aren't vanished.^[1](#n1)^ |
| `${sayanvanish vanish_prefix}` | Returns the prefix for the player while they are vanished or an empty String. |
| `${sayanvanish vanish_suffix}` | Returns the suffix for the player while they are vanished or an empty String. |
<small>^1^{ #n1 } Only works when Proxy mode is enabled and will otherwise return `PROXY_MODE IS NOT ENABLED!`</small>
///
/// tab | :simple-velocity: Velocity
[:octicons-file-code-24: Source][source-velocity]
| Placeholder | Description |
|----------------------------------|----------------------------------------------------------------------------------|
| `${sayanvanish vanished}` | Returns true or false based on if the player is vanished. |
| `${sayanvanish level}` | Returns the vanish level of the player. |
| `${sayanvanish count}` | Returns the number of online players that are vanished. |
| `${sayanvanish online_total}` | Returns the number of online players on the entire network that aren't vanished. |
| `${sayanvanish online_<server>}` | Returns the number of online players on `<server>` that aren't vanished. |
| `${sayanvanish vanish_prefix}` | Returns the prefix for the player while they are vanished or an empty String. |
| `${sayanvanish vanish_suffix}` | Returns the suffix for the player while they are vanished or an empty String. |
///
[SayanVanish]: https://modrinth.com/plugin/sayanvanish
[source-paper]: https://github.com/Syrent/SayanVanish/blob/6e03b874464a7f07c0baba233c94cdfefab5d3e2/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/hook/FeatureHookAdvancedServerList.kt
[source-velocity]: https://github.com/Syrent/SayanVanish/blob/6e03b874464a7f07c0baba233c94cdfefab5d3e2/sayanvanish-proxy/sayanvanish-proxy-velocity/src/main/kotlin/org/sayandev/sayanvanish/velocity/feature/features/hook/FeatureHookAdvancedServerList.kt
+183
View File
@@ -0,0 +1,183 @@
---
icon: octicons/plus-circle-24
---
AdvancedServerList allows you to add your own Placeholders to be useable through its `${identifier value}` format.
The benefit of this method over alternatives such as using PlaceholderAPI placeholders is availability and the fact that these placeholders can be used within the [`condition` option](../profiles/options/condition.md) of the plugin.
Adding your own placeholder is relatively easy and only requires the main API module to be used in your dependencies, unless you need platform-specific values (Explained later on).
## Create your PlaceholderProvider class
AdvancedServerList's placeholder system uses a dedicated [`PlaceholderProvider`](reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md) class where the placeholder gets defined and its values parsed.
In order to add your own, you'll need to first create a new class and make it extend the `PlaceholderProvider` class:
```java title="MyPlaceholder.java"
public class MyPlaceholder extends PlaceholderProvider {
}
```
Your IDE should now report issues, namely a missing method to override and a missing Constructor to match the extended class' one. Your IDE should allow you to easily implement those, if not, then manually add the constructor with a `String` argument and the `public String parsePlaceholder` method with `String`, [`GenericPlayer`](reference/api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) and [`GenericServer`](reference/api/ch.andre601.advancedserverlist.api/objects/genericserver.md) arguments:
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder(String identifier) {
super(identifier); // (1)
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
return null;
}
}
```
1. It is recommended to replace the Constructor with a No-Args Constructor and set the placeholder name directly in the `super` call:
```java
public MyPlaceholder() {
super("myplaceholder");
}
```
## Parsing placeholders
To now parse your placeholders, all you need to do is edit the `parsePlaceholder` method.
AdvancedServerList calls this method whenever it finds a matching identifier of a PlaceholderProvider, with the `String` argument being the actual value after the identifier and the `GenericPlayer` and `GenericServer` arguments holding the Player and server values respectively.
As an example, assuming you simply want to return `Hello` for the placeholder `${myplaceholder sayHello}`, this would be the code for it:
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder() {
super("myplaceholder");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if (placeholder.equals("sayHello")) {
return "Hello";
}
return null; // (1)
}
}
```
1. Returning `null` tells AdvancedServerList that the placeholder was invalid, making it return the placeholder unchanged, while also reporting an error, if used in `condition`.
## Registering the Placeholder
The final step now would be to register your placeholder for AdvancedServerList to use.
To do this, obtain an instance of the [`AdvancedServerListAPI`](reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md) through its static `get()` method and then call `addPlaceholderProvider(PlaceholderProvider)` through it:
/// tab | :fontawesome-solid-paper-plane: Paper Example
```java title="MyPlugin.java"
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
getLogger().info("Hooked into AdvancedServerList!");
}
}
```
///
/// tab | :octicons-git-merge-24: BungeeCord Example
```java title="MyPlugin.java"
public class MyPlugin extends Plugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
getLogger().info("Hooked into AdvancedServerList!");
}
}
```
///
/// tab | :simple-velocity: Velocity Example
```java title="MyPlugin.java"
@Plugin(
id = "myplugin",
version = "1.0.0",
authors = {"You?"},
dependencies = {
@Dependency(id = "advancedserverlist")
}
)
public class MyPlugin {
private final ProxyServer proxy;
private final Logger logger;
@Inject
public MyPlugin(ProxyServer proxy, Logger logger) {
this.proxy = proxy;
this.logger = logger;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
logger.info("Hooked into AdvancedServerList!");
}
}
```
///
## You're done
Your Placeholders should now be registered successfully if they check the following:
- The provided identifier is not `null` nor empty.
- The provided identifier does not contain spaces.
- The provided identifier is not already registered in the API.
## Note on `GenericPlayer` and `GenericServer`
The different platform APIs of AdvancedServerList provide extended versions of the `GenericPlayer` and `GenericServer` instances used, providing additional methods otherwise not available.
Should you want to use these specific instances will you need to add the platform API as an additional dependency to your project and then cast the `GenericPlayer` and/or `GenericServer` instance to the platform specific version.
Below is an example using the `platform-bukkit` API (This assumes your plugin is one running on Paper):
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder() {
super("myplaceholder");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if (!(player instanceof BukkitPlayer bukkitPlayer)) {
return null; // (1)
}
return switch (placeholder) {
case "playedBefore" -> String.valueOf(bukkitPlayer.hasPlayedBefore());
case "whitelisted" -> String.valueOf(bukkitPlayer.isWhitelisted());
case "banned" -> String.valueOf(bukkitPlayer.isBanned());
default -> null;
};
}
}
```
1. Depending on the Java version you use will you need to alter the code:
```java
if (!(player instanceof BukkitPlayer)) {
return null;
}
// You need to cast it separately.
BukkitPlayer bukkitPlayer = (BukkitPlayer) player;
// ...use bukkitPlayer here.
```
+14 -14
View File
@@ -14,7 +14,7 @@ They are ordered newest to oldest.
- 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)
[hidePlayersHoverEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayershoverenabled
## v4.0.0 { #v4.0.0 }
@@ -30,8 +30,8 @@ They are ordered newest to oldest.
- [`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)
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled
## v3.3.0 { #v3.3.0 }
@@ -62,15 +62,15 @@ 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(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(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)
[players]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#players(list<string>)
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayersenabled
[motd]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#motd
[playercounttext]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#playercounttext
[players]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#players
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.0-changed }
@@ -137,8 +137,8 @@ They are ordered newest to oldest.
- `setExtraPlayerEnabled(Integer)` in `ProfileEntry.Builder` - Typo in method name.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled()
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount()
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount
[profileentry.builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
+9 -161
View File
@@ -84,127 +84,21 @@ dependencies {
```
///
## Adding your own Placeholders
## Tutorials
<!-- admo:info This requires the main api module -->
Dedicated pages to explain aspects of the API are available:
The API allows you to add your own placeholders which would be available through the `${<identifier> <values>}` placeholder Pattern in a Server List profile.
To add your own placeholders, follow these steps:
### 1. Create a Placeholder class
You should first create a new class and make it extend the abstract [`PlaceholderProvider`][placeholderprovider]. This class includes a constructor and a method you need to add, so do that:
```java { .annotate title="Creating PlaceholderProvider class" }
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders(String identifier) {
super(identifier); // (1)
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
return null;
}
}
```
1. It is recommended to replace this constructor with a no-args Constructor and have the placeholder name set in the `super` directly:
```java
public MyPlaceholders() {
super("myplaceholders");
}
```
The [`parsePlaceholder(String, GenericPlayer, GenericServer)`][parseplaceholder] method is used by AdvancedServerList to replace a matching placeholder with a value.
What you return is completely up to you. Just keep in mind that returning `null` will be treated as an invalid placeholder by AdvancedServerList, resulting in the placeholder being returned as-is without any changes.
[placeholderprovider]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
[parseplaceholder]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md#parseplaceholder(string,-genericplayer,-genericserver)
/// details | Example of final class
type: example
```java title="MyPlaceholders.java"
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders() {
super("myplaceholders");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if(placeholder.equalsIgnoreCase("hello"))
return "Hello " + player.getName();
return null;
}
}
```
/// html | div.grid.cards
- [:octicons-plus-circle-24: Adding Placeholders](adding-placeholders.md)
- [:octicons-broadcast-24: Listening for Events](listening-for-events.md)
///
### 2. Register the Placeholders
Next step should be to register the placeholder. To achieve this, first obtain an instance of the [`AdvancedServerListAPI`][advancedserverlistapi] by using the static [`get()`][get] method. After that call [`addPlaceholderProvider(PlaceholderProvider placeholderProvider)`][addplaceholderprovider].
Your code may look similar to this:
```java title="Registering PlaceholderProvider class"
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholders());
}
}
```
[advancedserverlistapi]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
[get]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#get()
[addplaceholderprovider]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)
This should register your PlaceholderExpansion as long as it is valid, meaning that the identifier...
- ...is not `null`
- ...is not containing spaces
- ...is not using a name already registered in the API
### 3. Declare AdvancedServerList as (soft)depend
## Declare AdvancedServerList as (soft)depend
The final thing you should make sure is to define AdvancedServerList as a depend or soft-depend for your plugin, to make sure it loads after AdvancedServerList.
Below are example setups for Spigot, Paper, BungeeCord and Velocity:
/// tab | :simple-spigotmc: Spigot
//// tab | Softdepend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
softdepend:
- AdvancedServerList
```
////
//// tab | Depend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
depend:
- AdvancedServerList
```
////
///
/// tab | :fontawesome-solid-paper-plane: Paper
//// tab | Softdepend
```yaml title="paper-plugin.yml"
@@ -239,7 +133,7 @@ dependencies:
////
///
/// tab | :octicons-git-merge-24: BungeeCord
/// tab | :simple-spigotmc: BungeeCord
//// tab | Softdepend
```yaml title="bungee.yml"
name: "MyPlugin"
@@ -267,7 +161,7 @@ depends:
////
///
/// tab | :octicons-git-merge-24: Velocity
/// tab | :simple-velocity: Velocity
//// tab | Softdepend (File)
```json title="velocity-plugin.json"
{
@@ -355,50 +249,4 @@ public class MyPlugin {
### 4. You're done!
Your plugin should now hook into AdvancedServerList and register its own custom placeholders to use.
## Listening for events
<!-- admo:info These events require the platform-specific APIs -->
AdvancedServerList provides Events that your plugin can listen for specific situations.
### PreServerListSetEvent
This event is called **before** AdvancedServerList starts handling the PingEvent of the Server/Proxy.
It allows you to get and alter the [ProfileEntry][profileentry] used in the PingEvent, or even outright cancel the event itself.
The event offers the following methods:
- [`getEntry()`][getentry] - Gets the currently set [`ProfileEntry`][profileentry].
- [`setEntry(ProfileEntry)`][setentry] - Sets a new [`ProfileEntry`][profileentry] to use.
- [`isCancelled()`][iscancelled] - Gets the current cancelled state of the event.
- [`setCancelled(boolean)`][setcancelled] - Sets the current cancelled state.
Please check the server/proxy's documentation on how to listen for events with your plugin.
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry(profileentry)
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled()
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled(boolean)
### PostServerListSetEvent
This event is called **after** AdvancedServerList has completed its handling of the Server's/Proxy's PingEvent.
It provides a method to retrieve the [ProfileEntry][profileentry] used during the PingEvent.
Do note that this ProfileEntry is **not** a representation of what is actually displayed in the server list, but rather what has been used by AdvancedServerList. It may also be `null` should the event handling get cancelled for any reason.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
### ProfileEntry
The ProfileEntry record is the core class used within the `PreServerListSetEvent`. It sets what values (MOTD, Favicon, Players, etc.) should be displayed.
Note that the record is - by nature - immutable and that the [`Builder`][builder] class should be used to create a new ProfileEntry instance to use.
A convenience method ([`builder()`][builder()]) exists to create a `Builder` instance from an existing `ProfileEntry` in case you only want to alter certain options while everything else should remain unchanged.
This allows you to customize the Server list using your plugin. Just keep in mind that other plugins may also do the same, overriding your changes.
[builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
[builder()]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#builder()
Your plugin should now hook into AdvancedServerList and register its own custom placeholders to use.
+170
View File
@@ -0,0 +1,170 @@
---
icon: octicons/broadcast-24
---
AdvancedServerList provides some events that your plugin can listen to.
These events are structurally the same across all platforms, yet still require the usage of Platform-specific APIs due to how some events are registered and handled on some platforms.
The plugin currently offers the following events:
/// html | div.grid.cards
- [PreServerListSetEvent](#preserverlistsetevent)
- [PostServerListSetEvent](#postserverlistsetevent)
///
## PreServerListSetEvent
This event is executed before AdvancedServerList tries to modify the player list.
### Methods { #preserverlistsetevent-methods }
The following methods are available to use:
| Method | Description |
|-----------------------------------------|--------------------------------------------------------------------------------|
| [`getEntry()`][getentry] | Returns the [`ProfileEntry`][profileentry] that AdvancedServerList should use. |
| [`setEntry(ProfileEntry)`][setentry] | Sets the [`ProfileEntry`][profileentry] that should be used. |
| [`isCancelled()`][iscancelled] | Returns wether this event was cancelled or not. |
| [`setCancelled(boolean)`][setcancelled] | Sets the event's cancelled state. |
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled
### Notes { #preserverlistsetevent-notes }
- Providing `null` as the `ProfileEntry` for `setEntry(ProfileEntry)` is not allowed. Also, a copy of the provided `ProfileEntry` is made and used.
## PostServerListSetEvent
This event is executed after AdvancedServerList completed the server list modifications.
### Methods { #postserverlistsetevent-methods }
| Method | Description |
|--------------------------|--------------------------------------------------------------------------|
| [`getEntry()`][getentry] | Returns the [`ProfileEntry`][profileentry] that AdvancedServerList used. |
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry
### Notes { #postserverlistsetevent-notes }
- The returned `ProfileEntry` is not an actual representation of what is being displayed to the player and rather an instance of values the plugin received.
The returned value may also be `null` should the Ping Event be cancelled due to things such as an invalid Protocol or the [`PreServerListSetEvent`](#preserverlistsetevent) being cancelled.
## Registering the Events
/// tab | :fontawesome-solid-paper-plane: Paper
```java { title="MyPlugin.java" .annotate }
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
// (1)
Bukkit.getPluginManager().registerEvents(new ASLEventListener(), this);
}
}
```
1. `getServer()` from the `JavaPlugin` class can be used here too instead of the `Bukkit` singleton.
```java { title="ASLEventListener.java" }
public class ASLEventListener implements Listener {
@EventHandler
public void onPreServerListSet(PreServerListSetEvent event) {
System.out.println("PreServerListSetEvent fired!");
}
@EventHandler
public void onPostServerListSetEvent(PostServerListSetEvent event) {
System.out.println("PostServerListSetEvent fired!");
}
}
```
///
/// tab | :simple-spigotmc: BungeeCord
```java { title="MyPlugin.java" }
public class MyPlugin extends Plugin {
@Override
public void onEnable() {
getProxy().getPluginManager().registerListener(this, new ASLEventListener());
}
}
```
```java { title="ASLEventListener.java" }
public class ASLEventListener implements Listener {
@EventHandler
public void onPreServerListSet(PreServerListSetEvent event) {
System.out.println("PreServerListSetEvent fired!");
}
@EventHandler
public void onPostServerListSetEvent(PostServerListSetEvent event) {
System.out.println("PostServerListSetEvent fired!");
}
}
```
///
/// tab | :simple-velocity: Velocity
```java { title="MyPlugin.java" }
@Plugin(
id = "myplugin",
name = "MyPlugin",
version = "1.0.0",
authors = {"author"},
dependencies = {
@Dependency(
id = "advancedserverlist",
)
}
)
public class MyPlugin {
private final ProxyServer proxy;
@Inject
public MyPlugin(ProxyServer server) {
this.proxy = proxy;
}
@Subscribe
public void init(ProxyInitializeEvent event) {
proxy.getEventManager().register(this, new ASLEventListener());
}
}
```
```java { title="ASLEventListener.java" }
public class ASLEventListener {
@Subscribe
public void onPreServerListSet(PreServerListSetEvent event) {
System.out.println("PreServerListSetEvent fired!");
}
@Subscribe
public void onPostServerListSetEvent(PostServerListSetEvent event) {
System.out.println("PostServerListSetEvent fired!");
}
}
```
///
## What is a ProfileEntry?
Both events provide and use a so called [`ProfileEntry`][profileentry].
The `ProfileEntry` is a record, representing the values of a [Server List Profile](../profiles/index.md), meaning all values you can set in the profile configuration (Except condition and priority) will be available as a `ProfileEntry`.
It is important to note, that the `ProfileEntry` can be a representation of the [`profiles` option](../profiles/index.md#profiles), the global options or a mixture of both.
If you want to create your own instance, you'll need to use the [`ProfileEntry.Builder` class](reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md) as the `ProfileEntry` is unmodifiable.
A convenience method in the form of [`builder()`][builder] exists to create a Builder instance of the ProfileEntry with its values already pre-set.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
[builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#builder
@@ -1,10 +1,10 @@
---
template: api-doc.html
api: true
methods:
- name: 'get'
description: |
Retrieve the instance used of this API.<br>
Retrieve the instance used of this API.
If no instance has been made so far will a new one be created.
returns: 'Instance of this API.'
attributes:
@@ -14,38 +14,38 @@ methods:
type: 'object'
- name: 'addPlaceholderProvider'
description: |
Adds the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to the list, if it passes the following checks:<br>
<ul>
<li>Provided PlaceholderProvider instance is not null.</li>
<li>The identifier is not null nor empty.</li>
<li>The identifier does not contain any spaces.</li>
<li>A PlaceholderProvider with the same identifier doesn't exist already.</li>
</ul>
Not passing any of the above checks results in a <a href="./../exceptions/invalidplaceholderproviderexception/"><code>InvalidPlaceholderProviderException</code></a> being thrown.
Adds the provided [`PlaceholderAPIProvider`](placeholderprovider.md) to the list, if it passes the following checks:
- Provided PlaceholderProvider instance is not null.
- The identifier is not null nor empty.
- The identifier does not contain any spaces.
- A PlaceholderProvider with the same identifier doesn't exist already.
Not passing any of the above checks results in a [`InvalidPlaceholderProviderException`](exceptions/invalidplaceholderproviderexception.md) being thrown.
parameters:
- name: 'placeholderProvider'
description: 'The <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to add.'
description: 'The [`PlaceholderProvider`](placeholderprovider.md) to add.'
type: PlaceholderProvider
attributes:
- notnull
throws:
- name: 'InvalidPlaceholderProviderException'
description: 'When the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a> is null, has a null or empty identifier, the identifier contains spaces, or another PlaceholderProvider with the same identifier is already in use.'
description: 'When the provided [`PlaceholderProvider`](placeholderprovider.md) is null, has a null or empty identifier, the identifier contains spaces, or another PlaceholderProvider with the same identifier is already in use.'
type:
name: 'void'
- name: 'retrievePlaceholderProvider'
description: 'Retrieves the <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> associated with the provided identifier, or <code>null</code> should no such entry exist.'
description: 'Retrieves the [`PlaceholderProvider`](placeholderprovider.md) associated with the provided identifier, or `null` should no such entry exist.'
parameters:
- name: 'identifier'
description: 'The identifier to find a matching <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> for.'
description: 'The identifier to find a matching [`PlaceholderProvider`](placeholderprovider.md) for.'
type: String
returns: 'Possibly-null <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a>.'
returns: 'Possibly-null [`PlaceholderProvider` instance](placeholderprovider.md).'
attributes:
- nullable
type:
name: PlaceholderProvider
type: object
link: './../placeholderprovider'
link: 'placeholderprovider.md'
---
# <api__class></api__class> AdvancedServerListAPI
@@ -1,27 +1,27 @@
---
template: api-doc.html
api: true
methods:
- name: 'getEntry'
description: 'Gets the <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> currently set.'
description: 'Gets the [`ProfileEntry`](../profiles/profileentry/index.md) currently set.'
returns: The currently used ProfileEntry.
type:
name: ProfileEntry
type: object
link: '../../profiles/profileentry/'
link: '../profiles/profileentry/index.md'
- name: 'setEntry'
description: |-
Sets the new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.<br>
This may not be <code>null</code>.
Sets the new [`ProfileEntry`](../profiles/profileentry/index.md) to use.
This may not be `null`.
parameters:
- name: 'entry'
description: 'The new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.'
description: 'The new [`ProfileEntry`](../profiles/profileentry/index.md) to use.'
type: ProfileEntry
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'When the provided ProfileEntry is <code>null</code>'
description: 'When the provided ProfileEntry is `null`'
type:
name: 'void'
- name: 'isCancelled'
@@ -1,11 +1,13 @@
---
template: 'api-doc.html'
api: true
constructors:
- name: 'InvalidPlaceholderProviderException'
description: Basic Constructor to create an instance of this Exception.
parameters:
- name: msg
type: String
description: The reason of the exception.
---
# <api__class></api__class> InvalidPlaceholderProviderException
@@ -1,29 +1,27 @@
---
template: api-doc.html
api: true
methods:
- name: 'getName'
description: |
Returns the name of the player.<br>
Note that on Spigot, Paper and other forks can the name differ from the one cached by AdvancedServerList, if the plugin was able to retrieve an OfflinePlayer instance from the server. On BungeeCord and Velocity will the returned String always be the name from the cache.<br>
<br>
Name may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by the plugin.
Returns the name of the player.
On BungeeCord and Velocity is the returned value always what AdvancedServerList has cached, while on paper the value may differ, should the plugin be able to obtain a OfflinePlayer instance from the Server.
Name may also be whatever has been defined in AdvancedServerList's `unknownPlayer -> name` config.yml Option.
returns: 'String representing the player''s name'
type:
name: String
type: object
- name: 'getProtocol'
description: |
Returns the protocol ID the player is using.<br>
The protocol ID is an integer used by Minecraft to determine what version a server or client is running.
description: Returns the protocol ID the player is using. The protocol ID is a unique positive integer that is used in Minecraft to determine the Version used by the Client and Server.
returns: 'Integer representing the protocol version of this player.'
type:
name: int
- name: 'getUUID'
description: |
Returns the unique ID associated with this player.<br>
<br>
UUID may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by AdvancedServerList.
Returns the unique ID associated with this player.
UUID may also be whatever has been defined in AdvancedServerList's `unknownPlayer -> uuid` config.yml Option.
returns: 'UUID of the player'
type:
name: UUID
@@ -32,11 +30,11 @@ methods:
# <api__interface></api__interface> GenericPlayer
A basic interface used to store generic player data to use in placeholder resolving.
The different variants of AdvancedServerList implement this into their own class and may provide additional data not available through this interface.
Interface used by the API to share common information across all platforms.
The following values will always be present, no matter the platform this interface is used on:
Platform-specific interfaces extending this interface are available and may offer additional features in addition to what this interface is offering.
This interface always offers data for the following:
- [Name of the Player](#getname())
- [Protocol version of the Player](#getprotocol())
- [UUID of the Player](#getuuid())
- [Name of the Player](#getname)
- [Protocol version of the Player](#getprotocol)
- [UUID of the Player](#getuuid)
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getPlayersOnline'
@@ -24,4 +24,11 @@ methods:
# <api__interface></api__interface> GenericServer
Simple class used to wrap around some generic server data such as online player count, number of total players that can join and the host (IP/Domain) that got pinged by the player.
Interface used to share common information across all platforms.
Platform-specific interfaces extending this interface are available and may offer additional features in addition to what this interface is offering.
This interface always offers data for the following:
- [Players currently online on the Proxy/Server](#getplayersonline)
- [Max Players allowed to join the Proxy/Server](#getplayersmax)
- [IP/Domain pinged by the Player](#gethost)
@@ -1,23 +1,23 @@
---
template: api-doc.html
api: true
enums:
- name: 'true'
description: 'Boolean value <code>true</code>'
description: 'Boolean value `true`'
- name: 'false'
description: 'Boolean value <code>false</code>'
description: 'Boolean value `false`'
- name: 'not_set'
description: 'Boolean value <code>null</code>'
description: 'Boolean value `null`'
methods:
- name: 'resolve'
description: |
Returns a NullBool instance based on the provided <code>Boolean</code> value.<br>
In case of <code>null</code> being provided will <a href="#not_set"><code>NullBool.NOT_SET</code></a> be returned, otherwise will the corresponding NullBool instance matching the Boolean value be returned.
returns: 'NullBool instance based on the provided <code>Boolean</code> value.'
Returns a NullBool instance based on the provided `Boolean` value.
In case of `null` being provided will [`NullBool.NOT_SET`](#not_set) be returned, otherwise will the corresponding NullBool instance matching the Boolean value be returned.
returns: 'NullBool instance based on the provided `Boolean` value.'
parameters:
- name: 'bool'
description: 'The <code>Boolean</code> value to receive a NullBool instance for.'
description: 'The `Boolean` value to receive a NullBool instance for.'
type: Boolean
attributes:
- nullable
@@ -27,19 +27,19 @@ methods:
name: 'NullBool'
type: 'object'
- name: 'isNotSet'
description: 'Returns whether the NullBool is <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
returns: 'True if the instance is <a href="#not_set"><code>NullBool.NOT_SET</code></a>, otherwise false.'
description: 'Returns whether the NullBool is [`NullBool.NOT_SET`](#not_set)'
returns: 'True if the instance is [`NullBool.NOT_SET`](#not_set), otherwise false.'
type:
name: 'boolean'
type: 'primitive'
- name: 'getOrDefault'
description: |
Gets the corresponding boolean value associated with the NullBool instance.<br>
In the case of NullBool <a href="#isnotset()">not being set</a> will the provided default value be returned.
Gets the corresponding boolean value associated with the NullBool instance.
In the case of NullBool [not being set](#isnotset) will the provided default value be returned.
returns: 'True or false depending on the NullBool instance and the provided default value.'
parameters:
- name: 'def'
description: 'The default boolean value to return should the NullBool instance be <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
description: 'The default boolean value to return should the NullBool instance be [`NullBool.NOT_SET`](#not_set).'
type: boolean
type:
name: 'boolean'
@@ -48,4 +48,4 @@ methods:
# <api__enum></api__enum> NullBool
Enum used to return a `Boolean` value with a default one should no value be set.
Enum used to return a [`Boolean`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html){ target="_blank" rel="noopener" } Value with a fallback, should the boolean be `null`.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PlaceholderProvider'
@@ -8,27 +8,27 @@ constructors:
- name: 'identifier'
description: 'The identifier to use for the placeholder. Cannot be empty.'
type: String
attribute:
attributes:
- notnull
methods:
- name: 'parsePlaceholder'
description: |
Method called by AdvancedServerList's StringReplacer class to replace any appearances of <code>${&lt;identifier&gt; &lt;placeholder&gt;}</code> with whatever value a matching PlaceholderProvider may return.<br>
<br>
Returning <code>null</code> will be treated as an invalid placeholder by the plugin, making it return the placeholder as-is without any changes.
Method called by AdvancedServerList's StringReplacer class to replace any appearances of `${<identifier> <placeholder>}` with whatever value a matching PlaceholderProvider may return.
Returning `null` will be treated as an invalid placeholder by the plugin, making it return the placeholder as-is without any changes.
parameters:
- name: 'placeholder'
type: String
description: 'The part of the Placeholder that comes after the identifier and before the closing curly bracket.'
- name: 'player'
type: GenericPlayer
description: 'The <a href="./../objects/genericplayer/"><code>GenericPlayer</code> instance</a> used.'
description: 'The [`GenericPlayer` instance](objects/genericplayer.md) used.'
- name: 'server'
type: GenericServer
description: 'The <a href="./../objects/genericserver/"><code>GenericServer</code> instance</a> used.'
description: 'The [`GenericServer` instance](objects/genericserver.md) used.'
returns: 'Possibly-parsed or possibly-null String to replace the placeholder with.'
attribute:
attributes:
- nullable
- abstract
type:
@@ -47,4 +47,4 @@ methods:
Abstract class that is used to provide your own Placeholder patterns for AdvancedServerList to parse.
In order for your class to be considered a valid PlaceholderProvider will you need to set the `identifier` to a non-null, non-empty value without having any spaces in it.
Once set, use [`AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)`](advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)) to register your class for AdvancedServerList to use.
Once set, use [`AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)`](advancedserverlistapi.md#addplaceholderprovider) to register your class for AdvancedServerList to use.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
defaults:
type:
@@ -13,199 +13,199 @@ constructors:
methods:
- name: 'extraPlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#setextraplayersenabled(nullbool)"><code>disable extra Players</code></a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`extraPlayersEnabled()`](index.md#extraplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the max player count. Alternatively [disable extra Players](#extraplayersenabled).
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
- name: 'extraPlayersEnabled'
description: |
Sets whether the extra players feature should be enabled or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets whether the extra players feature should be enabled or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.
description: Thrown by the `CheckUtil` in case `null` has been provided as parameter.
- name: 'favicon'
description: |
Sets the value to use for the favicon.<br>
Sets the value to use for the favicon.
The following values are supported:
<ul>
<li>URL to a valid PNG file.</li>
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
<li><code>${player uuid}</code> to display the avatar of the player.
</ul>
Set to an empty String or <code>null</code> to not alter the Favicon.
- URL to a valid PNG file
- File name (with `.png` extension) matching a file saved in the favicons folder of AdvancedServerList
- `${player uuid}` to display the avatar of the player
Set to an empty String or `null` to not alter the Favicon.
parameters:
- name: 'favicon'
description: 'The favicon to set.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the Favicon has been set. Useful for chaining.'
- name: 'hidePlayersEnabled'
description: |
Sets whether the player count should be hidden or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets whether the player count should be hidden or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'hidePlayersHoverEnabled'
description: |
Sets ehther the Hover List of online Players should be hidden or not.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets ehther the Hover List of online Players should be hidden or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'hidePlayersHoverEnabled'
description: 'Whether the online players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'maxPlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#maxplayersenabled(nullbool)">disable max Players</a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`maxPlayersEnabled(NullBool)`](#maxplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the max player count. Alternatively [disable max Players](#maxplayersenabled).
parameters:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: 'Integer'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the max player count has been set. Useful for chaining.'
- name: 'maxPlayersEnabled'
description: |
Sets whether the max players feature should be enabled.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should maxPlayersEnabled be null.
Sets whether the max players feature should be enabled.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should maxPlayersEnabled be null.
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'motd'
description: |
Sets a new MOTD to use.<br>
<br>
Set to an empty list to not change the MOTD.<br>
Only the first two entries of the list will be considered and any additional ones discarded.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided motd list be null.
Sets a new MOTD to use.
Set to an empty list to not change the MOTD.
Only the first two entries of the list will be considered and any additional ones discarded.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should the provided motd list be null.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the motd has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'onlinePlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#onlineplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the online player count. Alternatively <a href="#onlineplayersenabled(nullbool)">disable online Players</a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`onlinePlayersEnabled(NullBool)`](#onlineplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the online player count. Alternatively [disable online Players.](#onlineplayersenabled).
parameters:
- name: 'onlinePlayersCount'
description: 'The number of online players to set.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the max player count has been set. Useful for chaining.'
- name: 'onlinePlayersEnabled'
description: |
Sets whether the online players feature should be enabled.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should onlinePlayersEnabled be null.
Sets whether the online players feature should be enabled.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should onlinePlayersEnabled be null.
parameters:
- name: 'onlinePlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'playerCountText'
description: |
Sets the text to override the player count with.<br>
<br>
Set to an empty String or <code>null</code> to not alter the player count text.
Set to an empty String or `null` to not alter the player count text.
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the player count text has been set. Useful for chaining.'
- name: 'players'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Sets the players (lines) to use for the hover.
Set to an empty list to not change the hover text.
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided okayersmotd list be null.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should the provided okayersmotd list be null.
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the players have been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'build'
description: 'Creates a new <a href="./.."><code>ProfileEntry</code> instance</a> with the values set in this Builder.'
returns: 'New <a href="./.."><code>ProfileEntry</code> instance</a>.'
description: 'Creates a new [`ProfileEntry` instance](index.md) with the values set in this Builder.'
returns: 'New [`ProfileEntry` instance](index.md).'
type:
name: 'ProfileEntry'
type: 'object'
link: './..'
link: 'index.md'
---
# <api__class></api__class> Builder
@@ -1,11 +1,11 @@
---
template: api-doc.html
api: true
constructors:
- name: 'ProfileEntry'
description: |
Creates a new instance of a ProfileEntry with the given values.<br>
It's recommended to use the <a href="./builder/"><code>Builder</code> class</a> for a more convenient configuration of the Settings.
Creates a new instance of a ProfileEntry with the given values.
It's recommended to use the [`Builder` class](builder.md) for a more convenient configuration of the Settings.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
@@ -64,32 +64,31 @@ constructors:
- nullable
seealso:
- name: 'ProfileEntry.Builder'
link: './builder/'
link: 'builder.md'
classes:
- name: 'Builder'
description: 'Builder class to create a new ProfileEntry instance.'
type: 'static class'
link: 'builder/'
link: 'builder.md'
methods:
- name: 'empty'
description: |
Creates an "empty" PlayerEntry with the following values set:<br>
<ul>
<li><a href="#motd()"><code>motd</code></a>: Empty List</li>
<li><a href="#players()"><code>players</code></a>: Empty List</li>
<li><a href="#playercounttext()"><code>playerCountText</code></a>: Empty String</li>
<li><a href="#favicon()"><code>favicon</code></a>: Empty String</li>
<li><a href="#hideplayersenabled()"><code>hidePlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
<li><a href="#extraplayersenabled()"><code>extraPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
<li><a href="#maxplayersenabled()"><code>maxPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#onlineplayersenabled()"><code>onlinePlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#hideplayershoverenabled()"><code>hidePlayersHoverEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#extraplayerscount()"><code>extraPlayersCount</code></a>: <code>null</code></li>
<li><a href="#maxplayerscount()"><code>maxPlayersCount</code></a>: <code>null</code></li>
<li><a href="#onlineplayerscount()"><code>onlinePlayersCount</code></a>: <code>null</code></li>
</ul>
Creates an "empty" PlayerEntry with the following values set:
- [`motd`](#motd): Empty List
- [`players`](#players): Empty List
- [`playerCountText`](#playercounttext): Empty String
- [`favicon`](#favicon): Empty String
- [`hidePlayersEnabled`](#hideplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`extraPlayersEnabled`](#extraplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`maxPlayersEnabled`](#maxplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`onlinePlayersEnabled`](#onlineplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`hidePlayersHoverEnabled`](#hideplayershoverenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`extraPlayersCount`](#extraplayerscount): `null`
- [`maxPlayersCount`](#maxplayerscount): `null`
- [`onlinePlayersCount`](#onlineplayerscount): `null`
returns: 'New ProfileEntry instance with empty/null values defined'
attributes:
- static
@@ -98,26 +97,32 @@ methods:
type: 'object'
- name: 'copy'
description: |
Creates a copy of this ProfileEntry instance.<br>
<br>
This is simply a convenience method to not have to call <a href="#builder()"><code>builder()</code></a><code>.</code><a href="./builder/#build()"><code>build()</code></a>.<br>
If you want to modify the ProfileEntry <a href="#builder()"><code>builder()</code></a> is preferred.
Creates a copy of this ProfileEntry instance.
This is a convenience method that avoids using [`builder()`](#builder) first followed by [`ProfileEntry.Builder.build()`](builder.md#build):
```java
ProfileEntry entry = ProfileEntry.empty(); // Obtain ProfileEntry
// Both do the same
ProfileEntry newEntry1 = entry.builder().build();
ProfileEntry newEntry2 = entry.copy();
```
returns: 'A copy of this ProfileEntry instance.'
seealso:
- name: 'builder()'
link: '#builder()'
link: '#builder'
type:
name: 'ProfileEntry'
type: 'object'
- name: 'builder'
description: |
Creates a <a href="./builder/"><code>Builder</code> instance</a> with the values from this ProfileEntry set.<br>
Creates a [`Builder` instance](builder.md) with the values from this ProfileEntry set.
Use this method if you would like to modify the ProfileEntry.
returns: 'A new <a href="./builder/"><code>Builder</code> instance</a> with the values of this ProfileEntry set.'
returns: 'A new [`Builder` instance](builder.md) with the values of this ProfileEntry set.'
type:
name: 'Builder'
type: 'object'
link: './builder/'
link: 'builder.md'
- name: 'motd'
description: 'Gets the currently set MOTD of this ProfileEntry.'
returns: 'The current MOTD used by this ProfileEntry.'
@@ -138,64 +143,63 @@ methods:
type: 'object'
- name: 'favicon'
description: |
Gets the currently set favicon of this ProfileEntry.<br>
Gets the currently set favicon of this ProfileEntry.
Note that the favicon usually is and supports one of the following options:
<ul>
<li>URL to a valid PNG file</li>
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList</li>
<li><code>${player uuid}</code> to display the avatar of the player</li>
</ul>
- URL to a valid PNG file
- File name (with `.png` extension) matching a file saved in the favicons folder of AdvancedServerList
- `${player uuid}` to display the avatar of the player
returns: 'The current favicon used by this ProfileEntry.'
type:
name: 'String'
type: 'object'
- name: 'hidePlayersEnabled'
description: |
Whether the player count should be hidden or not in this ProfileEntry.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the player count should be hidden or not in this ProfileEntry.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the player count should be hidden or not in this ProfileEntry.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'extraPlayersEnabled'
description: |
Whether the extra players feature should be used or not in this ProfileEntry.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the extra players feature should be used or not in this ProfileEntry.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the extra players feature should be used or not in this ProfileEntry.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'maxPlayersEnabled'
description: |
Whether the max players feature should be used or not.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the max players feature should be used or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the max players feature should be used or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'onlinePlayersEnabled'
description: |
Whether the online players feature should be used or not.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the online players feature should be used or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the online players feature should be used or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'hidePlayersHoverEnabled'
description: |
Whether the Hover List of online players should be hidden or not.<br>
To get the actual boolean value, use <a href="../../objects/nullbool/#getordefault()"><code>getOrDefault(boolean)</code></a> of the returned <a href="../../objects/nullbool"><code>NullBool</code></a>.<br>
<br>
When true, this option will force the <a href="#players()"><code>players()</code></a> list to be ignored.
Whether the Hover List of online players should be hidden or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
When true, this option will force the [`players()`](#players) list to be ignored.
returns: 'Whether the Hover List of online players should be hidden or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'extraPlayersCount'
description: 'Gets the currently set number of extra players of this ProfileEntry.'
returns: 'The current number of extra players used by this ProfileEntry.'
@@ -222,15 +226,15 @@ methods:
type: 'object'
- name: 'isInvalid'
description: |
Whether this ProfileEntry is considered invalid or not.<br>
Whether this ProfileEntry is considered invalid or not.
The ProfileEntry is considered invalid if all the following is true:
<ul>
<li><a href="#motd()"><code>motd()</code></a> is empty.</li>
<li><a href="#players()"><code>players()</code></a> is empty.</li>
<li><a href="#playercounttext()"><code>playerCountText()</code></a> is null/empty <b>and</b> <a href="#hideplayersenabled()"><code>hidePlayersEnabled()</code></a> is <code>false</code>.</li>
<li><a href="#favicon()"><code>favicon()</code></a> is null/empty.</li>
</ul>
As long as one of the above is <b>not</b> true is this ProfileEntry considered valid and <code>false</code> will be returned.
- [`motd()`](#motd) is empty.
- [`players()`](#players) is empty.
- [`playerCountText()`](#playercounttext) is null/empty **and** [`hidePlayersEnabled()`](#hideplayersenabled) is `false`.
- [`favicon()`](#favicon) is null/empty.
As long as one of the above is **not** true is this ProfileEntry considered valid and `false` will be returned.
returns: 'Whether this ProfileEntry is invalid or not.'
type:
name: 'boolean'
@@ -242,4 +246,4 @@ methods:
This record represents the content found in a server list profile YAML file.
The content may come from either the "profiles" list, the options in the file itself (global options) or a mix of both.
This class is immutable. Use [`builder()`](#builder()) to get a [`Builder` instance](builder.md) with the values of this class added.
This class is immutable. Use [`builder()`](#builder) to get a [`Builder` instance](builder.md) with the values of this class added.
@@ -1,20 +1,20 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
methods:
- name: 'getHandlerList'
description: 'Static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList</code></a> getter. Required by Paper.'
returns: 'The static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList instance</code></a> of this event.'
description: 'Static [`HandlerList`](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html){ target="_blank" rel="nofollow" } getter. Required by Paper.'
returns: 'The static [`HandlerList` instance](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html){ target="_blank" rel="nofollow" } of this event.'
attributes:
- static
type:
@@ -22,9 +22,9 @@ methods:
type: 'object'
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -32,18 +32,19 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
inherits:
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- 'getHandlers()'
- name: 'getHandlers()'
link: 'getHandlers()'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -9,7 +9,7 @@ constructors:
methods:
- name: 'getHandlerList'
returns: 'Static <code>HandlerList</code> instance.'
returns: 'Static `HandlerList` instance.'
attributes:
- static
type:
@@ -18,19 +18,24 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- 'getHandlers()'
- name: 'getHandlers()'
link: 'getHandlers()'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getPlayer'
@@ -10,24 +10,24 @@ methods:
type: 'object'
- name: 'hasPlayedBefore'
description: |
Returns whether this player has played on the server before.<br>
<br>
Returns whether this player has played on the server before.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player has played on the server before.'
type:
name: 'boolean'
- name: 'isBanned'
description: |
Returns whether this player has been banned from the server.<br>
<br>
Returns whether this player has been banned from the server.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player has been banned from the server.'
type:
name: 'boolean'
- name: 'isWhitelisted'
description: |
Returns whether this player is whitelisted on the server.<br>
<br>
Returns whether this player is whitelisted on the server.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player is whitelisted on the server.'
type:
@@ -35,16 +35,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> BukkitPlayer
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the SpigotMC/Paper server implementation of AdvancedServerList.
This interface includes a [`OfflinePlayer` instance](#getplayer()) obtained from the server the plugin runs on alongside some getters to get if the player [has played on the server before](#hasplayedbefore()), [is banned](#isbanned()) or [is whitelisted](#iswhitelisted()). These options actually require a proper OfflinePlayer instance to be present or will otherwise default to `false`.
This interface includes a [`OfflinePlayer` instance](#getplayer) obtained from the server the plugin runs on alongside some getters to get if the player [has played on the server before](#hasplayedbefore), [is banned](#isbanned) or [is whitelisted](#iswhitelisted). These options actually require a proper OfflinePlayer instance to be present or will otherwise default to `false`.
This class is useful for cases where you want to use the OfflinePlayer. Simply cast the GenericPlayer instance to a SpigotPlayer (Granted that it actually is an instance of it to begin with).
@@ -1,9 +1,9 @@
---
template: api-doc.html
api: true
methods:
- name: 'getWorlds'
description: 'Returns a <code>Map&lt;String, World&gt;</code> where the key is the name of the World and the value the world of the server.'
description: 'Returns a `Map<String, World>` where the key is the name of the World and the value the world of the server.'
returns: 'Possibly-empty Map containing pairs of Strings and Worlds.'
type:
name: 'Map<String, World>'
@@ -11,16 +11,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> BukkitServer
Spigot/Paper specific instance of a [`GenericServer`](../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md).
This interface includes a [Map of Worlds](#getworlds()) the server currently has.
This interface includes a [Map of Worlds](#getworlds) the server currently has.
This interface is useful for cases where you want to get the worlds of the Server itself, by simply casting your GenericServer instance to a BukkitServer one. Make sure to do proper instanceof checks first before attempting to cast.
@@ -1,12 +1,12 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
@@ -14,9 +14,9 @@ constructors:
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -24,12 +24,12 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -10,15 +10,19 @@ constructors:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,13 +1,16 @@
---
template: api-doc.html
api: true
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> BungeePlayer
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getServers'
@@ -11,11 +11,14 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> BungeeProxy
@@ -1,12 +1,12 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
@@ -14,9 +14,9 @@ constructors:
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -24,12 +24,12 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -9,15 +9,19 @@ constructors:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,9 +1,9 @@
---
template: api-doc.html
api: true
methods:
- name: 'getVersion'
description: 'Returns the <a href="../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/#getprotocol()">protocol version</a> of the player in a readable MC version format (i.e. 1.19.3).'
description: 'Returns the [protocol version](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md#getprotocol) of the player in a readable MC version format (i.e. 1.19.3).'
returns: 'The readable MC version the player uses.'
type:
name: 'String'
@@ -11,16 +11,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> VelocityPlayer
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the Velocity proxy implementation of AdvancedServerList.
Provides a [`getVersion()` method](#getversion()) to get the MC version used as a readable String (i.e. 1.19.3) rather than just the protocol version.
Provides a [`getVersion()` method](#getversion) to get the MC version used as a readable String (i.e. 1.19.3) rather than just the protocol version.
To get an instance of this class from a GenericPlayer instance, simply cast it to a VelocityPlayer (Granted that the GenericPlayer instance actually is a VelocityPlayer instance).
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getServers'
@@ -11,11 +11,14 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> VelocityProxy
+1 -1
View File
@@ -54,7 +54,7 @@ There are 5 frontmatter options, each following a specific structure:
- [`Constructors`](#constructors)
- [`Nested Classes`](#nested-classes)
- [`Enum Constants`](#enum constants)
- [`Enum Constants`](#enum-constants)
- [`Methods`](#methods)
- [`Inherits`](#inherits)
File renamed without changes.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

+3 -6
View File
@@ -1,7 +1,4 @@
document$.subscribe(async () => {
const url = 'https://api.allorigins.win/raw?url='
const apiUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/asl-api/releases/latest')}`
const repo_stats = document.querySelector('[data-md-component="source"] .md-source__repository');
async function loadCodebergInfo(data) {
@@ -61,7 +58,7 @@ document$.subscribe(async () => {
}
async function fetchApiInfo() {
const tag = await fetch(`${apiUrl}`)
const tag = await fetch('https://codeberg.org/api/v1/repos/Andre601/asl-api/releases/latest')
.then(_ => _.json());
const data = {
@@ -74,8 +71,8 @@ document$.subscribe(async () => {
async function fetchInfo() {
const [release, repo] = await Promise.all([
fetch(`${url}${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/latest')}`).then(_ => _.json()),
fetch(`${url}${encodeURIComponent('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList')}`).then(_ => _.json()),
fetch('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList/releases/latest').then(_ => _.json()),
fetch('https://codeberg.org/api/v1/repos/Andre601/AdvancedServerList').then(_ => _.json()),
]);
const data = {
+6
View File
@@ -55,4 +55,10 @@
.md-banner__inner.md-grid.md-typeset {
text-align: center;
}
.md-typeset .md-button.md-button--icon {
padding: .5em;
line-height: 0;
color: var(--md-default-fg-color);
}
+14
View File
@@ -0,0 +1,14 @@
---
title: /asl clearcache
---
# `/asl clearcache`
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.clearcache`
///
Resets the current Favicon and Player cache.
+19
View File
@@ -0,0 +1,19 @@
---
title: /asl help
---
# `/asl help [query]`
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.help`
**Arguments:**
- `[query]` - Optional search query to use
///
Displays information about provided commands.
If no query is provided will it list all commands. A page number can be used as query to switch between pages.
+3 -63
View File
@@ -4,68 +4,8 @@ icon: octicons/rel-file-path-24
# Commands
The plugin adds commands to use for various things related to the plugin itself.
The main command is `/advancedserverlist` but an alias called `/asl` is also registered to use.
AdvancedServerList adds commands that can be accessed via `/advancedserverlist` or `/asl` and provide different functionalities.
## Permissions
## Available commands
The main permission is `advancedserverlist.admin` for all commands, but you can also grant access to specific commands using `advancedserverlist.command.<subcommand>` instead (i.e. `advancedserverlist.command.help` to grant access to [`/asl help`](#help)).
## Subcommands
The following subcommands are available (Subcommands are case-insensitive):
- [`help`](#help)
- [`reload`](#reload)
- [`clearCache`](#clearcache)
- [`migrate <plugin>`](#migrate)
- [`profiles <add <profile> | copy <profile> <name> | list>`](#profiles)
### `help`
**Permission:** `advancedserverlist.command.help`
Shows a list of all available [subcommands](#subcommands) for AdvancedServerList.
----
### `reload`
**Permission:** `advancedserverlist.command.reload`
Reloads the plugin's `config.yml` and all available YAML files in the `profiles` folder.
----
### `clearcache`
**Permission:** `advancedserverlist.command.clearcache`
Clears the currently cached favicons and players.
----
### `migrate <plugin>` { #migrate }
**Permission:** `advancedserverlist.command.migrate`
**Arguments:**
- `<plugin>` - The plugin to migrate from.
Migrates files from one plugin over to AdvancedServerList.
Check the [Migration Page](../migration/index.md) for a list of supported plugins.
----
### `profiles <add <profile> | copy <profile> <name> | list>` { #profiles }
**Permission:** `advancedserverlist.command.profiles`
**Arguments:**
- `add <profile>` - Creates a new profile with name `<profile>` using the default profile values.
- `copy <profile> <name>` - Creates a copy of `<profile>` and saves it as `<name>`.
- `list` - Lists all loaded profiles. The entries have hover text for extra info.
Creates, copies or shows profiles in AdvancedServerList.
{nav}
+19
View File
@@ -0,0 +1,19 @@
---
title: /asl migrate
---
# `/asl migrate <plugin>`
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.`
**Arguments:**
- `<plugin>` - The plugin to migrate from.
///
Migrates configuration from the provided plugin to AdvancedServerList.
A list of supported plugins and known limitations can be found on the [Migration page](../migration/index.md).
+108
View File
@@ -0,0 +1,108 @@
---
title: /asl profiles
---
# `/asl profiles add <profile>`<br>`/asl profiles copy <profile> <name>`<br>`/asl profiles info <profile>`<br>`/asl profiles list`<br>`/asl profiles set <profile> <option> [value]`
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
**Subcommands:**
- [`add <profile>`](#add)
- [`copy <profile> <name>`](#copy)
- [`info <profile>`](#info)
- [`list`](#list)
- [`set <profile> <option> [value]`](#set)
///
Creates, copies, lists (info of) or sets values for profiles.
## `/asl profiles add <profile>` { #add }
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
- `advancedserverlist.command.profiles.add`
**Arguments:**
- `<profile>` - Name of the profile to create.
///
Creates a new profile using default values.
[`/asl reload`](reload.md) needs to be executed to load the new profile.
## `/asl profiles copy <profile> <name>` { #copy }
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
- `advancedserverlist.command.profiles.copy`
**Arguments:**
- `<profile>` - Name of the profile to copy.
- `<name>` - Name of the copy to make.
///
Creates a copy from the provided profile.
[`/asl reload`](reload.md) needs to be executed to load the new profile.
## `/asl profiles info <profile>` { #info }
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
- `advancedserverlist.command.profiles.info`
**Arguments:**
- `<profile>` - The profile to list info from.
///
<!-- admo:info Only executable by players. -->
Lists currently set values for the provided profile.
Each option has hover text to show the value and a click action to receive the matching [`/asl profiles set ...`](#set) command.
## `/asl profiles list` { #list }
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
- `advancedserverlist.command.profiles.list`
///
Lists all currently loaded profiles.
Each profile has a hover text displaying their priority, condition and whether they are considered valid.
## `/asl profiles set <profile> <option> [value]` { #set }
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.profiles`
- `advancedserverlist.command.profiles.set`
**Arguments:**
- `<profile>` - The profile to modify.
- `<option>` - The option to modify.
- `[value]` - Optional value to set. Leave empty to reset the option.
///
Sets the config option `<option>` to the provided `[value]`. Leaving value empty results in the option being reset to an empty/unset state.
[`/asl reload`](reload.md) needs to be executed to apply the changes.
+14
View File
@@ -0,0 +1,14 @@
---
title: /asl reload
---
# `/asl reload`
/// info |
**Permissions:**
- `advancedserverlist.admin`
- `advancedserverlist.command.reload`
///
Reloads the config.yml and any YAML file in the profiles folder.
+56 -41
View File
@@ -12,8 +12,7 @@ The guide is designed to be as easy to understand as possible. If you still have
The first step would be to download the plugin from a download page of your choice.
AdvancedServerList is available on the following places (Please note the current status!):
<div class="grid cards" markdown>
/// html | div.grid.cards
- [:simple-modrinth: **Modrinth**][modrinth]{ target="_blank" rel="nofollow" }
----
@@ -38,8 +37,7 @@ AdvancedServerList is available on the following places (Please note the current
----
:octicons-alert-24:{ style="color: var(--md-badge-fg--warning);" } **Discontinued!**
</div>
///
[spigot]: https://www.spigotmc.org/resources/102910/
@@ -47,8 +45,7 @@ The plugin is available for Paper, BungeeCord, Waterfall and Velocity, and has b
The plugin also supports these additional plugins. They are all optional.
<div class="grid cards" markdown>
/// html | div.grid.cards
- [**PlaceholderAPI**][placeholderapi]{ target="_blank" rel="nofollow" }
----
@@ -58,7 +55,7 @@ The plugin also supports these additional plugins. They are all optional.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
<!-- icon:paper -->
- [**ViaVersion**][viaversion]{ target="_blank" rel="nofollow" }
@@ -69,7 +66,7 @@ The plugin also supports these additional plugins. They are all optional.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
<!-- icon:paper -->
- [**PAPIProxyBridge**][papiproxybridge]{ target="_blank" rel="nofollow" }
@@ -80,7 +77,7 @@ The plugin also supports these additional plugins. They are all optional.
----
**Supported on:**
:simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
<!-- icon:proxies -->
- [**Maintenance**][maintenance]{ target="_blank" rel="nofollow" }
@@ -91,7 +88,7 @@ The plugin also supports these additional plugins. They are all optional.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
<!-- icon:all -->
- [**BanPlugins Addon**][addon]
@@ -102,11 +99,10 @@ The plugin also supports these additional plugins. They are all optional.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
<!-- icon:all -->
///
</div>
[addon]: ../addons/banplugins.md
[addon]: ../addons/first-party/banplugins.md
## 2. Installation { #installation }
@@ -136,7 +132,7 @@ Let's cover the files and folders...
#### Favicons folder
This folder allows you to store PNG images that should be used as favicons by the plugin. A favicon from this folder can be used by referencing the name (Including the `.png` file extension) in the [`favicon` option of the server list profile](../profiles/index.md#favicon).
This folder allows you to store PNG images that should be used as favicons by the plugin. A favicon from this folder can be used by referencing the name (Including the `.png` file extension) in the [`favicon` option of the server list profile](../profiles/options/favicon.md).
#### Profiles folder and default.yml { #profiles-folder-and-default-yml }
@@ -159,9 +155,9 @@ priority: 0
# 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 '||'.
# 'AND'/'&&' and 'OR'/'||' can be used to chain together multiple conditions.
#
# No condition or an empty condition will be treated as true by default.
# Removing the condition option or setting it to an empty String will be treated as a true condition being returned.
#
# Read more: https://asl.andre601.ch/profiles/#condition
#
@@ -189,8 +185,11 @@ profiles:
#
# 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.
# This option supports RGB colors for 1.16+ Servers and clients. More advanced MiniMessage features such as <gradient>
# can be used for further styling the text.
#
# <center> can be put at the start of a line to have AdvancedServerList automatically center the text as good as
# possible.
#
# Only the first two lines will be considered and any additional one is ignored.
#
@@ -204,20 +203,14 @@ motd:
#
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
# This option supports three types of input:
#
# 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.
# 1. Filename, including the .png extension, matching a filename in the favicons folder of the plugin.
# - 'random' can be used to have AdvancedServerList select a random image from the favicons folder every time
# the server is pinged.
# 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.
# 4. Player name, UUID or a placeholder that returns either.
# - https://mc-heads.net will be used to retrieve an image of the provided name/UUID.
#
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
#
@@ -225,6 +218,15 @@ motd:
#
# Read more: https://asl.andre601.ch/profiles/#favicon
#
# "The favicon isn't showing!"
# This is a side effect of using either URLs or player names/UUIDs for the favicon.
# These types require AdvancedServerList to create a new favicon object from scratch. This action takes a significant
# amount of time, which can cause the server to show with a huge ping.
# To avoid this is this action performed asynchronously. This means that the plugin doesn't wait for the favicon to
# be created before continuing, which can result in no favicon being available when it is done handling the ping.
# This should only happen for the first ping of a player and subsequent pings should display the favicon, if the
# pings are done within the configured cache time (See 'faviconCacheTime' in the config.yml).
#
favicon: ''
#
@@ -255,7 +257,7 @@ playerCount:
#
# 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.
# down-sampled to the nearest matching color.
#
# If not present or empty (hover: []), defaults to not modifying the hover.
#
@@ -448,6 +450,19 @@ printBanner: true
#
faviconCacheTime: 1
#
# Sets how AdvancedServerList should handle the size and positioning of images for favicons.
#
# Available options:
#
# - resize: Resizes the image to 64x64 pixels if it isn't these dimensions already.
# - center: Doesn't resize the image, but instead tries to center it as good as possible in a 64x64 area.
# - none: Doesn't resize the image and leaves it positioned at x 0 and y 0 (top-left) of the 64x64 area.
#
# Setting any not listed option or leaving this blank/removing it sets the option to resize.
#
faviconStrategy: 'resize'
#
# Options to disable while the Maintenance Plugin is present and Maintenance Mode is active.
#
@@ -516,7 +531,7 @@ 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.
#
configVersion: 7
configVersion: 9
```
///
@@ -535,14 +550,14 @@ There are certain files and folders that get created when certain events happen:
Creating your first profile is relatively simple.
It's best to open the `default.yml` file located inside `profiles` with the file editor of your choice ([:simple-vscodium: VSCodeium](https://vscodium.com/) or [:simple-notepadplusplus: Notepad++](https://notepad-plus-plus.org/) are recommended).
It's best to open the `default.yml` file located inside `profiles` with the file editor of your choice ([:simple-vscodium: VSCodeium](https://vscodium.com/){ target="_blank" rel="nofollow" } or [:simple-notepadplusplus: Notepad++](https://notepad-plus-plus.org/){ target="_blank" rel="nofollow" } are recommended).
This file should contain all available options that you can set and alter.
Edit the options to whatever you like. All text-based options, except [`condition`](../profiles/index.md#condition), support [MiniMessage formatting](../profiles/formatting.md).
Hexadecimal (RGB) colors are supported, however, only the [`motd` option](../profiles/index.md#motd) may display them and only for MC 1.16+ clients. Any other option will have the color down-sampled to the nearest supported color code.
Edit the options to whatever you like. All text-based options, except [`condition`](../profiles/options/condition.md), support [MiniMessage formatting](../profiles/formatting.md).
Hexadecimal (RGB) colors are supported, however, only the [`motd` option](../profiles/options/motd.md) may display them and only for MC 1.16+ clients. Any other option will have the color down-sampled to the nearest supported color code.
If you're unsure how a specific option should look like, head over to the [Profiles page](../profiles/index.md) for more information about the general structure.
All you need to know is, that a bare-bones server list profile requires a valid [priority](../profiles/index.md#priority) and at least one of the settings to be present.
All you need to know is, that a bare-bones server list profile requires a valid [priority](../profiles/options/priority.md) and at least one of the other options (except condition) to be present.
To give an example is here a basic profile that only modifies the MOTD and nothing else:
```yaml title="default.yml"
@@ -555,10 +570,10 @@ motd:
### Additional profiles
Additional profiles can be created to display different content under specific situations. To create a new file, either manually create a YAML file in the `profiles` folder, or use [`/asl profiles add <name>`](../commands/index.md#profiles) to have one created for you. In either case is it recommended to only use alphanummeric (`a-z` abd `0-9`) characters, dashes and underscores for the file name. You should also choose a name that fits the purpose of the file (i.e. for a profile that displays stuff when someone is banned, name it `banned.yml`).
Additional profiles can be created to display different content under specific situations. To create a new file, either manually create a YAML file in the `profiles` folder, or use [`/asl profiles add {name}`](../commands/profiles.md#add) to have one created for you. In either case is it recommended to only use alphanummeric (`a-z` abd `0-9`) characters, dashes and underscores for the file name. You should also choose a name that fits the purpose of the file (i.e. for a profile that displays stuff when someone is banned, name it `banned.yml`).
In case you manually created a YAML file, make sure it contains the [`priority`](../profiles/index.md#priority) setting and one of the other settings, to have a valid profile.
You should also add a [`condition`](../profiles/index.md#condition) to ensure that the profile is only loaded when needed. The [Expressions page](../profiles/expressions.md) covers what counts as valid expressions and conditions.
In case you manually created a YAML file, make sure it contains the [`priority`](../profiles/options/priority.md) setting and one of the other settings, to have a valid profile.
You should also add a [`condition`](../profiles/options/condition.md) to ensure that the profile is only loaded when needed. The [Expressions page](../profiles/expressions.md) covers what counts as valid expressions and conditions.
Do note that the plugin goes through the profiles in order of priority, starting with the highest number first, picking the first one that returns a `condition` returning true.
/// info | Note about Condition
@@ -582,7 +597,7 @@ The [Examples page](../examples/index.md) contains more examples of different se
## 4. Loading profiles { #loading-profiles }
Once you've set up your server list profile(s) is it time to load it/them.
To do this, simply run `/asl reload` as player (Requires permission `advancedserverlist.admin` or `advancedserverlist.command.reload`) or `asl reload` through the Server/Proxy console.
To do this, simply run [`/asl reload`](../commands/reload.md).
The plugin should then load any valid YAML file inside the `profiles` folder to then use.
+14 -2
View File
@@ -22,13 +22,25 @@ you can click the image to be sent to the actual video.
**Video Language:** :flag_gb: English
[![thumbnail](https://img.youtube.com/vi/9cU0uUWHOO0/0.jpg)](https://youtube.com/watch?v=9cU0uUWHOO0){ target="_blank" rel="nofollow" }
[![thumbnail](https://img.youtube.com/vi/9cU0uUWHOO0/0.jpg){ loading="lazy" }](https://youtube.com/watch?v=9cU0uUWHOO0){ target="_blank" rel="nofollow" }
### Ajneb97
**Video Language:** :flag_es: Spanish
[![thumbnail](https://img.youtube.com/vi/rIbljm_4HVI/0.jpg)](https://youtube.com/watch?v=rIbljm_4HVI){ target="_blank" rel="nofollow" }
[![thumbnail](https://img.youtube.com/vi/rIbljm_4HVI/0.jpg){ loading="lazy" }](https://youtube.com/watch?v=rIbljm_4HVI){ target="_blank" rel="nofollow" }
### faajrikha
**Video Language:** :flag_id: Indonesian
[![thumbnail](https://img.youtube.com/vi/-p938rOmqy4/0.jpg){ loading="lazy" }](https://www.youtube.com/watch?v=-p938rOmqy4){ target="_blank" rel="nofollow" }
### FINNI GAMER
**Video Language:** :flag_de: German
[![thumbnail](https://img.youtube.com/vi/1Kh3cPMDd0c/0.jpg){ loading="lazy" }](https://www.youtube.com/watch?v=1Kh3cPMDd0c){ target="_blank" rel="nofollow" }
## Text Tutorials
+18 -11
View File
@@ -43,8 +43,7 @@ AdvancedServerList supports the following platforms:
## Pages
<div class="grid cards" markdown>
/// html | div.grid.cards
- [:octicons-milestone-24: **Getting Started**](getting-started/index.md)
----
@@ -62,6 +61,16 @@ AdvancedServerList supports the following platforms:
----
A list of all available commands in AdvancedServerList.
----
**Other Pages:**
- [/asl clearcache](commands/clearcache.md)
- [/asl help](commands/help.md)
- [/asl migrate](commands/migrate.md)
- [/asl profiles](commands/profiles.md)
- [/asl reload](commands/reload.md)
- [:octicons-note-24: **Profiles**](profiles/index.md)
@@ -113,6 +122,8 @@ AdvancedServerList supports the following platforms:
**Other Pages:**
- [:octicons-plus-circle-24: Adding Placeholders](api/adding-placeholders.md)
- [:octicons-broadcast-24: Listening for Events](api/listening-for-events.md)
- [:octicons-log-24: Changelog](api/changelog.md)
- [:octicons-link-external-24: Javadocs](api/javadocs.md)
- [:simple-codeberg: Source Code](api/source.md)
@@ -128,12 +139,8 @@ AdvancedServerList supports the following platforms:
**Other Pages:**
- [:octicons-stop-24: BanPlugins Addon](addons/banplugins.md)
- [:material-percent: **PlaceholderAPI**](placeholderapi/index.md)
----
Information about available placeholders to use in PlaceholderAPI and how to use placeholders from other plugins in AdvancedServerList using PlaceholderAPI.
</div>
- First Party
- [:octicons-stop-24: BanPlugins Addon](addons/first-party/banplugins.md)
- Third Party
- [:octicons-eye-closed-24: SayanVanish](addons/third-party/sayanvanish.md)
///
+4 -8
View File
@@ -9,8 +9,7 @@ icon: octicons/file-directory-symlink-24
The below pages show guides on how to migrate from another plugin to AdvancedServerList.
These pages may include important information about the migration process and what you may have to do before, during or after the process.
<div class="grid cards" markdown>
/// html | div.grid.cards
- [**MiniMOTD**](plugins/minimotd.md)
----
@@ -22,16 +21,14 @@ These pages may include important information about the migration process and wh
----
Migrate from the Plugin [ServerListPlus](https://github.com/Minecrell/ServerListPlus){ target="_blank" rel="nofollow" }.
</div>
///
## AdvancedServerList
The below pages show guides on how to migrate from one version to another of AdvancedServerList.
These guides are only for the Server List Profile files, as the config.yml gets automatically migrated (Feature since v3.1.0).
<div class="grid cards" markdown>
/// html | div.grid.cards
- [**v3.8.0 to v3.9.0**](versions/v3.8.0-to-v3.9.0.md)
----
@@ -61,5 +58,4 @@ These guides are only for the Server List Profile files, as the config.yml gets
----
Migrate from version 1.5.3 to 1.6.0.
</div>
///
+1 -1
View File
@@ -11,7 +11,7 @@ Version `4.10.0` added support for migrating your existing `main.conf` configura
## How to Migrate
Execute the command [`/asl migrate minimotd`](../../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
Execute the command [`/asl migrate minimotd`](../../commands/migrate.md) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
## Example
+9 -11
View File
@@ -28,13 +28,15 @@ The following placeholders get converted:
### Colors/Formatting
The following color and formatting codes get converted[^1]:
The following color and formatting codes get converted[^1^](#n1):
| Color/Formatting code | Conversion |
|--------------------------------------------|-------------------------------------------------------------------------------|
| `&<color/format>` | Corresponding color/formatting code in MiniMessage (i.e. `&1 -> <dark_blue>`) |
| `&#<hexcode>` | `<#<hexcode>>` |
| `%gradient#<start>#<end>%<text>%gradient%` | `<gradient:#<start>:#<end>><text></gradient>` |
| `&{color/format}` | Corresponding color/formatting code in MiniMessage (i.e. `&1 -> <dark_blue>`) |
| `&#{hexcode}` | `#!mm <#{hexcode}>` |
| `%gradient#{start}#{end}%{text}%gradient%` | `#!mm <gradient:#{start}:#{end}>{text}</gradient>` |
<small>^1^{ #n1 }Conversion is done lazily and without context, which means that a text such as `&aHello &l%player%&a!` will be converted to `#!mm <green>Hello <bold>${player name}<green>!` when it should be `#!mm <green>Hello <bold>${player name}</bold>!`</small>
### Favicon options
@@ -42,13 +44,13 @@ The following Favicon options get converted into an equivalent one:
| Option | Conversion |
|---------|---------------------------------------------------------------------------------|
| `Heads` | `https://mc-heads.net/avatar/<entry>/64/nohelm` |
| `Heads` | `https://mc-heads.net/avatar/{entry}/64/nohelm` |
| `Helms` | Returned as-is with [placeholders replaced](#placeholders). |
| `Files` | Only `.png` files will be included with [placeholders replaced](#placeholders). |
## How to Migrate
Execute the command [`/asl migrate serverlistplus`](../../commands/index.md#migrate) to start the migration process. Make sure that ServerListPlus is present and enabled.
Execute the command [`/asl migrate serverlistplus`](../../commands/migrate.md) to start the migration process. Make sure that ServerListPlus is present and enabled.
## Example
@@ -275,8 +277,4 @@ playerCount:
amount: 0
favicon: ''
```
///
[^1]:
Converting of color and formatting codes is done lazely and without context.
This means that a text such as `&aHello &l%player%&a!` gets converted into `<aqua>Hello <bold>${player name}<aqua>!` when it actually should be `<aqua>Hello <bold>${player name}</bold>!`
///
@@ -5,7 +5,7 @@ icon: octicons/arrow-right-24
# < v3.7.0 to v3.7.0
Version 3.7.0 of AdvancedServerList brought significant changes to its conditions system.
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../../profiles/index.md#condition) option should now be used instead.
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../../profiles/options/condition.md) option should now be used instead.
## Migration
-33
View File
@@ -1,33 +0,0 @@
---
icon: material/percent
---
# PlaceholderAPI Placeholder support
AdvancedServerList provides support for [PlaceholderAPI] placeholders to be used, while also providing its own set of placeholders.
## Own placeholders
The below listed placeholders can be used through PlaceholderAPI in other plugins.
Note that the values depend on the player it is used for, as AdvancedServerList will try and get a matching [Server List Profile](../profiles/index.md) to display values from.
| Placeholder | Description |
|----------------------------------|--------------------------------------------------------------------------------------------------------|
| `%asl_favicon%` | Gives the value of `favicon` from a matching Profile. |
| `%asl_motd%` | Gives the value of `motd` in the matching Profile as a single String. |
| `%asl_playercount_extraplayers%` | Gives the value of `playerCount -> extraPlayers -> amount` from a matching Profile. Can return `null`. |
| `%asl_playercount_hover%` | Gives the value of `playerCount -> hover` from a matching Profile as a single String. |
| `%asl_playercount_maxplayers%` | Gives the value of `playerCount -> maxPlayers -> amount` from a matching profile. Can return `null`. |
| `%asl_playercount_text%` | Gives the value of `playerCount -> text` from a matching Profile. |
| `%asl_server_playersmax%` | Gives the output of `${server playersMax}` |
## Using Placeholders in Server List profiles
You can use any PlaceholderAPI placeholder in a server list profile, if the following conditions are met:
- The placeholder does not require the player to be online.
- [PAPIProxyBridge] is installed alongside AdvancedServerList, if used on a Proxy.
To use a placeholder, simply use its default `%identifier_parameters%` format.
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
+90 -79
View File
@@ -2,132 +2,143 @@
icon: octicons/file-code-24
---
Expressions are part of a Server List Profile's condition system and allows you to define when a profile should and should not be displayed.
The condition of a Server List Profile consists of one or multiple expressions.
The complete expression should return a boolean. If not, will the returned value be converted based on the following rules:
This page covers what the Expression system of AdvancedServerList offers and can do.
- Numbers will be converted to true, if not `0`
- Strings will be converted to true, if equal to `"true"`
## Content
The content below lists all supported forms of expressions that can be used to form a condition:
- [Types](#types)
- [Literals](#literals)
- [Numbers](#numbers)
- [Strings](#strings)
- [Booleans](#booleans)
- [Placeholders](#placeholders)
- [Binary Operators](#binary-operators)
- [Parenthesis](#parenthesis)
- [Negation](#negation)
- [Credits](#credits)
## Literals
## Types
The following values are treated as literal and can form a valid expression.
An expression contains different types of components that are evaluated to return a boolean output of either `true` or `false`.
Depending on the type(s) will the output be differently understood and handled.
### Numbers
### Literals
The following cases are considered literal values:
#### Numbers
Any number is considered an expression, meaning the below examples are considered valid:
Any postive or negative number with or without decimal points can form a valid expression.
/// example | Examples
```shell
```ruby
0
1000
-7
47.2
100
-1.0
10.2
```
///
#### Strings
### Strings
A String in single or double quotes is a valid expression.
Any quoted String can form a valid expression.
/// warning | Important
Specific keywords will be treated as [Binary Operators](#binary-operators) even if they are part of a word.
As an example, `Sand` would cause the expression engine to see `S AND` due to parts of the word matching `and`.
To avoid this is it very important to always surround Strings with single or double quotes, as that tells the expression engine to treat as a String.
/// note
Always surround Strings with single or double quotes to avoid ambiguities.
The parser may understand specific characters as [binary operands](#binary-operators) should they match an existing text causing issues. Wrapping a String in single or double quotes forces it to treat the value as a String literal.
///
/// example | Examples
```shell
```ruby
"Hello World!"
""
''
```
///
#### Booleans
### Booleans
Strings `true` and `false` are treated as boolean literals.
### Placeholders
Any [placeholder](placeholders.md) is a valid expression.
Words `true` and `false` (case insensitive) are treated as literal boolean values - unless quoted - and can form valid expressions.
/// example | Examples
```shell
${player protocol}
${player name}
```ruby
true
false
```
///
## Placeholders
[Placeholders](placeholders.md) are resolved into corresponding [Literals](#literals) and can therefore be valid expressions.
/// example | Examples
```ruby
${player name}
${player protocol}
${server playersOnline}
${server host}
```
///
### Binary Operators
## Binary Operators
`<expression> <binary operator> <expression>` is a valid expression.
Binary operators can be used to combine multiple expressions to form a new one.
### Boolean Binary Operators
The following binary operators can be used for boolean evaluation:
| Operator | True if |
|---------------|-------------------------------------------------------------------------------------------------------------|
| `and` / `&&` | Both expressions return true. |
| `or` / `\|\|` | Either expression returns true. |
| `==` / `=` | Both expressions are equal (Case sensitive). |
| `=~` / `~` | Both expressions are equal (Not Case sensitive). |
| `!=` | Both expressions are not equal (Case sensitive). |
| `!~` | Both expressions are not equal (Not case sensitive). |
| `\|-` | Left expression starts with right expression. |
| `-\|` | Left expression ends with right expression. |
| `<_` | Left expression contains right expression. |
| `<` | Left expression is less than the right expression. Strings use their text length as number. |
| `<=` | Left expression is less than, or equal to, the right expression. Strings use their text length as number. |
| `>` | Left expression is larger than the right expression. Strings use their text length as number. |
| `>=` | Left expression is larger than, or equal to, the right expression. Strings use their text length as number. |
These additional binary operators can also be used to perform certain actions:
| Operator | Semantic |
|----------|-----------------------------------------------------------------------------|
| `.` | Concatenates (merges) two Strings |
| `+` | Adds two numbers. Strings use their text length as number. |
| `-` | Subtracts one number from another. Strings use their text length as number. |
| `*` | Multiplies two numbers. Strings use their text length as number. |
| `/` | Divides one number by another. Strings use their text length as number. |
| Operator | True if | Case Sensitive? |
|---------------|------------------------------------------------------------------------------|-----------------|
| `and` / `&&` | Both expressions return true. | No |
| `or` / `\|\|` | Either expression returns true. | No |
| `==` / `=` | Both expressions are equal. | Yes |
| `=~` / `~` | Both expressions are equal. | No |
| `!=` | Both expressions are not equal. | Yes |
| `!~` | Both expressions are not equal. | No |
| `\|-` | Left expression starts with right expression. | Yes |
| `\|~` | Left expression starts with right expression. | No |
| `-\|` | Left expression ends with right expression. | Yes |
| `~\|` | Left expression ends with right expression. | No |
| `<_` | Left expression contains right expression. | Yes |
| `<~` | Left expression contains right expression. | No |
| `<` | Left expression is less than the right expression.^[1](#n1)^ | No |
| `<=` | Left expression is less than, or equal to, the right expression.^[1](#n1)^ | No |
| `>` | Left expression is larger than the right expression.^[1](#n1)^ | No |
| `>=` | Left expression is larger than, or equal to, the right expression.^[1](#n1)^ | No |
/// example | Examples
```shell
```ruby
${player name} != "Anonymous"
763 > ${player protocol} > 758
${player hasPlayedBefore} and ${player isBanned} == "false"
```
///
### Parenthesis
### Other Binary Operators
`( <expression> )` is a valid expression.
Parenthesis can be used to prevent ambiguities.
These additional binary operators can also be used to perform certain actions:
### Negation
| Operator | Semantic |
|----------|----------------------------------------------|
| `.` | Concatenates (merges) two Strings |
| `+` | Adds two numbers.^[1](#n1)^ |
| `-` | Subtracts one number from another.^[1](#n1)^ |
| `*` | Multiplies two numbers.^[1](#n1)^ |
| `/` | Divides one number by another.^[1](#n1)^ |
<small>^1^{ #n1 } In case of text will the text length be used to compare against.</small>
/// example | Examples
```ruby
${player protocol} + 10
"<green>" . ${player name}
```
///
## Parenthesis
Parenthesis can be used to enclose one or multiple expressions to create a new expression and avoid ambiguities.
/// example | Example
```ruby
(${player protocol} + 10) / 100
```
///
## Negation
`!` can be used to negate boolean expressions.
/// example | Examples
```shell
```ruby
!${player isWhitelisted}
```
///
+86 -47
View File
@@ -4,69 +4,108 @@ icon: octicons/pencil-24
# Formatting
AdvancedServerList utilizes the [MiniMessage] text formatting to allow colors, formatting codes, gradients, etc. for the text options `motd`, `playerCount -> hover` and `playerCount -> text`.
You can find a collection of available tags on the library's [Format] page. Please make sure to see the [Unsupported Formatting](#unsupported-formatting) section below for tags with no support.
This page explains specific points of formatting in AdvancedServerList, be it [text formatting](#text-formatting) or special quirks of [YAML formatting](#yaml-formatting).
If you have questions, don't hesitate to join the [M.O.S.S. Discord][discord] and ask in the `#asl-support` channel.
## Why no legacy colors (`&`/`§` codes) support?
## Text Formatting
### The tl;dr
AdvancedServerList uses the [MiniMessage Text Formatting][minimessage] for all formatting of text options ([`motd`](options/motd.md), [`playerCount -> hover`](options/playercount/hover.md) and [`playerCount -> text`](options/playercount/text.md)).
It supports all available [formatting tags][tags] with a [few exceptions and limitations](#exceptions-and-limitations).
MiniMessage tags are overall more readable while also allowing a lot more ways of formatting, with Legacy colors becoming an unreadable mess the more complex your formatting is.
### The long explanation
Legacy colors are a mess to read. This becomes especially evident with gradients using RGB color support.
As an example is here the text `Hello World` made into a Gradient with starting color `#084CFB` and end color `#ADF3FD` both in Legacy Color (Using `&` character) and MiniMessage format:
/// tab | Legacy Color Codes
```
&#084CFBH&#195DFBe&#296DFBl&#3A7EFCl&#4A8FFCo &#6BB0FCW&#7CC1FCo&#8CD2FDr&#9DE2FDl&#ADF3FDd
```
/// note
Please note that the available tags in MiniMessage depend heavily on the version used on the Server or Proxy.
While AdvancedServerList downloads MiniMessage for BungeeCord, is it using the built-in version on Paper and Velocity. Due to this could the version used be older than the one the plugin is compiled against.
///
/// tab | MiniMessage
```
<gradient:#084CFB:#ADF3FD>Hello World</gradient>
```
///
[minimessage]: https://docs.advntr.dev/minimessage/index.html
[tags]: https://docs.advntr.dev/minimessage/format.html
This becomes even more difficult to work with if you want to add text formatting to only parts of the text.
Assuming you want to make `World` be bold, with legacy colors, you would need to add `&l` before every character of the word, as colors reset any formatting applied. In MiniMessage all you need to do is put `<bold>` before the word and `</bold>` after it.
### Why MiniMessage and not `&`/`§`? { #why-minimessage }
Another benefit for gradients in particular is, that MiniMessage allows more than one color to be set for the gradient, i.e. you can set three colors for a start, middle and end color.
The reason to only support MiniMessage and not the so-called legacy color and formatting codes can be boiled down to 3 specific reasons:
## Web Editor
1. **MiniMessage tags are more clear on what they do.**
`<aqua>` makes it clear that it colors the text while `&b` is not as clear on that matter.
2. **MiniMessage allows easier combination of color and formatting codes.**
MiniMessage "remembers" what colors and formatting you applied, meaning if you close a tag and a previous one was set before it, that will continue.
/// details | Example
type: example
Below is a comparison of the same text made in MiniMessage and Color codes.
//// tab | MiniMessage
```mm
<aqua>Hello <green><bold>World! <red>How</bold> are</red> you?
```
////
//// tab | Color Codes
```
# We add &c after "How" to avoid a "bold space"
&bHello &a&lWorld! &c&lHow&c are &ayou?
```
////
///
3. **MiniMessage adds easier support for advanced features (RGB colors, gradients, etc.)**
With MiniMessage is it significantly more easy to use more advanced features such as gradients, rgb colors and similar.
While legacy colors have a form of RGB support is the format weird to look at and gradients become a mess. This is even worse when including bold for specific characters.
/// details | Example
type: example
Below is an example of a Gradient starting at `#084CFB` (:octicons-dot-fill-24:{ style="color: #084CFB;" }) and ending at `#ADF3FD` (:octicons-dot-fill-24:{ style="color: #ADF3FD;" }).
//// tab | MiniMessage
```mm
<gradient:#084CFB:#ADF3FD>Hello World!</gradient>
```
////
//// tab | Color Codes
```
&#084CFBH&#195DFBe&#296DFBl&#3A7EFCl&#4A8FFCo &#6BB0FCW&#7CC1FCo&#8CD2FDr&#9DE2FDl&#ADF3FDd
```
////
///
The Adventure team offers an [Online Web tool][webviewer]{ target="_blank" rel="nofollow" } that allows you to create the right MiniMessage tags while also having a preview.
Just visit the page and make sure to select `Server List` at the top to have a preview in a server list.
In general is MiniMessage a lot easier to manage and read as legacy color codes, as their appearance is more distinct from normal text.
## YAML Formatting
### Exceptions and Limitations
It is recommended to always surround your text with single or double quotes. This avoids situations where the YAML parses sees a specific character and treats it as a special YAML feature.
This is especially the case with MiniMessage tags, where `<` can be seen as the start of a so-called scolar value.
Due to the situation MiniMessage is used in are not all of its features available to use.
Below is a list of all features that cannot be used by AdvancedServerList, or can only be used by it under specific conditions.
Should you be using single quotes inside the text itself - i.e. for words such as `you're` - will you either need to surround the text with double quotes, or change the single quote in the word to two single quotes (`you're` becomes `you''re`).
| Feature | Tag | Supported? |
|---------------|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Hex Colors | `#!mm <#rrggbb>` | Only works properly on `motd` and will be downsampled to the closest named color for the other options. |
| Hex Gradients | `#!mm <gradient:#rrggbb:#rrggbb>` | Only works properly on `motd` and will be downsampled to the closest named color for the other options. |
| Click Actions | `#!mm <click:_type_:_value_>` | Tag will be rendered, but clicking the text won't do anything. |
| Hover Actions | `#!mm <hover:_type_:_value_>` | Tag will be rendered, but hovering the text won't show anything. |
| Insertions | `#!mm <insertion:_value_>` | Tag will be rendered, but clicking the text won't do anything. |
| Font | `#!mm <font:_font_>` | May work with the default fonts (`default`, `alt` and `uniform`) and with custom ones should the client already have it. |
| Selector | `#!mm <selector:_sel_>` | Tag will be rendered, but clicking the text won't do anything. |
| Score | `#!mm <score:_name_:_objective_>` | Will not render due to requiring the player to be on the server. |
| Pride | `#!mm <pride[:_flag_]>` | Only works if the server (Paper) or Proxy (Velocity) use `v4.18.0` of MiniMessage. BungeeCord is unaffected due to downloading the library. |
## Unsupported Formatting
## Yaml Formatting
### Non-functional Tags
YAML has some special quirks that require attention when editing the file.
Such quirks include features such as...
While MiniMessage will parse most, if not all tags, will not all work.
The following list of tags will do nothing, or only work under specific circumstances:
- Reading `~` and `null` as literal null values.
- Reading `>` and `|` as multi-line indicators.
| Tag | Note |
|---------------|------------------------------------------------------------------------------------------------------|
| `<click>` | |
| `<hover>` | |
| `<insertion>` | |
| `<font>` | May work if either a default MC font is used, or the player has a resourcepack with the font loaded. |
| `<selector>` | |
| `<score>` | |
To avoid this should you always surround text values with single (`'`) or double quotes (`"`) to force the YAML parser to see those as Strings.
### Non-supported RGB
/// note | Note on Single quotes inside text
Using single quotes, the YAML parser may get confused when the text itself also contains a single quote.
As an example `'You're banned'` would mess up the value because the `'` in `You're` is understood as the end of the String.
Only the `motd` option supports RGB colors. Every other option allowing MiniMessage format may only support the default colors provided by Minecraft (`<aqua>`, `<yellow>`, etc) with RGB colors being downsampled to their next supported option.
To avoid this issue, do one of the following:
[MiniMessage]: https://docs.advntr.dev/minimessage/index.html
[Format]: https://docs.advntr.dev/minimessage/format.html
[webviewer]: https://webui.advntr.dev/
- Surround the text with Double quotes instead of Single quotes (`"You're banned"`)
- Use two single quotes (`''`) inside the text every time you want to display a single quote character (`'You''re banned'`)
///
+18 -394
View File
@@ -2,398 +2,22 @@
icon: octicons/note-24
---
# Profiles { #profiles-file }
AdvancedServerList allows you to create multiple so called Server List Profiles.
A Server List Profile is a YAML file located in the plugin's `profiles` folder. Each Server List Profile allows you to modify one or multiple aspects of your server's display in a Multiplayer Server list.
Additionally can [Conditions](#condition) and a [Priority](#priority) be set to set when a specific profile should be displayed to a player.
## Required Options
For a Server List Profile to be valid, will it require the following options to be set:
- A valid [`priority`](#priority) option with a single, whole number.
- **At least** one of the following options:
- [`profiles`](#profiles) with at least one of the below options set.
- [`motd`](#motd) with at least one line to display.
- [`favicon`](#favicon) with a non-empty String.
- [`playerCount -> hidePlayers`](#hideplayers) with value `true`.
- [`playerCount -> hover`](#hover) with at least one line to display.
- [`playerCount -> text`](#text) with a non-empty String.
## Priority
The Priority option allows you to define what Server List Profile should be chosen first.
The plugin will go highest value to lowest value and will select the first Profile that has a [`condition`](#condition) returning `true`.
Should AdvancedServerList not find any profile with a positive condition will it not modify the server list for the players.
/// note
It is important to note that should no [`condition`](#condition) option be set will it default to `true`, meaning that a profile with priority 1 and no condition will be chosen over a profile with priority 0 and a condition, even if said condition also returns true.
///
## Condition
The `condition` option allows you to define specific requirements that need to be met to display the profile in question.
Not setting this option, or setting it to an empty String (`condition: ''`), will result in `true` being returned.
The condition option can hold one or multiple expressions. The Expression system is explained on the [Expressions page](expressions.md).
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
condition: '${player isWhitelisted}'
motd:
- '<grey>Hello ${player name}!'
- '<grey>Nice to see you.'
```
///
## Profiles
The `profile` option allows you to define a list of all other options, with the exception of [`priority`](#priority), [`condition`](#condition) or itself.
When multiple entries are defined will AdvancedServerList randomly select one.
Should an option exist in the file itself (i.e. [`motd`](#motd)) but not in the selected profiles entry will it be used. This allows you to randomize only one aspect of a Server List Profile while keeping all other options the same.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
profiles:
- motd: # You can also use ['<rainbow>Line1</rainbow>','<rainbow:!>Line 2</rainbow>']
- '<rainbow>Line 1</rainbow>'
- '<rainbow:!>Line 2</rainbow>'
playerCount:
text: '<green><bold>Awesome!'
- playerCount:
text: '<yellow><bold>Also Awesome!'
# This MOTD is used when the second profiles entry is selected.
motd:
- '<rainbow:2>Line A</rainbow>'
- '<rainbow:!2>Line B</rainbow>'
```
<div class="result" markdown>
![profiles-example-1](../assets/images/examples/profiles-example-1.jpg){ loading="lazy" }
![profiles-example-2](../assets/images/examples/profiles-example-2.jpg){ loading="lazy" }
</div>
///
## Motd
<!-- admo:tip Start a line with <code>&lt;center&gt;</code> to have it centered. -->
The `motd` option allows you to alter the "Message of the day" that is being displayed on a server in the multiplayer screen.
Please see the [Formatting](formatting.md) for all supported formatting options.
Multiple, randomly selected, MOTDs can be displayed by using the [`profiles`](#profiles) option.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
motd:
- '<rainbow:2>Rainbow Gradient</rainbow>'
- '<rainbow:!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
<div class="result" markdown>
![motd-example](../assets/images/examples/motd-example.jpg){ loading="lazy" }
</div>
///
## Favicon
<!-- admo:info Images will be resized to 64x64 pixels. -->
The `favicon` option can be used to define an image to display in the server list.
The Value can be one of the following:
- A URL pointing to a Image file. The URL needs to start with `https://` for it to work.
- A filename matching a pre-existing file in the `favicons` folder of the Plugin.
- Only PNG files are supported for now and the provided filename needs to end with `.png`
- `random` can be used to have the plugin select a random image from the Favicons folder.
- A player name or UUID.
- `${player name}`, `${player uuid}` or any [placeholder](placeholders.md) that resolves into a player name/UUID can be used.
- Uses [mc-heads.net](https://mc-heads.net) to resolve the Player Name/UUID.
/// details | Why is the favicon from URL/Placeholder not showing?
type: question
AdvancedServerList has to create a Favicon instance to use, as the Proxy/Server doesn't directly use PNG images.
This action takes time, so to not unnecessarely delay the Pinged Proxy/Server from showing is this done asynchrnously.
This has the issue that the Proxy/Server may be done with handling the Ping before AdvancedServerList is done creating the Favicon, resulting in no favicon being displayed.
This issue is only present for when using either a URL or a Player name/uuid and not for local favicons, as those are created when the plugin loads.
Favicons *should* display on the second ping, if pinged within the configured favicon cache time (Default: 1 minute).
///
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
# Placeholder resolves to UUID of Andre_601
favicon: '${player uuid}'
```
<div class="result" markdown>
![favicon-example](../assets/images/examples/favicon-example.jpg){ loading="lazy" }
</div>
///
## PlayerCount
The `playerCount` option contains various other options that are used to modify the player count (The text next to the ping icon that shows the online and max players of a server).
### HidePlayers
The `playerCount -> hidePlayers` option takes a boolean (`true` or `false`) to set whether the player count should be hidden or not.
When set to true will the player count be replaced with `???`.
In addition are the [`playerCount -> text`](#text) and [`playerCount -> hover`](#hover) options ignored.
If you want to not show any text at all, set this option to `false` (or remove it) and instead use the [`playerCount -> text`](#text) option.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayers: true
```
<div class="result" markdown>
![hideplayers-example](../assets/images/examples/hideplayers-example.jpg){ loading="lazy" }
</div>
///
### HidePlayersHover
The `playerCount -> hidePlayersHover` option takes a boolean (`true` or `false`) to set whether the hover displayed on the player count should be hidden or not.
When set to true will hovering over the player count show nothing.
In addition will [`playerCount -> hover`](#hover) not be used.
### Hover
The `playerCount -> hover` option allows you to define lines of text to show when a player hovers over the player count with their cursor.
/// info | Notes
Only basic color and formatting codes such as `<aqua>` and `<bold>` are accepted. Hex colors will be downsampled to the closest supported color.
///
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
hover:
- '<grey>Line 1'
- '<aqua>Line 2'
- '<gold>Line 3'
```
<div class="result" markdown>
![hover-example](../assets/images/examples/hover-example.jpg){ loading="lazy" }
</div>
///
### Text
The `playerCount -> text` option allows you to define a custom text to display instead of the usual `<online>/<max>`.
Please take note of the following caveats:
- The plugin won't automatically add the `<online>/<max>` back to the text you set. Instead you'll have to use `${server playersOnline}/${server playersMax}` to recreate this.
- The override is done by using the "outdated server" text displayed when a client pings a server that is not compatible. This means that the ping icon will appear crossed out and your server will be seen as "outdated" by the client (When hovering over the ping icon). This can't be avoided nor fixed by the plugin.
If you want to not show any text, just use a single color (i.e. `text: '<grey>'`) to do so.
This option only supports basic colors and no HEX colors.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
text: '<yellow><bold>Cool text!'
```
<div class="result" markdown>
![text-example](../assets/images/examples/text-example.jpg){ loading="lazy" }
</div>
///
### ExtraPlayers
<!-- admo:warning Using this option overrides the output of the <code>${server playersMax}</code> placeholder (Except in condition). -->
The `playerCount -> extraPlayers` option contains settings for the "extra players" feature, which adds X to the current online player count and sets it as the server's max player count.
#### Enabled { #extraplayers-enabled }
Enables the extraPlayers feature.
Use the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option to set how much to add to the max players count.
#### Amount { #extraplayers-amount }
<!-- admo:info This option does nothing when <code>playerCount -> hidePlayers</code> is enabled. -->
The `playerCount -> extraPlayers -> amount` option defines how much should be added to the current online player count to then use as max player count.
Example: Setting this option to `1` while currently 10 players are online will result in `10/11` being displayed on the player count (Assuming it is not being overriden by the [`playerCount -> text`](#text) option).
You can use placeholders that resolve into numbers for this option.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
extraPlayers:
enabled: true
amount: 1
```
<div class="result" markdown>
![extraplayers-example](../assets/images/examples/extraplayers-example.jpg){ loading="lazy" }
</div>
///
### MaxPlayers
<!-- admo:info This feature is ignored should <code>playerCount -> extraPlayers</code> be enabled. -->
<!-- admo:warning Using this option overrides the output of the <code>${server playersMax}</code> placeholder (Except in condition). -->
The `playerCount -> maxPlayers` option is similar in nature to the [`playerCount -> extraPlayers`](#extraplayers) option, with the difference that the number set is being used as the max player count, instead of adding it together with the online player count first.
#### Enabled { #maxplayers-enabled }
Enables the maxPlayers feature.
Use the [`playerCount -> maxPlayers -> amount`](#maxplayers-amount) option to set the max player count itself.
#### Amount { #maxplayers-amount }
<!-- admo:info This option does nothing when <code>playerCount -> hidePlayers</code> is enabled. -->
The `playerCount -> maxPlayers -> amount` option defines the number to use as the server's max players count.
Unlike the [`playerCount -> extraPlayers -> amount`](#extraplayers-amount) option does this one not first add the current online player count to the number to then set.
You can use placeholders that resolve into numbers for this option.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
maxPlayers:
enabled: true
amount: -1
```
<div class="result" markdown>
![maxplayers-example](../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
</div>
///
### OnlinePlayers
<!-- admo:warning Using this option alters the output of <code>playerCount -> extraPlayers</code> -->
The `playerCount -> onlinePlayers` option contains settings to enable and set the number of players online on the server.
#### Enabled { #onlineplayers-enabled }
Enables the online players feature.
Use the [`playerCount -> onlinePlayers -> amount`](#onlineplayers-amount) option to set the online players value itself.
#### Amount { #onlineplayers-amount }
Sets the number to display as the server's only player count.
You can use placeholders that resolve into numbers for this option.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
playerCount:
onlinePlayers:
enabled: true
amount: 10
```
<div class="result" markdown>
![onlineplayers-example](../assets/images/examples/onlineplayers-example.png)
</div>
# Profiles
The Server List Profile is a YAML file containing various options to modify and alter the appearance of your server in a player's server list.
Below can you find a list of all available options, including explanations and some examples.
/// html | div.grid.cards
- [`priority`](options/priority.md)
- [`condition`](options/condition.md)
- [`profiles`](options/profiles.md)
- [`motd`](options/motd.md)
- [`favicon`](options/favicon.md)
- [`playerCount -> hidePlayers`](options/playercount/hideplayers.md)
- [`playerCount -> hidePlayersHover`](options/playercount/hideplayershover.md)
- [`playerCount -> hover`](options/playercount/hover.md)
- [`playerCount -> text`](options/playercount/text.md)
- [`playerCount -> extraPlayers`](options/playercount/extraplayers.md)
- [`playerCount -> maxPlayers`](options/playercount/maxplayers.md)
- [`playerCount -> onlinePlayers`](options/playercount/onlineplayers.md)
///
+24
View File
@@ -0,0 +1,24 @@
# Condition
The `condition` option is a String that allows you to set a single or multiple requirements that need to be fulfilled to display the profile itself.
The String can contain [any valid expression](../expressions.md) that returns a boolean. Non-boolean values will be converted to one based on their value.
/// note
An empty condition String or no condition will always be treated as a true condition.
///
## Example
```yaml
priority: 1
#
# This condition returns true if the player's protocol version is
# less than 735.
#
# 735 is the protocol version for 1.16, which means this returns true
# if the player uses a version older than MC 1.16.
#
condition: '${player protocol} <= 735'
```
+63
View File
@@ -0,0 +1,63 @@
# Favicon
/// info | Favicon Merging (New since 5.6.0)
You can define multiple entries to be merged into a single Favicon by separating them with a semicolon.
Example: `background.png;${player uuid};foreground.png`
///
The `favicon` option is a String that sets the image that should be displayed in the server list.
The final image itself is 64x64 pixels and any images used with a differing size will be automatically resized to fit.
The option supports specific values:
- A URL with `https://` at the start that points to an image.
- A filename with `.png` extension that matches an existing file in the `favicons` folder of the plugin.
- You can use `random` to have the plugin randomly select an image from the folder.
- A player name or UUID that will be resolved into a Player head image using https://mc-heads.net{ target="_blank" rel="nofollow" }.
- Placeholders that get resolved into a player name or UUID (i.e. `${player name}` or `${player uuid}`) can be used.
/// details | Why is the favicon from URL/Player name/Player UUID/Placeholder not loading?
type: question
Servers and Proxies don't use the image file directly, but have their own specific Favicon instance.
To set the Favicon is AdvancedServerList required to create such a Favicon instance from the provided URL. This process takes a lot of time, so to not slow down the server/proxy more then necessary is this done asynchronously.
A downside of this is, that the server/proxy won't wait for the plugin to be done with creating the favicon, which results in the ping event being completed before the plugin could set the Favicon, resulting in none being displayed.
The created favicon is being cached and *should* display on the next ping, if done so within the configured `faviconCacheTime` (Default: 1 minute).
This issue only exists for Favicons created from a URL, player name/uuid or Placeholder and doesn't exist for local favicons located in the `favicons` folder as they are converted into Favicon instances during the plugin's startup.
///
## Favicon Resizing
Any image used that is not 64x64 pixels will by default be resized to be 64x64 pixels.
To allow more customization - especially with favicon merging - different modes can be used for images that do not have the right dimensions.
The mode used is set in the `faviconStrategy` option in the `config.yml` and can be one of the following options:
| Mode | Description |
|----------|---------------------------------------------------------------------------------------------------------------|
| `resize` | Default mode used. Resizes the image to 64x64 pixels. |
| `center` | Doesn't resize the image, but centers it as good as possible. |
| `none` | Won't resize nor move the image. The image itself will be placed at `0,0` which is the top-left of the image. |
Please note that the actual favicon displayed will always be 64x64 pixels, even if the image(s) depicted in it aren't.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
#
# In this example is the player Andre_601 watching the server
# list, so ${player uuid} is being resolved into their UUID,
# resulting in the head of their skin being displayed.
#
favicon: '${player uuid}'
```
/// html | div.result
![favicon-example](../../assets/images/examples/favicon-example.jpg){ loading="lazy" }
///
+25
View File
@@ -0,0 +1,25 @@
# Motd
The `motd` option is a List of Strings that sets the "Message of the day", referring to the two lines of text shown in the Multiplayer Server List.
This is the only option that supports RGB colors, if the server and client use at least version 1.16 of Minecraft.
/// tip | Centering the MOTD
Centering the MOTD can be done automatically by prefixing the lines with `<center>` (Even before color and formatting text), but only since version 5.2.0.
Before this version, you would need to manually center the text by adding spaces yourself.
///
## Example
```yaml
priority: 0
#
# Creates a MOTD with a smooth Rainbow gradient.
#
motd:
- '<rainbow:2>Rainbow Gradients</rainbow>'
- '<rainbow!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
/// html | div.result
![motd-example](../../assets/images/examples/motd-example.jpg)
///
@@ -0,0 +1,36 @@
# ExtraPlayers
The `extraPlayers` option contains additional options to enable and set the extra players feature.
The extra players feature modifies the displayed max players count by taking the current online player count, adding the configured [`amount`](#amount) to it and using that as the number.
/// warning | Important
Using this option will affect the output of the `${server playersMax}` option, except when used within the [`condition`](../condition.md) option.
This option is also ignored should the [`hidePlayers`](hideplayers.md) option be enabled.
///
## Enabled
Sets the enabled state of this option.
## Amount
Sets the amount that should be added to the online player count. Negative numbers are supported!
Placeholders that resolve into numbers can be used.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
extraPlayers:
enabled: true
amount: 1
```
/// html | div.result
![extraplayers-example](../../../assets/images/examples/extraplayers-example.jpg){ loading="lazy" }
///
@@ -0,0 +1,20 @@
# HidePlayers
The `hidePlayers` option is a boolean that sets wether the player count should be displayed or not.
When set to `true` will the player counte be replaced with three question marks. This also disables the [`hover`](hover.md) option.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayers: true
```
/// html | div.result
![hideplayers-example](../../../assets/images/examples/hideplayers-example.jpg){ loading="lazy" }
///
@@ -0,0 +1,20 @@
# HidePlayersHover
The `hidePlayersHover` is a boolean that sets wether the hover on the player count should be displayed or not.
When set to true will hovering over the player count with your cursor show nothing. This will also disable the [`hover`](hover.md) option.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
hidePlayersHover: true
```
/// html | div.result
No example image to show :C
///
@@ -0,0 +1,25 @@
# Hover
The `hover` option is a String list that overrides the Hover of the player count that usually displays the players currently on the server.
This option only supports basic color and formatting options, meaning you can't use RGB colors here.
There can also be an issue with the hover showing "...and X more" at the bottom. This is an issue that cannot be fixed by the plugin itself unfortunately.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
hover:
- '<grey>Line 1'
- '<aqua>Line 2'
- '<gold>Line 3'
```
/// html | div.result
![hover-example](../../../assets/images/examples/hover-example.jpg){ loading="lazy" }
///
@@ -0,0 +1,14 @@
# PlayerCount
The `playerCount` option contains various options all related to the player count (The text that displays `<online players>/<max players>` on the right side).
See below for available options:
/// html | div.grid.cards
- [`hidePlayers`](hideplayers.md)
- [`hidePlayersHover`](hideplayershover.md)
- [`hover`](hover.md)
- [`text`](text.md)
- [`extraPlayers`](extraplayers.md)
- [`maxPlayers`](maxplayers.md)
- [`onlinePlayers`](onlineplayers.md)
///
@@ -0,0 +1,36 @@
# MaxPlayers
The `maxPlayers` option contains additional options to enable and set the max players feature.
The max players feature modifies the displayed max players count by setting the configured [`amount`](#amount) to it.
/// warning | Important
Using this option will affect the output of the `${server playersMax}` option, except when used within the [`condition`](../condition.md) option.
This option is also ignored should the [`hidePlayers`](hideplayers.md) or [`extraPlayers`](extraplayers.md) option be enabled.
///
## Enabled
Sets the enabled state of this option.
## Amount
Sets the amount that should be displayed as the max players count!
Placeholders that resolve into numbers can be used.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
maxPlayers:
enabled: true
amount: -1
```
/// html | div.result
![maxplayers-example](../../../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
///
@@ -0,0 +1,35 @@
# OnlinePlayers
The `onlinePlayers` option contains additional options to enable and set the online players feature.
The online players feature modifies the displayed online players count by setting the configured [`amount`](#amount) to it.
/// warning | Important
This option affects the result of the [`extraPlayers`](extraplayers.md) option.
///
## Enabled
Sets the enabled state of this option.
## Amount
Sets the amount that should be displayed as the online players count!
Placeholders that resolve into numbers can be used.
## Example
```yaml
priority: 0
motd:
- '<grey>'
- '<grey>'
playerCount:
onlinePlayers:
enabled: true
amount: 10
```
/// html | div.result
![onlineplayers-example](../../../assets/images/examples/onlineplayers-example.jpg){ loading="lazy" }
///
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff. Show more