Compare commits

...
266 Commits
Author SHA1 Message Date
Andre601 a5ca6fb53e Bump version 2024-03-27 16:19:09 +01:00
Andre601 164a4823e8 Fix wrong regex for LibertyBansPlaceholders and limit to 2 results 2024-03-27 16:18:27 +01:00
Andre601 352191695a Merge pull request 'Remove dependencies section' (#251) from docs/remove-dependencies-section into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/251
2024-03-19 20:49:51 +00:00
Andre601 b2235e1d8b Fix formatting 2024-03-19 20:45:47 +00:00
Andre601 324b6d6f82 Try without remote branches 2024-03-19 20:39:29 +00:00
Andre601 fd6e2e736f Merge branch 'master' into docs/remove-dependencies-section 2024-03-19 20:34:26 +00:00
Andre601 efd5164b8e Add attr_list 2024-03-19 20:32:10 +00:00
Andre601 cdb86ae83f Use branch option for git clone 2024-03-19 20:30:11 +00:00
Andre601 90c02da02e Update default.yml and config.yml examples 2024-03-19 20:19:28 +00:00
Andre601 53d56c5891 Different wording 2024-03-19 20:16:07 +00:00
Andre601 7dd02fa0e5 Try without branch option 2024-03-19 20:15:06 +00:00
Andre601 e02b944181 revert 299eff1b0d
revert Try without branch
2024-03-19 20:14:42 +00:00
Andre601 299eff1b0d Try without branch 2024-03-19 20:14:10 +00:00
Andre601 aa24ab336b Remove .pages.yml file 2024-03-19 20:13:39 +00:00
Andre601 a8b9e69e30 Remove dependencies section 2024-03-19 20:11:42 +00:00
Andre601 065c9abf9c Try with just the branch option. 2024-03-19 20:09:49 +00:00
Andre601 bdc9668b29 Merge pull request 'Fix link' (#250) from docs/fix-link into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/250
2024-03-19 20:03:49 +00:00
Andre601 7d1abdd2b2 Fix link 2024-03-19 20:03:28 +00:00
Andre601 667c642708 Merge pull request 'Add "Available on Codeberg" badge' (#248) from docs/available-on-codeberg-badge into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/248
2024-03-19 19:56:12 +00:00
Andre601 79b13ceab6 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-19 19:55:45 +00:00
Andre601 169f560b2c Add mastodon posting 2024-03-19 15:26:56 +00:00
Andre601 7e8c41c27a Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.13.0' (#249) from renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/249
2024-03-19 12:03:54 +00:00
Andre601's Bot 973966c844 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.13.0 2024-03-19 12:01:18 +00:00
Andre601 eee90cc02f Remove not needed content 2024-03-18 22:10:33 +00:00
Andre601 ecf052b955 Remove unused setting 2024-03-18 22:09:43 +00:00
Andre601 a791c86df0 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:06:38 +00:00
Andre601 63d0b0ac62 Fix wrong workflow file target 2024-03-18 22:06:26 +00:00
Andre601 c46bc37818 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:05:13 +00:00
Andre601 268d5b84c9 Add quotes 2024-03-18 22:05:05 +00:00
Andre601 0c63abfac8 Merge branch 'master' into docs/available-on-codeberg-badge 2024-03-18 22:02:59 +00:00
Andre601 35ca151424 Set default branch directly 2024-03-18 22:02:45 +00:00
Andre601 e28800f72f Add evaluate when check 2024-03-18 21:43:51 +00:00
Andre601 8232357aba Add "Available on Codeberg" badge 2024-03-18 21:35:28 +00:00
Andre601 eae7f1117c Merge pull request 'Create PR-preview' (#247) from feature/pr-preview into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/247
2024-03-18 21:26:11 +00:00
Andre601 d25053b285 Add switch and set-branches git commands 2024-03-18 21:25:54 +00:00
Andre601 57273bd265 Use bot token for docs publish 2024-03-18 20:44:11 +00:00
Andre601 9cf694a7d6 Use bot token 2024-03-18 20:43:38 +00:00
Andre601 5bc0c7b843 Create PR-preview 2024-03-18 20:35:45 +00:00
Andre601 1c48fd61bc Fix wrong target URL 2024-03-18 19:54:15 +00:00
Andre601 8e622b4038 Add woodpecker file to CI run 2024-03-18 19:51:37 +00:00
Andre601 35e37bca2e Move site to dedicated repository 2024-03-18 19:50:47 +00:00
Andre601 cdb508994f Improve default.yml file 2024-03-18 15:53:20 +01:00
Andre601 1113c41379 Merge pull request 'Update dependency mkdocs-material to v9.5.14' (#246) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/246
2024-03-18 12:05:24 +00:00
Andre601's Renovate Bot d186ca82a2 Update dependency mkdocs-material to v9.5.14 2024-03-18 12:01:09 +00:00
Andre601 5cda9e819b Add missing changelog entry 2024-03-17 01:30:19 +00:00
Andre601 fe5a73440b Update API Javadocs URL 2024-03-16 21:39:01 +00:00
Andre601 a91e839f8c Update API reference 2024-03-14 14:53:36 +01:00
Andre601 d4668e0e76 Add PostServerListSetEvent 2024-03-14 14:08:17 +01:00
Andre601 305f3452c4 Merge pull request 'Update dependency com.google.guava:guava to v33.1.0-jre' (#245) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/245
2024-03-14 12:02:24 +00:00
Andre601's Renovate Bot fec3361fd7 Update dependency com.google.guava:guava to v33.1.0-jre 2024-03-14 12:01:22 +00:00
Andre601 f0861ffa6a Merge pull request 'Allow handling of options while Maintenance is active' (#244) from feature/configure-maintenance-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/244
2024-03-13 23:15:49 +00:00
Andre601 cfca3f72dc Fix ambigous method call getBoolean 2024-03-13 22:04:17 +01:00
Andre601 aca83e8350 Update priorities and bump version 2024-03-13 20:44:08 +01:00
Andre601 8383c8b97f Allow handling of options while Maintenance is active 2024-03-13 20:33:41 +01:00
Andre601 3d1ddaa782 Update Nav 2024-03-13 16:06:07 +01:00
Andre601 1d615e252f Update requirements.txt 2024-03-13 02:51:02 +01:00
Andre601 310e72d048 Don't use awesome-pages 2024-03-13 02:50:31 +01:00
Andre601 2754bf13aa Allow support for vanished players 2024-03-10 14:01:10 +01:00
Andre601 9ff5fcdaa7 Unify Placeholder parsing system. 2024-03-07 22:01:18 +01:00
Andre601 0ba7ed6ece Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.9.3' (#241) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/241
2024-03-06 12:46:39 +00:00
Andre601 2d8c774401 Merge pull request 'Update dependency mkdocs-material to v9.5.13' (#242) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/242
2024-03-06 12:46:23 +00:00
Andre601's Renovate Bot f68be63f64 Update dependency mkdocs-material to v9.5.13 2024-03-06 12:14:43 +00:00
Andre601's Renovate Bot 2695b393d8 Update dependency com.viaversion:viaversion-api to v4.9.3 2024-03-06 12:14:35 +00:00
Andre601 55821d2edf Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.3' (#240) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/240
2024-03-05 12:02:36 +00:00
Andre601's Renovate Bot b64e32503e Update dependency ch.qos.logback:logback-classic to v1.5.3 2024-03-05 12:01:13 +00:00
Andre601 c5ab9b118f Use code highlighting for expression examples 2024-03-05 02:11:01 +01:00
Andre601 6cc54349b5 Fix typo with fontawesome 2024-03-05 01:02:47 +00:00
Andre601 98d2de975e Add divider lines to optional dependencies 2024-03-05 00:59:59 +00:00
Andre601 6d1c118660 Remove unusued project.build.commit tag 2024-03-03 22:14:34 +01:00
Andre601 49e5b195ec Update way of reporting condition errors 2024-03-03 22:14:11 +01:00
Andre601 c92611e7f8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.2' (#238) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/238
2024-03-03 13:46:52 +00:00
Andre601's Renovate Bot 233414c45c Update dependency ch.qos.logback:logback-classic to v1.5.2 2024-03-03 12:01:19 +00:00
Andre601 c0629e10bc Add BanPlugins Addon to optional dependencies 2024-03-03 02:00:17 +00:00
Andre601 621eb7c489 Update API reference for ProfileEntry.Builder + changelog 2024-03-03 00:50:16 +01:00
Andre601 38e16f1d4b Bump version to 4.3.0 2024-03-03 00:14:42 +01:00
Andre601 2e61531079 Merge pull request 'Add LibertyBans' (#233) from feature/libertybans-addon into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/233
2024-03-02 23:12:05 +00:00
Andre601 5cf295d4c5 Merge branch 'master' into feature/libertybans-addon 2024-03-02 23:08:55 +00:00
Andre601 24d5865a57 Also add asl parent 2024-03-03 00:08:17 +01:00
Andre601 03c5e7d9d0 Add ExpressionParser to matchPackageNames 2024-03-03 00:08:17 +01:00
Andre601's Renovate Bot 7874fcf265 Update api.version to v3.2.1 2024-03-03 00:08:13 +01:00
Andre601 3e9070ebf9 Fix renovate.json 2024-03-03 00:06:12 +01:00
Andre601 478fa88a97 Also add asl parent 2024-03-02 12:10:33 +00:00
Andre601 346f94decc Add ExpressionParser to matchPackageNames 2024-03-02 12:09:06 +00:00
Andre601 f5e8a7e460 Merge pull request 'Update api.version to v3.2.1' (#237) from renovate/api.version into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/237
2024-03-02 12:06:58 +00:00
Andre601's Renovate Bot 3cb470a086 Update api.version to v3.2.1 2024-03-02 12:06:01 +00:00
Andre601 348ecce315 Fix renovate.json 2024-03-02 12:05:24 +00:00
Andre601 78463bca4f Merge branch 'master' into feature/libertybans-addon 2024-03-01 19:17:49 +00:00
Andre601 a6bde40f30 Update registry URL for asl API 2024-03-01 16:39:29 +00:00
Andre601 45fa7b5d69 Fix banExpiration placeholder using muteExpiration(player). 2024-03-01 16:18:34 +01:00
Andre601 1f52ff39d1 Update getting started guide 2024-02-29 16:06:42 +00:00
Andre601 bc66d925ff Merge pull request 'Update dependency mkdocs-material to v9.5.12' (#235) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/235
2024-02-29 12:25:20 +00:00
Andre601 41f8f6b29d Merge branch 'master' into renovate/mkdocs-material-9.x 2024-02-29 12:25:07 +00:00
Andre601 e032b2cc7f Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.1' (#234) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/234
2024-02-29 12:24:51 +00:00
Andre601's Renovate Bot 7c6d4a3840 Update dependency mkdocs-material to v9.5.12 2024-02-29 12:01:25 +00:00
Andre601's Renovate Bot 2f2095237d Update dependency ch.qos.logback:logback-classic to v1.5.1 2024-02-29 12:01:20 +00:00
Andre601 2a20af1f9a Update Javadoc link 2024-02-29 11:45:05 +01:00
Andre601 c424c5abd5 Use custom admonition for files 2024-02-28 15:55:31 +01:00
Andre601 101fc593d2 Update files 2024-02-28 15:50:41 +01:00
Andre601 cb9e65105e Add LibertyBans placeholder docs 2024-02-26 23:17:42 +01:00
Andre601 9b95bb1222 docs/api/index.md aktualisiert 2024-02-26 19:41:17 +00:00
Andre601 2b01ed9725 Use Collections.max and Update PlatformInfo 2024-02-26 20:29:45 +01:00
Andre601 9b77a1274d Update Link for api/source redirect 2024-02-26 17:49:01 +01:00
Andre601 18d5cca185 Update Repository URL for API 2024-02-26 17:48:32 +01:00
Andre601 d5b604c1d0 Add LibertyBans 2024-02-26 17:18:00 +01:00
Andre601 e9b4ccbb93 Merge pull request 'Update dependency mkdocs-material to v9.5.11' (#232) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/232
2024-02-24 12:03:07 +00:00
Andre601's Renovate Bot a14f8c961f Update dependency mkdocs-material to v9.5.11 2024-02-24 12:01:08 +00:00
Andre601 ba311f42c4 Use separated ExpressionParser system 2024-02-23 19:50:27 +01:00
Andre601 1b5379d54b Merge pull request 'Update dependency club.minnced:discord-webhooks to v0.8.4' (#231) from renovate/club.minnced-discord-webhooks-0.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/231
2024-02-23 12:02:14 +00:00
Andre601's Renovate Bot 03a1908ca6 Update dependency club.minnced:discord-webhooks to v0.8.4 2024-02-23 12:01:13 +00:00
Andre601 f9574d2f83 Add DISCORD_WEBHOOK_URL env variable to workflow 2024-02-22 13:42:41 +01:00
Andre601 7e45439dfe Merge pull request 'Make better local favicon handling' (#230) from feature/better-local-favicon-handling into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/230
2024-02-22 12:41:03 +00:00
Andre601 2a8b4ed640 Optimize Imports 2024-02-22 13:32:29 +01:00
Andre601 86c053e445 Remove unused createFavicon method in GenericEventWrapper 2024-02-22 13:29:39 +01:00
Andre601 7eba04bb9a Make better local favicon handling 2024-02-22 13:27:27 +01:00
Andre601 b4ac677f67 Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.2' (#228) from renovate/org.apache.maven.plugins-maven-shade-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/228
2024-02-21 12:15:13 +00:00
Andre601 989d44cc5e Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v4.16.0' (#229) from renovate/net.kyori-adventure-text-serializer-legacy-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/229
2024-02-21 12:15:00 +00:00
Andre601's Renovate Bot 9821875e7a Update dependency net.kyori:adventure-text-serializer-legacy to v4.16.0 2024-02-21 12:01:15 +00:00
Andre601's Renovate Bot 07e3b6702b Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.2 2024-02-21 12:01:09 +00:00
Andre601 31889fbd9c Merge pull request 'Update dependency net.kyori:adventure-text-minimessage to v4.16.0' (#227) from renovate/net.kyori-adventure-text-minimessage-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/227
2024-02-20 12:12:40 +00:00
Andre601 87a089a0fa Merge pull request 'Update dependency net.kyori:adventure-api to v4.16.0' (#226) from renovate/net.kyori-adventure-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/226
2024-02-20 12:12:14 +00:00
Andre601 88b91e8859 Add AdvancedBan to special registry lookup 2024-02-20 12:09:55 +00:00
Andre601's Renovate Bot f8097e3c72 Update dependency net.kyori:adventure-text-minimessage to v4.16.0 2024-02-20 12:01:39 +00:00
Andre601's Renovate Bot e237c990d8 Update dependency net.kyori:adventure-api to v4.16.0 2024-02-20 12:01:33 +00:00
Andre601 21c0ba975c Merge pull request 'Update dependency mkdocs-material to v9.5.10' (#225) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/225
2024-02-19 12:02:37 +00:00
Andre601's Renovate Bot 642ce922c3 Update dependency mkdocs-material to v9.5.10 2024-02-19 12:01:15 +00:00
Andre601 6e5466aacf Use relativePath for pom.xml resolving 2024-02-18 23:47:09 +01:00
Andre601 e6635cd844 Fix wrong add-on name 2024-02-18 23:37:38 +01:00
Andre601 229ab60c57 Add ExpressionsWarnHelper for (hopefully) better warnings. 2024-02-18 23:23:06 +01:00
Andre601 483daee999 Merge pull request 'v4.0.0: AdvancedBan Addon' (#222) from feature/advanced-ban-addon into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/222
2024-02-18 20:45:42 +00:00
Andre601 31ffcd7f7b Add placeholders for mute and ban expiration dates 2024-02-18 17:44:16 +01:00
Andre601 e5139cc00d Slightly better wording for loaded placeholder sets 2024-02-18 15:35:55 +01:00
Andre601 9b1b95b27a Merge branch 'master' into feature/advanced-ban-addon 2024-02-18 14:33:37 +00:00
Andre601 88d3ceeaf3 Use PlatformInfo to store add-ons paths 2024-02-18 15:33:11 +01:00
Andre601 f74f2f337c Only supports 1.20+ on Paper 2024-02-18 15:22:53 +01:00
Andre601 87b35f240e Make the addon more generic and work on Paper too 2024-02-18 15:20:58 +01:00
Andre601 fc861ea304 Merge pull request 'Update api.version to v3.2.0' (#224) from renovate/api.version into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/224
2024-02-18 12:29:57 +00:00
Andre601's Renovate Bot 927971ca12 Update api.version to v3.2.0 2024-02-18 12:01:52 +00:00
Andre601 0ecb8383e3 Make the AdvancedBan Addon actually work. 2024-02-17 16:56:04 +01:00
Andre601 9c3b2220d5 Add some debug messages 2024-02-17 14:13:16 +01:00
Andre601 46e15441fd Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.0' (#223) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/223
2024-02-17 12:09:19 +00:00
Andre601's Renovate Bot 2d2a1ca805 Update dependency ch.qos.logback:logback-classic to v1.5.0 2024-02-17 12:01:07 +00:00
Andre601 c577264e1d Update documentation 2024-02-16 11:13:50 +01:00
Andre601 27c3972ab0 Bump to v4.0.0 and remove expressions 2024-02-16 11:03:48 +01:00
Andre601 e4c90730ba Add AdvancedBan Addon 2024-02-16 10:51:35 +01:00
Andre601 0694e08399 Remove unused import 2024-02-15 18:18:08 +01:00
Andre601 2fefa966dd Improve formatting page 2024-02-14 20:58:46 +01:00
Andre601 a57cf3df17 Update outdated info in get-started 2024-02-13 20:55:41 +00:00
Andre601 1ae7260cf3 Update Hangar status 2024-02-13 20:44:30 +00:00
Andre601 8459eee57d Fix wrong Modrinth ID. 2024-02-13 21:19:38 +01:00
Andre601 f5cebf42ab Change ~= to ~= 2024-02-13 21:05:52 +01:00
Andre601 731bdeba7d Change way of applying dependencies in ModrinthVersionUploader 2024-02-13 17:31:45 +01:00
Andre601 d14cda243a Bump mkdocs-material to 9.5.9 2024-02-10 14:23:29 +00:00
Andre601 0a98aad138 Use hook to remove backslash from | 2024-02-09 16:00:52 +01:00
Andre601 1249a08264 Make sure Anonymous is in double quotes. 2024-02-09 01:36:15 +00:00
Andre601 c0414a5962 Actually, starts with operator is better 2024-02-09 01:34:50 +00:00
Andre601 9cc4d4bb36 Add example for contains expression 2024-02-09 01:33:51 +00:00
Andre601 338358a2ab Why did it remove magiclink? 2024-02-09 01:23:41 +00:00
Andre601 805ba83bb6 fix typos and improve readme 2024-02-08 00:30:21 +00:00
Andre601 0f646a8f8d Merge pull request 'Update dependency mkdocs-material to v9.5.8' (#220) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/220
2024-02-07 12:31:20 +00:00
Andre601's Renovate Bot 2519f09f6f Update dependency mkdocs-material to v9.5.8 2024-02-07 12:01:04 +00:00
Andre601 60bca9e3d7 Redo getting started guide and migration page 2024-02-07 01:41:08 +01:00
Andre601 da8f72fc50 Update mkdocs.yml... I think 2024-02-07 01:06:06 +01:00
Andre601 c42d4b8967 Add operand examples and open original in new tab 2024-02-05 12:46:30 +00:00
Andre601 0110854ae4 Fix some typo 2024-02-04 19:20:01 +00:00
Andre601 d6d5952cbc Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.2' (#219) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/219
2024-02-04 12:54:07 +00:00
Andre601's Renovate Bot f9d961cae7 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.2 2024-02-04 12:01:05 +00:00
Andre601 a387feea23 Fix wrong operand for contains in docs 2024-02-03 17:39:51 +01:00
Andre601 359c58163b Only add ViaVersion on paper platform. 2024-02-03 17:34:55 +01:00
Andre601 0892f5cd1d Use <_ for contains instead of <- 2024-02-03 17:21:54 +01:00
Andre601 452a7e6dcf Merge pull request 'Update dependency mkdocs-material to v9.5.7' (#218) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/218
2024-02-03 12:02:21 +00:00
Andre601's Renovate Bot 162dd10a73 Update dependency mkdocs-material to v9.5.7 2024-02-03 12:01:15 +00:00
Andre601 35120c5364 Bump version to 7.0.0 2024-01-31 21:42:24 +01:00
Andre601 6c828171d2 Add new operands to use 2024-01-31 21:41:22 +01:00
Andre601 dcc51f8458 [Docs] Improve profiles page 2024-01-30 17:32:10 +01:00
Andre601 1287ca62fe Fix platform for ${server host} 2024-01-29 23:24:18 +00:00
Andre601 1ff439fa95 Use Java's HttpClient for update checks 2024-01-29 16:37:49 +01:00
Andre601 ed0f832b2f Merge pull request 'Update dependency mkdocs-material to v9.5.6' (#217) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/217
2024-01-28 12:02:57 +00:00
Andre601's Renovate Bot b8e6b2acc6 Update dependency mkdocs-material to v9.5.6 2024-01-28 12:01:18 +00:00
Andre601 fba32c91c5 Add page about expressions 2024-01-28 00:20:52 +01:00
Andre601 6505ded12b Use assertEquals(...) for testing 2024-01-27 23:25:17 +01:00
Andre601 53088affcb docs/profiles/index.md aktualisiert 2024-01-27 22:23:00 +00:00
Andre601 9c030764fa Merge pull request 'Update dependency mkdocs-glightbox to v0.3.7' (#215) from renovate/mkdocs-glightbox-0.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/215
2024-01-25 12:06:08 +00:00
Andre601 d5d58f1eea Merge branch 'master' into renovate/mkdocs-glightbox-0.x 2024-01-25 12:05:53 +00:00
Andre601 7181092821 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.3.1' (#216) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/216
2024-01-25 12:05:37 +00:00
Andre601's Renovate Bot fc5ee4f242 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.3.1 2024-01-25 12:01:04 +00:00
Andre601's Renovate Bot 6e74c4fb14 Update dependency mkdocs-glightbox to v0.3.7 2024-01-25 12:00:59 +00:00
Andre601 f6a27342e6 Merge pull request 'Update dependency mkdocs-material to v9.5.5' (#214) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/214
2024-01-24 12:17:57 +00:00
Andre601's Renovate Bot 38b50df2c9 Update dependency mkdocs-material to v9.5.5 2024-01-24 12:00:49 +00:00
Andre601 db93816e55 Remove configurate relocation in Velocity 2024-01-23 15:40:49 +01:00
Andre601 244c2440fc Add migration for pre 3.7.0 files 2024-01-20 22:27:43 +01:00
Andre601 8e2c644669 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.1' (#213) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/213
2024-01-20 12:04:27 +00:00
Andre601 a68809ab31 Merge pull request 'Update dependency net.md-5:bungeecord-api to v1.20-R0.2' (#212) from renovate/net.md-5-bungeecord-api-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/212
2024-01-20 12:03:07 +00:00
Andre601's Renovate Bot 4b4fd80abe Update dependency org.junit.jupiter:junit-jupiter-engine to v5.10.1 2024-01-20 12:01:07 +00:00
Andre601's Renovate Bot 48ea128267 Update dependency net.md-5:bungeecord-api to v1.20-R0.2 2024-01-20 12:01:00 +00:00
Andre601 68e5795618 Link to new condition option 2024-01-19 15:37:27 +00:00
Andre601 1aa20e4196 Bump version to 3.7.0-b1 2024-01-19 16:10:56 +01:00
Andre601 6db25c8f9c Merge pull request 'Use BungeeTabListPlus inspired Condition system' (#209) from feature/use-btlp-condition-system into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/209
2024-01-19 15:06:30 +00:00
Andre601 0ef3db752d Improve docs 2024-01-19 16:05:54 +01:00
Andre601 1a26f5ad34 Merge branch 'master' into feature/use-btlp-condition-system 2024-01-19 14:51:10 +00:00
Andre601 17a5574be7 Fix placeholder issue (I hope) 2024-01-18 22:33:36 +01:00
Andre601 c7bfb8a736 Update examples and bump version 2024-01-18 14:29:54 +01:00
Andre601 7a756c3b98 Merge pull request 'Update actions/cache action to v4' (#211) from renovate/actions-cache-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/211
2024-01-18 12:09:07 +00:00
Andre601's Renovate Bot 1539e1c3c0 Update actions/cache action to v4 2024-01-18 12:01:20 +00:00
Andre601 a86872c021 Remove unused applyStringToStringFunction 2024-01-17 16:53:07 +01:00
Andre601 7d12499f39 Update docs and add basic tests 2024-01-17 16:48:35 +01:00
Andre601 455434b5f3 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.5' (#210) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/210
2024-01-17 12:02:54 +00:00
Andre601's Renovate Bot b66251ab20 Update dependency net.william278:papiproxybridge to v1.5 2024-01-17 12:01:18 +00:00
Andre601 4a1dfa5cb4 Use dedicated Template class for errors. 2024-01-16 22:58:06 +01:00
Andre601 1efd65e16c Merge branch 'master' into feature/use-btlp-condition-system 2024-01-16 21:48:26 +00:00
Andre601 908da9cd32 Add some logging messages 2024-01-16 22:47:53 +01:00
Andre601 e8a30c6ef7 Use BungeeTabListPlus inspired Condition system 2024-01-16 22:23:24 +01:00
Andre601 df164c104f Merge pull request 'Update dependency mkdocs-material to v9.5.4' (#208) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/208
2024-01-15 12:02:23 +00:00
Andre601's Renovate Bot acdf6f6e9a Update dependency mkdocs-material to v9.5.4 2024-01-15 12:01:07 +00:00
Andre601 f52a63a8f1 Merge pull request 'Update dependency mkdocs-glightbox to v0.3.6' (#207) from renovate/mkdocs-glightbox-0.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/207
2023-12-31 14:14:03 +00:00
Andre601's Renovate Bot 6a92cb3a16 Update dependency mkdocs-glightbox to v0.3.6 2023-12-31 12:01:29 +00:00
Andre601 1175451753 Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.12.1' (#206) from renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/206
2023-12-25 13:39:01 +00:00
Andre601's Renovate Bot 5c4130411b Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.12.1 2023-12-25 12:02:04 +00:00
Andre601 05727eeec5 Merge pull request 'Update dependency mkdocs-material to v9.5.3' (#205) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/205
2023-12-24 13:02:23 +00:00
Andre601's Renovate Bot 10af949abc Update dependency mkdocs-material to v9.5.3 2023-12-24 12:01:33 +00:00
Andre601 9851347e74 Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.3.2' (#204) from renovate/net.kyori-adventure-platform-bungeecord-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/204
2023-12-22 12:06:31 +00:00
Andre601's Renovate Bot c3e01c8b9c Update dependency net.kyori:adventure-platform-bungeecord to v4.3.2 2023-12-22 12:01:07 +00:00
Andre601 a646d9e998 Merge pull request 'Update dependency com.google.guava:guava to v33' (#203) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/203
2023-12-21 12:06:31 +00:00
Andre601's Renovate Bot 3c50a30d4a Update dependency com.google.guava:guava to v33 2023-12-21 12:01:11 +00:00
Andre601 4328ad6b44 Merge pull request 'Update actions/upload-pages-artifact action to v3' (#202) from renovate/actions-upload-pages-artifact-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/202
2023-12-20 12:18:17 +00:00
Andre601 34b0555508 Merge pull request 'Update actions/deploy-pages action to v4' (#201) from renovate/actions-deploy-pages-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/201
2023-12-20 12:18:04 +00:00
Andre601's Renovate Bot c92cd0058b Update actions/upload-pages-artifact action to v3 2023-12-20 12:01:05 +00:00
Andre601's Renovate Bot 2cfe8b8a27 Update actions/deploy-pages action to v4 2023-12-20 12:01:01 +00:00
Andre601 6530fed704 Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.12.0' (#200) from renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/200
2023-12-19 12:05:46 +00:00
Andre601 7efb203e7b Merge branch 'master' into renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x 2023-12-19 12:05:24 +00:00
Andre601 1a34376100 Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v4.15.0' (#199) from renovate/net.kyori-adventure-text-serializer-legacy-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/199
2023-12-19 12:05:00 +00:00
Andre601's Renovate Bot ec1aa5b393 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.12.0 2023-12-19 12:01:42 +00:00
Andre601's Renovate Bot 9683d3c001 Update dependency net.kyori:adventure-text-serializer-legacy to v4.15.0 2023-12-19 12:01:30 +00:00
Andre601 db60545fcc Add 1.20.4 in ModrinthVersionUploader 2023-12-18 20:19:44 +01:00
Andre601 392495ef63 Merge pull request 'Update dependency net.kyori:adventure-text-minimessage to v4.15.0' (#198) from renovate/net.kyori-adventure-text-minimessage-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/198
2023-12-18 12:53:37 +00:00
Andre601 903764b234 Merge branch 'master' into renovate/net.kyori-adventure-text-minimessage-4.x 2023-12-18 12:53:18 +00:00
Andre601 72329ed1e4 Merge pull request 'Update dependency net.kyori:adventure-api to v4.15.0' (#197) from renovate/net.kyori-adventure-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/197
2023-12-18 12:53:04 +00:00
Andre601's Renovate Bot c516b56053 Update dependency net.kyori:adventure-text-minimessage to v4.15.0 2023-12-18 12:44:29 +00:00
Andre601's Renovate Bot 5e4295fbfb Update dependency net.kyori:adventure-api to v4.15.0 2023-12-18 12:44:20 +00:00
Andre601 b140c0aa32 Merge pull request 'Add debug option for log messages' (#194) from feature/add-debug into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/194
2023-12-15 19:55:08 +00:00
Andre601 8f7b293541 Merge branch 'master' into feature/add-debug 2023-12-15 19:50:01 +00:00
Andre601 6f878164c5 Add debug option to getting started guide. 2023-12-13 18:27:17 +00:00
Andre601 a16801ff56 Remove mention of spigot being tested 2023-12-13 18:25:41 +00:00
Andre601 65a89cf762 Merge branch 'master' into feature/add-debug 2023-12-12 22:01:57 +00:00
Andre601 27d4ada179 Merge pull request 'Update maven Docker tag to v3.9.6' (#196) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/196
2023-12-12 12:03:23 +00:00
Andre601 574edfb246 Merge branch 'master' into renovate/maven-3.x 2023-12-12 12:03:04 +00:00
Andre601 7b7aad9d4e Merge pull request 'Update dependency mkdocs-material to v9.5.2' (#195) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/195
2023-12-12 12:02:38 +00:00
Andre601's Renovate Bot c5c9ed8109 Update maven Docker tag to v3.9.6 2023-12-12 12:01:19 +00:00
Andre601's Renovate Bot 58fea4090d Update dependency mkdocs-material to v9.5.2 2023-12-12 12:01:11 +00:00
Andre601 cd0aad6ec1 Add debug option for log messages 2023-12-09 20:26:54 +01:00
Andre601 fa45844434 Merge pull request 'Update dependency mkdocs-material to v9.5.1' (#192) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/192
2023-12-08 12:28:41 +00:00
Andre601 c4e2a144b5 Merge pull request 'Update actions/setup-python action to v5' (#193) from renovate/actions-setup-python-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/193
2023-12-08 12:28:31 +00:00
Andre601's Renovate Bot 7fe93c7021 Update actions/setup-python action to v5 2023-12-08 12:01:09 +00:00
Andre601's Renovate Bot 1d413a5c2a Update dependency mkdocs-material to v9.5.1 2023-12-08 12:01:00 +00:00
Andre601 51db52dbdd Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.9.2' (#190) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/190
2023-12-07 12:07:24 +00:00
Andre601 4ade528188 Merge pull request 'Update dependency mkdocs-material to v9.5.0' (#191) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/191
2023-12-07 12:07:12 +00:00
Andre601's Renovate Bot 64ba48a7c7 Update dependency mkdocs-material to v9.5.0 2023-12-07 12:02:54 +00:00
Andre601's Renovate Bot ac4edb2b97 Update dependency com.viaversion:viaversion-api to v4.9.2 2023-12-07 12:02:49 +00:00
Andre601 3ea000c98b Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.3' (#189) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/189
2023-12-06 13:06:15 +00:00
Andre601 746bef13e1 Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.9.1' (#188) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/188
2023-12-06 13:06:01 +00:00
Andre601's Renovate Bot 355ab73546 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.3 2023-12-06 12:01:10 +00:00
Andre601's Renovate Bot 67170c70e0 Update dependency com.viaversion:viaversion-api to v4.9.1 2023-12-06 12:01:07 +00:00
Andre601 f99c2df4e8 Merge pull request 'Update actions/configure-pages action to v4' (#186) from renovate/actions-configure-pages-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/186
2023-12-05 12:12:05 +00:00
Andre601 212ec04fb8 Merge pull request 'Update actions/deploy-pages action to v3' (#187) from renovate/actions-deploy-pages-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/187
2023-12-05 12:11:49 +00:00
Andre601's Renovate Bot 89c6089101 Update actions/deploy-pages action to v3 2023-12-05 12:01:17 +00:00
Andre601's Renovate Bot 87bce39d9a Update actions/configure-pages action to v4 2023-12-05 12:01:12 +00:00
Andre601 18900547a0 Remove leading and trailing whitespaces from server names 2023-12-05 01:46:45 +01:00
125 changed files with 4496 additions and 1539 deletions

No files matched your search

+5 -5
View File
@@ -24,11 +24,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.7
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Create/Get Cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
key: ${{ github.ref }}
path: .cache
@@ -39,11 +39,11 @@ jobs:
- name: Build docs
run: mkdocs build
- name: Configure GitHub Pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
uses: actions/upload-pages-artifact@v3
with:
path: 'site/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
+52
View File
@@ -0,0 +1,52 @@
when:
- event: pull_request
path:
include: ['.woodpecker/pr_preview.yml', 'requirements.txt', 'mkdocs.yml', 'docs/**']
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "andre@andre601.ch"
- git config --global user.name "ASL Docs Builder"
steps:
cloneTargetRepo:
image: alpine:3.18.4
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone https://codeberg.org/Andre601/asl-docs.git site
- chmod -R a+w site
- cd site
- git switch pr-${CI_COMMIT_PULL_REQUEST} 2>/dev/null || git switch -c pr-${CI_COMMIT_PULL_REQUEST}
buildDocs:
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
commitAndPush:
image: alpine:3.18.4
secrets:
- bot_token
commands:
- <<: *setup_git
- mv domains site/.domains
- cd site
- git remote add upstream https://$BOT_TOKEN@codeberg.org/Andre601/asl-docs.git
- git add --all
- git commit -m "Update Preview for PR ${CI_COMMIT_PULL_REQUEST} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push --set-upstream upstream pr-${CI_COMMIT_PULL_REQUEST} -f
writeComment:
image: mcs94/gitea-comment
secrets:
- bot_token
settings:
gitea_address: https://codeberg.org
gitea_token:
from_secret: BOT_TOKEN
comment: |-
Build-preview created!
| Name | Value |
|--------|-------------------------------------------------------|
| Commit | ${CI_COMMIT_SHA} |
| Link | https://asl.andre601.ch/@pr-${CI_COMMIT_PULL_REQUEST} |
+16 -3
View File
@@ -4,7 +4,7 @@ when:
steps:
createFiles:
image: maven:3.9.5-eclipse-temurin-17
image: maven:3.9.6-eclipse-temurin-17
secrets:
- source: cb_token
target: codeberg_api_token
@@ -12,6 +12,8 @@ steps:
target: modrinth_api_token
- source: hangar_api_token
target: hangar_api_token
- source: discord_webhook_url
target: discord_webhook_url
commands:
# Create the jar files.
- mvn clean install
@@ -20,7 +22,7 @@ steps:
- mv VersionUploader.jar ../../
- cd ../../
# Execute Jar file
- java -jar VersionUploader.jar --modrinth
- java -jar VersionUploader.jar --all
uploadToCodeberg:
image: woodpeckerci/plugin-gitea-release
settings:
@@ -29,5 +31,16 @@ steps:
- "bungeecord/target/AdvancedServerList-*.jar"
- "paper/target/AdvancedServerList-*.jar"
- "velocity/target/AdvancedServerList-*.jar"
- "addons/banplugins/target/AdvancedServerList-*.jar"
api_key:
from_secret: CB_TOKEN
from_secret: CB_TOKEN
postOnMastodon:
image: woodpeckerci/plugin-mastodon-post
when:
- status: ['success']
settings:
server: https://blobfox.coffee
access_token:
from_secret: MASTODON_TOKEN
status: '${CI_COMMIT_TAG} of #AdvancedServerList has been released and can be found on Modrinth (https://modrinth.com/plugin/AdvancedServerList), Hangar (https://hangar.papermc.io/Andre_601/AdvancedServerList) and Codeberg (https://codeberg.org/Andre601/AdvancedServerList).'
visibility: public
+5 -5
View File
@@ -1,8 +1,8 @@
when:
- branch: master
- branch: '${CI_REPO_DEFAULT_BRANCH}'
event: push
path:
include: ['requirements.txt', 'mkdocs.yml', 'docs/**']
include: ['.woodpecker/publish_docs.yml', 'requirements.txt', 'mkdocs.yml', 'docs/**']
variables:
setup_git: &setup_git
@@ -16,7 +16,7 @@ steps:
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone -b pages https://codeberg.org/Andre601/AdvancedServerList.git site
- git clone -b pages https://codeberg.org/Andre601/asl-docs site
- chmod -R a+w site
buildDocs:
image: woodpeckerci/plugin-mkdocs:latest
@@ -25,12 +25,12 @@ steps:
commitAndPush:
image: alpine:3.18.4
secrets:
- cb_token
- bot_token
commands:
- <<: *setup_git
- mv domains site/.domains
- cd site
- git remote set-url origin https://$CB_TOKEN@codeberg.org/Andre601/AdvancedServerList.git
- git remote set-url origin https://$BOT_TOKEN@codeberg.org/Andre601/asl-docs.git
- git add --all
- git commit -m "Update AdvancedServerList Docs ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push
+9 -5
View File
@@ -1,6 +1,6 @@
# AdvancedServerList
AdvancedServerList is a plugin that allowys you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
AdvancedServerList is a plugin that allows you to customize your server's MOTD, favicon, Player count text and player count hover displayed in a player's multiplayer server list based on conditions and priorities.
## Downloads
@@ -30,29 +30,33 @@ AdvancedServerList is a plugin that allowys you to customize your server's MOTD,
</a>
## What is a Server List Profile?
A Server List Profile refers to a YAML file located in the plugin's `profiles` directory.
It allows you to configure specific aspects of the server display in the MC-Client's multiplayer server list, such as the MOTD, player count text, player count hover or Favicon.
> [*Read More*][profiles]
### Conditions
Thanks to conditions can you determine when a profile should be displayed in the player’s server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes the profile automatically return true.
Thanks to conditions can you determine when a profile should be displayed in the player's server list, to allow displaying specific text (i.e. a warning when they are using an outdated version).
When multiple profiles exist that have valid conditions will the one with the highest priority (Higher number = higher priority) be selected. Having no conditions makes it automatically true.
> [*Read More*][conditions]
### Placeholders
Placeholders can be used within conditions to further customize them. They can also be used in any other text option to display their respective values.
The format is `${<target> <identifier>}` which was adopted from BungeeTabListPlus. Depending on what platform you use the plugin on are only specific placeholders available.
When using the SpigotMC/PaperMC version, or while PAPIProxyBridge is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed for that.
When using the SpigotMC/PaperMC version, or while [PAPIProxyBridge][papiproxybridge] is installed on your proxy, can you also use placeholders from [PlaceholderAPI][placeholderapi] using its `%<identifier>_<values>%` placeholder format. PlaceholderAPI needs to be installed on the server (not proxy) for that.
If you're a plugin dev can you even add your own custom placeholders through AdvancedServerList's own API.
> [*Read More*][placeholders]
### Formatting
The plugin uses the MiniMessage format for a consistent, easy way of formatting your text.
Only certain options are usable for each option. As an example does motd support HEX colours and gradients, while the other options only support default colour codes.
@@ -98,7 +102,7 @@ You can disable this in the global bStats config file located in `/plugins/bstat
<!-- Links -->
[profiles]: https://asl.andre601.ch/profiles/
[conditions]: https://asl.andre601.ch/profiles/#conditions
[conditions]: https://asl.andre601.ch/profiles/#condition
[placeholders]: https://asl.andre601.ch/profiles/placeholders/
[minimessage]: https://asl.andre601.ch/profiles/formatting/
+129
View File
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>ch.andre601.advancedserverlist</groupId>
<version>parent</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>banplugins</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>libertybans</id>
<url>https://mvn-repo.arim.space/affero-gpl3/</url>
</repository>
</repositories>
<dependencies>
<!-- Proxy/Server -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.20-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Plugin APIs -->
<dependency>
<groupId>com.github.DevLeoko</groupId>
<artifactId>AdvancedBan</artifactId>
<version>v2.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>space.arim.libertybans</groupId>
<artifactId>bans-api</artifactId>
<version>1.1.0-RC1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>${api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}</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>
@@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.bungeecord;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.placeholders.AdvancedBanPlaceholders;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum BungeeCordBanPlugins{
ADVANCED_BAN("AdvancedBan", new AdvancedBanPlaceholders()),
LIBERTY_BANS("LibertyBans", new LibertyBansPlaceholders());
private final String plugin;
private final PlaceholderProvider placeholderProvider;
BungeeCordBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
this.placeholderProvider = placeholderProvider;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(BungeeCordBanPlugins bungeeCordBanPlugins : BungeeCordBanPlugins.values()){
content.put(bungeeCordBanPlugins.plugin, bungeeCordBanPlugins.placeholderProvider);
}
return content;
}
}
@@ -0,0 +1,68 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.bungeecord;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.Map;
public class BungeeCordBanPluginsAddon extends Plugin{
@Override
public void onEnable(){
if(getProxy().getPluginManager().getPlugin("AdvancedServerList") == null){
getLogger().warning("AdvancedServerList is not enabled. This plugin requires it to function!");
return;
}
int loadedPlaceholders = loadPlaceholderProviders();
if(loadedPlaceholders == 0){
getLogger().warning("No compatible Ban plugin was found to register placeholders for.");
}else{
getLogger().info("Loaded " + loadedPlaceholders + " Placeholder Set(s) for AdvancedServerList!");
}
}
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = BungeeCordBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(getProxy().getPluginManager().getPlugin(entry.getKey()) != null){
getLogger().info("Registering Placeholders for " + entry.getKey() + "...");
api.addPlaceholderProvider(entry.getValue());
getLogger().info("Placeholder successfully registered!");
loaded++;
}
}
return loaded;
}
}
@@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.paper;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.placeholders.AdvancedBanPlaceholders;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum PaperBanPlugins{
ADVANCED_BAN("AdvancedBan", new AdvancedBanPlaceholders()),
LIBERTY_BANS("LibertyBans", new LibertyBansPlaceholders());
private final String plugin;
private final PlaceholderProvider placeholderProvider;
PaperBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
this.placeholderProvider = placeholderProvider;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(PaperBanPlugins paperBanPlugins : PaperBanPlugins.values()){
content.put(paperBanPlugins.plugin, paperBanPlugins.placeholderProvider);
}
return content;
}
}
@@ -0,0 +1,71 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.paper;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Map;
public class PaperBanPluginsAddon extends JavaPlugin{
@Override
public void onEnable(){
if(!getServer().getPluginManager().isPluginEnabled("AdvancedServerList")){
getLogger().warning("AdvancedServerList is not enabled. This plugin requires it to function!");
getServer().getPluginManager().disablePlugin(this);
return;
}
int loadedPlaceholders = loadPlaceholderProviders();
if(loadedPlaceholders == 0){
getLogger().warning("No compatible Ban plugin was found to register placeholders for. Disabling plugin...");
getServer().getPluginManager().disablePlugin(this);
}else{
getLogger().info("Loaded " + loadedPlaceholders + " Placeholder Set(s) for AdvancedServerList!");
}
}
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = PaperBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(getServer().getPluginManager().isPluginEnabled(entry.getKey())){
getLogger().info("Registering Placeholders for " + entry.getKey() + "...");
api.addPlaceholderProvider(entry.getValue());
getLogger().info("Placeholder successfully registered!");
loaded++;
}
}
return loaded;
}
}
@@ -0,0 +1,84 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.banplugins.providers.AdvancedBanProvider;
public class AdvancedBanPlaceholders extends PlaceholderProvider{
private final AdvancedBanProvider provider = new AdvancedBanProvider();
public AdvancedBanPlaceholders(){
super("advancedban");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
String[] args = placeholder.split("\\s", 2);
return switch(args[0]) {
// Mute-related placeholders
case "isMuted" -> String.valueOf(provider.muted(player));
case "muteReason" -> provider.muteReason(player);
case "muteDuration" -> {
if(args.length == 1)
yield provider.muteDuration(player);
boolean fromStart = Boolean.getBoolean(args[1]);
yield provider.muteDuration(player, fromStart);
}
case "muteExpiration" -> {
if(args.length == 1)
yield provider.muteExpirationDate(player);
yield provider.banExpirationDate(player, args[1]);
}
// Ban-related placeholders
case "isBanned" -> String.valueOf(provider.banned(player));
case "banReason" -> provider.banReason(player);
case "banDuration" -> {
if(args.length == 1)
yield provider.banDuration(player);
boolean fromStart = Boolean.getBoolean(args[1]);
yield provider.banDuration(player, fromStart);
}
case "banExpiration" -> {
if(args.length == 1)
yield provider.banExpirationDate(player);
yield provider.banExpirationDate(player, args[1]);
}
// Unknown/Invalid placeholder.
default -> null;
};
}
}
@@ -0,0 +1,70 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.banplugins.providers.LibertyBansProvider;
public class LibertyBansPlaceholders extends PlaceholderProvider{
private final LibertyBansProvider provider = LibertyBansProvider.create();
public LibertyBansPlaceholders(){
super("libertybans");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
String[] args = placeholder.split("\\s", 2);
return switch(args[0]){
// Mute-related placeholders
case "isMuted" -> String.valueOf(provider.muted(player));
case "muteReason" -> provider.muteReason(player);
case "muteExpiration" -> {
if(args.length == 1)
yield provider.muteExpirationDate(player);
yield provider.muteExpirationDate(player, args[1]);
}
// Ban-related placeholders
case "isBanned" -> String.valueOf(provider.banned(player));
case "banReason" -> provider.banReason(player);
case "banExpiration" -> {
if(args.length == 1)
yield provider.banExpirationDate(player);
yield provider.banExpirationDate(player, args[1]);
}
// Unknown/Invalid placeholder
default -> null;
};
}
}
@@ -0,0 +1,139 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.providers;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import com.google.common.base.Strings;
import com.google.common.primitives.UnsignedLongs;
import me.leoko.advancedban.manager.PunishmentManager;
import me.leoko.advancedban.utils.Punishment;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class AdvancedBanProvider implements PunishmentProvider{
private static PunishmentManager getAPI(){
return PunishmentManager.get();
}
private static String noDashesUUID(UUID uuid){
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
}
private static Punishment mute(GenericPlayer player){
return getAPI().getMute(noDashesUUID(player.getUUID()));
}
private static Punishment ban(GenericPlayer player){
return getAPI().getBan(noDashesUUID(player.getUUID()));
}
private static String hexString(long unsigned){
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
}
@Override
public boolean muted(GenericPlayer player){
return getAPI().isMuted(noDashesUUID(player.getUUID()));
}
@Override
public boolean banned(GenericPlayer player){
return getAPI().isBanned(noDashesUUID(player.getUUID()));
}
@Override
public String muteReason(GenericPlayer player){
Punishment mute = mute(player);
if(mute == null)
return null;
return mute.getReason();
}
@Override
public String banReason(GenericPlayer player){
Punishment ban = ban(player);
if(ban == null)
return null;
return ban.getReason();
}
@Override
public String muteDuration(GenericPlayer player){
return muteDuration(player, false);
}
@Override
public String banDuration(GenericPlayer player){
return banDuration(player, false);
}
@Override
public String muteExpirationDate(GenericPlayer player, String pattern){
Punishment mute = mute(player);
if(mute == null)
return null;
long end = mute.getEnd();
if(end < 0L)
return "never";
return this.returnDate(pattern, end);
}
@Override
public String banExpirationDate(GenericPlayer player, String pattern){
Punishment ban = ban(player);
if(ban == null)
return null;
long end = ban.getEnd();
if(end < 0L)
return "never";
return this.returnDate(pattern, end);
}
public String muteDuration(GenericPlayer player, boolean fromStart){
Punishment mute = mute(player);
if(mute == null)
return null;
return mute.getDuration(fromStart);
}
public String banDuration(GenericPlayer player, boolean fromStart){
Punishment ban = ban(player);
if(ban == null)
return null;
return ban.getDuration(fromStart);
}
}
@@ -0,0 +1,136 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.providers;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import space.arim.libertybans.api.LibertyBans;
import space.arim.libertybans.api.PunishmentType;
import space.arim.libertybans.api.punish.Punishment;
import space.arim.libertybans.api.user.KnownAccount;
import space.arim.omnibus.Omnibus;
import space.arim.omnibus.OmnibusProvider;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
public class LibertyBansProvider implements PunishmentProvider{
private final LibertyBans libertyBans;
private LibertyBansProvider(LibertyBans libertyBans){
this.libertyBans = libertyBans;
}
public static LibertyBansProvider create(){
Omnibus omnibus = OmnibusProvider.getOmnibus();
LibertyBans libertyBans = omnibus.getRegistry().getProvider(LibertyBans.class).orElseThrow();
return new LibertyBansProvider(libertyBans);
}
@Override
public boolean muted(GenericPlayer player){
return punishment(player.getUUID(), PunishmentType.MUTE) != null;
}
@Override
public boolean banned(GenericPlayer player){
return punishment(player.getUUID(), PunishmentType.BAN) != null;
}
@Override
public String muteReason(GenericPlayer player){
Punishment mute = punishment(player.getUUID(), PunishmentType.MUTE);
if(mute == null)
return null;
return mute.getReason();
}
@Override
public String banReason(GenericPlayer player){
Punishment ban = punishment(player.getUUID(), PunishmentType.BAN);
if(ban == null)
return null;
return ban.getReason();
}
@Override
public String muteDuration(GenericPlayer player){
return null;
}
@Override
public String banDuration(GenericPlayer player){
return null;
}
@Override
public String muteExpirationDate(GenericPlayer player, String pattern){
Punishment mute = punishment(player.getUUID(), PunishmentType.MUTE);
if(mute == null)
return null;
if(mute.isPermanent())
return "never";
return this.returnDate(pattern, mute.getEndDate().toEpochMilli());
}
@Override
public String banExpirationDate(GenericPlayer player, String pattern){
Punishment ban = punishment(player.getUUID(), PunishmentType.BAN);
if(ban == null)
return null;
if(ban.isPermanent())
return "never";
return this.returnDate(pattern, ban.getEndDate().toEpochMilli());
}
private Punishment punishment(UUID uuid, PunishmentType type){
List<? extends KnownAccount> accounts = libertyBans.getAccountSupervisor()
.findAccountsMatching(uuid)
.join();
if(accounts.isEmpty())
return null;
KnownAccount sorted = Collections.max(accounts, Comparator.comparing(KnownAccount::recorded));
return libertyBans.getSelector()
.selectionByApplicabilityBuilder(sorted.uuid(), sorted.address())
.type(type)
.build()
.getFirstSpecificPunishment()
.toCompletableFuture()
.join()
.orElse(null);
}
}
@@ -0,0 +1,68 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.providers;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import java.text.SimpleDateFormat;
import java.util.Date;
public interface PunishmentProvider{
boolean muted(GenericPlayer player);
boolean banned(GenericPlayer player);
String muteReason(GenericPlayer player);
String banReason(GenericPlayer player);
String muteDuration(GenericPlayer player);
String banDuration(GenericPlayer player);
default String muteExpirationDate(GenericPlayer player){
return muteExpirationDate(player, "dd, MMM yyyy HH:mm:ss");
}
String muteExpirationDate(GenericPlayer player, String pattern);
default String banExpirationDate(GenericPlayer player){
return banExpirationDate(player, "dd, MMM yyyy HH:mm:ss");
}
String banExpirationDate(GenericPlayer player, String pattern);
default String returnDate(String pattern, long end){
Date date = new Date(end);
try{
return new SimpleDateFormat(pattern).format(date);
}catch(IllegalArgumentException ex){
return new SimpleDateFormat("dd, MMM yyyy HH:mm:ss").format(date);
}
}
}
@@ -0,0 +1,56 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.velocity;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.banplugins.paper.PaperBanPlugins;
import ch.andre601.advancedserverlist.banplugins.placeholders.LibertyBansPlaceholders;
import java.util.HashMap;
import java.util.Map;
public enum VelocityBanPlugins{
LIBERTY_BANS("libertybans", new LibertyBansPlaceholders());
private final String plugin;
private final PlaceholderProvider placeholderProvider;
VelocityBanPlugins(String plugin, PlaceholderProvider placeholderProvider){
this.plugin = plugin;
this.placeholderProvider = placeholderProvider;
}
public static Map<String, PlaceholderProvider> getBanPlugins(){
Map<String, PlaceholderProvider> content = new HashMap<>();
for(VelocityBanPlugins velocityBanPlugins : VelocityBanPlugins.values()){
content.put(velocityBanPlugins.plugin, velocityBanPlugins.placeholderProvider);
}
return content;
}
}
@@ -0,0 +1,82 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.velocity;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import net.md_5.bungee.api.ProxyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class VelocityBanPluginsAddon{
private final Logger logger = LoggerFactory.getLogger("ASLBanPluginsAddon");
private final ProxyServer proxy;
@Inject
public VelocityBanPluginsAddon(ProxyServer proxy){
this.proxy = proxy;
}
@Subscribe
public void init(ProxyInitializeEvent event){
if(proxy.getPluginManager().getPlugin("advancedserverlist") == null){
logger.warn("AdvancedServerList is not enabled. This plugin requires it to function!");
return;
}
int loadedPlaceholders = loadPlaceholderProviders();
if(loadedPlaceholders == 0){
logger.warn("No compatible Ban plugin was found to register placeholders for.");
}else{
logger.info("Loaded {} Placeholder Set(s) for AdvancedServerList!", loadedPlaceholders);
}
}
private int loadPlaceholderProviders(){
int loaded = 0;
Map<String, PlaceholderProvider> banPlugins = VelocityBanPlugins.getBanPlugins();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(Map.Entry<String, PlaceholderProvider> entry : banPlugins.entrySet()){
if(proxy.getPluginManager().getPlugin(entry.getKey()) != null){
logger.info("Registering placeholders for {}...", entry.getKey());
api.addPlaceholderProvider(entry.getValue());
logger.info("Placeholder successfully registered!");
loaded++;
}
}
return loaded;
}
}
@@ -0,0 +1,11 @@
name: 'ASLBanPluginsAddon'
author: 'Andre_601'
version: '${plugin.version}'
description: 'AdvancedBan Add-on for AdvancedServerList to add placeholders to use.'
softDepends:
- AdvancedServerList
- AdvancedBan
- LibertyBans
main: 'ch.andre601.advancedserverlist.banplugins.bungeecord.BungeeCordBanPluginsAddon'
@@ -0,0 +1,19 @@
name: 'ASLBanPluginsAddon'
author: 'Andre_601'
version: '${plugin.version}'
main: 'ch.andre601.advancedserverlist.banplugins.paper.AdvancedBanPlaceholders'
api-version: '1.19'
dependencies:
server:
AdvancedServerList:
required: false
load: BEFORE
AdvancedBans:
required: false
load: BEFORE
LibertyBans:
required: false
load: BEFORE
@@ -0,0 +1,20 @@
{
"id": "aslbanpluginsaddon",
"name": "ASLBanPluginsAddon",
"version": "${plugin.version}",
"description": "${plugin.description}",
"authors": [
"Andre_601"
],
"dependencies": [
{
"id": "advancedserverlist",
"optional": true
},
{
"id": "libertybans",
"optional": true
}
],
"main": "ch.andre601.advancedserverlist.banplugins.velocity.VelocityBanPluginsAddon"
}
+21 -15
View File
@@ -64,55 +64,65 @@
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<!-- BungeeCord API -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.1</version>
<version>1.20-R0.2</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.1</version>
<version>1.20-R0.2</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<!-- Adventure Library. Needs to be shaded in -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.14.0</version>
<version>4.16.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.14.0</version>
<version>4.16.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.3.1</version>
<version>4.3.2</version>
<scope>compile</scope>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bungeecord</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<!-- Configurate -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
<scope>compile</scope>
<groupId>com.github.LeonMangler</groupId>
<artifactId>PremiumVanishAPI</artifactId>
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -128,12 +138,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -149,10 +159,6 @@
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>okhttp3</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.okhttp3</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
@@ -29,28 +29,34 @@ 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.logging.BungeeLogger;
import ch.andre601.advancedserverlist.bungeecord.objects.BungeePlayerPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.BungeeServerPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeePlayerPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeServerPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private final PluginLogger logger = new BungeeLogger(getLogger());
private final PluginLogger logger = new BungeeLogger(this);
@Override
public void onEnable(){
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init());
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
}
@Override
@@ -77,12 +83,17 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
}
@Override
public void loadFaviconHandler(AdvancedServerList<Favicon> core){
faviconHandler = new FaviconHandler<>(core);
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.clearCache();
faviconHandler.cleanCache();
}
@Override
@@ -122,4 +133,20 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
public String getLoader(){
return "bungeecord";
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
public int getOnlinePlayers(ServerInfo server){
List<ProxiedPlayer> players = new ArrayList<>(server == null ? getProxy().getPlayers() : server.getPlayers());
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().getPlugin("PremiumVanish") != null){
players.removeIf(BungeeVanishAPI::isInvisible);
}
return players.size();
}
}
@@ -25,12 +25,12 @@
package ch.andre601.advancedserverlist.bungeecord.listeners;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.objects.BungeePlayerImpl;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.bungeecord.objects.BungeeProxyImpl;
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeePlayerImpl;
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeeProxyImpl;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
@@ -46,7 +46,6 @@ import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ProxyPingEvent;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
@@ -148,7 +147,7 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
@Override
public int getOnlinePlayers(){
return ping.getPlayers().getOnline();
return plugin.getOnlinePlayers(null);
}
@Override
@@ -205,9 +204,4 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
return new BungeeProxyImpl(servers, playersOnline, playersMax, host);
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
}
@@ -25,12 +25,13 @@
package ch.andre601.advancedserverlist.bungeecord.listeners;
import ch.andre601.advancedserverlist.api.bungeecord.events.PostServerListSetEvent;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public class PingEvent implements Listener{
@@ -41,8 +42,10 @@ public class PingEvent implements Listener{
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@EventHandler(priority = EventPriority.LOW)
@EventHandler(priority = 90) // Maintenance has Event Priority 80, so we need to be AFTER it.
public void onProxyPing(ProxyPingEvent event){
PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
ProfileEntry entry = PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
plugin.getProxy().getPluginManager().callEvent(new PostServerListSetEvent(entry));
}
}
@@ -25,6 +25,7 @@
package ch.andre601.advancedserverlist.bungeecord.logging;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import java.util.logging.Level;
@@ -32,10 +33,24 @@ import java.util.logging.Logger;
public class BungeeLogger implements PluginLogger{
private final BungeeCordCore plugin;
private final Logger logger;
public BungeeLogger(Logger logger){
this.logger = logger;
public BungeeLogger(BungeeCordCore plugin){
this.plugin = plugin;
this.logger = plugin.getLogger();
}
@Override
public void debug(Class<?> clazz, String msg, Object... args){
if(plugin.isDebugEnabled())
info("[DEBUG] [" + clazz.getSimpleName() + "] " + msg, args);
}
@Override
public void debugWarn(Class<?> clazz, String msg, Object... args){
if(plugin.isDebugEnabled())
warn("[DEBUG] [" + clazz.getSimpleName() + "] " + msg, args);
}
@Override
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects;
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
@@ -31,8 +31,8 @@ import ch.andre601.advancedserverlist.core.profiles.players.GenericPlayerImpl;
public class BungeePlayerImpl extends GenericPlayerImpl{
public BungeePlayerImpl(CachedPlayer player, int protocol){
this.name = player.getName();
this.name = player.name();
this.protocol = protocol;
this.uuid = player.getUuid();
this.uuid = player.uuid();
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects;
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
import net.md_5.bungee.api.config.ServerInfo;
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects;
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,24 +23,28 @@
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects;
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.md_5.bungee.api.config.ServerInfo;
import java.net.InetSocketAddress;
public class BungeeServerPlaceholders extends PlaceholderProvider{
private BungeeServerPlaceholders(){
private final BungeeCordCore plugin;
private BungeeServerPlaceholders(BungeeCordCore plugin){
super("server");
this.plugin = plugin;
}
public static BungeeServerPlaceholders init(){
return new BungeeServerPlaceholders();
public static BungeeServerPlaceholders init(BungeeCordCore plugin){
return new BungeeServerPlaceholders(plugin);
}
@Override
@@ -60,11 +64,11 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
if(serverName.isEmpty())
continue;
ServerInfo info = proxy.getServers().get(serverName);
ServerInfo info = proxy.getServers().get(serverName.strip());
if(info == null)
continue;
players += info.getPlayers().size();
players += plugin.getOnlinePlayers(info);
}
yield String.valueOf(players);
@@ -85,6 +89,8 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
if(args.length == 2){
ServerInfo info = proxy.getServers().get(args[1]);
if(info == null)
yield null;
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
}
+31 -16
View File
@@ -41,6 +41,7 @@
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>5</plugin.config.version>
</properties>
<repositories>
@@ -56,6 +57,10 @@
<id>sonatype</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>codeberg</id>
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
</repository>
</repositories>
<dependencies>
@@ -65,42 +70,46 @@
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>1.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>provided</scope>
</dependency>
<!-- MiniMessage -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.14.0</version>
<version>4.16.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.14.0</version>
<version>4.16.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.14.0</version>
<version>4.16.0</version>
<scope>provided</scope>
</dependency>
<!-- Misc -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.unascribed</groupId>
<artifactId>flexver-java</artifactId>
@@ -110,13 +119,15 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
<version>33.1.0-jre</version>
<scope>provided</scope>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>net.william278</groupId>
<artifactId>papiproxybridge</artifactId>
<version>1.4.2</version>
<version>1.5</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -128,9 +139,9 @@
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -147,12 +158,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
@@ -169,6 +180,10 @@
<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>
</configuration>
<executions>
@@ -31,11 +31,11 @@ import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.profiles.players.PlayerHandler;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
@@ -46,7 +46,8 @@ public class AdvancedServerList<F>{
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private final ProfileConditionParser parser = ProfileConditionParser.create();
private UpdateChecker updateChecker;
@@ -58,7 +59,7 @@ public class AdvancedServerList<F>{
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
placeholders.forEach(this.api::addPlaceholderProvider);
placeholders.forEach(AdvancedServerList.getApi()::addPlaceholderProvider);
load();
}
@@ -87,10 +88,14 @@ public class AdvancedServerList<F>{
return version;
}
public AdvancedServerListAPI getApi(){
public static AdvancedServerListAPI getApi(){
return api;
}
public ProfileConditionParser getParser(){
return parser;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving playercache.json file...");
getPlayerHandler().save();
@@ -136,15 +141,13 @@ public class AdvancedServerList<F>{
}
if(getFileHandler().loadProfiles()){
getPlugin().getPluginLogger().info("Successfully loaded " + getFileHandler().getProfiles().size() + " profiles!");
getPlugin().getPluginLogger().info("Successfully loaded %d profile(s)!", getFileHandler().getProfiles().size());
}else{
getPlugin().getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
return;
}
Path folder = getPlugin().getFolderPath().resolve("favicons");
if(!folder.toFile().exists() && folder.toFile().mkdirs())
getPlugin().getPluginLogger().info("Successfully created favicons folder.");
getPlugin().loadFaviconHandler(this);
getPlugin().getPluginLogger().info("Loading Commands...");
plugin.loadCommands();
@@ -30,18 +30,17 @@ import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.unascribed.flexver.FlexVerComparator;
import io.leangen.geantyref.TypeToken;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -49,12 +48,10 @@ import java.util.concurrent.TimeUnit;
public class UpdateChecker{
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=[\"%s\"]";
private final OkHttpClient client = new OkHttpClient();
private final AdvancedServerList<?> core;
private final PluginLogger logger;
private final String loader;
@SuppressWarnings("FieldCanBeLocal")
// 'https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=["%s"]' URL encoded.
private final String url = "https://api.modrinth.com/v2/project/advancedserverlist/version?loaders=%%5B%%22%s%%22%%5D";
private final HttpClient client = HttpClient.newHttpClient();
private final Type listType = new TypeToken<ArrayList<ModrinthVersion>>(){}.getType();
private final Gson gson = new GsonBuilder()
@@ -65,6 +62,10 @@ public class UpdateChecker{
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
private final AdvancedServerList<?> core;
private final PluginLogger logger;
private final String loader;
public UpdateChecker(AdvancedServerList<?> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
@@ -73,42 +74,13 @@ public class UpdateChecker{
startUpdateChecker();
}
public void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Checking for a new update...");
checkUpdate().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. See previous messages for reasons.");
return;
}
int result = version.compare(core.getVersion());
switch(result){
case -1 -> printUpdateBanner(version.getVersionNumber(), version.getId(), version.isRelease());
case 0 -> logger.info("No new update found. You're running the latest version!");
case 1 -> logger.info(
"Your version (%s) is higher than the latest release (%s). Are you running a dev build?",
core.getVersion(), version.getVersionNumber()
);
}
});
}, 0L, 12L, TimeUnit.HOURS);
}
public void disable(){
executor.shutdown();
client.dispatcher().executorService().shutdown();
try{
if(!executor.awaitTermination(1, TimeUnit.SECONDS)){
executor.shutdownNow();
if(!executor.awaitTermination(1, TimeUnit.SECONDS))
logger.warn("Scheduler didn't terminate in time!");
}
if(!client.dispatcher().executorService().awaitTermination(1, TimeUnit.SECONDS)){
client.dispatcher().executorService().shutdownNow();
if(!client.dispatcher().executorService().awaitTermination(1, TimeUnit.SECONDS))
logger.warn("OkHttp's Scheduler didn't terminate in time!");
logger.warn("Scheduler did not terminate in time!");
}
}catch(InterruptedException ex){
executor.shutdownNow();
@@ -116,108 +88,93 @@ public class UpdateChecker{
}
}
private CompletableFuture<ModrinthVersion> checkUpdate(){
return CompletableFuture.supplyAsync(() -> {
PluginLogger logger = core.getPlugin().getPluginLogger();
if(core.getVersion().equals("UNKNOWN")){
logger.warn("Cannot perform Update check! Plugin version couldn't be parsed.");
return null;
}
private void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Looking for an update...");
Request request = new Request.Builder()
.url(String.format(url, loader))
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
.build();
try(Response response = client.newCall(request).execute()){
if(!response.isSuccessful()){
logger.warn("Encountered a non-successful response from Modrinth! Code: %d", response.code());
return null;
}
ResponseBody body = response.body();
if(body == null){
logger.warn("Received an empty Response body from Modrinth!");
return null;
performUpdateCheck().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. Check previous messages for causes.");
return;
}
String responseString = body.string();
if(responseString.isEmpty()){
logger.warn("Received an empty Response body from Modrinth!");
return null;
logger.debug(UpdateChecker.class, "Comparing versions...");
int result = version.compare(core.getVersion());
switch(result){
case -1 -> printUpdateBanner(version);
case 0 -> logger.info("You are running the latest version!");
case 1 -> logger.info(
"Your version (%s) seems to be newer than the latest release (%s). Are you running a dev build?",
core.getVersion(), version.versionNumber()
);
}
List<ModrinthVersion> list = gson.fromJson(responseString, listType);
if(list == null || list.isEmpty()){
logger.warn("Couldn't convert JSON Array into a valid list.");
return null;
}
ModrinthVersion version = list.get(0);
if(version.getVersionNumber() == null || version.getVersionNumber().isEmpty()){
logger.warn("Cannot check latest version. Received version number was null/empty.");
return null;
}
return version;
}catch(JsonSyntaxException ex){
logger.warn("Encountered invalid JSON from Response body!", ex);
return null;
}catch(IOException ex){
logger.warn("Encountered Exception while checking for an update!", ex);
return null;
}
});
});
}, 0L, 12L, TimeUnit.HOURS);
}
private void printUpdateBanner(String version, String versionId, boolean isRelease){
private CompletableFuture<ModrinthVersion> performUpdateCheck(){
String finalUrl = String.format(url, loader);
logger.debug(UpdateChecker.class, "Checking '%s' for updates...", finalUrl);
if(core.getVersion().equals("UNKNOWN")){
logger.warn("Cannot perform update check. Plugin version is 'UNKNOWN'!");
return CompletableFuture.completedFuture(null);
}
HttpRequest request;
try{
request = HttpRequest.newBuilder()
.uri(new URI(finalUrl))
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
.build();
}catch(URISyntaxException ex){
logger.warn("Cannot perform update check. URL '%s' is not a valid URI.", ex, finalUrl);
return CompletableFuture.completedFuture(null);
}
return client.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))
.thenApply(response -> new ArrayList<ModrinthVersion>(gson.fromJson(response.body(), listType)))
.thenApply(list -> list.get(0))
.exceptionally((throwable) -> {
logger.warn("Encountered exception while performing update check!", throwable);
return null;
});
}
private void printUpdateBanner(ModrinthVersion version){
logger.info("==================================================================");
logger.info("You are running an outdated version of AdvancedServerList!");
logger.info("");
logger.info("Your version: %s", core.getVersion());
logger.info("Modrinth version: %s", version);
logger.info("Modrinth: %s", version.versionNumber());
logger.info("");
if(!isRelease){
logger.info("WARNING: This release is an Alpha/Beta! It may contain");
logger.info(" breaking changes!");
if(!version.isRelease()){
logger.info("WARNING!");
logger.info("This is a %s version and may contain breaking changes and/or bugs!", version.versionType());
logger.info("");
}
logger.info("You can download the latest release from here:");
logger.info("https://modrinth.com/plugin/advancedserverlist/version/%s", versionId);
logger.info("Download the latest version from here:");
logger.info("https://modrinth.com/plugin/advancedserverlist/version/%s", version.id());
logger.info("==================================================================");
}
public static class ModrinthVersion{
@SuppressWarnings("FieldMayBeFinal")
private String id;
@SuppressWarnings("FieldMayBeFinal")
private String versionNumber;
@SuppressWarnings("FieldMayBeFinal")
private String versionType;
public ModrinthVersion(String id, String versionNumber, String versionType){
this.id = id;
this.versionNumber = versionNumber;
this.versionType = versionType;
}
public String getId(){
return id;
}
public String getVersionNumber(){
return versionNumber;
}
public record ModrinthVersion(String id, String versionNumber, String versionType){
public boolean isRelease(){
return versionType.equals("release");
return versionType().equals("release");
}
public int compare(String version){
return FlexVerComparator.compare(version, versionNumber);
return FlexVerComparator.compare(version, versionNumber());
}
@Override
public String toString(){
return String.format("ModrinthVersion{id=%s,versionNumber=%s,versionType=%s}", id, versionNumber, versionType);
}
}
}
@@ -27,7 +27,10 @@ package ch.andre601.advancedserverlist.core.compat.papi;
import net.william278.papiproxybridge.api.PlaceholderAPI;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -30,9 +30,10 @@ import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
@@ -43,12 +44,18 @@ public class PingEventHandler{
private static PAPIUtil papiUtil = null;
private static MaintenanceUtil maintenanceUtil = null;
public static <F, P extends GenericPlayer> void handleEvent(GenericEventWrapper<F, P> event){
if(event.isInvalidProtocol() || event.isMaintenanceModeActive())
return;
public static <F, P extends GenericPlayer> ProfileEntry handleEvent(GenericEventWrapper<F, P> event){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
if(event.isInvalidProtocol()){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Not handling event. Protocol was invalid.");
return null;
}
PluginCore<F> plugin = event.getPlugin();
String host = event.getVirtualHost();
PluginLogger logger = plugin.getPluginLogger();
logger.debug(PingEventHandler.class, "Protocol valid. Continue handling...");
int online = event.getOnlinePlayers();
int max = event.getMaxPlayers();
@@ -61,32 +68,50 @@ public class PingEventHandler{
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
if(profile == null)
return;
if(profile == null){
logger.debugWarn(PingEventHandler.class, "Server List Profile couldn't be resolved properly. Cancelling event handling...");
return null;
}
logger.debug(PingEventHandler.class, "Received valid Server List Profile. Calling PreServerListSetEvent...");
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
if(e == null || e.isCancelled())
return;
if(e == null || e.isCancelled()){
logger.debug(PingEventHandler.class, "PreServerListSetEvent was cancelled. Stopping ping handling...");
return null;
}
logger.debug(PingEventHandler.class, "PreServerListSetEvent completed. Proceeding with ping handling...");
ProfileEntry entry = e.getEntry();
if(entry.isInvalid())
return;
if(entry.isInvalid()){
logger.debugWarn(PingEventHandler.class, "No valid ProfileEntry retrieved. Cancelling ping handling...");
return null;
}
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayers){
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
event.setMaxPlayers(max);
}
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers){
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
event.setMaxPlayers(max);
}
GenericServer finalServer = event.createGenericServer(online, max, host);
if(ProfileManager.checkOption(entry.motd())){
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
event.setMotd(
ComponentParser.list(entry.motd())
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
@@ -97,11 +122,15 @@ public class PingEventHandler{
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
if(hidePlayers){
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
event.hidePlayers();
}
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers){
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
event.setPlayerCount(
ComponentParser.text(entry.playerCountText())
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
@@ -110,30 +139,34 @@ public class PingEventHandler{
);
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers){
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
event.setPlayers(entry.players(), player, server);
}
if(ProfileManager.checkOption(entry.favicon())){
String favicon = StringReplacer.replace(entry.favicon(), player, server);
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
F fav = plugin.getFaviconHandler().getFavicon(favicon, image -> {
try{
return event.createFavicon(image);
}catch(Exception ex){
plugin.getPluginLogger().warn("Encountered an Exception while creating Favicon!", ex);
return null;
}
});
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
if(fav == null){
F favicon = plugin.getFaviconHandler().getFavicon(faviconString);
if(favicon == null){
logger.debugWarn(PingEventHandler.class, "Favicon was invalid or not yet resolved! Using default favicon of Server/Proxy...");
event.setDefaultFavicon();
}else{
event.setFavicon(fav);
logger.debug(PingEventHandler.class, "Applying favicon...");
event.setFavicon(favicon);
}
}
logger.debug(PingEventHandler.class, "Event handling completed. Updating Ping data...");
event.updateEvent();
return entry;
}
public static PAPIUtil getPAPIUtil(){
@@ -149,4 +182,11 @@ public class PingEventHandler{
return (maintenanceUtil = new MaintenanceUtil());
}
private static <F, P extends GenericPlayer> boolean ignoreMaintenance(GenericEventWrapper<F, P> event, String option){
if(!event.isMaintenanceModeActive())
return true;
return !event.getPlugin().getCore().getFileHandler().getBool(true, "disableDuringMaintenance", option);
}
}
@@ -25,6 +25,7 @@
package ch.andre601.advancedserverlist.core.file;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
@@ -32,16 +33,59 @@ import org.spongepowered.configurate.NodePath;
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
import org.spongepowered.configurate.transformation.TransformAction;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ConfigMigrator{
public static final int LATEST = 1;
public static final int LATEST = resolveConfigVersion();
private ConfigMigrator(){}
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, oneToTwo())
.addVersion(LATEST, fourToFive())
.addVersion(4, threeToFour())
.addVersion(3, twoToThree())
.addVersion(2, oneToTwo())
.build();
}
public static ConfigurationTransformation fourToFive(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("disableDuringMaintenance", "motd").set(true);
value.node("disableDuringMaintenance", "favicon").set(true);
value.node("disableDuringMaintenance", "hidePlayers").set(true);
value.node("disableDuringMaintenance", "playerCountText").set(true);
value.node("disableDuringMaintenance", "playerCountHover").set(true);
value.node("disableDuringMaintenance", "extraPlayers").set(true);
value.node("disableDuringMaintenance", "maxPlayers").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation threeToFour(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("faviconCacheTime").set(1);
return null;
})
.build();
}
public static ConfigurationTransformation twoToThree(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("debug").set(false);
return null;
})
.build();
}
@@ -67,9 +111,21 @@ public class ConfigMigrator{
versioned.apply(node);
final int endVersion = versioned.version(node);
if(startVersion < endVersion)
logger.info("Migrated config.yml from " + startVersion + " to " + endVersion);
logger.info("Migrated config.yml from v" + startVersion + " to v" + endVersion);
}
return node;
}
private static int resolveConfigVersion(){
try(InputStream is = AdvancedServerList.class.getResourceAsStream("/version.properties")){
Properties properties = new Properties();
properties.load(is);
return Integer.parseInt(properties.getProperty("config-version"));
}catch(IOException | NumberFormatException ex){
return -1;
}
}
}
@@ -25,10 +25,10 @@
package ch.andre601.advancedserverlist.core.file;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
@@ -157,7 +157,7 @@ public class FileHandler{
continue;
profiles.add(ServerListProfile.Builder.resolve(file.getName(), tmp, logger).build());
logger.info("Loaded " + file.getName());
logger.info("Loaded '%s'!", file.getName());
}
if(profiles.isEmpty()){
@@ -165,7 +165,7 @@ public class FileHandler{
return false;
}
profiles.sort(Comparator.comparing(ServerListProfile::getPriority).reversed());
profiles.sort(Comparator.comparing(ServerListProfile::priority).reversed());
return !profiles.isEmpty();
}
@@ -178,7 +178,7 @@ public class FileHandler{
try{
return loader.load();
}catch(IOException ex){
logger.warn("Cannot load " + path.toFile().getName() + " due to an IOException!", ex);
logger.warn("Cannot load '%s' due to an IOException!", ex, path.toFile().getName());
return null;
}
}
@@ -187,8 +187,17 @@ public class FileHandler{
return node.node(path).getString(def);
}
public boolean getBool(boolean def, Object... path){
return node.node(path).getBoolean(def);
}
public boolean getBoolean(Object... path){
return node.node(path).getBoolean();
return getBool(false, path);
}
public long getLong(long def, long limit, Object... path){
long value = node.node(path).getLong(def);
return Math.max(value, limit);
}
public boolean isOldConfig(){
@@ -214,7 +223,7 @@ public class FileHandler{
}
Files.copy(config, configBackup.toPath(), StandardCopyOption.REPLACE_EXISTING);
logger.info("Saved backup as '" + configBackup.getName() + "'!");
logger.info("Saved backup as '%s'!", configBackup.getName());
return true;
}catch(IOException ex){
@@ -27,6 +27,10 @@ package ch.andre601.advancedserverlist.core.interfaces;
public interface PluginLogger{
void debug(Class<?> clazz, String msg, Object... args);
void debugWarn(Class<?> clazz, String msg, Object... args);
void info(String msg, Object... args);
void warn(String msg, Object... args);
@@ -29,6 +29,7 @@ import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
public interface PluginCore<F>{
@@ -39,6 +40,8 @@ public interface PluginCore<F>{
void loadMetrics();
void loadFaviconHandler(AdvancedServerList<F> core);
void clearFaviconCache();
AdvancedServerList<F> getCore();
@@ -54,4 +57,13 @@ public interface PluginCore<F>{
String getPlatformVersion();
String getLoader();
F createFavicon(BufferedImage image) throws Exception;
default boolean isDebugEnabled(){
if(getCore() == null)
return false;
return getCore().getFileHandler().getBoolean("debug");
}
}
@@ -25,15 +25,14 @@
package ch.andre601.advancedserverlist.core.interfaces.events;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.api.events.GenericServerListEvent;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import net.kyori.adventure.text.Component;
import java.awt.image.BufferedImage;
import java.net.InetSocketAddress;
import java.util.List;
@@ -79,8 +78,6 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
GenericServer createGenericServer(int playersOnline, int playersMax, String host);
F createFavicon(BufferedImage image) throws Exception;
default String resolveHost(InetSocketAddress address){
return address == null ? null : address.getHostString();
}
@@ -27,28 +27,4 @@ package ch.andre601.advancedserverlist.core.objects;
import java.util.UUID;
@SuppressWarnings("FieldMayBeFinal")
public class CachedPlayer{
private String ip;
private String name;
private UUID uuid;
public CachedPlayer(String ip, String name, UUID uuid){
this.ip = ip;
this.name = name;
this.uuid = uuid;
}
public String getIp(){
return ip;
}
public String getName(){
return name;
}
public UUID getUuid(){
return uuid;
}
}
public record CachedPlayer(String ip, String name, UUID uuid){}
@@ -29,7 +29,9 @@ import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.profiles.conditions.Expression;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -37,38 +39,32 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ServerListProfile{
public record ServerListProfile(int priority, String condition, ProfileEntry defaultProfile, List<ProfileEntry> profiles, String file){
private static final Random random = new Random();
private final int priority;
private final List<Expression> expressions;
private final ProfileEntry defaultProfile;
private final List<ProfileEntry> profiles;
private final Random random = new Random();
public ServerListProfile(int priority, List<Expression> expressions, ProfileEntry defaultProfile, List<ProfileEntry> profiles){
this.priority = priority;
this.expressions = expressions;
this.defaultProfile = defaultProfile;
this.profiles = profiles;
}
public int getPriority(){
return priority;
}
public boolean evalConditions(GenericPlayer player, GenericServer server){
if(expressions.isEmpty())
public boolean evalConditions(ProfileConditionParser parser, PluginLogger logger, GenericPlayer player, GenericServer server){
if(condition == null || condition.isEmpty())
return true;
for(Expression expression : expressions){
if(!expression.evaluate(player, server))
return false;
ParseWarnCollector collector = new ParseWarnCollector(condition);
ExpressionTemplate template = parser.compile(condition, player, server, collector);
if(collector.hasWarnings()){
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
for(ParseWarnCollector.Context context : collector.getWarnings()){
logger.warn(" - At position %s:", context.position() == -1 ? "Unknown" : context.position());
logger.warn(" %s", condition);
logger.warn(" ".repeat(context.position() + 5) + "^");
logger.warn(" -> %s", context.message());
}
}
return true;
if(template == null)
return false;
return template.returnBooleanExpression().evaluate();
}
public ProfileEntry getRandomProfile(){
@@ -84,10 +80,6 @@ public class ServerListProfile{
}
}
public ProfileEntry getDefaultProfile(){
return defaultProfile;
}
/*
* Returns true if the Profile...
* ...doesn't have any valid MOTD set AND
@@ -96,12 +88,12 @@ public class ServerListProfile{
* ...doesn't have a favicon set.
*/
public boolean isInvalidProfile(){
if(profiles.isEmpty())
return defaultProfile.isInvalid();
if(profiles().isEmpty())
return defaultProfile().isInvalid();
boolean profilesValid = false;
for(ProfileEntry profile : profiles){
for(ProfileEntry profile : profiles()){
if(profile.isInvalid())
continue;
@@ -117,10 +109,10 @@ public class ServerListProfile{
private final String fileName;
private final ConfigurationNode node;
private final int priority;
private final List<Expression> expressions = new ArrayList<>();
private final PluginLogger logger;
private String condition = null;
private List<ProfileEntry> profiles = new ArrayList<>();
private ProfileEntry defaultProfile = ProfileEntry.empty();
@@ -133,34 +125,17 @@ public class ServerListProfile{
public static Builder resolve(String fileName, ConfigurationNode node, PluginLogger logger){
return new Builder(fileName, node, logger)
.resolveExpressions()
.resolveCondition()
.resolveProfiles()
.resolveDefaultProfile();
}
private Builder resolveExpressions(){
List<String> temp;
try{
temp = node.node("conditions").getList(String.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving conditions for %s", ex, fileName);
return this;
}
if(temp == null || temp.isEmpty())
private Builder resolveCondition(){
String condition = node.node("condition").getString();
if(condition == null || condition.isEmpty())
return this;
for(String str : temp){
Expression expr = Expression.resolve(str);
if(expr.getResult() != Expression.ExpressionResult.VALID){
logger.warn("Found invalid expression in condition '%s'! Reason: %s", str, expr.getResult().getMessage());
continue;
}
this.expressions.add(expr);
}
this.condition = condition;
return this;
}
@@ -184,7 +159,7 @@ public class ServerListProfile{
}
public ServerListProfile build(){
return new ServerListProfile(this.priority, this.expressions, this.defaultProfile, this.profiles);
return new ServerListProfile(this.priority, this.condition, this.defaultProfile, this.profiles, this.fileName);
}
}
}
@@ -1,226 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.conditions;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
public class Expression{
private final ExpressionResult result;
private final String left;
private final Operator operator;
private final String right;
private Expression(ExpressionResult result, String left, Operator operator, String right){
this.result = result;
this.left = left;
this.operator = operator;
this.right = right;
}
public static Expression createInvalid(ExpressionResult result){
return new Expression(result, null, Operator.UNKNOWN, null);
}
public static Expression resolve(String expression){
Operator operator = Operator.UNKNOWN;
if(expression == null || expression.isEmpty()){
return Expression.createInvalid(ExpressionResult.INVALID_NO_EXPRESSION);
}
char[] chars = expression.toCharArray();
StringBuilder leftBuilder = new StringBuilder();
StringBuilder rightBuilder = new StringBuilder();
boolean foundOperator = false;
for(int i = 0; i < chars.length; i++){
char c = chars[i];
char next = (i == (chars.length - 1)) ? '\0' : chars[i + 1];
Operator tmp = Operator.getOperand(c, next);
if(tmp != Operator.UNKNOWN && !foundOperator){
operator = tmp;
foundOperator = true;
if(tmp.hasSecond())
i++; // Skip next character if operator has 2
continue;
}
if(foundOperator){
rightBuilder.append(c);
}else{
leftBuilder.append(c);
}
}
if(leftBuilder.isEmpty() || rightBuilder.isEmpty()){
return Expression.createInvalid(ExpressionResult.INVALID_EMPTY_PARTS);
}
return new Expression(ExpressionResult.VALID, leftBuilder.toString().trim(), operator, rightBuilder.toString().trim());
}
public boolean evaluate(GenericPlayer player, GenericServer server){
String newLeft = StringReplacer.replace(left, player, server);
String newRight = StringReplacer.replace(right, player, server);
return operator.evaluate(newLeft, newRight);
}
public ExpressionResult getResult(){
return result;
}
public enum Operator{
LESS('<', '\0'){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
int rightInt = Operator.getInt(right);
return leftInt < rightInt;
}
},
LESS_OR_EQUAL('<', '='){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
int rightInt = Operator.getInt(right);
return leftInt <= rightInt;
}
},
EQUAL('=', '\0'){
@Override
public boolean evaluate(String left, String right){
return left.equals(right);
}
},
EQUALS_IGNORE_CASE('~', '='){
@Override
public boolean evaluate(String left, String right){
return left.equalsIgnoreCase(right);
}
},
NOT_EQUAL('!', '='){
@Override
public boolean evaluate(String left, String right){
return !left.equals(right);
}
},
NOT_EQUAL_IGNORE_CASE('!', '~'){
@Override
public boolean evaluate(String left, String right){
return !left.equalsIgnoreCase(right);
}
},
GREATER('>', '\0'){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
int rightInt = Operator.getInt(right);
return leftInt > rightInt;
}
},
GREATER_OR_EQUAL('>', '='){
@Override
public boolean evaluate(String left, String right){
int leftInt = Operator.getInt(left);
int rightInt = Operator.getInt(right);
return leftInt >= rightInt;
}
},
UNKNOWN('\0', '\0'){
@Override
public boolean evaluate(String left, String right){
return false;
}
};
private static final Operator[] VALUES = values();
private final char first;
private final char second;
Operator(char first, char second){
this.first = first;
this.second = second;
}
public static Operator getOperand(char first, char second){
for(Operator operator : VALUES){
if(operator.first == first){
if((!operator.hasSecond() && second != '=' && second != '~') || operator.second == second)
return operator;
}
}
return Operator.UNKNOWN;
}
public boolean hasSecond(){
return second != '\0';
}
public abstract boolean evaluate(String left, String right);
private static int getInt(String text){
try{
return Integer.parseInt(text);
}catch(NumberFormatException ex){
return text.length();
}
}
}
public enum ExpressionResult{
VALID(null),
INVALID_NO_EXPRESSION("Received empty condition which isn't allowed!"),
INVALID_EMPTY_PARTS ("Received condition with either left or right part being empty.");
private final String message;
ExpressionResult(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
}
@@ -0,0 +1,78 @@
/*
* 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.conditions;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.reader.PlaceholderTokenReader;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.reader.PlaceholderValueReader;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.CustomExpressionTokenizer;
import ch.andre601.expressionparser.ExpressionParserEngine;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.operator.Operator;
import ch.andre601.expressionparser.parsers.ExpressionTemplateParser;
import ch.andre601.expressionparser.parsers.ValueReader;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import ch.andre601.expressionparser.tokens.Token;
import ch.andre601.expressionparser.tokens.readers.TokenReader;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
public class ProfileConditionParser implements ExpressionParserEngine{
private final CustomExpressionTokenizer tokenizer;
private final ExpressionTemplateParser parser;
private ProfileConditionParser(List<TokenReader> tokenReaders, ImmutableMap<Token, Operator> operators, ImmutableList<ValueReader> valueReaders){
this.tokenizer = new CustomExpressionTokenizer(tokenReaders);
this.parser = new ExpressionTemplateParser(operators, valueReaders);
}
public static ProfileConditionParser create(){
return new ProfileConditionParserBuilder().addDefaults()
.addTokenReader(new PlaceholderTokenReader(-20))
.addValueReader(new PlaceholderValueReader())
.build();
}
public ExpressionTemplate compile(String text, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
return parser.parse(tokenizer.parse(text, player, server, collector), collector);
}
@Override
public ExpressionTemplate compile(String s, ParseWarnCollector parseWarnCollector){
return null;
}
private static class ProfileConditionParserBuilder extends ExpressionParserEngine.Builder<ProfileConditionParser>{
@Override
public ProfileConditionParser build(){
return new ProfileConditionParser(this.getTokenReaders(), ImmutableMap.copyOf(this.getOperators()), ImmutableList.copyOf(this.getValueReaders()));
}
}
}
@@ -0,0 +1,48 @@
/*
* 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.conditions.placeholders.reader;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.tokens.Token;
import ch.andre601.expressionparser.tokens.readers.TokenReader;
import java.text.ParsePosition;
public abstract class CustomTokenReader extends TokenReader{
public CustomTokenReader(int priority){
super(priority);
}
@Override
public Token read(String text, ParsePosition position, ParseWarnCollector collector){
return null;
}
public abstract Token read(String text, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector);
}
@@ -0,0 +1,51 @@
/*
* 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.conditions.placeholders.reader;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.tokens.Token;
import java.text.ParsePosition;
public class PlaceholderTokenReader extends CustomTokenReader{
public PlaceholderTokenReader(int priority){
super(priority);
}
@Override
public Token read(String text, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
if(position.getIndex() + 1 < text.length() && text.charAt(position.getIndex()) == '$' && text.charAt(position.getIndex() + 1) == '{'){
position.setIndex(position.getIndex() + 2);
return new PlaceholderToken(StringReplacer.parsePlaceholder(text, position, player, server, collector));
}
return null;
}
}
@@ -0,0 +1,46 @@
/*
* 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.conditions.placeholders.reader;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.parsers.ExpressionTemplateParser;
import ch.andre601.expressionparser.parsers.ValueReader;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import ch.andre601.expressionparser.tokens.Token;
import java.util.List;
public class PlaceholderValueReader extends ValueReader{
@Override
public ExpressionTemplate read(ExpressionTemplateParser parser, List<Token> tokens, ParseWarnCollector collector){
if(tokens.get(0) instanceof PlaceholderToken){
PlaceholderToken token = (PlaceholderToken)tokens.remove(0);
return token.getValue();
}
return null;
}
}
@@ -0,0 +1,85 @@
/*
* 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.conditions.placeholders.tokens;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.reader.CustomTokenReader;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.tokens.Token;
import ch.andre601.expressionparser.tokens.readers.TokenReader;
import com.google.common.collect.Ordering;
import java.text.ParsePosition;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class CustomExpressionTokenizer{
private static final Ordering<TokenReader> TOKEN_READER_ORDERING = Ordering.from(Comparator.comparingInt(TokenReader::getPriority)).reverse();
private final List<TokenReader> tokenReaders;
public CustomExpressionTokenizer(Iterable<TokenReader> tokenReaders){
this.tokenReaders = TOKEN_READER_ORDERING.immutableSortedCopy(tokenReaders);
}
public List<Token> parse(String text, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
ParsePosition position = new ParsePosition(0);
List<Token> tokens = new LinkedList<>();
next_token:
while(true){
while(position.getIndex() < text.length() && Character.isWhitespace(text.charAt(position.getIndex())))
position.setIndex(position.getIndex() + 1);
if(position.getIndex() >= text.length())
break;
for(TokenReader tokenReader : tokenReaders){
Token token;
if(tokenReader instanceof CustomTokenReader customTokenReader){
if(null != (token = customTokenReader.read(text, position, player, server, collector))){
tokens.add(token);
continue next_token;
}
}else{
if(null != (token = tokenReader.read(text, position, collector))){
tokens.add(token);
continue next_token;
}
}
}
collector.appendWarningFormatted(position.getIndex(), "Illegal Token '%c'.", text.charAt(position.getIndex()));
break;
}
return tokens;
}
}
@@ -0,0 +1,81 @@
/*
* 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.conditions.placeholders.tokens;
import ch.andre601.expressionparser.expressions.ToBooleanExpression;
import ch.andre601.expressionparser.expressions.ToDoubleExpression;
import ch.andre601.expressionparser.expressions.ToStringExpression;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import ch.andre601.expressionparser.tokens.Token;
public class PlaceholderToken extends Token{
private final Placeholder value;
public PlaceholderToken(Placeholder value){
super("PLACEHOLDER");
this.value = value;
}
public Placeholder getValue(){
return value;
}
public static class Placeholder implements ExpressionTemplate{
private final ToBooleanExpression toBooleanExpression;
private final ToDoubleExpression toDoubleExpression;
private final ToStringExpression toStringExpression;
public Placeholder(String value){
double doubleValue;
try{
doubleValue = Double.parseDouble(value);
}catch(NumberFormatException ex){
doubleValue = value.length();
}
this.toBooleanExpression = ToBooleanExpression.literal(Boolean.parseBoolean(value));
this.toDoubleExpression = ToDoubleExpression.literal(doubleValue);
this.toStringExpression = ToStringExpression.literal(value);
}
@Override
public ToBooleanExpression returnBooleanExpression(){
return toBooleanExpression;
}
@Override
public ToDoubleExpression returnDoubleExpression(){
return toDoubleExpression;
}
@Override
public ToStringExpression returnStringExpression(){
return toStringExpression;
}
}
}
@@ -26,122 +26,167 @@
package ch.andre601.advancedserverlist.core.profiles.favicon;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Stream;
public class FaviconHandler<F>{
private final Cache<String, CompletableFuture<F>> favicons = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
private final AdvancedServerList<F> core;
private final PluginLogger logger;
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();
public FaviconHandler(AdvancedServerList<F> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.faviconThreadPool = createFaviconThreadPool();
this.faviconCache = CacheBuilder.newBuilder()
.expireAfterWrite(core.getFileHandler().getLong(1, 1, "faviconCacheTime"), TimeUnit.MINUTES)
.build();
loadLocalFavicons();
}
public F getFavicon(String input, Function<BufferedImage, F> function){
public F getFavicon(String input){
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT).split("\\.")[0])){
return localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]);
}
try{
return favicons.get(input, () -> convert(input, function)).getNow(null);
}catch(ExecutionException e){
return faviconCache.get(input, () -> getFuture(input)).getNow(null);
}catch(ExecutionException ex){
logger.warn("Received ExecutionException while retrieving Favicon for '%s'.", ex, input);
return null;
}
}
public void clearCache(){
favicons.invalidateAll();
public void cleanCache(){
faviconCache.invalidateAll();
loadLocalFavicons();
}
private CompletableFuture<F> convert(String input, Function<BufferedImage, F> function){
return CompletableFuture.supplyAsync(() -> {
BufferedImage img = resolveImage(core, input);
if(img == null)
return null;
return function.apply(img);
}, faviconThreadPool);
}
private BufferedImage resolveImage(AdvancedServerList<F> core, String input){
InputStream stream;
private CompletableFuture<F> getFuture(String input){
if(input.toLowerCase(Locale.ROOT).startsWith("https://")){
stream = getFromUrl(core, input);
logger.debug(FaviconHandler.class, "Resolving URL '%s'...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, input), this.faviconThreadPool);
}else
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
File folder = core.getPlugin().getFolderPath().resolve("favicons").toFile();
if(!folder.exists()){
core.getPlugin().getPluginLogger().warn("Cannot get Favicon %s from favicons folder. Folder doesn't exist!", input);
return null;
}
File file = new File(folder, input);
try{
stream = new FileInputStream(file);
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon from File %s.", input);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
return null;
}
logger.debug(FaviconHandler.class, "Resolving image file '%s'...", input);
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]));
}else{
stream = getFromUrl(core, "https://mc-heads.net/avatar/" + input + "/64");
logger.debug(FaviconHandler.class, "Resolving Name/UUID as https://mc-heads.net/avatar/%s/64...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, "https://mc-heads.net/avatar/" + input + "/64"), this.faviconThreadPool);
}
}
private void loadLocalFavicons(){
this.localFavicons.clear();
logger.info("Loading local image files as Favicons...");
Path folder = core.getPlugin().getFolderPath().resolve("favicons");
if(!Files.exists(folder)){
try{
Files.createDirectories(folder);
logger.info("Created favicons folder.");
}catch(IOException ex){
logger.warn("Cannot create favicons folder. Encountered an IOException.", ex);
return;
}
}
if(stream == null){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. InputStream was null.");
return null;
try(Stream<Path> pathStream = Files.list(folder)){
pathStream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
}catch(IOException ex){
logger.warn("Cannot load files from Favicons folder.", ex);
}
try{
BufferedImage original = ImageIO.read(stream);
if(original == null){
core.getPlugin().getPluginLogger().warn("Cannot create Favicon. Unable to create BufferedImage.");
return null;
}
private void loadFile(Path path){
try(InputStream stream = Files.newInputStream(path)){
F favicon = createFavicon(stream);
if(favicon == null){
logger.warn("Cannot create Favicon from file '%s'. Received Favicon was null.", path.getFileName().toString());
return;
}
BufferedImage favicon = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D img = favicon.createGraphics();
// Resize original image to 64x64 and apply to favicon.
img.drawImage(original, 0, 0, 64, 64, null);
img.dispose();
return favicon;
localFavicons.put(path.getFileName().toString().split("\\.")[0], favicon);
logger.info("Loaded file '%s' as Favicon.", path.getFileName().toString());
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Unable to create Favicon. Encountered IOException during creation.");
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
logger.warn("Cannot create Favicon from file '%s'. Encountered IOException.", ex);
}
}
private F fromURL(AdvancedServerList<F> core, String url){
try{
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();
try(InputStream stream = client.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()){
return createFavicon(stream);
}catch(InterruptedException | IOException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an Exception.", ex, url);
return null;
}
}catch(URISyntaxException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an IOException.", ex, url);
return null;
}
}
private InputStream getFromUrl(AdvancedServerList<F> core, String url){
private F createFavicon(InputStream stream){
try{
URL faviconUrl = new URL(url);
URLConnection connection = faviconUrl.openConnection();
connection.setRequestProperty("User-Agent", "AdvancedServerList/" + core.getVersion());
connection.connect();
logger.debug(FaviconHandler.class, "Creating BufferedImage from InputStream...");
BufferedImage original = ImageIO.read(stream);
if(original == null){
logger.warn("Cannot create Favicon. Received null BufferedImage.");
return null;
}
return connection.getInputStream();
}catch(IOException ex){
core.getPlugin().getPluginLogger().warn("Error while connecting to %s for Favicon creation.", url);
core.getPlugin().getPluginLogger().warn("Cause: %s", ex.getMessage());
// 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, "Resizing image to 64x64 pixels...");
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = image.createGraphics();
graphics2D.drawImage(original, 0, 0, 64, 64, null);
graphics2D.dispose();
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);
return null;
}
}
@@ -29,6 +29,8 @@ import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import io.leangen.geantyref.TypeToken;
import java.io.BufferedReader;
@@ -38,7 +40,9 @@ import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PlayerHandler{
@@ -68,19 +72,18 @@ public class PlayerHandler{
}
if(core.getFileHandler().getBoolean("disableCache")){
logger.info("'disable_cache' is set to true. Skipping playercache.json loading...");
logger.info("'disableCache' is set to true. Skipping playercache.json loading...");
return;
}
try{
BufferedReader reader = Files.newBufferedReader(cache);
try(BufferedReader reader = Files.newBufferedReader(cache)){
cachedPlayers = gson.fromJson(reader, listType);
reader.close();
}catch(IOException ex){
logger.warn("Encountered IOException while reading the playercache.json file!", ex);
return;
}catch(JsonIOException | JsonSyntaxException ex){
logger.warn("Encountered Json exception while parsing playercache.json file!", ex);
return;
}
// In case Gson messes up... I guess.
@@ -127,7 +130,7 @@ public class PlayerHandler{
return getDefaultPlayer();
for(CachedPlayer player : cachedPlayers){
if(player.getIp().equals(key))
if(player.ip().equals(key))
return player;
}
@@ -136,7 +139,7 @@ public class PlayerHandler{
public CachedPlayer getCachedPlayer(UUID uuid){
for(CachedPlayer player : cachedPlayers){
if(player.getUuid().equals(uuid))
if(player.uuid().equals(uuid))
return player;
}
@@ -150,7 +153,7 @@ public class PlayerHandler{
private boolean contains(String ip){
for(CachedPlayer player : cachedPlayers){
if(player.getIp().equals(ip))
if(player.ip().equals(ip))
return true;
}
@@ -28,9 +28,9 @@ package ch.andre601.advancedserverlist.core.profiles.profile;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -45,7 +45,7 @@ public class ProfileManager{
*/
public static ProfileEntry merge(ServerListProfile profile){
ProfileEntry entry = profile.getRandomProfile();
ProfileEntry defEntry = profile.getDefaultProfile();
ProfileEntry defEntry = profile.defaultProfile();
List<String> motd = resolveMOTD(entry, defEntry);
List<String> players = resolvePlayers(entry, defEntry);
@@ -67,7 +67,7 @@ public class ProfileManager{
if(profile.isInvalidProfile())
continue;
if(profile.evalConditions(player, server))
if(profile.evalConditions(core.getParser(), core.getPlugin().getPluginLogger(), player, server))
return profile;
}
@@ -86,15 +86,15 @@ public class ProfileManager{
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
return new ProfileEntry.Builder()
.setMotd(motd)
.setPlayers(players)
.setPlayerCountText(playerCountText)
.setFavicon(favicon)
.setHidePlayersEnabled(hidePlayers)
.setExtraPlayersEnabled(extraPlayersEnabled)
.setMaxPlayersEnabled(maxPlayersEnabled)
.setExtraPlayersCount(extraPlayers)
.setMaxPlayersCount(maxPlayers)
.motd(motd)
.players(players)
.playerCountText(playerCountText)
.favicon(favicon)
.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.extraPlayersCount(extraPlayers)
.maxPlayersCount(maxPlayers)
.build();
}
@@ -25,11 +25,11 @@
package ch.andre601.advancedserverlist.core.profiles.profile;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import java.lang.reflect.Type;
@@ -29,6 +29,11 @@ import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import java.text.ParsePosition;
public class StringReplacer{
@@ -36,99 +41,113 @@ public class StringReplacer{
if(input == null)
return null;
char[] chars = input.toCharArray();
ParsePosition position = new ParsePosition(0);
StringBuilder builder = new StringBuilder(input.length());
StringBuilder identifier = new StringBuilder();
StringBuilder placeholder = new StringBuilder();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(int i = 0; i < chars.length; i++){
char c = chars[i];
char next = (i == (chars.length - 1)) ? '\0' : chars[i + 1];
if(c != '$' || i + 2 >= chars.length){
builder.append(c);
while(position.getIndex() < input.length()){
if(position.getIndex() + 1 < input.length() && input.charAt(position.getIndex()) == '$' && input.charAt(position.getIndex() + 1) == '{'){
position.setIndex(position.getIndex() + 2);
builder.append(parsePlaceholder0(input, position, player, server, null));
continue;
}
if(next != '{'){
if(next == '\0')
continue;
builder.append(next);
i++;
continue;
}
i++;
boolean identified = false;
boolean invalid = true;
while(++i < chars.length){
final char id = chars[i];
if(id == '}'){
invalid = false;
break;
}
if(id == ' ' && !identified){
identified = true;
continue;
}
if(identified){
placeholder.append(id);
}else{
identifier.append(id);
}
}
String identifierString = identifier.toString();
String placeholderString = placeholder.toString();
identifier.setLength(0);
placeholder.setLength(0);
if(invalid){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
continue;
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierString);
if(provider == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
String replacement = provider.parsePlaceholder(placeholderString, player, server);
if(replacement == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
builder.append(replacement);
builder.append(input.charAt(position.getIndex()));
position.setIndex(position.getIndex() + 1);
}
return builder.toString();
}
public static PlaceholderToken.Placeholder parsePlaceholder(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
return new PlaceholderToken.Placeholder(parsePlaceholder0(input, position, player, server, collector));
}
private static String parsePlaceholder0(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
AdvancedServerListAPI api = AdvancedServerList.getApi();
int placeholderStart = position.getIndex() - 2;
int index = position.getIndex();
StringBuilder identifier = new StringBuilder();
StringBuilder values = new StringBuilder();
boolean identified = false;
boolean invalid = true;
char[] chars = input.substring(index).toCharArray();
for(final char c : chars){
index++;
if(c == '}'){
invalid = false;
break;
}
if(c == ' ' && !identified){
identified = true;
continue;
}
if(identified){
values.append(c);
}else{
identifier.append(c);
}
}
String identifierStr = identifier.toString();
String valuesStr = values.toString();
StringBuilder raw = new StringBuilder();
// Condition parsing needs one extra increase of index... for some reason
if(collector != null)
index++;
position.setIndex(index);
if(invalid){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
return raw.toString();
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierStr);
if(provider == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
return raw.toString();
}
String replacement = provider.parsePlaceholder(valuesStr, player, server);
if(replacement == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
return raw.toString();
}
return replacement;
}
}
+56 -1
View File
@@ -31,10 +31,65 @@ disableCache: false
#
checkUpdates: true
#
# Should debug mode be enabled?
#
# When set to true will AdvancedServerList print additional messages to the console prefixed with "[DEBUG]".
# It is recommended to only enable this when having problems or when being told to by the plugin dev, as it could
# otherwise cause significant spam in your console.
#
# Defaults to false when not present.
#
debug: false
#
# Sets the time in minutes for favicons to be cached.
# The number cannot be less than 1.
#
# Defaults to 1 if not set.
#
faviconCacheTime: 1
#
# List of options that should be disabled while the Maintenance Mode of the plugin Maintenance is active.
# Any option not listed here will NOT be disabled, meaning AdvancedServerList will continue to handle it.
#
# Each option defaults to true when not present, disabling said option while Maintenance is active.
#
disableDuringMaintenance:
#
# When true (Default), disables handling of MOTD while Maintenance is enabled.
#
motd: true
#
# When true (Default), disables handling of Favicon while Maintenance is enabled.
#
favicon: true
#
# When true (Default), disables hiding of player count while Maintenance is enabled.
#
hidePlayers: true
#
# When true (Default), disables handling of player count text while Maintenance is enabled.
#
playerCountText: true
#
# When true (Default), disables handling of player count hover while Maintenance is enabled.
#
playerCountHover: true
#
# When true (Default), disables use of extra players feature while Maintenance is enabled.
#
extraPlayers: true
#
# When true (Default), disables use of max players feature while Maintenance is enabled.
#
maxPlayers: true
#
# DO NOT EDIT!
#
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
config-version: 2
config-version: ${plugin.config.version}
+81 -79
View File
@@ -1,167 +1,169 @@
#
# Set the priority of this profile.
# Higher number = Higher priority.
# If there are multiple profiles (files) will they be sorted by priority, starting with highest.
#
# Read more: https://asl.andre601.ch/profiles/#priority
#
priority: 0
#
# Set conditions that needs to be met.
# Only when all conditions return true will the profile be shown (Given no profile with higher priority is used).
# 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).
#
# Read more: https://asl.andre601.ch/profiles/#conditions
# Multiple conditions can be chaing with the keywords 'and', 'or', or their counterparts '&&' and '||'.
#
#conditions:
# - '{playerVersion} < 759'
# No condition or an empty condition will be treated as true by default.
#
# Read more: https://asl.andre601.ch/profiles/#condition
#
condition: ''
#
# Option that allows you to define multiple profiles to use.
# Each entry supports the same options as the server list profile does. Whenever an option is not present, or set to
# an empty value (If supported) would the option in the file be used (if present).
# This allows you to f.e. randomize the MOTD while keeping other options the same, without copy-pasting the same options.
# Set one or multiple profiles.
#
# A profile will be selected randomly.
# A profile can contain the same options as used in the file itself, except for priority and condition.
# If multiple entries are present, a random one will be selected. Any options set in the selected profile will override
# any existing option in the file.
#
# Remove this option or set it to profiles: [] to use the global options of this file.
# Example: The below profile configuration will randomly change the MOTD between two types, but keep the Hover text
# the same.
#
# When not present or empty (profiles: []), no profiles will be used and global options from the file will be used instead.
#
# Read more: https://asl.andre601.ch/profiles/#profiles
#
#profiles:
# - motd:
# - '<aqua>Line 1'
# - '<aqua>Line 2'
# favicon: ''
# playerCount:
# hidePlayers: false
# hover:
# - '<green>Line 1'
# - '<green>Line 2'
# - '<green>Line 3'
# text: ''
# extraPlayers:
# enabled: false
# amount: 0
profiles:
- motd: ['<aqua>Line A', '<gold>Line B']
- motd:
- '<aqua>Line 1'
- '<gold>Line 2'
#
# Set the default (Global) MOTD used by this server list profile.
# Supports HEX colors for 1.16+ servers including gradients using MiniMessage's <gradient:color:color> format.
#
# Remove this option or set it to motd: [] to not alter the MOTD.
# Set the "Message of the day" to display.
# This option supports RGB colors for 1.16+ Servers and clients, including gradients using MiniMessage's <gradient>
# option.
#
# Only the first two lines will be considered and any additional one is ignored.
#
# When not present or empty (motd: []), no MOTD will be set.
#
# Read more: https://asl.andre601.ch/profiles/#motd
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>First Line'
- '<grey>Second Line'
#
# Allows you to set a global (Default) favicon for this server list profile.
# You can use one of three possible options:
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
# 2. A URL pointing to a valid Image
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
#
# Remove this option or set to favicon: '' to not replace the Favicon.
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
# 2. URL pointing to an image.*
# 3. 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.
#
# * These images are loaded asynchronously, meaning they may not yet be "ready" when AdvancedServerList is done with
# the event, requiring a refresh of the server list by the player to have it shown.
#
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
#
# If not present or empty (favicon: ''), defaults to not modifying the favicon.
#
# Read more: https://asl.andre601.ch/profiles/#favicon
#
favicon: ''
#
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
# Contains options for modifying the player count (Text displaying <online>/<max>).
#
# Read more: https://asl.andre601.ch/profiles/#playercount
#
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
# Set whether the Player count should be hidden.
# When set to true, the player count will be displayed as '???' instead of the usual '<online>/<max>' and all other
# playerCount options, except for extraPlayers and maxPlayers, will be ignored.
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
# Set 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.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
# If not present or empty (hover: []), defaults to not modifying the hover.
#
# Read more: https://asl.andre601.ch/profiles/#hover
#
hover:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
- '<aqua>Line 1'
- '<yellow>Line 2'
- '<green>Line 3'
#
# Modifies the text that usually displays '<online>/<max>'
#
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
# This is nothing that can be fixed or avoided and would require changes from Mojang.
# Set the text that should be displayed instead of the default '<online>/<max>' text.
#
# Remove this option or set it to text: '' to not modify the player count text.
# Using this option will show the server as "outdated" to the client (Have the ping icon crossed out).
# This cannot be fixed and would require Mojang to change stuff.
#
# If not present or empty (text: ''), defaults to not modifying the text.
#
# Read more: https://asl.andre601.ch/profiles/#text
#
text: ''
#
# Allows you to modify the max player count displayed.
# Note that this will affect ${server playersMax} (Except for when used in conditions).
# The extraPlayers feature allows to set a number that should be added to the current online players and then be
# used as the "max" player count.
#
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers
#
extraPlayers:
#
# Enables/Disables the extraPlayers option.
# When enabled will the total amount of players allowed to join be modified to the current
# number of online players + 'amount'
# Set whether the extraPlayers feature should be enabled or not.
# When set to true, the max players count will be modified to be the number of online players with the 'amount'
# value added to it.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
#
enabled: false
#
# Sets how much should be added/subtracted from the current number of online players
# to then use for the max player count.
# Set the number that should be added to the online player count to then use as the new max player count.
#
# Example:
# When set to 1 while 10 players are online would the player count - if unmodified -
# display '10/11'. When -1 is used will it display '10/9'
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
# 9 when 8 are online and so on.
#
# Defaults to 0 when not present.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
#
amount: 0
#
# Allows you to set the max players that could join your server.
# Note that this option influences the '${server playersMax}' placeholder.
# The maxPlayers feature allows to set a number to use as the max player count to display.
#
# The settings of this option have no effect should 'extraPlayers' be enabled
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers
#
maxPlayers:
#
# Enables/Disables the maxPlayers option.
# When enabled will the total amount of players allowed to join be changed to what 'amount' is set to.
# Set whether the maxPlayers feature should be enabled or not.
# When set to true, the max player count will be set to the 'amount' value.
#
# If not present, defaults to false.
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
#
enabled: false
#
# Sets the number to display for the max number of players allowed to join your server.
# Set the number that should be used as the new max players count.
#
# Example:
# Setting this option to 0 (Default) while 1 player is online would display '1/0'
#
# Defaults to 0 if not set.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
#
+2 -1
View File
@@ -23,4 +23,5 @@
#
#
version=${plugin.version}
version=${plugin.version}
config-version=${plugin.config.version}
@@ -0,0 +1,60 @@
/*
* 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.test;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
public class DummyPluginLogger implements PluginLogger{
@Override
public void debug(Class<?> clazz, String msg, Object... args){
info("[DEBUG] [" + clazz.getSimpleName() + "] " + msg, args);
}
@Override
public void debugWarn(Class<?> clazz, String msg, Object... args){
warn("[DEBUG] [" + clazz.getSimpleName() + "] " + msg, args);
}
@Override
public void info(String msg, Object... args){
System.out.printf((msg) + "%n", args);
}
@Override
public void warn(String msg, Object... args){
System.out.printf((msg) + "%n", args);
}
@Override
public void warn(String msg, Throwable throwable){
System.out.printf((msg) + "%n", throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
System.out.printf((msg) + "%n", args);
}
}
@@ -0,0 +1,76 @@
/*
* 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.test;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.templates.ExpressionTemplate;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ExpressionParserTests{
private final ProfileConditionParser parser = ProfileConditionParser.create();
private final DummyPluginLogger logger = new DummyPluginLogger();
private final Map<String, Boolean> testValuesMap = getTestMap();
@Test
public void testBasicExpressionResults(){
for(Map.Entry<String, Boolean> values : testValuesMap.entrySet()){
logger.info("TEST[expression=\"%s\", expected=%b]", values.getKey(), values.getValue());
ParseWarnCollector collector = new ParseWarnCollector(values.getKey());
ExpressionTemplate template = parser.compile(values.getKey(), null, null, collector);
boolean result;
if(template == null){
result = false;
}else{
result = template.returnBooleanExpression().evaluate();
}
logger.info("Result (output, isExpected): " + result + ", " + (result == values.getValue()));
assertEquals(result, values.getValue());
}
}
private Map<String, Boolean> getTestMap(){
return Map.of(
"20 > 10", true,
"10 > 20", false,
"10 = 10", true,
"10 = 20", false,
"(10 - 5) > (1 + 1)", true,
"(10 - 10) > (1 + 1)", false,
"100 > 50 and 50 < 100", true,
"100 < 50 and 50 > 100", false,
"true or 100 > 10", true,
"false or 100 < 10", false
);
}
}
@@ -26,7 +26,9 @@
package ch.andre601.advancedserverlist.test;
import com.unascribed.flexver.FlexVerComparator;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FlexVerTests{
@@ -286,7 +288,9 @@ public class FlexVerTests{
private void compare(String version1, String comparator, String version2, int expected){
String expression = version1 + " " + comparator + " " + version2 + "?";
int result = FlexVerComparator.compare(version1, version2);
System.out.printf("│ %-24s %5b │\n", expression, FlexVerComparator.compare(version1, version2) == expected);
assertEquals(result, expected);
}
}
+13 -16
View File
@@ -9,7 +9,6 @@
from __future__ import annotations
import posixpath
import re
from mkdocs.config.defaults import MkDocsConfig
@@ -25,21 +24,19 @@ def on_page_markdown(
def replace(match: Match):
type, args = match.groups()
args = args.strip()
if type == "abstract": return _admo(text = args, type = "abstract")
elif type == "info": return _admo(text = args, type = "info")
elif type == "tip": return _admo(text = args, type = "tip")
elif type == "success": return _admo(text = args, type = "success")
elif type == "question": return _admo(text = args, type = "question")
elif type == "warning": return _admo(text = args, type = "warning")
elif type == "failure": return _admo(text = args, type = "failure")
elif type == "danger": return _admo(text = args, type = "danger")
elif type == "bug": return _admo(text = args, type = "bug")
elif type == "example": return _admo(text = args, type = "example")
elif type == "quote": return _admo(text = args, type = "quote")
else: return _admo(text = args)
# Otherwise, raise an error
raise RuntimeError(f"Unknown shortcode: {type}")
if type == "abstract": return _admo(text = args, type = "abstract")
elif type == "info": return _admo(text = args, type = "info")
elif type == "tip": return _admo(text = args, type = "tip")
elif type == "success": return _admo(text = args, type = "success")
elif type == "question": return _admo(text = args, type = "question")
elif type == "warning": return _admo(text = args, type = "warning")
elif type == "failure": return _admo(text = args, type = "failure")
elif type == "danger": return _admo(text = args, type = "danger")
elif type == "bug": return _admo(text = args, type = "bug")
elif type == "example": return _admo(text = args, type = "example")
elif type == "quote": return _admo(text = args, type = "quote")
elif type == "deprecated": return _admo(text = args, type = "deprecated")
else: return _admo(text = args)
# Find and replace all external asset URLs in current page
return re.sub(
+26
View File
@@ -0,0 +1,26 @@
#
# A simple hook that replaces any appearances of \| with just |.
#
# There is an inconsistency between GitHub flavourited Markdown and Python Markdown
# where the former treats | as part of a table, even if it is inside inline code
# causing unwanted table rendering.
#
# The only way to prevent this is to escape it by prefixing it with a back slash (\).
# Unfortunately does this cause issues on Python-Markdown, as it renders inline code
# content as-is without special treatments whatsoever, meaning that `\|` will be
# rendered as <code>\|</code> in the end.
#
# Using this hook, `\|` is being turned into `|` before further processing, resulting
# in <code>|</code> being rendered in the end, while preserving proper table rendering
# on GitHub and co.
#
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.pages import Page
def on_page_markdown(
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
):
return re.sub(r"\\\|","|",markdown)
+7 -7
View File
@@ -8,28 +8,28 @@
Object summaries
-->
{% if page.meta.constructors %}
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor') }}
{{ 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') }}
{{ 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') }}
{{ 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') }}
{{ 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) }}
{{ 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, true) }}
{{ 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)}}
{{ info.info('Method Detail', page.meta.methods, 'method', defaults=page.meta.defaults)}}
{% endif %}
{% endif %}
{% endblock %}
+15 -5
View File
@@ -1,4 +1,4 @@
{% macro summary(title, summaries, inherits, details_type = 'unknown') -%}
{% macro summary(title, summaries, inherits, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
@@ -28,6 +28,8 @@
{% 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 %}
@@ -103,14 +105,14 @@
</div>
{%- endmacro %}
{% macro info(title, details, enum = false) -%}
{% 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 enum %}
{% if details_type == "enum" %}
{% set final_name.name = detail.name | upper() %}
{% else %}
{% set final_name.name = detail.name ~ "(" %}
@@ -121,7 +123,7 @@
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if not enum %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
@@ -138,12 +140,20 @@
<api__static></api__static> <api__final></api__final>
{% endif %}
{% if detail.type %}
{% 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>
-10
View File
@@ -6,16 +6,6 @@
<!-- Actions -->
{% include "partials/actions.html" %}
{% if config.extra.github_repository %}
<div class="admonition info">
<p class="admonition-title">Moved</p>
<p>
The documenation has been moved and can now be found at <a href="https://asl.andre601.ch" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch</strong></a>.<br>
This page in particular can be found at <a href="https://asl.andre601.ch/{{ page.url }}" target="_blank" rel="noreferral nofollow noopener"><strong>asl.andre601.ch/{{ page.url }}</strong></a>.
</p>
</div>
{% endif %}
<!--
Hack: check whether the content contains a h1 headline. If it doesn't, the
page title (or respectively site name) is used as the main headline.
-9
View File
@@ -1,9 +0,0 @@
nav:
- Home: index.md
- getting-started
- commands
- profiles
- examples
- migration
- api
- PlaceholderAPI: placeholderapi
+64
View File
@@ -0,0 +1,64 @@
# BanPlugins Addon
The BanPlugins Addon was made to provide placeholders for different punishment plugins to use in AdvancedServerList.
## Placeholders
### AdvancedBan
Placeholders for the plugin [AdvancedBan](https://www.spigotmc.org/resources/8695/){ target="_blank" rel="nofollow" } are available to use.
| Placeholder | Description |
|---------------------------------|-------------------------------------------------------------------------------------------|
| `${advancedban isMuted}` | Whether the player is muted or not. |
| `${advancedban muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${advancedban muteDuration}` | Relative time until the mute expires.[^1] Returns invalid placeholder if no mute was set. |
| `${advancedban muteExpiration}` | Date on when the mute will expire.[^2] |
| `${advancedban isBanned}` | Whether the player is banned or not. |
| `${advancedban banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${advancedban banDuration}` | Relative time until the ban expires.[^3] Returns invalid placeholder if no ban was set. |
| `${advancedban banExpiration}` | Date on when the ban will expire.[^4] |
[^1]:
An optional boolean can be added to set whether the duration should be from the start or not. `false` is the default.
Example: `${advancedban muteDuration true}`
[^2]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${advancedban muteExpiration yyyy-MM-dd HH:mm:ss}`
[^3]:
An optional boolean can be added to set whether the duration should be from the start or not. `false` is the default.
Example: `${advancedban banDuration true}`
[^4]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${advancedban banExpiration yyyy-MM-dd HH:mm:ss}`
### LibertyBans
Placeholders for the plugin [LibertyBans](https://modrinth.com/plugin/libertybans/){ target="_blank" rel="nofollow" } are available to use.
| Placeholder | Description |
|---------------------------------|------------------------------------------------------------------------------------------|
| `${libertybans isMuted}` | Whether the player is muted or not. |
| `${libertybans muteReason}` | The reason for why the player was muted. Returns invalid placeholder if no mute was set. |
| `${libertybans muteExpiration}` | Date on when the mute will expire.[^5] |
| `${libertybans isBanned}` | Whether the player is banned or not. |
| `${libertybans banReason}` | The reason for why the player was banned. Returns invalid placeholder if no ban was set. |
| `${libertybans banExpiration}` | Date on when the ban will expire.[^6] |
[^5]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${libertybans muteExpiration yyyy-MM-dd HH:mm:ss}`
[^6]:
An optional Date and time Pattern can be set to change the displayed output. The default is `dd, MMM yyyy HH:mm:ss`.
Example: `${libertybans banExpiration yyyy-MM-dd HH:mm:ss}`
## Example
```yaml title="banned.yml"
priority: 1
condition: '${advancedban isBanned}'
motd:
- '<red>You were <bold>BANNED</bold>!'
- '<red>Expires: <grey>${advancedban banExpiration}'
```
+28
View File
@@ -0,0 +1,28 @@
---
icon: octicons/plus-circle-24
---
# Addons
This section contains a curated list of add-ons for AdvancedServerList which can be used to enhance the plugin in different ways.
Do you have a plugin that hooks into AdvancedServerList that is not listed here? Contact Andre601 on Discord and it will be added!
## First-party Addons
These Addons are made by Andre601 and available together with the plugin downloads.
<div class="grid cards" markdown>
- [**BanPlugins**](banplugins.md)
----
Addon for different Punishment plugins such as AdvancedBan, that add new placeholders to use in AdvancedServerList.
</div>
## Third-party
Third-party addons made by other people not working on AdvancedServerList.
*Currently no entries*
-2
View File
@@ -1,2 +0,0 @@
nav:
- ...
+88 -1
View File
@@ -7,6 +7,93 @@ icon: octicons/log-24
This page lists the recent changes made towards the AdvancedServerListAPI.
They are ordered newest to oldest.
## v3.3.0 { #v3.3.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.3.0-added }
- Added `PostServerListSetEvent` to the different platform APIs.
- Fired **after** AdvancedServerList is done with handling the PingEvent.
- Allows to retrieve the [`ProfileEntry`][profileentry] used for the PingEvent.
## v3.2.1 { #v3.2.1 }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.1-changed }
- Removed usage of `${api.version}` in the different pom.xml for version resolving.
## v3.2.0 { #v3.2.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.2.0-added }
- New setter methods added to [`ProfileEntry.Builder`][profileentry.builder] class, replacing old ones (See deprecations below):
- [`extraPlayersCount(Integer)`][extraplayerscount]
- [`extraPlayersEnabled(NullBool)`][extraplayersenabled]
- [`favicon(String)`][favicon]
- [`hidePlayersEnabled(NullBool)`][hideplayersenabled]
- [`maxPlayersCount(Integer)`][maxplayerscount]
- [`maxPlayersEnabled(NullBool)`][maxplayersenabled]
- [`motd(List<String>)`][motd]
- [`playerCountText(String)`][playercounttext]
- [`players(List<String>)`][players]
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount(integer)
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled(nullbool)
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon(string)
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled(nullbool)
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount(integer)
[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>)
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.0-changed }
- The API has been moved to Codeberg and is now available under a new repository URL to download. The group and artifact ID remained the same, but version no longer has a `v` prefix:
/// tab | ":simple-apachemaven: Maven (pom.xml)"
```xml
<repositories>
<repository>
<id>codeberg</id>
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
</dependencies>
```
///
/// tab | ":simple-gradle: Gradle (build.gradle)"
```groovy
repositories {
maven = { url ="https://codeberg.org/api/packages/Andre601/maven/" }
}
dependencies {
compileOnly "ch.andre601.asl-api:api:{apiVersion}"
}
```
///
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v3.2.0-deprecated }
- Setters in [`ProfileEntry.Builder`][profileentry.builder] deprecated in favour of more consistent method naming.
- `setExtraPlayersCount(Integer)`
- `setExtraPlayersEnabled(NullBool)`
- `setFavicon(String)`
- `setHidePlayersEnabled(NullBool)`
- `setMaxPlayersCount(Integer)`
- `setMaxPlayersEnabled(NullBool)`
- `setMotd(List<String>)`
- `setPlayerCountText(String)`
- `setPlayers(List<String>)`
## v3.1.0 { #v3.1.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.1.0-added }
@@ -111,6 +198,6 @@ Templates for changelog
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v-added }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v-removed }
### :octicons-zap-24:{ .changelog-deprecated title="Deprecated" } Deprecated { #v-deprecated }
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v-deprecated }
-->
+5 -6
View File
@@ -4,8 +4,7 @@ icon: octicons/command-palette-24
# API
AdvancedServerList v2 introduced a new API that plugins can hook into to use.
It provides a way for your plugin to provide its own placeholders that should be parsed by AdvancedServerList and also an event to modify the server list.
AdvancedServerList offers an API that other plugins can use to add their own placeholder to the plugin, listen for specific events or even modify Server List Profiles on the fly.
## Add dependency
@@ -15,8 +14,8 @@ Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depend
```xml title="pom.xml"
<repositories>
<repository>
<id>jitpack</id>
<url>https://jitpack.io/</url>
<id>codeberg</id>
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
</repository>
</repositories>
@@ -54,7 +53,7 @@ Add the following to your `pom.xml`, `build.gradle` or `build.gradle.kts` depend
/// tab | :simple-gradle: Gradle
```groovy title="build.gradle"
repositorories {
maven { url = 'https://jitpack.io/' }
maven { url = 'https://codeberg.org/api/packages/Andre601/maven/' }
}
dependencies {
@@ -71,7 +70,7 @@ dependencies {
/// tab | :simple-gradle: Gradle (KTS)
```kotlin title="build.gradle.kts"
repositories {
maven("https://jitpack.io")
maven("https://codeberg.org/api/packages/Andre601/maven/")
}
dependencies {
+1 -1
View File
@@ -1,7 +1,7 @@
---
template: redirect.html
location: https://docs.andre601.ch/asl-api
location: https://jd.andre601.ch/asl-api
title: Javadocs
icon: octicons/link-external-24
-6
View File
@@ -1,6 +0,0 @@
nav:
- index.md
- api: api
- platform-bukkit: platform-bukkit
- platform-bungeecord: platform-bungeecord
- platform-velocity: platform-velocity
-3
View File
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api: ch.andre601.advancedserverlist.api
@@ -8,7 +8,7 @@ constructors:
- name: 'identifier'
description: 'The identifier to use for the placeholder. Cannot be empty.'
type: String
attributes:
attribute:
- notnull
methods:
@@ -28,7 +28,7 @@ methods:
type: GenericServer
description: 'The <a href="./../objects/genericserver/"><code>GenericServer</code> instance</a> used.'
returns: 'Possibly-parsed or possibly-null String to replace the placeholder with.'
attributes:
attribute:
- nullable
- abstract
type:
@@ -1,59 +1,213 @@
---
template: api-doc.html
defaults:
type:
name: 'Builder'
type: 'object'
constructors:
- name: 'Builder'
description: 'Empty Builder Constructor used to create a new instance of this class.'
methods:
- name: 'setMotd'
- name: 'extraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<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, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: 'Integer'
attribute:
- '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.
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
- '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.
- name: 'favicon'
description: |
Sets the value to use for the favicon.<br>
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.
parameters:
- name: 'favicon'
description: 'The favicon to set.'
type: 'String'
attribute:
- '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.
parameters:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: 'NullBool'
attribute:
- '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.'
- name: 'maxPlayersCount'
description: |
Sets the number of max players allowed to join this server.<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>.
parameters:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: 'Integer'
attribute:
- '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.
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
- '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.'
- 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.
returns: 'This Builder after the motd has been set. Useful for chaining.'
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.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attributes:
- notnull
attribute:
- '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.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayers'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Set to an empty list to not change the hover text.
returns: 'This Builder after the players have been set. Useful for chaining.'
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayerCountText'
- 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.
returns: 'This Builder after the player count text has been set. Useful for chaining.'
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: String
attributes:
type: 'String'
attribute:
- '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>
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.
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
- '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.'
- 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>.'
type:
name: 'ProfileEntry'
type: 'object'
link: './..'
#
# Deprecated stuff
#
- name: 'setExtraPlayerCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<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, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attribute:
- nullable
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<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, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayerscount(integer)">extraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersEnabled'
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.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayersenabled(nullbool)">extraPlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
@@ -71,8 +225,9 @@ methods:
- name: 'favicon'
description: 'The favicon to set'
type: String
attributes:
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#favicon(string)">favicon(String)</a> instead.'
type:
name: 'Builder'
type: 'object'
@@ -86,83 +241,15 @@ methods:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: NullBool
attributes:
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#hideplayersenabled(nullbool)">hidePlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersEnabled'
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.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setMaxPlayersEnabled'
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.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayerCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<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, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attributes:
- nullable
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<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, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attributes:
- nullable
type:
name: 'Builder'
type: 'object'
- name: 'setMaxPlayersCount'
description: |
Sets the number of max players allowed to join this server.<br>
@@ -174,18 +261,86 @@ methods:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: Integer
attributes:
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayerscount(integer)">maxPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- 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>.'
- name: 'setMaxPlayersEnabled'
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.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'ProfileEntry'
name: 'Builder'
type: 'object'
- name: 'setMotd'
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.
returns: 'This Builder after the motd has been set. Useful for chaining.'
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#motd(string)">motd(String)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayerCountText'
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.
returns: 'This Builder after the player count text has been set. Useful for chaining.'
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: String
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#playercounttext(string)">playerCountText(String)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayers'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Set to an empty list to not change the hover text.
returns: 'This Builder after the players have been set. Useful for chaining.'
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#players(list<string>)">players(List&lt;String&gt;)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
link: './..'
---
# <api__class></api__class> Builder
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.bukkit: ch.andre601.advancedserverlist.api.bukkit
@@ -0,0 +1,49 @@
---
template: api-doc.html
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.'
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.'
attributes:
- static
type:
name: 'HandlerList'
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 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:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
inherits:
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- '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 entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.bungeecord: ch.andre601.advancedserverlist.api.bungeecord
@@ -0,0 +1,35 @@
---
template: api-doc.html
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.'
type: ProfileEntry
attribute:
- nullable
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 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:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
---
# <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 entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.velocity: ch.andre601.advancedserverlist.api.velocity
@@ -0,0 +1,35 @@
---
template: api-doc.html
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.'
type: ProfileEntry
attribute:
- nullable
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 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:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
---
# <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 entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
+2 -2
View File
@@ -1,10 +1,10 @@
---
template: redirect.html
location: https://github.com/Andre601/asl-api
location: https://codeberg.org/Andre601/asl-api
title: Source Code
icon: octicons/mark-github-16
icon: simple/codeberg
---
<!-- Comment to trigger proper build -->
-1
View File
@@ -1 +0,0 @@
hide: true
+7 -7
View File
@@ -1,5 +1,5 @@
document$.subscribe(async () => {
const url = 'https://codeberg-stats-proxy.vercel.app/repo'
const url = 'https://codeberg-stats-proxy.vercel.app'
const repo_stats = document.querySelector('[data-md-component="source"] .md-source__repository');
function loadCodebergInfo(data) {
@@ -31,7 +31,7 @@ document$.subscribe(async () => {
const versionToken = '{apiVersion}';
const codeBlocks = document.querySelectorAll('.md-content pre code');
for(const codeBlock of codeBlocks) {
codeBlock.innerHTML = codeBlock.innerHTML.replace(new RegExp(versionToken, 'g'), version);
codeBlock.innerHTML = codeBlock.innerHTML.replace(new RegExp(versionToken, 'g'), version.substring(1));
}
}
@@ -40,15 +40,15 @@ document$.subscribe(async () => {
const versionToken = '{version}'
const entries = document.querySelectorAll('.md-content code');
for(const entry of entries) {
entry.innerHTML = entry.innerHTML.replace(new RegExp(versionToken, 'g'), version);
entry.innerHTML = entry.innerHTML.replace(new RegExp(versionToken, 'g'), version.substring(1));
}
}
async function fetchApiInfo() {
const tag = await fetch("https://api.github.com/repos/Andre601/asl-api/releases/latest").then(_ => _.json());
const tag = await fetch(`${url}/api/latest-release`).then(_ => _.json());
const data = {
"version": tag.tag_name
"version": tag.name
};
__md_set("__api_tag", data, sessionStorage);
@@ -57,8 +57,8 @@ document$.subscribe(async () => {
async function fetchInfo() {
const [release, repo] = await Promise.all([
fetch(`${url}/latest-release`).then(_ => _.json()),
fetch(`${url}/stats`).then(_ => _.json()),
fetch(`${url}/repo/latest-release`).then(_ => _.json()),
fetch(`${url}/repo/stats`).then(_ => _.json()),
]);
const data = {
+20 -1
View File
@@ -23,11 +23,13 @@
--md-badge-bg--example: #7c4dff1a;
--md-badge-fg--quote: #9e9e9e;
--md-badge-bg--quote: #9e9e9e1a;
--md-badge-fg--deprecated: #ff5252;
--md-badge-bg--deprecated: #ff52521a;
--badge-icon--note: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M17.263 2.177a1.75 1.75 0 0 1 2.474 0l2.586 2.586a1.75 1.75 0 0 1 0 2.474L19.53 10.03l-.012.013L8.69 20.378a1.753 1.753 0 0 1-.699.409l-5.523 1.68a.748.748 0 0 1-.747-.188.748.748 0 0 1-.188-.747l1.673-5.5a1.75 1.75 0 0 1 .466-.756L14.476 4.963ZM4.708 16.361a.26.26 0 0 0-.067.108l-1.264 4.154 4.177-1.271a.253.253 0 0 0 .1-.059l10.273-9.806-2.94-2.939-10.279 9.813ZM19 8.44l2.263-2.262a.25.25 0 0 0 0-.354l-2.586-2.586a.25.25 0 0 0-.354 0L16.061 5.5Z"></path></svg>');
--badge-icon--abstract: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M5.962 2.513a.75.75 0 0 1-.475.949l-.816.272a.25.25 0 0 0-.171.237V21.25c0 .138.112.25.25.25h14.5a.25.25 0 0 0 .25-.25V3.97a.25.25 0 0 0-.17-.236l-.817-.272a.75.75 0 0 1 .474-1.424l.816.273A1.751 1.751 0 0 1 21 3.97v17.28A1.75 1.75 0 0 1 19.25 23H4.75A1.75 1.75 0 0 1 3 21.25V3.97a1.75 1.75 0 0 1 1.197-1.66l.816-.272a.75.75 0 0 1 .949.475Z"></path><path d="M7 1.75C7 .784 7.784 0 8.75 0h6.5C16.216 0 17 .784 17 1.75v1.5A1.75 1.75 0 0 1 15.25 5h-6.5A1.75 1.75 0 0 1 7 3.25Zm1.75-.25a.25.25 0 0 0-.25.25v1.5c0 .138.112.25.25.25h6.5a.25.25 0 0 0 .25-.25v-1.5a.25.25 0 0 0-.25-.25Z"></path></svg>');
--badge-icon--info: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M13 7.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-3 3.75a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 .75.75v4.25h.75a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1 0-1.5h.75V12h-.75a.75.75 0 0 1-.75-.75Z"></path><path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Z"></path></svg>');
--badge-icon--tip: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M14.265 1.627c0 3.545 1.869 5.327 3.479 7.021 1.54 1.62 3.006 3.163 3.006 6.102 0 4.812-3.753 8.25-8.565 8.25-4.813 0-8.935-3.421-8.935-8.25 0-2.039.962-4.011 2.509-4.899.305-.175.672.007.803.334C7.563 12.684 8.797 12.64 9.437 12c.388-.387.47-1.116-.004-2.062-2.405-4.812 1.863-8.279 4.2-8.854.336-.082.615.198.632.543ZM12.185 21.5c4.059 0 7.065-2.84 7.065-6.75 0-2.337-1.093-3.489-2.678-5.158l-.021-.023c-1.44-1.517-3.139-3.351-3.649-6.557a6.148 6.148 0 0 0-1.911 1.76c-.787 1.144-1.147 2.633-.216 4.495.603 1.205.777 2.74-.277 3.794-.657.657-1.762 1.1-2.956.586-.752-.324-1.353-.955-1.838-1.79-.567.706-.954 1.74-.954 2.893 0 3.847 3.288 6.75 7.435 6.75Z"></path></svg>');
--badge-icon--tip: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M12 2.5c-3.81 0-6.5 2.743-6.5 6.119 0 1.536.632 2.572 1.425 3.56.172.215.347.422.527.635l.096.112c.21.25.427.508.63.774.404.531.783 1.128.995 1.834a.75.75 0 0 1-1.436.432c-.138-.46-.397-.89-.753-1.357a18.111 18.111 0 0 0-.582-.714l-.092-.11c-.18-.212-.37-.436-.555-.667C4.87 12.016 4 10.651 4 8.618 4 4.363 7.415 1 12 1s8 3.362 8 7.619c0 2.032-.87 3.397-1.755 4.5-.185.23-.375.454-.555.667l-.092.109c-.21.248-.405.481-.582.714-.356.467-.615.898-.753 1.357a.751.751 0 0 1-1.437-.432c.213-.706.592-1.303.997-1.834.202-.266.419-.524.63-.774l.095-.112c.18-.213.355-.42.527-.634.793-.99 1.425-2.025 1.425-3.561C18.5 5.243 15.81 2.5 12 2.5ZM8.75 18h6.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5Zm.75 3.75a.75.75 0 0 1 .75-.75h3.5a.75.75 0 0 1 0 1.5h-3.5a.75.75 0 0 1-.75-.75Z"></path></svg>');
--badge-icon--success: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M21.03 5.72a.75.75 0 0 1 0 1.06l-11.5 11.5a.747.747 0 0 1-1.072-.012l-5.5-5.75a.75.75 0 1 1 1.084-1.036l4.97 5.195L19.97 5.72a.75.75 0 0 1 1.06 0Z"></path></svg>');
--badge-icon--question: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M10.97 8.265a1.45 1.45 0 0 0-.487.57.75.75 0 0 1-1.341-.67c.2-.402.513-.826.997-1.148C10.627 6.69 11.244 6.5 12 6.5c.658 0 1.369.195 1.934.619a2.45 2.45 0 0 1 1.004 2.006c0 1.033-.513 1.72-1.027 2.215-.19.183-.399.358-.579.508l-.147.123a4.329 4.329 0 0 0-.435.409v1.37a.75.75 0 1 1-1.5 0v-1.473c0-.237.067-.504.247-.736.22-.28.486-.517.718-.714l.183-.153.001-.001c.172-.143.324-.27.47-.412.368-.355.569-.676.569-1.136a.953.953 0 0 0-.404-.806C12.766 8.118 12.384 8 12 8c-.494 0-.814.121-1.03.265ZM13 17a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path><path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Z"></path></svg>');
--badge-icon--warning: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M13 17.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm-.25-8.25a.75.75 0 0 0-1.5 0v4.5a.75.75 0 0 0 1.5 0v-4.5Z"></path><path d="M9.836 3.244c.963-1.665 3.365-1.665 4.328 0l8.967 15.504c.963 1.667-.24 3.752-2.165 3.752H3.034c-1.926 0-3.128-2.085-2.165-3.752Zm3.03.751a1.002 1.002 0 0 0-1.732 0L2.168 19.499A1.002 1.002 0 0 0 3.034 21h17.932a1.002 1.002 0 0 0 .866-1.5L12.866 3.994Z"></path></svg>');
@@ -36,6 +38,7 @@
--badge-icon--bug: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M7.72.22a.75.75 0 0 1 1.06 0l1.204 1.203A4.98 4.98 0 0 1 12 1c.717 0 1.4.151 2.016.423L15.22.22a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-.971.972A4.991 4.991 0 0 1 17 6v1.104a2.755 2.755 0 0 1 1.917 1.974l1.998-.999a.75.75 0 0 1 .67 1.342L19 10.714V13.5l3.25.003a.75.75 0 0 1 0 1.5L19 15.001V16c0 .568-.068 1.134-.204 1.686l.04.018 2.75 1.375a.75.75 0 1 1-.671 1.342l-2.638-1.319A6.998 6.998 0 0 1 12 23a6.998 6.998 0 0 1-6.197-3.742l-2.758 1.181a.752.752 0 0 1-1.064-.776.752.752 0 0 1 .474-.602l2.795-1.199A6.976 6.976 0 0 1 5 16v-.996H1.75a.75.75 0 0 1 0-1.5H5v-2.79L2.415 9.42a.75.75 0 0 1 .67-1.342l1.998.999A2.756 2.756 0 0 1 7 7.104V6a4.99 4.99 0 0 1 1.69-3.748l-.97-.972a.75.75 0 0 1 0-1.06ZM6.5 9.75V16a5.5 5.5 0 1 0 11 0V9.75c0-.69-.56-1.25-1.25-1.25h-8.5c-.69 0-1.25.56-1.25 1.25ZM8.5 7h7V6a3.5 3.5 0 1 0-7 0Z"></path></svg>');
--badge-icon--example: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M8 8.807V3.5h-.563a.75.75 0 0 1 0-1.5h9.125a.75.75 0 0 1 0 1.5H16v5.307l5.125 9.301c.964 1.75-.302 3.892-2.299 3.892H5.174c-1.998 0-3.263-2.142-2.3-3.892ZM4.189 18.832a1.123 1.123 0 0 0 .985 1.668h13.652a1.123 1.123 0 0 0 .985-1.668L17.7 15H6.3ZM14.5 3.5h-5V9a.75.75 0 0 1-.093.362L7.127 13.5h9.746l-2.28-4.138A.75.75 0 0 1 14.5 9Z"></path></svg>');
--badge-icon--quote: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M3 6.25a.75.75 0 0 1 .75-.75h13.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.25Zm5 6.063a.75.75 0 0 1 .75-.75h11.5a.75.75 0 0 1 0 1.5H8.75a.75.75 0 0 1-.75-.75Zm0 5.937a.75.75 0 0 1 .75-.75h11.5a.75.75 0 0 1 0 1.5H8.75a.75.75 0 0 1-.75-.75ZM3.75 11a.75.75 0 0 1 .75.75v7a.75.75 0 0 1-1.5 0v-7a.75.75 0 0 1 .75-.75Z"></path></svg>');
--badge-icon--deprecated: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M16 1.75V3h5.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H8V1.75C8 .784 8.784 0 9.75 0h4.5C15.216 0 16 .784 16 1.75Zm-6.5 0V3h5V1.75a.25.25 0 0 0-.25-.25h-4.5a.25.25 0 0 0-.25.25ZM4.997 6.178a.75.75 0 1 0-1.493.144L4.916 20.92a1.75 1.75 0 0 0 1.742 1.58h10.684a1.75 1.75 0 0 0 1.742-1.581l1.413-14.597a.75.75 0 0 0-1.494-.144l-1.412 14.596a.25.25 0 0 1-.249.226H6.658a.25.25 0 0 1-.249-.226L4.997 6.178Z"></path><path d="M9.206 7.501a.75.75 0 0 1 .793.705l.5 8.5A.75.75 0 1 1 9 16.794l-.5-8.5a.75.75 0 0 1 .705-.793Zm6.293.793A.75.75 0 1 0 14 8.206l-.5 8.5a.75.75 0 0 0 1.498.088l.5-8.5Z"></path></svg>');
}
/*
@@ -257,4 +260,20 @@
-webkit-mask-image: var(--badge-icon--quote);
mask-image: var(--badge-icon--quote);
}
/* Deprecated */
.mdx-admo--deprecated {
border-color: var(--md-badge-fg--deprecated);
}
.mdx-admo--deprecated .mdx-grid-child--icon {
background-color: var(--md-badge-bg--deprecated);
}
.mdx-admo--deprecated .mdx-grid-child--icon::before {
background-color: var(--md-badge-fg--deprecated);
-webkit-mask-image: var(--badge-icon--deprecated);
mask-image: var(--badge-icon--deprecated);
}
+23
View File
@@ -0,0 +1,23 @@
:root {
--admonition-icon--file: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M3 3a2 2 0 0 1 2-2h9.982a2 2 0 0 1 1.414.586l4.018 4.018A2 2 0 0 1 21 7.018V21a2 2 0 0 1-2 2H4.75a.75.75 0 0 1 0-1.5H19a.5.5 0 0 0 .5-.5V8.5h-4a2 2 0 0 1-2-2v-4H5a.5.5 0 0 0-.5.5v6.25a.75.75 0 0 1-1.5 0Zm12-.5v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 0-.146-.336l-4.018-4.018A.5.5 0 0 0 15 2.5Z"></path><path d="M4.53 12.24a.75.75 0 0 1-.039 1.06l-2.639 2.45 2.64 2.45a.75.75 0 1 1-1.022 1.1l-3.23-3a.75.75 0 0 1 0-1.1l3.23-3a.75.75 0 0 1 1.06.04Zm3.979 1.06a.75.75 0 1 1 1.02-1.1l3.231 3a.75.75 0 0 1 0 1.1l-3.23 3a.75.75 0 1 1-1.021-1.1l2.639-2.45-2.64-2.45Z"></path></svg>');
--admonition-color-fg--file: #00c853;
--admonition-color-bg--file: #00c8531a;
}
.md-typeset .admonition.file,
.md-typeset details.file {
border-color: var(--admonition-color-fg--file);
}
.md-typeset .file > .admonition-title,
.md-typeset .file > summary {
background-color: var(--admonition-color-bg--file);
}
.md-typeset .file > .admonition-title::before,
.md-typeset .file > summary::before {
background-color: var(--admonition-color-fg--file);
-webkit-mask-image: var(--admonition-icon--file);
mask-image: var(--admonition-icon--file);
}
+31 -15
View File
@@ -6,7 +6,7 @@ icon: octicons/list-unordered-24
## About
<!-- admo:info The below examples may only work in v1.10.0 or newer! -->
<!-- admo:info The below examples may only work in v3.7.0 or newer! -->
This page lists some examples you may want to use for your proxy or server.
@@ -17,7 +17,9 @@ Feel free to suggest additional examples on my [Discord Server](https://discord.
- [Versions](#versions)
- [Different List for outdated Clients](#different-list-for-outdated-clients)
- [Different MOTD for < 1.16](#different-motd-for-116)
- [Spigot/PaperMC](#spigotpapermc)
- [BungeeCord/Velocity](#bungeecordvelocity)
- [Display MOTD for a set of subdomains](#display-motd-for-a-set-of-subdomains)
- [PaperMC](#papermc)
- [Different profile for banned Player](#different-profile-for-banned-player)
- [Other](#other)
- [Different profile for different host](#different-profile-for-different-host)
@@ -38,8 +40,7 @@ This example here shows a separate MOTD and player count message for when the pl
priority: 1
# Display this profile, if the version of the player is below 760 (1.19.1)
conditions:
- '${player protocol} < 760'
condition: '${player protocol} < 760'
motd:
- '<red>You are using an outdated client!'
@@ -57,8 +58,7 @@ This profile would display a MOTD without HEX colours if the player's version is
priority: 1
# Display this profile, if the version of the player is below 735 (1.16)
conditions:
- '${player protocol} < 735'
condition: '${player protocol} < 735'
motd:
- '<grey>Welcome to <aqua>YourServer.com</aqua>!'
@@ -66,9 +66,28 @@ motd:
```
----
## Spigot/PaperMC
## BungeeCord/Velocity
Examples that can be used with the Spigot or PaperMC version.
Examples usable on the BungeeCord and Velocity version.
### Display MOTD for a set of subdomains
Displays the same MOTDs for the server when pinged on any sub-domain starting with `lobby` (i.e. `lobby-1.example.com`).
```yaml title="lobby-motd.yml"
priority: 1
condition: '${server host} |- "lobby"'
motd:
- '<green>Lobby Server'
- '<grey>Example Server'
```
----
## PaperMC
Examples that can be used with the PaperMC version.
### Different profile for banned Player
@@ -79,8 +98,7 @@ Displays a separate profile for when the player has been banned from the server.
```yaml title="banned.yml"
priority: 1
conditions:
- '${player isBanned} = true'
condition: '${player isBanned}'
motd:
- '<red>You have been <bold>BANNED</bold>!'
@@ -103,8 +121,7 @@ Display a different profile when the playing pings a specific domain/IP.
```yaml title="specific-host.yml"
priority: 1
conditions:
- '${server host} = other.example.com'
condition: '${server host} = "host.example.com"'
motd:
- '<grey>Please use <aqua>mc.example.com'
@@ -118,12 +135,11 @@ Display a different profile, if the player pinging the server is "known" by Adva
```yaml title="personalized.yml"
priority: 1
conditions:
- `${player name} != Anonymous` # "Anonymous" should be replaced with whatever you use in 'unknown_player'
condition: '${player name} != "Anonymous"' # "Anonymous" would be the value from the "unknownPlayer > name" option.
motd:
- '<grey>Hello there <aqua>${player name}</aqua>!'
- '<grey>It's nice to see you again.'
- '<grey>It''s nice to see you again.'
playerCount:
hover:
+259 -112
View File
@@ -5,39 +5,115 @@ icon: octicons/milestone-24
# Getting Started
This page will explain how to set up AdvancedServerList and make it work for your server.
It tries to be an easy to understand as possible. But if you still have problems, consider joining the [Discord Server](https://discord.gg/6dazXp6) for help.
It tries to be as easy to understand as possible. But if you still have problems, consider joining the [Discord Server](https://discord.gg/6dazXp6){ target="_blank" rel="nofollow" } for help.
## 1. Download the plugin { #download-the-plugin }
The first step would be to download the plugin from a download page of your choice. As of writing this is AdvancedServerList updated and available on these sites:
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!):
- [Modrinth]
- [Codeberg]
<div class="grid cards" markdown>
- [:simple-modrinth: **Modrinth**][modrinth]{ target="_blank" rel="nofollow" }
----
:octicons-check-24:{ style="color: var(--md-badge-fg--success);" } **Actively updated!**
- [:simple-codeberg: **Codeberg**][codeberg]{ target="_blank" rel="nofollow" }
----
:octicons-check-24:{ style="color: var(--md-badge-fg--success);" } **Actively updated!**
- [:fontawesome-solid-paper-plane: **HangarMC**][hangar]{ target="_blank" rel="nofollow" }
----
:octicons-check-24:{ style="color: var(--md-badge-fg--success);" } **Actively updated!**
- [:simple-spigotmc: **SpigotMC**][spigot]{ target="_blank" rel="nofollow" }
----
:octicons-alert-24:{ style="color: var(--md-badge-fg--warning);" } **Discontinued!**
</div>
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[codeberg]: https://codeberg.org/Andre601/AdvancedServerList
The plugin is also available on these platforms, but not actively updated there anymore:
- [Spigot] (Latest version: `3.3.0-b1`)
- [Hangar] (Latest version: `3.5.0`)
[spigot]: https://www.spigotmc.org/resources/102910/
[hangar]: https://hangar.papermc.io/Andre_601/AdvancedServerList
The plugin is available for Spigot, Paper, BungeeCord, Waterfall and Velocity, and has been tested on these platforms. It may support additional forks, but this is not guaranteed.
The plugin is available for Paper, BungeeCord, Waterfall and Velocity, and has been tested on these platforms. It may support additional forks, but this is not guaranteed.
The plugin also supports these additional plugins. Depending on the platform they are used in is the plugin required.
The plugin also supports these additional plugins. They are all optional.
- [PlaceholderAPI] - Used on the Spigot and Paper server for additional Placeholder parsing.
- - [ViaVersion] - Used on the Spigot and Paper server for additional protocol version handling.
- [PAPIProxyBridge] - Used on BungeeCord, Waterfall and Velocity for PlaceholderAPI support.
- [Maintenance] - Used to disable server list handling while maintenance is active.
<div class="grid cards" markdown>
- [**PlaceholderAPI**][placeholderapi]{ target="_blank" rel="nofollow" }
----
AdvancedServerList supports the use of placeholder from PlaceholderAPI in all its text options, except for the `condition` option.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
- [**ViaVersion**][viaversion]{ target="_blank" rel="nofollow" }
----
When installed will AdvancedServerList use ViaVersion to resolve the protocol version of a player for its PlaceholderAPI placeholders.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
- [**PAPIProxyBridge**][papiproxybridge]{ target="_blank" rel="nofollow" }
----
Allows AdvancedServerList to parse placeholders from PlaceholderAPI while being used on a proxy.
----
**Supported on:**
:simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
- [**Maintenance**][maintenance]{ target="_blank" rel="nofollow" }
----
AdvancedServerList will disable any modification of the server list entry should Maintenance mode be enabled.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
- [**BanPlugins Addon**][addon]
----
Official Add-on for AdvancedServerList that adds placeholders for different Ban/Punishment plugins such as AdvancedBan and LibertyBans.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
</div>
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
[addon]: ../addons/banplugins.md
## 2. Installation { #installation }
@@ -46,11 +122,11 @@ Here is a quick table showing the jar file name with the platforms it is made fo
| Jar file name | Platforms |
|-----------------------------------------------|-----------------------|
| `AdvancedServerList-Paper-{version}.jar` | Spigot, Paper |
| `AdvancedServerList-Paper-{version}.jar` | Paper |
| `AdvancedServerList-BungeeCord-{version}.jar` | BungeeCord, Waterfall |
| `AdvancedServerList-Velocity-{version}.jar` | Velocity |
After you added it to your plugins folder - alongside any other dependency you may want or need - (re)start your server or proxy to enable the plugin.
After you added it to your plugins folder - alongside any other dependency you may want - (re)start your server or proxy to enable the plugin.
If everything goes well should AdvancedServerList create a folder named `AdvancedServerList` (`advancedserverlist` on Velocity) with additional files and folders inside of it.
### Folder structure
@@ -75,171 +151,175 @@ The profiles folder is home of the server list profile files which allow you to
On first creation will the folder have a `default.yml` file. This file contains all the options available to use alongside comments to try and help you in using it properly.
/// details | default.yml content
type: file
```yaml
#
# Set the priority of this profile.
# Higher number = Higher priority.
# If there are multiple profiles (files) will they be sorted by priority, starting with highest.
#
# Read more: https://asl.andre601.ch/profiles/#priority
#
priority: 0
#
# Set conditions that needs to be met.
# Only when all conditions return true will the profile be shown (Given no profile with higher priority is used).
# 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).
#
# Read more: https://asl.andre601.ch/profiles/#conditions
# Multiple conditions can be chaing with the keywords 'and', 'or', or their counterparts '&&' and '||'.
#
#conditions:
# - '{playerVersion} < 759'
# No condition or an empty condition will be treated as true by default.
#
# Read more: https://asl.andre601.ch/profiles/#condition
#
condition: ''
#
# Option that allows you to define multiple profiles to use.
# Each entry supports the same options as the server list profile does. Whenever an option is not present, or set to
# an empty value (If supported) would the option in the file be used (if present).
# This allows you to f.e. randomize the MOTD while keeping other options the same, without copy-pasting the same options.
# Set one or multiple profiles.
#
# A profile will be selected randomly.
# A profile can contain the same options as used in the file itself, except for priority and condition.
# If multiple entries are present, a random one will be selected. Any options set in the selected profile will override
# any existing option in the file.
#
# Remove this option or set it to profiles: [] to use the global options of this file.
# Example: The below profile configuration will randomly change the MOTD between two types, but keep the Hover text
# the same.
#
# When not present or empty (profiles: []), no profiles will be used and global options from the file will be used instead.
#
# Read more: https://asl.andre601.ch/profiles/#profiles
#
#profiles:
# - motd:
# - '<aqua>Line 1'
# - '<aqua>Line 2'
# favicon: ''
# playerCount:
# hidePlayers: false
# hover:
# - '<green>Line 1'
# - '<green>Line 2'
# - '<green>Line 3'
# text: ''
# extraPlayers:
# enabled: false
# amount: 0
profiles:
- motd: ['<aqua>Line A', '<gold>Line B']
- motd:
- '<aqua>Line 1'
- '<gold>Line 2'
#
# Set the default (Global) MOTD used by this server list profile.
# Supports HEX colors for 1.16+ servers including gradients using MiniMessage's <gradient:color:color> format.
#
# Remove this option or set it to motd: [] to not alter the MOTD.
# Set the "Message of the day" to display.
# This option supports RGB colors for 1.16+ Servers and clients, including gradients using MiniMessage's <gradient>
# option.
#
# Only the first two lines will be considered and any additional one is ignored.
#
# When not present or empty (motd: []), no MOTD will be set.
#
# Read more: https://asl.andre601.ch/profiles/#motd
#
motd:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>First Line'
- '<grey>Second Line'
#
# Allows you to set a global (Default) favicon for this server list profile.
# You can use one of three possible options:
# 1. A file name matching a PNG file located in the 'favicons' folder (Needs to end with .png)
# 2. A URL pointing to a valid Image
# 3. ${player name} to display the player's head as favicon. Uses https://mc-heads.net for this
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
#
# Remove this option or set to favicon: '' to not replace the Favicon.
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
# 2. URL pointing to an image.*
# 3. 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.
#
# * These images are loaded asynchronously, meaning they may not yet be "ready" when AdvancedServerList is done with
# the event, requiring a refresh of the server list by the player to have it shown.
#
# Any images above or below 64x64 pixels will be automatically resized to these dimensions.
#
# If not present or empty (favicon: ''), defaults to not modifying the favicon.
#
# Read more: https://asl.andre601.ch/profiles/#favicon
#
favicon: ''
#
# Contains various options to manipulate the player count (Text displaying online and max players allowed).
# Contains options for modifying the player count (Text displaying <online>/<max>).
#
# Read more: https://asl.andre601.ch/profiles/#playercount
#
playerCount:
#
# Whether AdvancedServerList should hide the player count or not.
# When set to true will the player count display '???' instead of <online>/<max>
# Set whether the Player count should be hidden.
# When set to true, the player count will be displayed as '???' instead of the usual '<online>/<max>' and all other
# playerCount options, except for extraPlayers and maxPlayers, will be ignored.
#
# Note that when this is enabled will all other options, except for 'extraPlayers', be ignored.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayers
#
hidePlayers: false
#
# Sets the text displayed when hovering over the player count.
# Set 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.
#
# Remove this option or set it to hover: [] to not modify the player samples on the player count.
# If not present or empty (hover: []), defaults to not modifying the hover.
#
# Read more: https://asl.andre601.ch/profiles/#hover
#
hover:
- '<grey>Line 1'
- '<grey>Line 2'
- '<grey>Line 3'
- '<aqua>Line 1'
- '<yellow>Line 2'
- '<green>Line 3'
#
# Modifies the text that usually displays '<online>/<max>'
#
# Note that when used, the Ping icon will display as 'outdated server'/'outdated client'.
# This is nothing that can be fixed or avoided and would require changes from Mojang.
# Set the text that should be displayed instead of the default '<online>/<max>' text.
#
# Remove this option or set it to text: '' to not modify the player count text.
# Using this option will show the server as "outdated" to the client (Have the ping icon crossed out).
# This cannot be fixed and would require Mojang to change stuff.
#
# If not present or empty (text: ''), defaults to not modifying the text.
#
# Read more: https://asl.andre601.ch/profiles/#text
#
text: ''
#
# Allows you to modify the max player count displayed.
# Note that this will affect ${server playersMax} (Except for when used in conditions).
# The extraPlayers feature allows to set a number that should be added to the current online players and then be
# used as the "max" player count.
#
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers
#
extraPlayers:
#
# Enables/Disables the extraPlayers option.
# When enabled will the total amount of players allowed to join be modified to the current
# number of online players + 'amount'
# Set whether the extraPlayers feature should be enabled or not.
# When set to true, the max players count will be modified to be the number of online players with the 'amount'
# value added to it.
#
# Defaults to false when not present.
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
#
enabled: false
#
# Sets how much should be added/subtracted from the current number of online players
# to then use for the max player count.
# Set the number that should be added to the online player count to then use as the new max player count.
#
# Example:
# When set to 1 while 10 players are online would the player count - if unmodified -
# display '10/11'. When -1 is used will it display '10/9'
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
# 9 when 8 are online and so on.
#
# Defaults to 0 when not present.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
#
amount: 0
#
# Allows you to set the max players that could join your server.
# Note that this option influences the '${server playersMax}' placeholder.
# The maxPlayers feature allows to set a number to use as the max player count to display.
#
# The settings of this option have no effect should 'extraPlayers' be enabled
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers
#
maxPlayers:
#
# Enables/Disables the maxPlayers option.
# When enabled will the total amount of players allowed to join be changed to what 'amount' is set to.
# Set whether the maxPlayers feature should be enabled or not.
# When set to true, the max player count will be set to the 'amount' value.
#
# If not present, defaults to false.
#
# Defaults to false when not present.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
#
enabled: false
#
# Sets the number to display for the max number of players allowed to join your server.
# Set the number that should be used as the new max players count.
#
# Example:
# Setting this option to 0 (Default) while 1 player is online would display '1/0'
#
# Defaults to 0 if not set.
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
#
@@ -254,13 +334,17 @@ These functions include, but aren't limited to:
- Setting the default name and UUID used for an unknown (Not cached) player.
- Disabling/Enabling caching of players.
- Disabling/Enabling checking for updates
- Disabling/Enabling checking for updates.
- Disabling/Enabling debug mode.
- Setting how long favicons should be cached for.
- The config version used for migration. Don't touch this, or it may reset your config.
Similar to the default.yml is this file containing comments to try and explain the settings in questions.
Do note that if the config gets migrated from an older version, that the comments will be discarded in the process, unfortunately.
/// details | default config.yml content
type: file
```yaml
#
# Used for when AdvancedServerList doesn't have a cached player to use for player placeholders.
@@ -295,13 +379,68 @@ disableCache: false
#
checkUpdates: true
#
# Should debug mode be enabled?
#
# When set to true will AdvancedServerList print additional messages to the console prefixed with "[DEBUG]".
# It is recommended to only enable this when having problems or when being told to by the plugin dev, as it could
# otherwise cause significant spam in your console.
#
# Defaults to false when not present.
#
debug: false
#
# Sets the time in minutes for favicons to be cached.
# The number cannot be less than 1.
#
# Defaults to 1 if not set.
#
faviconCacheTime: 1
#
# List of options that should be disabled while the Maintenance Mode of the plugin Maintenance is active.
# Any option not listed here will NOT be disabled, meaning AdvancedServerList will continue to handle it.
#
# Each option defaults to true when not present, disabling said option while Maintenance is active.
#
disableDuringMaintenance:
#
# When true (Default), disables handling of MOTD while Maintenance is enabled.
#
motd: true
#
# When true (Default), disables handling of Favicon while Maintenance is enabled.
#
favicon: true
#
# When true (Default), disables hiding of player count while Maintenance is enabled.
#
hidePlayers: true
#
# When true (Default), disables handling of player count text while Maintenance is enabled.
#
playerCountText: true
#
# When true (Default), disables handling of player count hover while Maintenance is enabled.
#
playerCountHover: true
#
# When true (Default), disables use of extra players feature while Maintenance is enabled.
#
extraPlayers: true
#
# When true (Default), disables use of max players feature while Maintenance is enabled.
#
maxPlayers: true
#
# DO NOT EDIT!
#
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
config-version: 2
config-version: 5
```
///
@@ -309,18 +448,22 @@ config-version: 2
There are certain files and folders that get created when certain events happen:
- A `playercache.json` file will be created on plugin shutdown containing a list of IPs, UUIDs and Player names for every player that joined the server while AdvancedServerList was running.
This file allows to replace `${player name}` and `${player uuid}` with their name or UUID respectively, while they are not on the server, by using the IP they used to join with.
This file is not created nor updated when `disableCache` is set to `true` in the config.yml
- A `playercache.json` file will be created on plugin shutdown containing a collection of IPs, UUIDs and Player names for every player that joined the server while AdvancedServerList was running.
This file is used to identify a player through their last used IP, to replace placeholders such as `${player name}` or `${player uuid}` with their respective values using the cached data.
This file is not created, used nor updated when `disableCache` is set to `true` in the config.yml
- A `backups` folder containing old config.yml files.
This folder is created when AdvancedServerList migrates your old config to a new version. This allows you to transfer settings over in case the migration didn't work properly.
This folder is created when AdvancedServerList migrates your old config to a new version. This allows you to transfer settings over in case the migration didn't work properly.
Each backup will have the name pattern `config-<date>.yml` with `<date>` being the date and time of when this file has been created.
## 3. Creating your first profile { #creating-your-first-profile }
Creating your first profile is relatively simple.
To start, open the `default.yml` file located inside the `profiles` folder using a file editor of your choice (VSCode or Notepad++ are recommended). It should contain all the available options for a server list profile.
Next can you edit the options available to whatever you like. All text options (Except [conditions](../profiles/index.md#conditions)) support [MiniMessage formatting](../profiles/formatting.md).
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).
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).
The [`motd`](../profiles/index.md#motd) option also supports Hexadecimal colors, assuming the server/proxy runs at least MC 1.16.
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.
@@ -336,19 +479,23 @@ motd:
### Additional profiles
To add additional profiles, create a new YAML file inside the `profiles` folder. The name doesn't matter, but it is recommended to keep it lowercase, use alphanumeric characters (`a-z, 0-9`), hyphens (`-`), underscores (`_`) and avoid spaces.
To add additional profiles, create a new YAML file inside the `profiles` folder. The name doesn't matter, but it is recommended to keep it lowercase, use alphanumeric characters (`a-z, 0-9`), hyphens (`-`), underscores (`_`) and avoid spaces. You should also name it after what it is for, to have it more easily organized.
Inside the file, add a priority and at least one setting, similar to the above shown example.
This would already be enough and AdvancedServerList would use it. If you however want to only show it when certain conditions are met, should you set the priority to a higher value and add conditions.
This would already be enough to have a valid profile, but depending on the priority and file name may the file not be used, or used over other profiles.
Conditions can be multiple strings containing [operands](../profiles/index.md#operands) to evaluate them. As an example `${server playersOnline} >= 10` would return true if the current number of online players is larger or equal to 10.
If you want to only show this file under specific situations can you use the [`condition`](../profiles/index.md#condition) option to apply conditions that need to be met to show the profile.
The condition option would have a single String containing one or muliple [Expressions](../profiles/expressions.md). Only if the condition would return true, would the profile be displayed, granted that it has a higher priority than any other valid file with a true condition output.
Here is another example profile using conditions:
/// info | Note
Profiles which do not have any conditions, or have an empty condition, will always be considered to have a true condition, meaning that a profile with higher priority and no condition will be selected over a profile with lower priority and a condition, even if said condition returns true.
///
Here is another example profile using conditions to show it when the player was banned on the server:
```yaml title="other_profile.yml"
priority: 1
conditions:
- '${player isBanned} = true'
condition: '${player isBanned}'
motd:
- '<red>You got <bold>banned</bold> from this server.'
@@ -361,7 +508,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 through the Server/Proxy console.
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.
The plugin should then load any valid YAML file inside the `profiles` folder to then use.
+55 -34
View File
@@ -12,13 +12,16 @@ If you're new to the plugin is it recommended to check out the [Profiles page](p
## Downloads
[![modrinth-img]{ width="260" loading="lazy" }][modrinth-download]{ target="_blank" rel="noreferrer nofollow noopener" }
[![hangar-img]{ width="260" loading="lazy" }][hangar-download]{ target="_blank" rel="noreferrer nofollow noopener" }
[![hangar-img]{ width="260" loading="lazy" }][hangar-download]{ target="_blank" rel="noreferrer nofollow noopener" }
[![codeberg-img]{ width="260" loading="lazy" }][codeberg-download]{ target="_blank" rel="noreferrer nofollow noopener" }
[modrinth-img]: https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/modrinth_vector.svg "Available on Modrinth"
[hangar-img]: https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/hangar_vector.svg "Available on Hangar"
[codeberg-img]: https://cdn.jsdelivr.net/gh/Andre601/devins-badges@13e0142/assets/compact/available/codeberg_vector.svg "Available on Codeberg"
[modrinth-download]: https://modrinth.com/plugin/advancedserverlist
[hangar-download]: https://hangar.papermc.io/Andre_601/AdvancedServerList
[codeberg-download]: https://codeberg.org/Andre601/AdvancedServerList
## Platforms
@@ -38,38 +41,56 @@ AdvancedServerList supports the following platforms:
[paper]: https://papermc.io
[velocity]: https://velocitypowered.com
## Dependencies
/// info
All listed dependencies are optional.
///
| Dependency | Platforms |
|-------------------------------------------------------------------------|----------------------|
| [PlaceholderAPI]{ target="_blank" rel="noreferrer nofollow noopener" } | Paper |
| [ViaVersion]{ target="_blank" rel="noreferrer nofollow noopener" } | Paper |
| [PAPIProxyBridge]{ target="_blank" rel="noreferrer nofollow noopener" } | BungeeCord, Velocity |
| [Maintenance]{ target="_blank" rel="noreferrer nofollow noopener" } | All |
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
## Pages
- [Getting started](getting-started/index.md)
- [Commands](commands/index.md)
- [Profiles](profiles/index.md)
- [Formatting](profiles/formatting.md)
- [Placeholders](profiles/placeholders.md)
- [Examples](examples/index.md)
- [Migration](migration/index.md)
- [v1.5.3 to v1.6.0](migration/v1_5_3-to-v1_6_0.md)
- [v1.9.0 to v1.10.0](migration/v1_9_0-to-v1_10_0.md)
- [API](api/index.md)
- [Changelog](api/changelog.md)
- [Javadocs](api/javadocs.md) (External site)
- [Source Code](api/source.md) (External site)
- [Reference](api/reference/index.md)
- [PlaceholderAPI](placeholderapi/index.md)
<div class="grid cards" markdown>
- [:octicons-milestone-24: **Getting Started**](getting-started/index.md)
----
A simple guide on how to get started with AdvancedServerList.
- [:octicons-rel-file-path-24: **Commands**](commands/index.md)
----
A list of all available commands in AdvancedServerList.
- [:octicons-note-24: **Profiles**](profiles/index.md)
----
Pages containing information about the Server List Profile System and all its available options.
- [:octicons-list-unordered-24: **Examples**](examples/index.md)
----
Collection of various profile examples to use for different situations.
- [:octicons-file-directory-symlink-24: **Migration**](migration/index.md)
----
Pages explaining how to migrate from one version of the plugin to another.
- [:octicons-command-palette-24: **API**](api/index.md)
----
Pages all about the API of AdvancedServerList.
- [:octicons-plus-circle-24: **Addons**](addons/index.md)
----
Pages listing 1st-party and 3rd-party add-ons for AdvancedServerList.
- [: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>
+33 -1
View File
@@ -10,4 +10,36 @@ Note that these pages only cover server list profile files. The config.yml is au
## Pages
{nav}
<div class="grid cards" markdown>
- [**v3.8.0 to v3.9.0**](v3_8_0-to-v3_9_0.md)
----
Migrate from version 3.8.0 to 3.9.0.
- [**v3.7.0 to v3.8.0**](v3_7_0-to-v3_8_0.md)
----
Migrating from version 3.7.0 to 3.8.0.
- [**< v3.7.0 to v3.7.0**](pre-v3_7_0-to-v3_7_0.md)
----
Migrate from any version prior to 3.7.0 to 3.7.0 or newer.
- [**v1.9.0 to v1.10.0**](v1_9_0-to-v1_10_0.md)
----
Migrate from version 1.9.0 to 1.10.0.
- [**v1.5.3 to v1.6.0**](v1_5_3-to-v1_6_0.md)
----
Migrate from version 1.5.3 to 1.6.0.
</div>
+60
View File
@@ -0,0 +1,60 @@
---
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.
## Migration
To migrate, all you have to do is take the entries of the old conditions option and convert them into a single String connected with `and` operators in between. See the [Example below](#example).
## Example
Here is a before and after example to help visualize the change:
/// tab | Before
```yaml
priority: 0
conditions:
- '${player protocol} > 763'
- '${player isWhitelisted} == true'
motd:
- 'Welcome ${player name}!'
```
///
/// tab | After
```yaml
priority: 0
# The text can all be in one line. This is only for better readability.
condition: |
${player protocol} >= 763 and
${player isWhitelisted}
motd:
- 'Welcome ${player name}!'
```
///
/// tab | Diff View
```diff
priority: 0
-conditions:
- - '${player protocol} >= 763'
- - '${player isWhitelisted} == true'
+# The text can all be in one line. This is only for better readability.
+condition: |
+ ${player protocol} >= 763 and
+ ${player isWhitelisted}
motd:
- 'Welcome ${player name}!'
```
///
+49
View File
@@ -0,0 +1,49 @@
---
icon: octicons/arrow-right-24
---
# v3.7.0 to v3.8.0
v3.8.0 brought a small yet important change to the condition system, which is the change of the "contains" operand from `<-` to `<_` to avoid possible issues with numbers.
## Migration
To migrate, switch any appearances of `<-` with `<_`
## Example
Here is a before and after example to help visualize the change:
/// tab | Before
```yaml
priority: 0
condition: '${server host} <- "survival"'
motd:
- 'Welcome ${player name}!'
```
///
/// tab | After
```yaml
priority: 0
condition: '${server host} <_ "survival"'
motd:
- 'Welcome ${player name}!'
```
///
/// tab | Diff View
```diff
priority: 0
-condition: '${server host} <- "survival"'
+condition: '${server host} <_ "survival"'
motd:
- 'Welcome ${player name}!'
```
///
+49
View File
@@ -0,0 +1,49 @@
---
icon: octicons/arrow-right-24
---
# v3.8.0 to v3.9.0
v3.9.0 brings a small change to the `~=` operand by changing it to `=~` for sake of consistent pattern design. Additionally, was `~` added as a single-character equivalent to `=`.
## Migration
To migrate, switch any appearances of `~=` with `=~` or `~`.
## Example
Here is a before and after example to help visualize the change:
/// tab | Before
```yaml
priority: 0
condition: '${player name} ~= "Someone"'
motd:
- 'Welcome ${player name}!'
```
///
/// tab | After
```yaml
priority: 0
condition: '${player name} =~ "Someone"'
motd:
- 'Welcome ${player name}!'
```
///
/// tab | Diff View
```diff
priority: 0
-condition: '${player name} ~= "Someone"'
+condition: '${player name} =~ "Someone"'
motd:
- 'Welcome ${player name}!'
```
///
+135
View File
@@ -0,0 +1,135 @@
---
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.
This page covers what the Expression system of AdvancedServerList offers and can do.
## Content
- [Types](#types)
- [Literals](#literals)
- [Numbers](#numbers)
- [Strings](#strings)
- [Booleans](#booleans)
- [Placeholders](#placeholders)
- [Binary Operators](#binary-operators)
- [Parenthesis](#parenthesis)
- [Negation](#negation)
- [Credits](#credits)
## Types
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.
### Literals
The following cases are considered literal values:
#### Numbers
Any number is considered an expression, meaning the below examples are considered valid:
/// example | Examples
```shell
0
1000
-7
47.2
```
///
#### Strings
A String in single or double quotes is 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.
///
/// example | Examples
```shell
"Hello World!"
""
```
///
#### Booleans
Strings `true` and `false` are treated as boolean literals.
### Placeholders
Any [placeholder](placeholders.md) is a valid expression.
/// example | Examples
```shell
${player protocol}
${player name}
${server playersOnline}
${server host}
```
///
### Binary Operators
`<expression> <binary operator> <expression>` is a valid expression.
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. |
/// example | Examples
```shell
${player name} != "Anonymous"
763 > ${player protocol} > 758
${player hasPlayedBefore} and ${player isBanned} == "false"
```
///
### Parenthesis
`( <expression> )` is a valid expression.
Parenthesis can be used to prevent ambiguities.
### Negation
`!` can be used to negate boolean expressions.
```shell
!${player isWhitelisted}
```
## Credits
This page, including some examples used, was adobted from [:octicons-book-24: CodeCrafter47/BungeeTabListPlus/wiki](https://github.com/CodeCrafter47/BungeeTabListPlus/wiki/Expressions){ target="_blank" rel="nofollow" }.
+12 -2
View File
@@ -38,8 +38,18 @@ The following options are **not** supported, no matter what option they are used
## Colors
Color options (`<aqua>`, `<red>`, `<gray>`, etc.) are available for all text options.
24-Bit HEX colors (`<#ff0000>`, `<#123abc>`, etc.) are only available for the [`Motd` option](../index.md#motd) for a 1.16+ Server/Proxy.
### Default colors
Default colors such as `<red>`, `<green>`, `<aqua>`, etc. may be used in all text options.
### Hex Colors
Hexadecimal colors may be used in the [`motd`](index.md#motd) option using the `<#RRGGBB>` format.
### Gradients
Gradients can be created by using `<gradient:<color1>:<color2>>`, replacing `<color1>` with a starting color name or hex color value and `<color2>` with an ending color name or hex color value.
Only the [`motd`](index.md#motd) option may support hex color gradients and in all other options will it be downsampled.
## Formatting
+90 -98
View File
@@ -2,67 +2,50 @@
icon: octicons/note-24
---
# Profiles { #profiles-settings }
# Profiles { #profiles-file }
AdvancedServerList allows the creation of multiple profiles.
A profile is a single YAML file located in the plugin's `profiles` directory containing multiple settings including [Conditions](#conditions) and [Priority](#priority).
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.
/// info | Important
In order for a profile to be considered "valid" by AdvancedServerList will it need to meet the following conditions:
Additionally can [Conditions](#condition) and a [Priority](#priority) be set to set when a specific profile should be displayed to a player.
- Have a [`Priority`](#priority) set to a valid, whole number (i.e. `1`)
- Have **at least one** of the following options set:
- [`Profiles`](#profiles) with at least one entry containing one of the below option
- [`Motd`](#motd) set with at least one line of text
- [`Favicon`](#favicon) set with a non-empty String
- [`HidePlayers`](#hideplayers) set to `true`
- [`Hover`](#hover) set with at least one line of text
- [`Text`](#text) set with a non-empty String
///
## 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 determines the order in which the profiles are checked by AdvancedServerList, starting with the highest number.
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`.
It will go through each file until it finds one with [`conditions`](#conditions) returning true (Default if no conditions are set).
This means that a profile with no conditions and a priority of `1` will be used before a profile with a condition and priority `0` even if the player is meeting the condition.
Should AdvancedServerList not find any profile with a positive condition will it not modify the server list for the players.
## Conditions
/// 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.
///
A list of conditions can be set that need to be met in order to have this profile shown to the player.
[Placeholders](formatting.md#placeholders) can be used to further customize the conditions (PlaceholderAPI placeholders are **not** supported).
## Condition
Only when **all** conditions defined return true will the profile be displayed.
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.
You can remove this option, or set it to an empty list (`conditions: []`) to always return true.
### Operands
The following operants are available and can be used in the conditions.
<!-- admo:warning Only one operant can be used per condition! -->
| Operand | Description |
|---------|------------------------------------------------------------------------|
| `<` | Checks if the left value is less than the right one.[^1] |
| `<=` | Checks if the left value is less than or equal to the right one.[^1] |
| `>` | Checks if the left value is more than the right one.[^1] |
| `>=` | Checks if the left value is more than or equal to the right one.[^1] |
| `=` | Checks if the left value is equal to the right one. |
| `!=` | Checks if the left value is not equal to the right one. |
| `~=` | Checks if the left value is equal to the right one, ignoring case. |
| `!~` | Checks if the left value is not equal to the right one, ignoring case. |
[^1]:
Should the provided value not be a number, will AdvancedServerList use the text length to compare.
Example: `SomeString > String` would be translated to `10 > 6`.
The condition option can hold one or multiple expressions. The Expression system is explained on the [Expressions page](expressions.md).
## Profiles
<!-- admo:warning Priority and Conditions can NOT be used within profiles -->
The `profile` option allows you to define a list of all other options, with the exception of [`priority`](#priority), [`condition`](#condition) or itself.
The `profiles` option allows you to set multiple MOTDs, player counts, etc. which the plugin would randomly choose from.
If an option such as motd is not present in an entry will it check the file for the option and use that if present.
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
@@ -71,7 +54,7 @@ If an option such as motd is not present in an entry will it check the file for
priority: 0
profiles:
- motd:
- motd: # You can also use ['<rainbow>Line1</rainbow>','<rainbow:!>Line 2</rainbow>']
- '<rainbow>Line 1</rainbow>'
- '<rainbow:!>Line 2</rainbow>'
playerCount:
@@ -79,6 +62,7 @@ profiles:
- 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>'
@@ -93,10 +77,10 @@ motd:
## Motd
The motd option allows to set up to two lines to be displayed in an MOTD.
Normal colour and formatting codes such as `<aqua>` or `<bold>` are supported. On 1.16 and newer can you also use HEX colours using either `<#rrggbb>` or `<color:#rrggbb>`.
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.
If you want to display multiple MOTDs will you need to use the [`Profiles` option](#profiles)
Multiple, randomly selected, MOTDs can be displayed by using the [`profiles`](#profiles) option.
/// details | Example
type: example
@@ -105,7 +89,7 @@ If you want to display multiple MOTDs will you need to use the [`Profiles` optio
priority: 0
motd:
- '<rainbow:2>Rainbow Gradients</rainbow>'
- '<rainbow:2>Rainbow Gradient</rainbow>'
- '<rainbow:!2>|||||||||||||||||||||||||||||||||||||</rainbow>'
```
<div class="result" markdown>
@@ -117,53 +101,60 @@ motd:
## Favicon
The favicon option allows you to customize the favicon and display one or multiple different images.
<!-- admo:info Images will be resized to 64x64 pixels. -->
This option currently supports the following values:
The `favicon` option can be used to define an image to display in the server list.
- A URL pointing to a `64x64` PNG image.
- A name with `.png` extension that matches a PNG file in the `favicons` folder.
- `${player uuid}` (or alternatively `${player name}`) to display the head of the player. The UUID/Name resolving is handled by https://mc-heads.net
The Value can be one of three possible options, each being checked for in order:
Please note that AdvancedServerList will rescale the image to be 64x64 pixels, so be sure to provide images at that particular scale.
- A URL pointing to an image file. The URL needs to start with `https://` to work.
- A PNG filename, including `.png` file extension, matching a PNG file in the `favicons` folder.
- A player name or UUID, or a [placeholder](placeholders.md) that resolves into one.
Note that for the name/UUID, the site https://mc-heads.net is being used.
Use the URL option with the `${player uuid}` placeholder if you want to use another service.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
# Player is Andre_601
favicon: ${player uuid}
# Placeholder resolves to UUID of Andre_601
favicon: '${player uuid}'
```
<div class="result" markdown>
![hideplayers-example](../assets/images/examples/favicon-example.jpg){ loading="lazy" }
![favicon-example](../assets/images/examples/favicon-example.jpg){ loading="lazy" }
</div>
///
## PlayerCount
The `playerCount` option contains multiple different options all about the Player count itself.
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
Boolean option to set whether AdvancedServerList should hide the player count or not. When set to `true` will the player count be replaced with `???`.
Additionally will the [`Text`](#text) and [`Hover`](#hover) option be ignored.
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
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
@@ -180,17 +171,17 @@ playerCount:
### Hover
This option allows to override the hover text usually displaying the players on the server when hovering over the player count.
You can either remove this option or set to an empty list (`hover: []`) to not override the hover.
The `playerCount -> hover` option allows you to define lines of text to show when a player hovers over the player count with their cursor.
Note that this option only accepts basic colors such as `<blue>` or `<grey>` and that HEX colors are not supported.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
@@ -210,23 +201,24 @@ playerCount:
### Text
This option allows to override the text usually displaying the online players and total players that can join.
Note that AdvancedServerList will not add the `<online>/<max>` text to the player count. Instead will you need to use [`${server playersOnline}`](placeholders.md#server) and [`${server playersMax}`](placeholders.md#server)
The `playerCount -> text` option allows you to define a custom text to display instead of the usual `<online>/<max>`.
/// info | Note
This feature works by changing the "outdated server" message followed by altering the protocol version of the server.
Due to this will your server appear as "outdated" to the client (Have the ping icon crossed out). This is nothing that can be changed unfortunately.
///
Please take note of the following caveats:
To not override the player count, remove this option or set it to an empty String (`text: ''`).
- 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
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
@@ -236,35 +228,37 @@ playerCount:
```
<div class="result" markdown>
![hover-example](../assets/images/examples/text-example.jpg){ loading="lazy" }
![text-example](../assets/images/examples/text-example.jpg){ loading="lazy" }
</div>
///
### ExtraPlayers
Contains options to modify how the `<max>` number in the player count should look like.
<!-- admo:warning Using this option overrides the output of the <code>${server playersMax}</code> placeholder (Except in condition). -->
<!-- admo:warning Using this option will modify the <code>${server playersMax}</code> placeholder (Except when used in conditions) -->
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 }
Boolean option to set whether the extra players feature should be used or not.
When set to `true` will the max amount of players be modified by taking the current amount of online players, add [`Amount`](#amount) more to it and use it.
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 }
Sets the number to add to the current online players to then use as the new max players count.
<!-- admo:info This option does nothing when <code>playerCount -> hidePlayers</code> is enabled. -->
As an example, setting this to `1` while `10` players are online will display `11`, while `-1` would display `9`.
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).
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
@@ -283,32 +277,30 @@ playerCount:
### MaxPlayers
Contains options to set the max number of players allowed to join the server. This has only a visual effect and won't actually influence how many players can join your server.
<!-- 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). -->
Note that this feature is ignored should [`extraPlayers`](#extraplayers) be enabled.
In case [`hidePlayers`](#hideplayers) is enabled will the max player count not be displayed, but still changed by this option.
Should [`text`](#text) be set to a non-empty String will the max player count only be displayed when `${server playersMax}` is used.
<!-- admo:warning Using this option will modify the <code>${server playersMax}</code> placeholder (Except when used in conditions) -->
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 }
Boolean option to set whether the max players feature should be used or not.
When set to `true` will the value usually displaying how many players can join be changed to what you've set in the [`amount`](#maxplayers-amount) option.
Enables the maxPlayers feature.
Use the [`playerCount -> maxPlayers -> amount`](#maxplayers-amount) option to set the max player count itself.
#### Amount { #maxplayers-amount }
Sets the number to display as the max number of players allowed to join your server.
Note that this will also affect the `${server playersMax}` placeholder, except when it is used inside conditions.
<!-- 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.
/// details | Example
type: example
```yaml title="YAML file"
priority: 0
# We use just colour to hide the MOTD
# Hides the MOTD for demonstration purposes
motd:
- '<grey>'
- '<grey>'
@@ -320,7 +312,7 @@ playerCount:
```
<div class="result" markdown>
![maxplayes-example](../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
![maxplayers-example](../assets/images/examples/maxplayers-example.jpg){ loading="lazy" }
</div>
///
+12 -12
View File
@@ -21,9 +21,9 @@ These placeholders use the player who pinged the server, to return values. They
| `${player protocol}` | The protocol version of the player. | All | No |
| `${player uuid}` | The UUID of the player. | All | Yes[^3] |
| `${player version}` | The protocol version of the player as readable MC version. | Velocity | No |
| `${player hasPlayedBefore}` | Boolean for whether the player has played on the server before. | Spigot/Paper | Yes |
| `${player isBanned}` | Boolean for whether the player has been banned from the server. | Spigot/Paper | Yes |
| `${player isWhitelisted}` | Boolean for whether the player is whitelisted on the server. | Spigot/Paper | Yes |
| `${player hasPlayedBefore}` | Boolean for whether the player has played on the server before. | Paper | Yes |
| `${player isBanned}` | Boolean for whether the player has been banned from the server. | Paper | Yes |
| `${player isWhitelisted}` | Boolean for whether the player is whitelisted on the server. | Paper | Yes |
[^1]:
Whether this placeholder requires the player to have joined before while AdvancedServerList was running.
@@ -35,21 +35,21 @@ These placeholders use the player who pinged the server, to return values. They
These placeholders use values given by the server/proxy AdvancedServerList runs on.
| Placeholder | Description |
|------------------------------|-------------------------------------------------------------------------|
| `${server playersOnline}` | The number of players online on this proxy/server.[^4] |
| `${server playersMax}` | The total number of players that can join this server.[^5] |
| `${server host}` | The domain/IP the player pinged.[^6] |
| `${server whitelistEnabled}` | Whether the whitelist is enabled or not. Only available on Spigot/Paper |
| Placeholder | Description | Platforms |
|------------------------------|------------------------------------------------------------|-----------|
| `${server playersOnline}` | The number of players online on this proxy/server.[^4] | All |
| `${server playersMax}` | The total number of players that can join this server.[^5] | All |
| `${server host}` | The domain/IP the player pinged.[^6] | All |
| `${server whitelistEnabled}` | Whether the whitelist is enabled or not. | Paper |
[^4]:
A comma-separated list of world (On Paper) or Server (On BungeeCord/Velocity) names can be provided to display the added numbers of players in these worlds/servers.
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
[^5]:
When the [`amount` option](../index.md#amount) is used will this placeholder display the modified max players count.
The only exception is [`conditions`](../index.md#conditions) where it uses the actual max players of the server/proxy.
Using either the [extraPlayers' `amount`](index.md#extraplayers-amount) or [maxPlayers' `amount`](index.md#maxplayers-amount) option will make this placeholder return the modified max players count.
Only exception to this rule is when the placeholder is used in the [`condition`](index.md#condition) option in which case it returns the actual max player count of the proxy/server.
[^6]:
An optional server name can be provided to display the IP/Domain associated with that server. Only works on BungeeCord/Velocity.
An optional server name can be provided to display the IP/Domain associated with that server. This only works on BungeeCord or Velocity.
**Example:** `${server host survival}` would display the IP/Domain associated with the `survival` server.
## PlaceholderAPI
+76 -3
View File
@@ -29,6 +29,7 @@ theme:
- navigation.tabs
- navigation.tabs.sticky
- content.code.copy
- content.tooltips
icon:
repo: 'simple/codeberg'
@@ -50,12 +51,12 @@ extra_css:
- assets/stylesheets/custom.css
- assets/stylesheets/api-docs.css
- assets/stylesheets/admo.css
- assets/stylesheets/admonition.css
extra_javascript:
- assets/js/repo-stats.js
extra:
github_repository: !ENV [GITHUB_REPO_INSTANCE, False]
social:
- icon: 'simple/codeberg'
link: 'https://codeberg.org/Andre601/AdvancedServerList'
@@ -67,8 +68,6 @@ extra:
plugins:
- search
- glightbox
- awesome-pages:
filename: .pages.yml
- pagenav-generator
markdown_extensions:
@@ -105,3 +104,77 @@ markdown_extensions:
hooks:
- docs/.hooks/badges.py
- docs/.hooks/replacer.py
nav:
- Home: index.md
- Getting Started: getting-started/index.md
- Commands: commands/index.md
- Profiles:
- profiles/index.md
- Expressions: profiles/expressions.md
- Formatting: profiles/formatting.md
- Placeholders: profiles/placeholders.md
- Examples: examples/index.md
- Migration:
- migration/index.md
- v3.8.0 to v3.9.0: migration/v3_8_0-to-v3_9_0.md
- v3.7.0 to v3.8.0: migration/v3_7_0-to-v3_8_0.md
- '< v3.7.0 to v3.7.0': migration/pre-v3_7_0-to-v3_7_0.md
- v1.9.0 to v1.10.0: migration/v1_9_0-to-v1_10_0.md
- v1.5.3 to v1.6.0: migration/v1_5_3-to-v1_6_0.md
- API:
- api/index.md
- Changelog: api/changelog.md
- Javadocs: api/javadocs.md
- Source Code: api/source.md
- Reference:
- api/reference/index.md
- api:
- api/reference/api/index.md
- ch.andre601.advancedserverlist.api:
- api/reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
- api/reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
- events:
- api/reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md
- exceptions:
- api/reference/api/ch.andre601.advancedserverlist.api/exceptions/invalidplaceholderproviderexception.md
- objects:
- api/reference/api/ch.andre601.advancedserverlist.api/objects/genericplayer.md
- api/reference/api/ch.andre601.advancedserverlist.api/objects/genericserver.md
- api/reference/api/ch.andre601.advancedserverlist.api/objects/nullbool.md
- profiles:
- '<api__record></api__record> ProfileEntry':
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
- platform-bukkit:
- api/reference/platform-bukkit/index.md
- ch.andre601.advancedserverlist.api.bukkit:
- events:
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/events/postserverlistsetevent.md
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/events/preserverlistsetevent.md
- objects:
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/objects/bukkitplayer.md
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/objects/bukkitserver.md
- platform-bungeecord:
- api/reference/platform-bungeecord/index.md
- ch.andre601.advancedserverlist.api.bungeecord:
- events:
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/events/postserverlistsetevent.md
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/events/preserverlistsetevent.md
- objects:
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/objects/bungeeplayer.md
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/objects/bungeeproxy.md
- platform-velocity:
- api/reference/platform-velocity/index.md
- ch.andre601.advancedserverlist.api.velocity:
- events:
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/events/postserverlistsetevent.md
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/events/preserverlistsetevent.md
- objects:
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/objects/velocityplayer.md
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/objects/velocityproxy.md
- Addons:
- addons/index.md
- BanPlugins: addons/banplugins.md
- PlaceholderAPI: placeholderapi/index.md
+3 -11
View File
@@ -48,14 +48,6 @@
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>spigot</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>protocollib-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
</repository>
<repository>
<id>placeholderapi-repo</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
@@ -100,7 +92,7 @@
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.8.1</version>
<version>4.9.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -117,7 +109,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.13.0</version>
<configuration>
<release>16</release>
</configuration>
@@ -125,7 +117,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
@@ -1,60 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository;
import org.jetbrains.annotations.NotNull;
public class ASLLoader implements PluginLoader{
@Override
public void classloader(@NotNull PluginClasspathBuilder pluginClasspathBuilder){
ComponentLogger logger = pluginClasspathBuilder.getContext().getLogger();
logger.info(Component.text("Loading Libraries for plugin..."));
MavenLibraryResolver resolver = new MavenLibraryResolver();
resolver.addRepository(new RemoteRepository.Builder(
"paper-maven",
"default",
"https://repo.papermc.io/repository/maven-public/"
).build());
logger.info(Component.text("Loading com.squareup.okhttp3:okhttp:4.10.0 from repo.papermc.io..."));
resolver.addDependency(new Dependency(new DefaultArtifact("com.squareup.okhttp3:okhttp:4.10.0"), null));
pluginClasspathBuilder.addLibrary(resolver);
logger.info(Component.text("Loading libraries complete!"));
}
}
Loaded 100 of 125 files, more files were not shown because too many files have changed in this diff. Show more