Compare commits

...
790 Commits
Author SHA1 Message Date
Andre601 1e9c042795 Bump Plugin version 2026-09-27 15:50:09 +02:00
Andre601 1f4672a6a2 Add logs field to bug report template 2026-09-27 15:31:14 +02:00
Andre601 8a60206af6 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.6.4' (#628) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/628
2026-09-26 14:34:13 +02:00
Andre601's Bot 51b0123e5d Update dependency ch.qos.logback:logback-classic to v1.6.4 2026-09-26 12:03:56 +00:00
Andre601 c2c6dde058 Add server/proxy and plugin version fields and mark bungeecord and spigot as discontinued 2026-09-22 18:06:04 +02:00
Andre601 53a1c55634 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.12.0' (#627) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/627
2026-09-19 15:40:36 +02:00
Andre601's Bot c5588f6981 Update dependency com.viaversion:viaversion-api to v5.12.0 2026-09-19 12:03:47 +00:00
Andre601 bac9c7e0f4 Merge pull request 'Update all non-major dependencies to v2.0.1' (#625) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/625
2026-09-17 14:05:59 +02:00
Andre601's Bot f6c3f0f590 Update all non-major dependencies to v2.0.1 2026-09-17 12:05:22 +00:00
Andre601 31f66caef7 Merge pull request 'Update dependency com.velocitypowered:velocity-api to v4.2.0' (#624) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/624
2026-09-15 14:12:27 +02:00
Andre601's Bot f4c9fae031 Update dependency com.velocitypowered:velocity-api to v4.2.0 2026-09-15 12:05:23 +00:00
Andre601 9e212fa2ea Fix unclosed bold tag in announce header. 2026-09-11 01:35:01 +02:00
Andre601 3a25d6185c Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.16.0' (#623) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/623
2026-09-03 15:09:17 +02:00
Andre601's Bot 5cf4887ae8 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.16.0 2026-09-03 12:06:06 +00:00
Andre601 e9bb64affa Merge pull request 'Update dependency com.velocitypowered:velocity-api to v4.1.1' (#622) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/622
2026-08-27 14:10:55 +02:00
Andre601's Bot df34843b7f Update dependency com.velocitypowered:velocity-api to v4.1.1 2026-08-27 12:05:54 +00:00
Andre601 ee5b7d022a Merge pull request 'Update dependency com.velocitypowered:velocity-api to v4.1.0' (#621) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/621
2026-08-25 14:27:38 +02:00
Andre601's Bot 94fbcaa5f4 Update dependency com.velocitypowered:velocity-api to v4.1.0 2026-08-25 12:04:52 +00:00
Andre601 850becd183 Merge pull request 'Update dependency com.google.guava:guava to v33.7.1-jre' (#620) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/620
2026-08-18 14:34:05 +02:00
Andre601's Bot 2a488248af Update dependency com.google.guava:guava to v33.7.1-jre 2026-08-18 12:07:27 +00:00
Andre601 2e78b59c54 Remove duplicate "thank you". 2026-08-17 18:13:09 +02:00
Andre601 4919caefec Merge branch 'master' of https://codeberg.org/Andre601/AdvancedServerList 2026-08-17 18:03:42 +02:00
Andre601 158cac6bbc Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.5.0' (#619) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/619
2026-08-17 14:24:02 +02:00
Andre601's Bot babbadb495 Update dependency com.squareup.okhttp3:okhttp-jvm to v5.5.0 2026-08-17 12:04:50 +00:00
Andre601 772e25f9f9 Update banner 2026-08-16 18:06:13 +02:00
Andre601 f649c18e51 Use !== for downloads check 2026-08-15 23:58:03 +02:00
Andre601 6cdadae7b4 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.6.3' (#618) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/618
2026-08-14 14:41:25 +02:00
Andre601's Bot c36cb3b9ae Update dependency ch.qos.logback:logback-classic to v1.6.3 2026-08-14 12:04:11 +00:00
Andre601 1776de1ec0 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.6.2' (#617) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/617
2026-08-12 14:10:05 +02:00
Andre601's Bot 0ae7f0990f Update dependency ch.qos.logback:logback-classic to v1.6.2 2026-08-12 12:04:59 +00:00
Andre601 53c4d738af Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.4' (#616) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/616
2026-08-09 14:41:50 +02:00
Andre601's Bot 97d6b9cf2f Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.4 2026-08-09 12:06:37 +00:00
Andre601 cd390ad95e Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.3' (#615) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/615
2026-08-01 15:05:05 +02:00
Andre601's Bot 5a204b2650 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.3 2026-08-01 12:03:34 +00:00
Andre601 ffce2c7b8d Merge pull request 'Update dependency org.jspecify:jspecify to v1.0.1' (#614) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/614
2026-07-30 14:18:00 +02:00
Andre601's Bot 1fb5eabcad Update dependency org.jspecify:jspecify to v1.0.1 2026-07-30 12:02:51 +00:00
Andre601 7c53ea19e0 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.6.1' (#613) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/613
2026-07-28 14:28:24 +02:00
Andre601's Bot a614d1f2aa Update dependency ch.qos.logback:logback-classic to v1.6.1 2026-07-28 12:05:54 +00:00
Andre601 417303e804 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.6.0' (#612) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/612
2026-07-24 14:12:14 +02:00
Andre601's Bot 9956b02736 Update dependency ch.qos.logback:logback-classic to v1.6.0 2026-07-24 12:03:51 +00:00
Andre601 43b3ddf81c Merge pull request 'Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.5.1' (#611) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/611
2026-07-23 14:17:35 +02:00
Andre601's Bot f0a0c43351 Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.5.1 2026-07-23 12:06:24 +00:00
Andre601 734c124a65 Merge pull request 'Update https://code.forgejo.org/actions/setup-python action to v7' (#610) from renovate/https-code.forgejo.org-actions-setup-python-7.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/610
2026-07-21 14:23:31 +02:00
Andre601 741324d1c7 Merge pull request 'Update all non-major dependencies' (#609) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/609
2026-07-21 14:12:04 +02:00
Andre601's Bot b28ef832c8 Update https://code.forgejo.org/actions/setup-python action to v7 2026-07-21 12:05:08 +00:00
Andre601's Bot 2b1a5aa45b Update all non-major dependencies 2026-07-21 12:04:06 +00:00
Andre601 c9581fe79c Merge pull request 'Update dependency mkdocs-material to v9.7.7' (#608) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/608
2026-07-18 15:41:19 +02:00
Andre601's Bot d385b68d2c Update dependency mkdocs-material to v9.7.7 2026-07-18 12:04:18 +00:00
Andre601 dd82892d39 Merge pull request 'Update dependency com.velocitypowered:velocity-api to v4' (#607) from renovate/com.velocitypowered-velocity-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/607
2026-07-15 14:13:08 +02:00
Andre601's Bot 32239db674 Update dependency com.velocitypowered:velocity-api to v4 2026-07-15 12:04:42 +00:00
Andre601 16ece42116 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.11.0' (#606) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/606
2026-07-13 14:22:07 +02:00
Andre601's Bot 137cf6e8da Update dependency com.viaversion:viaversion-api to v5.11.0 2026-07-13 12:04:45 +00:00
Andre601 0ba3047acc Merge pull request 'Update dependency com.velocitypowered:velocity-api to v3.5.1' (#605) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/605
2026-07-12 14:04:43 +02:00
Andre601's Bot de7d0ed3ca Update dependency com.velocitypowered:velocity-api to v3.5.1 2026-07-12 12:03:45 +00:00
Andre601 7c6bb28d39 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.38' (#604) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/604
2026-07-09 14:15:28 +02:00
Andre601's Bot 0ce9ec0239 Update dependency ch.qos.logback:logback-classic to v1.5.38 2026-07-09 12:03:11 +00:00
Andre601 1aa196c3d5 Remove bungeecord from getting-started 2026-07-06 18:26:40 +02:00
Andre601 5c7366198e Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.4' (#603) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/603
2026-07-05 14:14:49 +02:00
Andre601's Bot cf7fe7236e Update dependency space.arim.libertybans:bans-api to v1.1.4 2026-07-05 12:03:12 +00:00
Andre601 e69c94da06 Fix wrong VersionUplaoder command 2026-07-03 18:13:53 +02:00
Andre601 7cd3835785 Update SECURITY.md and versions in uploader 2026-07-03 17:56:31 +02:00
Andre601 8c36d27360 Version 5.9.0 2026-07-03 17:47:17 +02:00
Andre601 5329ed1b88 Merge pull request 'Update dependency me.clip:placeholderapi to v2.12.3' (#602) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/602
2026-07-03 14:32:32 +02:00
Andre601's Bot d66494f4dd Update dependency me.clip:placeholderapi to v2.12.3 2026-07-03 12:02:25 +00:00
Andre601 d03ebf5fb1 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.2' (#601) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/601
2026-06-30 14:22:34 +02:00
Andre601's Bot c7ae2c130f Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.2 2026-06-30 12:03:47 +00:00
Andre601 017a1893c4 Merge pull request 'Update all non-major dependencies to v2.0.0-beta.17' (#600) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/600
2026-06-29 14:09:50 +02:00
Andre601's Bot 7a3af4cb26 Update all non-major dependencies to v2.0.0-beta.17 2026-06-29 12:04:34 +00:00
Andre601 0d05f2fe1d Merge pull request 'Update all non-major dependencies' (#599) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/599
2026-06-27 15:27:15 +02:00
Andre601's Bot 0acb097439 Update all non-major dependencies 2026-06-27 12:04:09 +00:00
Andre601 8a67fbead8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.36' (#598) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/598
2026-06-26 14:26:16 +02:00
Andre601's Bot 8f3252d66a Update dependency ch.qos.logback:logback-classic to v1.5.36 2026-06-26 12:04:11 +00:00
Andre601 7668a680c4 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.35' (#597) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/597
2026-06-23 14:10:30 +02:00
Andre601's Bot 944e5a7262 Update dependency ch.qos.logback:logback-classic to v1.5.35 2026-06-23 12:05:36 +00:00
Andre601 d7cefb77ce Add target and rel to link 2026-06-22 00:50:43 +02:00
Andre601 e7a44711c0 Use v3 of Modrinth API 2026-06-22 00:47:12 +02:00
Andre601 96750ec5fd Merge pull request 'Update all non-major dependencies' (#594) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/594
2026-06-21 13:15:55 +02:00
Andre601's Bot 16500f29e4 Update all non-major dependencies 2026-06-20 14:14:12 +00:00
Andre601 25e433d0ed Display downloads remaining for 100k 2026-06-20 01:09:55 +02:00
Andre601 21430e9a4e Use codeberg-small for longer runtime 2026-06-19 16:42:27 +02:00
Andre601 de5455ab39 Merge pull request 'Update https://code.forgejo.org/actions/checkout action to v7' (#593) from renovate/https-code.forgejo.org-actions-checkout-7.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/593
2026-06-19 15:26:46 +02:00
Andre601 a52ca1d8be .forgejo/workflows/pr_preview.yml aktualisiert 2026-06-19 15:26:40 +02:00
Andre601 34d8048dd4 Merge pull request 'Update all non-major dependencies to v2.0.0-beta.16' (#592) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/592
2026-06-19 14:12:18 +02:00
Andre601's Bot 3b1e676888 Update https://code.forgejo.org/actions/checkout action to v7 2026-06-19 12:06:42 +00:00
Andre601's Bot 9332a3e342 Update all non-major dependencies to v2.0.0-beta.16 2026-06-19 12:06:33 +00:00
Andre601 eacf227650 Merge pull request 'Update all non-major dependencies to v1.1.3' (#591) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/591
2026-06-16 14:45:50 +02:00
Andre601's Bot 56131f4478 Update all non-major dependencies to v1.1.3 2026-06-16 12:02:51 +00:00
Andre601 b362c34141 Use DefaultExpressionParserEngine 2026-06-09 21:55:46 +02:00
Andre601 41718611e7 Merge pull request 'Update all non-major dependencies to v5.4.0' (#590) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/590
2026-06-09 14:13:18 +02:00
Andre601's Bot a92d6716e4 Update all non-major dependencies to v5.4.0 2026-06-09 12:04:50 +00:00
Andre601 768509100d Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.34' (#588) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/588
2026-06-01 14:17:51 +02:00
Andre601's Bot a64ad0cfa0 Update dependency ch.qos.logback:logback-classic to v1.5.34 2026-06-01 12:04:07 +00:00
Andre601 2abde6ef63 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.33' (#587) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/587
2026-05-28 14:27:41 +02:00
Andre601's Bot da2cf4d501 Update dependency ch.qos.logback:logback-classic to v1.5.33 2026-05-28 12:04:02 +00:00
Andre601 2a00634ce2 Merge pull request 'Update maven Docker tag to v3.9.16' (#586) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/586
2026-05-19 14:04:23 +02:00
Andre601's Bot 58108a8b19 Update maven Docker tag to v3.9.16 2026-05-19 12:03:28 +00:00
Andre601 6e7260d8f2 Bump adventure to 5.1.1 to avoid dependency errors 2026-05-12 17:59:48 +02:00
Andre601 d75f43a4bd Merge pull request 'Update all non-major dependencies to v5.1.0' (#585) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/585
2026-05-12 17:56:09 +02:00
Andre601's Bot 442c1539e9 Update all non-major dependencies to v5.1.0 2026-05-12 12:02:57 +00:00
Andre601 a6188905dc Merge pull request 'andre601-patch-1' (#584) from andre601-patch-1 into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/584
2026-05-07 11:05:09 +02:00
Andre601 81e0778825 Use version range 2026-05-07 11:03:27 +02:00
Andre601 afdcd11f7c Use version range 2026-05-07 11:02:46 +02:00
Andre601 4ca00cd8ad Merge pull request 'Update all non-major dependencies' (#583) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/583
2026-05-06 15:01:59 +02:00
Andre601's Bot 3b2d6b98b2 Update all non-major dependencies 2026-05-05 12:06:22 +00:00
Andre601 348d1fcacf v5.8.0
- Use 1.7.0-b1 of ExpressionParser
- Wrap condition evaluation in try-catch to prevent stacktrace spams for invalid protocols (bots?) pinging.
2026-05-03 21:39:48 +02:00
Andre601 4451d2382b Remove FakePlayerProfile and make hover only work on newer Paper versions 2026-05-01 21:53:52 +02:00
Andre601 3d410631ef Merge pull request 'Update dependency io.papermc.paper:paper-api to v26' (#582) from renovate/io.papermc.paper-paper-api-26.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/582
2026-05-01 14:07:15 +02:00
Andre601 e0ba710aed paper/pom.xml aktualisiert 2026-05-01 14:07:06 +02:00
Andre601's Bot 966d817f29 Update dependency io.papermc.paper:paper-api to v26 2026-05-01 12:05:19 +00:00
Andre601 838416b1c5 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.4' (#581) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/581
2026-04-29 14:17:44 +02:00
Andre601's Bot 23ee4a08ad Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.4 2026-04-29 12:04:12 +00:00
Andre601 baba7c7076 Use git-pages action for docs deployment 2026-04-25 14:14:23 +02:00
Andre601 7e7228dd77 Merge pull request 'Update dependency com.google.code.gson:gson to v2.14.0' (#580) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/580
2026-04-25 14:09:40 +02:00
Andre601's Bot 103bf4f1db Update dependency com.google.code.gson:gson to v2.14.0 2026-04-25 12:04:19 +00:00
Andre601 0c7c8e56db Update default config in getting-started.md 2026-04-25 01:25:17 +02:00
Andre601 cb3161a118 Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v5' (#579) from renovate/major-dependency.adventure-text-serializer-legacy into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/579
2026-04-22 14:11:44 +02:00
Andre601 326fe7098a Merge pull request 'Update all non-major dependencies' (#578) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/578
2026-04-22 14:11:25 +02:00
Andre601's Bot d79c54f7c9 Update dependency net.kyori:adventure-text-serializer-legacy to v5 2026-04-22 12:04:30 +00:00
Andre601's Bot 1468febf72 Update all non-major dependencies 2026-04-22 12:04:25 +00:00
Andre601 afbcad6c3e Merge pull request 'Update dependency net.kyori:adventure-text-minimessage to v5' (#577) from renovate/major-dependency.adventure-text-minimessage into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/577
2026-04-19 14:06:31 +02:00
Andre601 79aefaa6a5 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.1' (#576) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/576
2026-04-19 14:06:06 +02:00
Andre601's Bot d6ac483a0e Update dependency net.kyori:adventure-text-minimessage to v5 2026-04-19 12:05:15 +00:00
Andre601's Bot 35df0d84ca Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.6.1 2026-04-19 12:04:58 +00:00
Andre601 45229bd6d2 Merge pull request 'Update dependency eu.kennytv.maintenance:maintenance-api to v5' (#575) from renovate/eu.kennytv.maintenance-maintenance-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/575
2026-04-18 14:14:07 +02:00
Andre601 7bfa88383d Merge pull request 'Update dependency net.kyori:adventure-api to v5.0.1' (#574) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/574
2026-04-18 14:12:28 +02:00
Andre601's Bot efaae58562 Update dependency eu.kennytv.maintenance:maintenance-api to v5 2026-04-18 12:07:08 +00:00
Andre601's Bot 7dfdbb621d Update dependency net.kyori:adventure-api to v5.0.1 2026-04-18 12:06:54 +00:00
Andre601 d2cd554fb1 Merge pull request 'Update dependency net.kyori:adventure-api to v5' (#573) from renovate/major-dependency.adventure-api into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/573
2026-04-16 15:50:12 +02:00
Andre601 69168efb01 Merge pull request 'Update dependency com.google.guava:guava to v33.6.0-jre' (#572) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/572
2026-04-16 15:49:56 +02:00
Andre601's Bot 55f94a8c27 Update dependency net.kyori:adventure-api to v5 2026-04-16 12:04:32 +00:00
Andre601's Bot e813bdaba4 Update dependency com.google.guava:guava to v33.6.0-jre 2026-04-16 12:04:13 +00:00
Andre601 b3f56aa398 Merge pull request 'Update all non-major dependencies to v2.0.0-beta.15' (#571) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/571
2026-04-12 14:43:39 +02:00
Andre601's Bot 87f0573162 Update all non-major dependencies to v2.0.0-beta.15 2026-04-12 12:04:33 +00:00
Andre601 e49fe391d0 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.8.1' (#570) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/570
2026-03-31 14:06:26 +02:00
Andre601's Bot d077efdc12 Update dependency com.viaversion:viaversion-api to v5.8.1 2026-03-31 12:04:41 +00:00
Andre601 90fdaf628c Merge pull request 'Update dependency mkdocs-redirects to v1.2.3' (#569) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/569
2026-03-29 14:17:30 +02:00
Andre601's Bot 9651011b19 Update dependency mkdocs-redirects to v1.2.3 2026-03-29 12:02:58 +00:00
Andre601 9bacc04a68 Compile with Java 25 2026-03-28 13:52:41 +01:00
Andre601 515081e395 Merge pull request 'Update all non-major dependencies' (#568) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/568
2026-03-28 13:07:37 +01:00
Andre601's Bot 95fec87c12 Update all non-major dependencies 2026-03-28 12:07:06 +00:00
Andre601 778a415b4f Merge pull request 'Update dependency properdocs to v1.6.7' (#567) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/567
2026-03-21 14:23:28 +01:00
Andre601's Bot db66945d99 Update dependency properdocs to v1.6.7 2026-03-21 12:02:41 +00:00
Andre601 cf4245842b Bump version 2026-03-20 20:37:39 +01:00
Andre601 d90084196b Only print Stacktrace in debug in FaviconHandler 2026-03-20 20:37:11 +01:00
Andre601 62b13a3cdf Use key from uuid and text for PAPI caching 2026-03-20 20:36:11 +01:00
Andre601 be6e5f8bfb Merge pull request 'Update dependency mkdocs-material to v9.7.6' (#566) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/566
2026-03-20 13:06:39 +01:00
Andre601's Bot aaf1439da8 Update dependency mkdocs-material to v9.7.6 2026-03-20 12:03:01 +00:00
Andre601 b304252140 Move to ProperDocs 2026-03-17 22:01:03 +01:00
Andre601 dda321f07b Add MiniPlaceholders info 2026-03-14 21:46:11 +01:00
Andre601 f487fd9cc1 Merge pull request 'Update maven Docker tag to v3.9.14' (#564) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/564
2026-03-13 13:04:03 +01:00
Andre601's Bot 5681e7a790 Update maven Docker tag to v3.9.14 2026-03-13 12:02:54 +00:00
Andre601 c3aa8bf536 Merge pull request 'Update dependency mkdocs-material to v9.7.5' (#563) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/563
2026-03-11 13:10:39 +01:00
Andre601's Bot 1ce27b2244 Update dependency mkdocs-material to v9.7.5 2026-03-11 12:02:59 +00:00
Andre601 74bce4c220 Merge pull request 'Update maven Docker tag to v3.9.13' (#562) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/562
2026-03-10 13:06:08 +01:00
Andre601's Bot 6605538b0f Update maven Docker tag to v3.9.13 2026-03-10 12:03:30 +00:00
Andre601 4aa9e946fd Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.2' (#560) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/560
2026-03-05 13:06:17 +01:00
Andre601's Bot 42ec17997e Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.2 2026-03-05 12:03:02 +00:00
Andre601 d2587e67f4 Merge pull request 'Update dependency mkdocs-material to v9.7.4' (#559) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/559
2026-03-04 13:12:17 +01:00
Andre601's Bot 3f8f0e0ff7 Update dependency mkdocs-material to v9.7.4 2026-03-04 12:02:13 +00:00
Andre601 b0dbbbfe82 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.7.2' (#558) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/558
2026-03-02 13:31:12 +01:00
Andre601's Bot 6a32ea7826 Update dependency com.viaversion:viaversion-api to v5.7.2 2026-03-02 12:02:40 +00:00
Andre601 a6bcc7036c Merge pull request 'Update all non-major dependencies' (#557) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/557
2026-02-25 13:20:20 +01:00
Andre601's Bot 639b32db23 Update all non-major dependencies 2026-02-25 12:02:18 +00:00
Andre601 53672243d3 Merge pull request 'Update all non-major dependencies to v3.2.0' (#556) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/556
2026-02-24 13:07:49 +01:00
Andre601's Bot 3b7e177e4f Update all non-major dependencies to v3.2.0 2026-02-24 12:02:50 +00:00
Andre601 6b43ef4dc3 Merge pull request 'Update dependency mkdocs-material to v9.7.2' (#555) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/555
2026-02-19 13:09:00 +01:00
Andre601's Bot 665990aae9 Update dependency mkdocs-material to v9.7.2 2026-02-19 12:02:36 +00:00
Andre601 70723ce35e Merge pull request 'Update all non-major dependencies' (#554) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/554
2026-02-16 13:04:30 +01:00
Andre601's Bot b2d689306b Update all non-major dependencies 2026-02-16 12:02:58 +00:00
Andre601 6ae3f0aea6 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.31' (#552) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/552
2026-02-15 13:07:43 +01:00
Andre601's Bot 9445e12f8d Update dependency ch.qos.logback:logback-classic to v1.5.31 2026-02-15 12:03:57 +00:00
Andre601 94da2bbd2d Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.30' (#551) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/551
2026-02-14 13:06:08 +01:00
Andre601's Bot b5d0246bce Update dependency ch.qos.logback:logback-classic to v1.5.30 2026-02-14 12:03:00 +00:00
Andre601 48b1e53d13 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.29' (#550) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/550
2026-02-10 13:09:07 +01:00
Andre601's Bot 5e7a59474d Update dependency ch.qos.logback:logback-classic to v1.5.29 2026-02-10 12:03:00 +00:00
Andre601 bfbc547712 Merge pull request 'Update dependency me.clip:placeholderapi to v2.12.2' (#549) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/549
2026-02-09 13:08:33 +01:00
Andre601's Bot 2f8273d6a3 Update dependency me.clip:placeholderapi to v2.12.2 2026-02-09 12:03:44 +00:00
Andre601 1f036727d8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.28' (#548) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/548
2026-02-07 13:15:45 +01:00
Andre601's Bot bc07dadf03 Update dependency ch.qos.logback:logback-classic to v1.5.28 2026-02-07 12:04:00 +00:00
Andre601 ac0c754050 Merge pull request 'Update dependency me.clip:placeholderapi to v2.12.1' (#547) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/547
2026-02-03 13:11:45 +01:00
Andre601's Bot b2d664b5b9 Update dependency me.clip:placeholderapi to v2.12.1 2026-02-03 12:03:33 +00:00
Andre601 58e9e55dc6 Use AlessioDP snapshot repository 2026-02-02 14:44:30 +01:00
Andre601 9b8e459b5c Merge pull request 'Update all non-major dependencies' (#546) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/546
2026-02-02 14:20:05 +01:00
Andre601's Bot 598343ebc7 Update all non-major dependencies 2026-02-02 12:03:54 +00:00
Andre601 c1fd983dab Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.27' (#545) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/545
2026-01-31 13:07:58 +01:00
Andre601's Bot d05faf30dc Update dependency ch.qos.logback:logback-classic to v1.5.27 2026-01-31 12:04:24 +00:00
Andre601 79a96f30ca Merge pull request 'Update all non-major dependencies' (#544) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/544
2026-01-26 14:01:04 +01:00
Andre601's Bot 54ddf4bb4d Update all non-major dependencies 2026-01-26 12:02:48 +00:00
Andre601 f8b85ce9ed Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.7.1' (#543) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/543
2026-01-19 13:38:34 +01:00
Andre601's Bot 2f5c1db3c1 Update dependency com.viaversion:viaversion-api to v5.7.1 2026-01-19 12:02:20 +00:00
Andre601 de7570ac6e Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.25' (#542) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/542
2026-01-18 14:08:29 +01:00
Andre601's Bot 41c7db5f27 Update dependency ch.qos.logback:logback-classic to v1.5.25 2026-01-18 12:03:56 +00:00
Andre601 ef0ef4e373 Merge pull request 'Update all non-major dependencies' (#539) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/539
2026-01-07 13:27:03 +01:00
Andre601's Bot e9ab05618e Update all non-major dependencies 2026-01-07 12:04:09 +00:00
Andre601 a28e62f53c Bump version to 5.7.2 2026-01-02 20:13:08 +01:00
Andre601 e82df2d1f7 Merge pull request 'fix date pattern argument not working with date placeholders' (#538) from UninenVille/AdvancedServerList:fix-date-pattern-argument into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/538
2026-01-02 20:10:17 +01:00
UninenVille 16a2b05b2b fix date pattern argument not working with date placeholders
Date pattern argument is third argument, not second
2026-01-02 19:43:12 +01:00
Andre601 5df3d6dd48 Add missing description 2026-01-02 15:54:51 +01:00
Andre601 91a6149dac Add LuckPerms addon to getting started page 2026-01-02 15:52:42 +01:00
Andre601 3f224504a1 Bump version to 5.7.1 2026-01-01 20:36:18 +01:00
Andre601 437e155a46 Fix NPE for '/asl profiles set' command due to no CommandType meta being added. 2026-01-01 17:59:11 +01:00
Andre601 8275069315 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.7.0' (#536) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/536
2025-12-30 13:07:38 +01:00
Andre601's Bot bd564a8638 Update dependency com.viaversion:viaversion-api to v5.7.0 2025-12-30 12:02:26 +00:00
Andre601 591279f70b Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.23' (#535) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/535
2025-12-22 13:15:18 +01:00
Andre601's Bot 80e84aa41b Update dependency ch.qos.logback:logback-classic to v1.5.23 2025-12-22 12:11:31 +00:00
Andre601 9024c4dc71 Merge pull request 'Update all non-major dependencies to v1.7.3' (#534) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/534
2025-12-21 13:10:53 +01:00
Andre601's Bot bb0f389016 Update all non-major dependencies to v1.7.3 2025-12-21 12:02:21 +00:00
Andre601 f8f8a45b1a Merge pull request 'Update all non-major dependencies' (#533) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/533
2025-12-20 13:54:48 +01:00
Andre601's Bot 0bae24bb66 Update all non-major dependencies 2025-12-20 12:02:32 +00:00
Andre601 2158caebe6 Fix bad cloud versions 2025-12-19 22:24:04 +01:00
Andre601 f9ea253da3 Add MiniPlaceholders as optional dependency 2025-12-19 22:06:03 +01:00
Andre601 7c53ddf4f4 Fix wrong value for dateFormat.parse 2025-12-19 21:56:16 +01:00
Andre601 8bcc88d620 Bump version to 5.7.0 2025-12-19 21:38:17 +01:00
Andre601 78b687587d Merge pull request 'Add bluesky Post step to publish_assets.yml' (#385) from feature/bluesky-poster into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/385
2025-12-19 21:36:53 +01:00
Andre601 168fe364b0 Looooooots of changes 2025-12-19 21:18:31 +01:00
Andre601 cd3f54dba6 Merge pull request 'Update all non-major dependencies' (#532) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/532
2025-12-18 13:08:30 +01:00
Andre601's Bot 79f15b2467 Update all non-major dependencies 2025-12-18 12:03:21 +00:00
Andre601 ade8ad5a33 Merge pull request 'Update all non-major dependencies' (#531) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/531
2025-12-14 21:25:07 +01:00
Andre601's Bot 6e343f1516 Update all non-major dependencies 2025-12-13 12:03:22 +00:00
Andre601 fee436fda6 Update links in default.yml 2025-12-09 23:59:37 +01:00
Andre601 27d4f5acd0 Merge pull request 'Update https://code.forgejo.org/actions/checkout action to v6' (#527) from renovate/https-code.forgejo.org-actions-checkout-6.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/527
2025-11-21 13:16:03 +01:00
Andre601's Bot e18c70d446 Update https://code.forgejo.org/actions/checkout action to v6 2025-11-21 12:02:31 +00:00
Andre601 0ca3ec62a9 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.2' (#526) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/526
2025-11-19 13:21:06 +01:00
Andre601's Bot 461ae5d0aa Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.2 2025-11-19 12:06:53 +00:00
Andre601 5696a9417b Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.1' (#523) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/523
2025-11-17 13:16:39 +01:00
Andre601's Bot 0705101cd6 Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.1 2025-11-17 12:04:39 +00:00
Andre601 69ad3554cf Merge pull request 'Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.5.0' (#522) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/522
2025-11-15 13:46:38 +01:00
Andre601's Bot 7f1de13dcc Update dependency org.apache.maven.plugins:maven-jar-plugin to v3.5.0 2025-11-15 12:02:40 +00:00
Andre601 c3e16eec31 Merge pull request 'Update dependency mkdocs-macros-plugin to v1.5.0' (#521) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/521
2025-11-14 13:06:21 +01:00
Andre601's Bot 207970a90b Update dependency mkdocs-macros-plugin to v1.5.0 2025-11-14 12:02:26 +00:00
Andre601 2628dbab56 Merge pull request 'Update all non-major dependencies' (#520) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/520
2025-11-11 13:13:53 +01:00
Andre601's Bot 3da9f8b400 Update all non-major dependencies 2025-11-11 12:02:48 +00:00
Andre601 ffd0a8c364 Merge pull request 'Update all non-major dependencies to v1.7.2' (#519) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/519
2025-11-06 15:17:34 +01:00
Andre601's Bot d9a7b244f9 Update all non-major dependencies to v1.7.2 2025-11-06 14:01:26 +00:00
Andre601 f1fb5ef6ea Merge pull request 'Update dependency me.clip:placeholderapi to v2.11.7' (#518) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/518
2025-11-03 13:23:37 +01:00
Andre601's Bot d3406aad1c Update dependency me.clip:placeholderapi to v2.11.7 2025-11-03 12:02:22 +00:00
Andre601 650bcc3235 Merge pull request 'Update dependency mkdocs-material to v9.6.23' (#517) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/517
2025-11-02 13:25:54 +01:00
Andre601's Bot 0cd91c63bb Update dependency mkdocs-material to v9.6.23 2025-11-02 12:02:33 +00:00
Andre601 e95a4634ec Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.1' (#516) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/516
2025-11-01 13:03:15 +01:00
Andre601's Bot d0293ae15e Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.1 2025-11-01 12:02:21 +00:00
Andre601 f5c6185b96 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.0' (#515) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/515
2025-10-31 13:10:21 +01:00
Andre601's Bot 61981db3cc Update dependency com.squareup.okhttp3:okhttp-jvm to v5.3.0 2025-10-31 12:03:05 +00:00
Andre601 52804adfdf Merge pull request 'Update all non-major dependencies to v1.7.1' (#514) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/514
2025-10-28 13:06:10 +01:00
Andre601's Bot 4b185be8a4 Update all non-major dependencies to v1.7.1 2025-10-28 12:03:01 +00:00
Andre601 46ac4ef5c1 Merge pull request 'Update dependency mkdocs-macros-plugin to v1.4.1' (#513) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/513
2025-10-26 13:44:51 +01:00
Andre601's Bot 00e2a8ebee Update dependency mkdocs-macros-plugin to v1.4.1 2025-10-26 12:03:57 +00:00
Andre601 c523da7477 Merge pull request 'Update dependency mkdocs-glightbox to v0.5.2' (#512) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/512
2025-10-24 14:06:11 +02:00
Andre601's Bot 01e586fa5e Update dependency mkdocs-glightbox to v0.5.2 2025-10-24 12:04:10 +00:00
Andre601 9322819538 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.20' (#511) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/511
2025-10-20 14:37:17 +02:00
Andre601's Bot 7ef4a9a61b Update dependency ch.qos.logback:logback-classic to v1.5.20 2025-10-20 12:02:54 +00:00
Andre601 af2da61500 Merge pull request 'Update dependency mkdocs-material to v9.6.22' (#510) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/510
2025-10-15 14:05:25 +02:00
Andre601's Bot 23d0626250 Update dependency mkdocs-material to v9.6.22 2025-10-15 12:02:21 +00:00
Andre601 74dfdb3022 Add profiles edit command 2025-10-14 03:07:19 +02:00
Andre601 4a589619bd Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.5.1' (#509) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/509
2025-10-13 15:19:37 +02:00
Andre601's Bot 9bdd519246 Update dependency com.viaversion:viaversion-api to v5.5.1 2025-10-13 12:05:43 +00:00
Andre601 cf4e08fe3e Merge pull request 'Update dependency org.incendo:cloud-minecraft-extras to v2.0.0-beta.13' (#508) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/508
2025-10-12 14:11:01 +02:00
Andre601's Bot 70bbb15c60 Update dependency org.incendo:cloud-minecraft-extras to v2.0.0-beta.13 2025-10-12 12:02:33 +00:00
Andre601 ee8e00f3a2 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.2.1' (#507) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/507
2025-10-10 14:37:51 +02:00
Andre601's Bot 0280668f9b Update dependency com.squareup.okhttp3:okhttp-jvm to v5.2.1 2025-10-10 12:07:09 +00:00
Andre601 e959f478a0 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.2.0' (#505) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/505
2025-10-08 14:03:52 +02:00
Andre601's Bot f024b2c763 Update dependency com.squareup.okhttp3:okhttp-jvm to v5.2.0 2025-10-08 12:02:40 +00:00
Andre601 c0665b450e Merge pull request 'Update all non-major dependencies' (#504) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/504
2025-10-07 15:25:22 +02:00
Andre601's Bot e50ed552b9 Update all non-major dependencies 2025-10-07 12:02:48 +00:00
Andre601 1601e41e9c Merge pull request 'Update https://github.com/peter-evans/create-or-update-comment action to v5' (#503) from renovate/https-github.com-peter-evans-create-or-update-comment-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/503
2025-10-03 14:04:33 +02:00
Andre601 f8b80f9e14 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.5.0' (#502) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/502
2025-10-03 14:03:52 +02:00
Andre601's Bot 22bfe2be00 Update https://github.com/peter-evans/create-or-update-comment action to v5 2025-10-03 12:02:31 +00:00
Andre601's Bot 7e9c6b909c Update dependency com.viaversion:viaversion-api to v5.5.0 2025-10-03 12:02:26 +00:00
Andre601 93ecdd736f Merge pull request 'Bump checkout action to v5' (#501) from feat/update-checkout-action into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/501
2025-10-02 15:54:08 +02:00
Andre601 abfbaf4498 Bump checkout action to v5 2025-10-02 15:53:12 +02:00
Andre601 ce3b80b05c Bump checkout action to v5 2025-10-02 15:52:46 +02:00
Andre601 9e3a77ad7d Merge pull request 'Update https://github.com/peter-evans/find-comment action to v4' (#500) from renovate/https-github.com-peter-evans-find-comment-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/500
2025-10-02 14:28:01 +02:00
Andre601's Bot cdc2115cb3 Update https://github.com/peter-evans/find-comment action to v4 2025-10-02 12:02:16 +00:00
Andre601 5173f61c6c Merge pull request 'Update all non-major dependencies' (#499) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/499
2025-10-01 14:09:07 +02:00
Andre601's Bot 8b12cb2402 Update all non-major dependencies 2025-10-01 12:02:30 +00:00
Andre601 3ab48396af Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.0' (#497) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/497
2025-09-30 14:56:02 +02:00
Andre601's Bot 00b34c8b47 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.14.0 2025-09-30 12:04:24 +00:00
Andre601 b06274638e Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5.1' (#496) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/496
2025-09-28 14:13:04 +02:00
Andre601's Bot cd3b2fe0b4 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5.1 2025-09-28 12:02:24 +00:00
Andre601 51d8ae6c42 Merge pull request 'Update dependency net.md-5:bungeecord-api to v1.21-R0.4' (#495) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/495
2025-09-27 14:07:19 +02:00
Andre601's Bot 1545be4709 Update dependency net.md-5:bungeecord-api to v1.21-R0.4 2025-09-27 12:02:43 +00:00
Andre601 7693e72728 Merge pull request 'Update dependency mkdocs-macros-plugin to v1.4.0' (#494) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/494
2025-09-23 14:07:14 +02:00
Andre601's Bot b879110379 Update dependency mkdocs-macros-plugin to v1.4.0 2025-09-23 12:02:24 +00:00
Andre601 80900089bb Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.1' (#493) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/493
2025-09-22 14:04:44 +02:00
Andre601's Bot df776f4e1c Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.1 2025-09-22 12:02:19 +00:00
Andre601 72afff8315 Merge pull request 'Update dependency com.google.guava:guava to v33.5.0-jre' (#492) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/492
2025-09-18 14:10:37 +02:00
Andre601's Bot 307384d1e1 Update dependency com.google.guava:guava to v33.5.0-jre 2025-09-18 12:03:10 +00:00
Andre601 84f31fad53 Merge pull request 'Update dependency mkdocs-material to v9.6.20' (#490) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/490
2025-09-15 14:36:25 +02:00
Andre601's Bot fe0774303a Update dependency mkdocs-material to v9.6.20 2025-09-15 12:05:20 +00:00
Andre601 563173679b Merge pull request 'Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.1' (#489) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/489
2025-09-13 14:14:06 +02:00
Andre601's Bot 6e96e06109 Update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.1 2025-09-13 12:02:50 +00:00
Andre601 dae25fd00a Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.2' (#488) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/488
2025-09-12 14:43:02 +02:00
Andre601's Bot d2ca0cfae5 Update dependency space.arim.libertybans:bans-api to v1.1.2 2025-09-12 12:02:50 +00:00
Andre601 afaae368ac Merge pull request 'Update dependency com.google.code.gson:gson to v2.13.2' (#487) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/487
2025-09-11 15:00:19 +02:00
Andre601's Bot 522ce7f932 Update dependency com.google.code.gson:gson to v2.13.2 2025-09-11 12:02:07 +00:00
Andre601 3f3d460f2f Merge pull request 'Update dependency mkdocs-material to v9.6.19' (#486) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/486
2025-09-08 14:06:06 +02:00
Andre601's Bot 3a03899688 Update dependency mkdocs-material to v9.6.19 2025-09-08 12:02:12 +00:00
Andre601 e6d4264525 Merge pull request 'Update dependency mkdocs-glightbox to v0.5.1' (#485) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/485
2025-09-05 14:37:00 +02:00
Andre601's Bot 61466074fd Update dependency mkdocs-glightbox to v0.5.1 2025-09-05 12:02:34 +00:00
Andre601 4516157ddf Merge pull request 'Update https://code.forgejo.org/actions/setup-python action to v6' (#483) from renovate/https-code.forgejo.org-actions-setup-python-6.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/483
2025-09-04 15:42:23 +02:00
Andre601 82c65bf13c Merge pull request 'Update dependency mkdocs-glightbox to v0.5.0' (#482) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/482
2025-09-04 15:41:29 +02:00
Andre601's Bot 3c6e73671d Update https://code.forgejo.org/actions/setup-python action to v6 2025-09-04 12:02:27 +00:00
Andre601's Bot c91a2c0d4e Update dependency mkdocs-glightbox to v0.5.0 2025-09-04 12:02:07 +00:00
Andre601 66b10656c3 Update PlaceholderAPI link 2025-09-03 21:53:10 +02:00
Andre601 b82a0ff0d9 Update PlaceholderAPI link 2025-09-03 21:48:17 +02:00
Andre601 2e02af5a67 Merge pull request 'Update dependency mkdocs-material to v9.6.18' (#480) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/480
2025-08-22 14:32:26 +02:00
Andre601's Bot 5626b38390 Update dependency mkdocs-material to v9.6.18 2025-08-22 12:03:34 +00:00
Andre601 415456447c Merge pull request 'Update dependency mkdocs-material to v9.6.17' (#479) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/479
2025-08-16 16:43:33 +02:00
Andre601's Bot c555a3c648 Update dependency mkdocs-material to v9.6.17 2025-08-16 12:02:07 +00:00
Andre601 9ec0c1c4ce Merge pull request 'Update dependency mkdocs-macros-plugin to v1.3.9' (#477) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/477
2025-08-13 20:07:50 +02:00
Andre601 d3eb43db39 Revert Checkout to v4 2025-08-13 20:07:45 +02:00
Andre601 b4b4f6a9fc Merge branch 'master' into renovate/all-minor-patch 2025-08-13 20:03:53 +02:00
Andre601 3217eee02b Revert Checkout to v4 2025-08-13 20:02:54 +02:00
Andre601 ea68fca70b Merge branch 'master' into renovate/all-minor-patch 2025-08-13 20:01:08 +02:00
Andre601 a8ceb88b67 Fix missing env in RUN_URL 2025-08-13 20:00:56 +02:00
Andre601's Bot 19d6ce28c4 Update dependency mkdocs-macros-plugin to v1.3.9 2025-08-13 12:02:11 +00:00
Andre601 05e61794a1 Merge pull request 'Update https://code.forgejo.org/actions/checkout action to v5' (#476) from renovate/https-code.forgejo.org-actions-checkout-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/476
2025-08-12 15:30:45 +02:00
Andre601's Bot 46e062eb8f Update https://code.forgejo.org/actions/checkout action to v5 2025-08-12 12:02:44 +00:00
Andre601 2196456dd4 Rename faviconStrategy to faviconResizeStrategy for clarity 2025-08-10 13:39:51 +02:00
Andre601 bfd1e2e2ad Add note about updating local favicons 2025-08-10 13:29:30 +02:00
Andre601 21af6df510 Merge pull request 'Update all non-major dependencies to v4.24.0' (#475) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/475
2025-07-31 14:18:42 +02:00
Andre601's Bot 713062d1b4 Update all non-major dependencies to v4.24.0 2025-07-31 12:03:06 +00:00
Andre601 673a134ab1 Merge pull request 'Update Docs banner' (#474) from feature/update-banner into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/474
2025-07-30 23:17:07 +02:00
Andre601 c777772a90 ❇️ Sparke up the banner ❇️ 2025-07-30 23:05:14 +02:00
Andre601 a43a9f8f19 docs/.overrides/main.html aktualisiert 2025-07-30 22:10:52 +02:00
Andre601 d4a416f85e Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.4.1' (#473) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/473
2025-07-30 14:05:15 +02:00
Andre601's Bot bc26ceae55 Update dependency net.kyori:adventure-platform-bungeecord to v4.4.1 2025-07-30 12:02:25 +00:00
Andre601 3d19a6688c Merge pull request 'Update dependency mkdocs-material to v9.6.16' (#472) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/472
2025-07-27 14:32:57 +02:00
Andre601's Bot 03a8258ddc Update dependency mkdocs-material to v9.6.16 2025-07-27 12:03:25 +00:00
Andre601 6df5015b0d Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.4.2' (#471) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/471
2025-07-24 15:42:01 +02:00
Andre601's Bot f1f8aaaad2 Update dependency com.viaversion:viaversion-api to v5.4.2 2025-07-24 12:02:08 +00:00
Andre601 151f5494fc Bumb version to 5.7.0-b2 2025-07-22 23:40:13 +02:00
Andre601 f997fa0a89 Use interfaces instead of Abstract classes 2025-07-22 23:39:16 +02:00
Andre601 2f1549eb8a Merge pull request 'Fix Dialog Support on Paper' (#468) from fix/paper-dialog-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/468
2025-07-22 23:27:47 +02:00
Andre601 77dba75c17 Use callback instead of event 2025-07-21 15:38:57 +02:00
Andre601 dfa72cb852 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.4' (#469) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/469
2025-07-21 14:05:12 +02:00
Andre601's Bot dc0cf6ebfc Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.4 2025-07-21 12:02:16 +00:00
Andre601 2c520e53c0 Fix Dialog Support on Paper 2025-07-20 23:42:16 +02:00
Andre601 356cca9ba0 Merge pull request 'Update maven Docker tag to v3.9.11' (#467) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/467
2025-07-18 18:43:57 +02:00
Andre601's Bot 4e7b17a601 Update maven Docker tag to v3.9.11 2025-07-18 12:04:19 +00:00
Andre601 033f4bd6ab Make it a beta 2025-07-16 20:54:36 +02:00
Andre601 13edca3c4c Bump version 2025-07-16 20:53:56 +02:00
Andre601 a626dc5b28 Merge pull request 'Implement dialog-based profiles editing.' (#466) from feature/dialog-based-editing into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/466
2025-07-16 20:52:03 +02:00
Andre601 7a60024bd0 Merge branch 'master' into feature/dialog-based-editing 2025-07-16 20:51:51 +02:00
Andre601 cedb1e5748 Update Version uploader 2025-07-16 20:51:22 +02:00
Andre601 8b0fb99bc5 Use CommandPostprocessor for CommandType handling 2025-07-16 20:46:27 +02:00
Andre601 31202a930a Change cancel to a Back button. 2025-07-13 23:17:26 +02:00
Andre601 a105e3186b Create Builder class for Dialog building 2025-07-13 20:33:38 +02:00
Andre601 e2df79c428 Implement dialog-based profiles editing. 2025-07-12 22:23:36 +02:00
Andre601 01ecce170c Merge pull request 'Update dependency org.incendo:cloud-minecraft-extras to v2.0.0-beta.11' (#465) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/465
2025-07-12 14:04:26 +02:00
Andre601's Bot 3bb171cecf Update dependency org.incendo:cloud-minecraft-extras to v2.0.0-beta.11 2025-07-12 12:02:09 +00:00
Andre601 f54bbe26e1 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8.4' (#464) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/464
2025-07-09 14:16:53 +02:00
Andre601's Bot ddede7abef Update dependency net.william278:papiproxybridge to v1.8.4 2025-07-09 12:02:15 +00:00
Andre601 2c6467f176 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp-jvm to v5.1.0' (#463) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/463
2025-07-08 14:05:49 +02:00
Andre601's Bot 8b92f8fc4d Update dependency com.squareup.okhttp3:okhttp-jvm to v5.1.0 2025-07-08 12:02:15 +00:00
Andre601 7bf6d8de0f Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8.3' (#462) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/462
2025-07-06 14:10:34 +02:00
Andre601's Bot 844a88d381 Update dependency net.william278:papiproxybridge to v1.8.3 2025-07-06 12:02:23 +00:00
Andre601 fcea4e90e3 Merge pull request 'Update all non-major dependencies' (#461) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/461
2025-07-05 16:26:05 +02:00
Andre601's Bot 6a97debdf7 Update all non-major dependencies 2025-07-05 12:03:08 +00:00
Andre601 07fa6cf0ec Fix OkHttp version change + method renamings 2025-07-05 00:21:24 +02:00
Andre601 367f0f3501 Merge pull request 'Update dependency com.squareup.okhttp3:okhttp to v5' (#460) from renovate/major-okhttp-monorepo into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/460
2025-07-04 14:06:52 +02:00
Andre601 16dcaef825 Merge branch 'master' into renovate/major-okhttp-monorepo 2025-07-04 14:06:38 +02:00
Andre601 f780372fda Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.1' (#459) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/459
2025-07-04 14:06:13 +02:00
Andre601's Bot a8f8c0d770 Update dependency com.squareup.okhttp3:okhttp to v5 2025-07-04 12:02:29 +00:00
Andre601's Bot 70e06afaf0 Update dependency space.arim.libertybans:bans-api to v1.1.1 2025-07-04 12:02:20 +00:00
Andre601 13e087eddd Merge pull request 'Update all non-major dependencies' (#458) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/458
2025-07-01 14:04:14 +02:00
Andre601's Bot 31af916f04 Update all non-major dependencies 2025-07-01 12:02:18 +00:00
Andre601 0c36667116 Version 5.6.0 2025-06-25 20:44:01 +02:00
Andre601 3417d7c0be Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.2' (#456) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/456
2025-06-25 14:05:24 +02:00
Andre601's Bot 96fa871204 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.2 2025-06-25 12:02:49 +00:00
Andre601 aaacd9944f Merge pull request 'Update maven Docker tag to v3.9.10' (#455) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/455
2025-06-24 14:35:21 +02:00
Andre601's Bot af44324cf1 Update maven Docker tag to v3.9.10 2025-06-24 12:02:49 +00:00
Andre601 77b6897bd4 Add note about favicon resizing 2025-06-23 23:21:02 +02:00
Andre601 9d963199ae Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.4.0' (#454) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/454
2025-06-21 14:03:06 +02:00
Andre601's Bot 580b87ebb5 Update dependency com.viaversion:viaversion-api to v5.4.0 2025-06-21 12:02:16 +00:00
Andre601 efd5762162 Update README 2025-06-19 23:55:08 +02:00
Andre601 62261ae6ed Update config.yml example in getting-started 2025-06-19 21:29:06 +02:00
Andre601 e52bfdf60b Add faviconStrategy config option 2025-06-19 21:18:41 +02:00
Andre601 0152ba3e1a Update default.yml in getting-started.md 2025-06-19 17:04:55 +02:00
Andre601 090787e292 Add german tutorial 2025-06-19 16:40:55 +02:00
Andre601 25d14eeaae Add indonesian tutorial 2025-06-19 16:32:57 +02:00
Andre601 386d490596 Merge pull request 'Update all non-major dependencies to v4.23.0' (#453) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/453
2025-06-18 20:56:11 +02:00
Andre601's Bot 207ce12452 Update all non-major dependencies to v4.23.0 2025-06-18 18:48:21 +00:00
Andre601 b87703c36c Merge pull request 'Update dependency net.md-5:bungeecord-api to v1.21-R0.3' (#452) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/452
2025-06-16 14:05:20 +02:00
Andre601's Bot 41677d0635 Update dependency net.md-5:bungeecord-api to v1.21-R0.3 2025-06-16 12:02:50 +00:00
Andre601 dfdb2aa767 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.1' (#451) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/451
2025-06-07 14:58:29 +02:00
Andre601's Bot d14c5f80e8 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.1 2025-06-07 12:02:12 +00:00
Andre601 bd9e376d08 Merge pull request 'Implement support for merging images' (#450) from feature/favicon-merging into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/450
2025-06-03 14:54:15 +02:00
Andre601 578242078b Move local and random Favicon handling to the start 2025-06-03 14:33:36 +02:00
Andre601 f84842729d Update documentation 2025-06-03 01:04:39 +02:00
Andre601 1daeecbbcf Create proper Favicon merging system 2025-06-03 00:56:37 +02:00
Andre601 5dcab6c37c Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.0' (#449) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/449
2025-05-30 14:02:34 +02:00
Andre601's Bot a146a10d53 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.13.0 2025-05-30 12:02:12 +00:00
Andre601 75db0d5e96 Add Favicon Merging 2025-05-28 20:17:40 +02:00
Andre601 644dd401d4 Update profiles option page 2025-05-28 19:58:14 +02:00
Andre601 32d85c6be1 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5' (#448) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/448
2025-05-23 14:04:19 +02:00
Andre601's Bot 1b47af6714 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.5 2025-05-23 12:03:00 +00:00
Andre601 4544696a54 Merge pull request 'Update dependency mkdocs-material to v9.6.14' (#447) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/447
2025-05-14 12:23:10 +00:00
Andre601's Bot a84848daee Update dependency mkdocs-material to v9.6.14 2025-05-14 12:03:01 +00:00
Andre601 3f8dd90e28 Merge pull request 'Update dependency net.kyori:adventure-platform-bungeecord to v4.4.0' (#446) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/446
2025-05-11 15:40:33 +00:00
Andre601's Bot f633741988 Update dependency net.kyori:adventure-platform-bungeecord to v4.4.0 2025-05-11 12:02:21 +00:00
Andre601 7e9ea9f470 Merge pull request 'Update dependency mkdocs-material to v9.6.13' (#445) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/445
2025-05-10 12:14:35 +00:00
Andre601's Bot c2c00dc47f Update dependency mkdocs-material to v9.6.13 2025-05-10 12:02:52 +00:00
Andre601 027503efab Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8.1' (#444) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/444
2025-05-06 12:31:54 +00:00
Andre601's Bot 7dd78cbbfc Update dependency net.william278:papiproxybridge to v1.8.1 2025-05-06 12:03:06 +00:00
Andre601 b27b8e78bd Merge pull request 'Update all non-major dependencies to v4.21.0' (#443) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/443
2025-04-30 12:13:12 +00:00
Andre601's Bot ad5b07feda Update all non-major dependencies to v4.21.0 2025-04-30 12:03:04 +00:00
Andre601 d79784d1c0 Merge pull request 'Update all non-major dependencies to v4.1.1' (#442) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/442
2025-04-29 12:06:11 +00:00
Andre601's Bot ef84e85426 Update all non-major dependencies to v4.1.1 2025-04-29 12:02:50 +00:00
Andre601 35782809ac Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.4' (#441) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/441
2025-04-25 12:08:42 +00:00
Andre601's Bot 3e3c4903e4 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.4 2025-04-25 12:02:49 +00:00
Andre601 79b45fb29d Merge pull request 'Update dependency com.google.code.gson:gson to v2.13.1' (#440) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/440
2025-04-24 14:20:27 +00:00
Andre601's Bot 46f40294e2 Update dependency com.google.code.gson:gson to v2.13.1 2025-04-24 14:08:23 +00:00
Andre601 ca5ab5d221 Merge pull request 'Update dependency mkdocs-material to v9.6.12' (#439) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/439
2025-04-17 12:04:54 +00:00
Andre601's Bot b2e5d7ae28 Update dependency mkdocs-material to v9.6.12 2025-04-17 12:02:51 +00:00
Andre601 649e9f07ef Merge pull request 'Update all non-major dependencies' (#438) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/438
2025-04-15 12:04:27 +00:00
Andre601's Bot eaa86aa93b Update all non-major dependencies 2025-04-15 12:02:50 +00:00
Andre601 8a90619810 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.2' (#437) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/437
2025-04-14 12:38:48 +00:00
Andre601's Bot 351db260ce Update dependency com.viaversion:viaversion-api to v5.3.2 2025-04-14 12:21:57 +00:00
Andre601 bcc9d88e8c Update appearance of playercount options in docs 2025-04-12 23:41:08 +00:00
Andre601 9c849157d3 Merge pull request 'Update all non-major dependencies' (#436) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/436
2025-04-12 12:12:05 +00:00
Andre601's Bot f171c951e7 Update all non-major dependencies 2025-04-12 12:02:23 +00:00
Andre601 cae808e3fc Add example for priority 2025-04-10 22:06:15 +02:00
Andre601 ae8e6304f9 Merge pull request 'Update dependency com.google.guava:guava to v33.4.7-jre' (#435) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/435
2025-04-09 12:26:44 +00:00
Andre601's Bot c975ba79b3 Update dependency com.google.guava:guava to v33.4.7-jre 2025-04-09 12:03:17 +00:00
Andre601 83fb13e1f2 Update wiki links 2025-04-07 23:49:05 +00:00
Andre601 586351e277 Update announcement banner 2025-04-08 01:46:40 +02:00
Andre601 098b6be0f4 Refactor profiles page 2025-04-08 01:40:36 +02:00
Andre601 1c881d2832 Update API Docs 2025-04-07 23:40:42 +02:00
Andre601 e6f3d122c7 Merge pull request 'Migrate renovate config' (#434) from renovate/migrate-config into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/434
2025-04-06 01:54:03 +00:00
Andre601's Bot 759474b344 Migrate config renovate.json 2025-04-06 01:52:21 +00:00
Andre601 6aef4c2de9 Enable config migration 2025-04-06 01:51:29 +00:00
Andre601 64d7c81c58 Merge pull request 'Update all non-major dependencies to v4.20.0' (#433) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/433
2025-04-06 01:30:06 +00:00
Andre601's Bot a070708323 Update all non-major dependencies to v4.20.0 2025-04-06 01:29:09 +00:00
Andre601 e9ba86508c Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.0' (#432) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/432
2025-04-05 12:36:42 +00:00
Andre601's Bot c1e3638534 Update dependency space.arim.libertybans:bans-api to v1.1.0 2025-04-05 12:02:18 +00:00
Andre601 f5260f3be1 Merge pull request 'Update dependency mkdocs-material to v9.6.11' (#431) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/431
2025-04-01 12:04:58 +00:00
Andre601's Bot 51372aa8f4 Update dependency mkdocs-material to v9.6.11 2025-04-01 12:02:14 +00:00
Andre601 025c9f4423 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.1' (#430) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/430
2025-03-31 12:25:08 +00:00
Andre601's Bot 99c34dd343 Update dependency com.viaversion:viaversion-api to v5.3.1 2025-03-31 12:02:53 +00:00
Andre601 cd91b799d6 Merge pull request 'Update dependency mkdocs-material to v9.6.10' (#429) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/429
2025-03-30 13:04:23 +00:00
Andre601's Bot 5b7eb014a3 Update dependency mkdocs-material to v9.6.10 2025-03-30 12:03:16 +00:00
Andre601 ad32952b97 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.3.0' (#428) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/428
2025-03-29 12:03:56 +00:00
Andre601's Bot 4a1e552d5d Update dependency com.viaversion:viaversion-api to v5.3.0 2025-03-29 12:02:13 +00:00
Andre601 ea1394dce9 Merge pull request 'Update all non-major dependencies' (#427) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/427
2025-03-28 12:10:16 +00:00
Andre601's Bot 317fa631e9 Update all non-major dependencies 2025-03-28 12:02:24 +00:00
Andre601 5dd26f6ab8 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.3' (#426) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/426
2025-03-27 12:05:14 +00:00
Andre601's Bot ba82df45ef Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.3 2025-03-27 12:03:35 +00:00
Andre601 d76339188d Merge pull request 'Update all non-major dependencies' (#425) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/425
2025-03-26 12:21:12 +00:00
Andre601's Bot a9fb8f3ed6 Update all non-major dependencies 2025-03-26 12:02:54 +00:00
Andre601 18291a6865 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.8' (#424) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/424
2025-03-23 13:12:05 +00:00
Andre601's Bot 83a1808ebc Update dependency net.william278:papiproxybridge to v1.8 2025-03-23 12:02:03 +00:00
Andre601 197967dea9 Use jspecify for (Non)Null annotations 2025-03-20 13:51:05 +01:00
Andre601 b25b65faba Merge pull request 'Update dependency com.google.guava:guava to v33.4.5-jre' (#423) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/423
2025-03-20 12:27:21 +00:00
Andre601's Bot fafcd3ae18 Update dependency com.google.guava:guava to v33.4.5-jre 2025-03-20 12:21:06 +00:00
Andre601 daae88074f Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.18' (#422) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/422
2025-03-19 12:02:45 +00:00
Andre601's Bot fbe019214d Update dependency ch.qos.logback:logback-classic to v1.5.18 2025-03-19 12:01:59 +00:00
Andre601 3e380342a7 Merge pull request 'Update dependency mkdocs-material to v9.6.9' (#421) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/421
2025-03-17 12:42:58 +00:00
Andre601's Bot fd2dbd2edb Update dependency mkdocs-material to v9.6.9 2025-03-17 12:02:33 +00:00
Andre601 e969208ae9 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.1' (#420) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/420
2025-03-16 12:20:14 +00:00
Andre601's Bot 77aa404e06 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.1 2025-03-16 12:10:40 +00:00
Andre601 a6c1840858 Merge pull request 'Update dependency mkdocs-material to v9.6.8' (#419) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/419
2025-03-13 12:35:37 +00:00
Andre601's Bot 762bd1d0fd Update dependency mkdocs-material to v9.6.8 2025-03-13 12:02:56 +00:00
Andre601 02ce580433 Merge pull request 'Update dependency com.github.LeonMangler:PremiumVanishAPI to v2.9.18-2' (#418) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/418
2025-03-09 12:19:41 +00:00
Andre601's Bot c7b7feb476 Update dependency com.github.LeonMangler:PremiumVanishAPI to v2.9.18-2 2025-03-09 12:06:02 +00:00
Andre601 0e145def83 Merge pull request 'Update dependency mkdocs-material to v9.6.7' (#417) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/417
2025-03-03 12:14:54 +00:00
Andre601's Bot 03e32feb1d Update dependency mkdocs-material to v9.6.7 2025-03-03 12:04:14 +00:00
Andre601 dbab282901 Merge pull request 'Update dependency mkdocs-material to v9.6.6' (#416) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/416
2025-03-01 12:10:43 +00:00
Andre601's Bot bd6b599267 Update dependency mkdocs-material to v9.6.6 2025-03-01 12:02:02 +00:00
Andre601 1a63430c1e Merge pull request 'Update all non-major dependencies' (#415) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/415
2025-02-26 12:14:58 +00:00
Andre601's Bot 661f9e6ad4 Update all non-major dependencies 2025-02-26 12:03:25 +00:00
Andre601 6bd8d40ff4 Remove temporary SVG Icon 2025-02-24 03:40:32 +01:00
Andre601 16b74433ff Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.0' (#414) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/414
2025-02-22 12:17:18 +00:00
Andre601's Bot 1aaafe474f Update dependency org.junit.jupiter:junit-jupiter-engine to v5.12.0 2025-02-22 12:03:51 +00:00
Andre601 26a7697b0f Merge pull request 'Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0' (#413) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/413
2025-02-21 12:05:52 +00:00
Andre601's Bot ec6b653988 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 2025-02-21 12:04:18 +00:00
Andre601 854eb67c54 Further API Doc updates 2025-02-20 14:56:29 +01:00
Andre601 00511f6e97 Update API doc page 2025-02-20 14:42:00 +01:00
Andre601 16eebb23a5 Update docs 2025-02-20 14:38:04 +01:00
Andre601 faae641c32 Merge pull request 'Update dependency mkdocs-material to v9.6.5' (#412) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/412
2025-02-20 12:57:14 +00:00
Andre601's Bot 4fa542a242 Update dependency mkdocs-material to v9.6.5 2025-02-20 12:02:25 +00:00
Andre601 2dc1f7ccc1 Update icon used for velocity + other stuff 2025-02-19 00:58:20 +01:00
Andre601 dd7b1a7392 Improve Expressions page 2025-02-17 20:21:20 +01:00
Andre601 a90d241cd2 Merge pull request 'Update all non-major dependencies to v4.19.0' (#411) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/411
2025-02-17 12:06:41 +00:00
Andre601's Bot 452ac00ee7 Update all non-major dependencies to v4.19.0 2025-02-17 12:03:06 +00:00
Andre601 f139270f0e Use inlinehilite 2025-02-16 21:50:38 +01:00
Andre601 b212b2af0f Add MiniMessage Pygments lexer to requirements.txt 2025-02-16 21:23:35 +01:00
Andre601 0d506379cf Add MiniMessage Pygment lexer 2025-02-16 21:22:21 +01:00
Andre601 995793e66d Update api-version and add safety-check to PaperCore 2025-02-16 21:20:54 +01:00
Andre601 f9ebc60d64 Add new SayanVanish placeholders 2025-02-13 19:18:39 +00:00
Andre601 1d531a32e3 Merge pull request 'Update all non-major dependencies to v1.6.5' (#410) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/410
2025-02-13 19:10:12 +00:00
Andre601's Bot 36340d9b9d Update all non-major dependencies to v1.6.5 2025-02-13 19:03:39 +00:00
Andre601 d023e22934 Merge pull request 'Update dependency mkdocs-material to v9.6.4' (#409) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/409
2025-02-12 13:52:19 +00:00
Andre601's Bot 260a0b4835 Update dependency mkdocs-material to v9.6.4 2025-02-12 12:02:41 +00:00
Andre601 3f18aaaf5b renovate.json aktualisiert 2025-02-11 19:56:22 +00:00
Andre601 3f0e7897d4 No longer use allorigins.win
Codeberg apparently no longer causes CORS issues for JS fetched requests.
2025-02-10 12:11:23 +00:00
Andre601 4bd35c810b Add subcommand permissions for profiles commands. 2025-02-09 02:58:52 +01:00
Andre601 b081be8f53 Improve Command docs 2025-02-09 02:40:58 +01:00
Andre601 eb474d061b Merge pull request 'Update dependency mkdocs-material to v9.6.3' (#407) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/407
2025-02-07 12:42:35 +00:00
Andre601 edbc893c65 Ignore 2.0.0-SNAPSHOT for cloud 2025-02-07 12:36:37 +00:00
Andre601's Bot d03dce9b29 Update all non-major dependencies 2025-02-07 12:02:26 +00:00
Andre601 de7d011216 Fix cloud-paper not being compiled into project 2025-02-06 13:45:21 +01:00
Andre601 4a2cb2078d Compile the bungee cloud dependency and make enum public. 2025-02-05 21:28:56 +01:00
Andre601 05381bd538 Rename CommandHandler to CommandManagerInterface 2025-02-04 23:17:05 +01:00
Andre601 51e561f2ba Use records instead of classes for Player implementations 2025-02-04 23:11:30 +01:00
Andre601 71a3bddc62 Remove no longer existing overrides and update docs 2025-02-04 22:16:09 +01:00
Andre601 3eeffd5520 Merge pull request 'Use Cloud for Command handling' (#400) from feature/cloud-command-system into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/400
2025-02-04 20:40:40 +00:00
Andre601 3590e4fa12 Merge pull request 'Update dependency mkdocs-material to v9.6.2' (#405) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/405
2025-02-04 12:54:04 +00:00
Andre601's Bot e1e7907d0f Update dependency mkdocs-material to v9.6.2 2025-02-04 12:02:22 +00:00
Andre601 1e8f71092c Update ExpressionParser 2025-02-04 02:33:47 +01:00
Andre601 1c12180fe3 Merge branch 'master' into feature/cloud-command-system 2025-02-03 17:54:42 +01:00
Andre601 7a41e27788 Merge pull request 'Use MkDocs macros plugin for API reference generation' (#398) from feature/docs/better-autogen-apidocs into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/398
2025-02-03 16:48:20 +00:00
Andre601 ddfc8763c4 Bump Sayanvanish to 1.6.4 and add it as addon to wiki 2025-02-03 14:28:38 +01:00
Andre601 086905ad53 Upate dependencies and saynvanish Repo URL 2025-02-03 14:09:49 +01:00
Andre601 4526e91e0f Add SayanVanish as third-party addon to the docs 2025-02-03 01:19:06 +01:00
Andre601 cfb74b277e Revert updating SayanVanishAPI to 1.6.3 to fix it being fully broken... 2025-02-02 14:40:43 +01:00
Andre601 d7c3a7d756 Merge pull request 'Update all non-major dependencies' (#403) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/403
2025-02-02 12:46:28 +00:00
Andre601's Bot 36c6af0a43 Update all non-major dependencies 2025-02-02 12:03:48 +00:00
Andre601 f9df11c9f8 Add Build ID on Jenkins Builds. 2025-02-01 23:09:38 +01:00
Andre601 8f42b63733 Merge pull request 'Update all non-major dependencies' (#402) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/402
2025-01-31 12:06:35 +00:00
Andre601's Bot 10604f4064 Update all non-major dependencies 2025-01-31 12:03:20 +00:00
Andre601 7a574513af Merge pull request 'Update dependency com.google.code.gson:gson to v2.12.0' (#401) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/401
2025-01-30 12:10:52 +00:00
Andre601's Bot deeea1578d Update dependency com.google.code.gson:gson to v2.12.0 2025-01-30 12:02:28 +00:00
Andre601 ac379b1668 Refactor some stuff 2025-01-30 02:12:04 +01:00
Andre601 c636764f4b Update default config in getting-started.md 2025-01-28 16:13:33 +00:00
Andre601 a823aebafd Exclude kyori in minecraft-extras dependency 2025-01-27 22:37:47 +01:00
Andre601 dd4c3c0eb3 Improve shading of dependencies 2025-01-27 22:32:37 +01:00
Andre601 23afe54e29 No need to use sublist (Is truncated in API) 2025-01-26 02:05:02 +01:00
Andre601 fab3731cf4 Update value change hover 2025-01-26 01:57:01 +01:00
Andre601 49a782d560 Fix broken inherits list for docs 2025-01-25 15:35:00 +00:00
Andre601 cdac325e71 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-25 15:24:16 +00:00
Andre601 88f4278f3f Implement different value types per option 2025-01-25 15:14:06 +01:00
Andre601 de4617e450 Display old and new value on setting 2025-01-24 23:52:41 +01:00
Andre601 4c4573b1e0 Add class to create Options list + /asl profiles set command 2025-01-23 23:39:11 +01:00
Andre601 f74f3ef766 Small restructure 2025-01-22 13:38:51 +01:00
Andre601 806a920d32 Update commands.md 2025-01-22 13:34:38 +01:00
Andre601 c9db8cbc97 Improve info structure a bit 2025-01-22 13:25:06 +01:00
Andre601 3e3cd112ec Change PlayerOnly to CommandType and use enum values 2025-01-22 03:05:53 +01:00
Andre601 fcc7d7c6b6 A loooooooot of work...
Yes, this was absolute pain to make, thanks for asking.
2025-01-22 02:51:15 +01:00
Andre601 cb31fc6f5a Use markdown for entries 2025-01-20 22:11:49 +01:00
Andre601 b26a614f87 Fix issues with Annotationa + add /asl profiles info {profile} 2025-01-20 17:21:35 +01:00
Andre601 eb6f4180bf Implement BungeeCord and Paper Command Handler 2025-01-19 21:13:02 +01:00
Andre601 02d6b1958b Add command alias + remove requiredSender declaration 2025-01-19 19:36:18 +01:00
Andre601 bf3c979819 Use Annotations for commands 2025-01-19 16:49:05 +01:00
Andre601 b5af4b9c47 Use Cloud for Command handling 2025-01-18 23:12:10 +01:00
Andre601 6b9cff2945 Merge pull request 'Update dependency mkdocs-material to v9.5.50' (#399) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/399
2025-01-18 12:16:39 +00:00
Andre601's Bot d17549ee68 Update dependency mkdocs-material to v9.5.50 2025-01-18 12:01:47 +00:00
Andre601 8b73eb3c8c Change PAPI Placeholder behaviour + new placeholders 2025-01-16 02:27:31 +01:00
Andre601 1ee9ae473d Remove api-doc.html 2025-01-13 23:40:04 +01:00
Andre601 37006063cf Add macros plugin to requirements.txt 2025-01-13 23:37:53 +01:00
Andre601 76d97de029 Update API reference pages 2025-01-13 23:36:27 +01:00
Andre601 cd8f6f4c22 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-13 22:32:13 +01:00
Andre601 ce14274e4c Remove PlaceholderAPI page link 2025-01-12 15:34:31 +01:00
Andre601 a5d777f4f1 Restructure Wiki 2025-01-12 15:32:09 +01:00
Andre601 f94e578694 Update formatting.md 2025-01-10 15:28:57 +01:00
Andre601 4ff55ddf28 First work on some templates 2025-01-08 02:13:35 +01:00
Andre601 7c441e6ab5 Update SECURITY.md 2025-01-07 13:36:47 +00:00
Andre601 2779f565a9 Add config option to ignore maintenance for hidePlayersHover 2025-01-06 17:41:37 +01:00
Andre601 6d3cd0c505 Update getting started 2025-01-06 16:33:16 +00:00
Andre601 cf95f11fdb Remove automerge (Useless under current setup) 2025-01-06 15:07:26 +00:00
Andre601 679dbb8c0b Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.16' (#397) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/397
2025-01-06 15:06:29 +00:00
Andre601's Bot f44e2759b9 Update dependency ch.qos.logback:logback-classic to v1.5.16 2025-01-06 12:01:41 +00:00
Andre601 29239cc4ed Add HidePlayersHover to docs 2025-01-05 22:24:16 +01:00
Andre601 bcd5e77166 Try new Bungeecord version to fix CI 2025-01-05 22:02:30 +01:00
Andre601 5d2fa03601 Upload hover examples 2025-01-05 20:39:54 +00:00
Andre601 8f1a5e5a37 Add option to hide online players list. 2025-01-05 20:19:57 +01:00
Andre601 05fde902a4 Merge pull request 'Update dependency space.arim.libertybans:bans-api to v1.1.0-SNAPSHOT' (#395) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/395
2025-01-04 12:18:43 +00:00
Andre601's Bot d69e70c485 Update dependency space.arim.libertybans:bans-api to v1.1.0-SNAPSHOT 2025-01-04 12:16:35 +00:00
Andre601 fba1e84171 Disable dependency Dashboard 2025-01-04 12:15:36 +00:00
Andre601 530f0fd954 Update renovate.json with some automerge and grouping stuff. 2025-01-03 16:06:13 +00:00
Andre601 8bec42bb91 Fix wrong Paper repo URL for renovate 2025-01-03 02:38:41 +00:00
Andre601 94982ff1e8 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.2.1' (#394) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/394
2025-01-02 13:29:51 +00:00
Andre601's Bot 1f9795ed97 Update dependency com.viaversion:viaversion-api to v5.2.1 2025-01-02 12:01:33 +00:00
Andre601 c6f95cb78a Update formatting.md 2024-12-30 13:48:48 +01:00
Andre601 571f9f6b38 Add support for SayanVanish 2024-12-29 01:24:55 +01:00
Andre601 17d0802e41 Add MkDocs Macros Plugin 2024-12-28 16:14:10 +01:00
Andre601 6d7fbb8c25 Merge pull request 'Update API reference' (#393) from feature/update-api-reference into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/393
2024-12-25 00:58:11 +00:00
Andre601 d3d83e5e11 Update ProfileEntry index page 2024-12-25 00:46:43 +00:00
Andre601 82fb9c90f4 Update API reference 2024-12-25 00:39:03 +00:00
Andre601 6841a5a6e0 Undo componentlogger changes on velocity 2024-12-24 22:27:26 +01:00
Andre601 6f41cd4e3a Use a fallback logger for velocity versions without ComponentLoggers 2024-12-24 22:05:56 +01:00
Andre601 379f36832e Use snippet links 2024-12-24 21:45:01 +01:00
Andre601 5d8a39cd22 Update config example in getting-started 2024-12-24 21:43:39 +01:00
Andre601 9dba820840 Reduce flood of messages on Startup + make ASL banner hidable.
(I really don't get why people get upset about a few lines of text... Won't make the Log file like 10GB bigger or smth...)
2024-12-24 21:41:39 +01:00
Andre601 58712ca5c5 Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0' (#392) from renovate/dependency.adventure-text-serializer-legacy into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/392
2024-12-24 12:04:13 +00:00
Andre601's Bot e19e942799 Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0 2024-12-24 12:01:21 +00:00
Andre601 03434130c4 Update dependency net.kyori:adventure-text-minimessage to v4.18.0 2024-12-23 13:20:48 +01:00
Andre601 99df25551a Merge pull request 'Update dependency net.kyori:adventure-api to v4.18.0' (#390) from renovate/dependency.adventure-api into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/390
2024-12-23 12:14:32 +00:00
Andre601's Bot 4f31e4ce6f Update dependency net.kyori:adventure-api to v4.18.0 2024-12-23 12:01:35 +00:00
Andre601 ba097c538d Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.15' (#389) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/389
2024-12-22 13:03:31 +00:00
Andre601's Bot aa52435591 Update dependency ch.qos.logback:logback-classic to v1.5.15 2024-12-22 12:01:59 +00:00
Andre601 f44194d24f Update docs 2024-12-21 02:21:33 +01:00
Andre601 0e2d760ea6 Upload center_text_example.jpg 2024-12-20 13:31:42 +00:00
Andre601 c1e7e6b3ff Merge pull request 'Add support for centering MOTD lines' (#388) from feature/motd-center-feature into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/388
2024-12-20 13:24:41 +00:00
Andre601 96d383a5a1 Merge branch 'master' into feature/motd-center-feature 2024-12-20 13:24:11 +00:00
Andre601 79ba7877bf Bump version and add docs 2024-12-20 13:46:53 +01:00
Andre601 86b9aaa7c6 Add support for centering MOTD lines 2024-12-20 13:40:11 +01:00
Andre601 0cb3c036af Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.14' (#387) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/387
2024-12-20 12:11:41 +00:00
Andre601's Bot b1f7b75e2d Update dependency ch.qos.logback:logback-classic to v1.5.14 2024-12-20 12:01:15 +00:00
Andre601 e9bc72c165 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.13' (#386) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/386
2024-12-19 12:02:24 +00:00
Andre601's Bot 93203249fe Update dependency ch.qos.logback:logback-classic to v1.5.13 2024-12-19 12:01:11 +00:00
Andre601 db06de243f Add bluesky Post step to publish_assets.yml 2024-12-17 16:27:40 +00:00
Andre601 2523ccb425 Merge pull request 'Update dependency com.google.guava:guava to v33.4.0-jre' (#384) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/384
2024-12-17 12:04:55 +00:00
Andre601 94972dad31 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4' (#383) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/383
2024-12-17 12:04:39 +00:00
Andre601's Bot f8ac310259 Update dependency com.google.guava:guava to v33.4.0-jre 2024-12-17 12:01:48 +00:00
Andre601's Bot 5d8f5d81ed Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4 2024-12-17 12:01:40 +00:00
Andre601 3111d7933d Merge pull request 'Move Migration pages to sub-pages' (#382) from docs/move-migration-pages into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/382
2024-12-16 21:42:31 +00:00
Andre601 55f7e17d34 Fix typo. 2024-12-16 21:42:14 +00:00
Andre601 0e88a50deb Move Migration pages to sub-pages 2024-12-16 22:38:55 +01:00
Andre601 83f351de6d Try github.run_number variable 2024-12-16 19:42:19 +00:00
Andre601 b96d1cb1a9 Merge pull request 'Update dependency mkdocs-material to v9.5.49' (#381) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/381
2024-12-16 12:04:47 +00:00
Andre601's Bot 517ff1df82 Update dependency mkdocs-material to v9.5.49 2024-12-16 12:01:18 +00:00
Andre601 e8c7c4ee18 Merge pull request 'Update Wiki Announcement' (#380) from feature/wiki-update-announcement into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/380
2024-12-13 14:15:21 +00:00
Andre601 da44eac70e Fix typos 2024-12-13 14:05:41 +00:00
Andre601 e85c121ee4 Add missing .svg 2024-12-13 13:58:10 +00:00
Andre601 0c175999fc Update announcement 2024-12-13 13:57:32 +00:00
Andre601 9c3f237f6d Use ruby for hocon highlighting 2024-12-11 20:42:52 +01:00
Andre601 777545c94f Possible fix for IndexOutOfBoundsException in condition parsing. 2024-12-10 23:22:41 +01:00
Andre601 dd197609e1 Set secrets via ENV (secrets is deprecated) 2024-12-10 13:29:13 +00:00
Andre601 14ee306463 Bump version 2024-12-10 14:09:34 +01:00
Andre601 a635aa8c91 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7.2' (#379) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/379
2024-12-09 12:05:22 +00:00
Andre601 050ac3262a Merge pull request 'Update dependency mkdocs-material to v9.5.48' (#378) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/378
2024-12-09 12:05:12 +00:00
Andre601's Bot 89aa309c90 Update dependency net.william278:papiproxybridge to v1.7.2 2024-12-09 12:02:16 +00:00
Andre601's Bot e9b004c3f2 Update dependency mkdocs-material to v9.5.48 2024-12-09 12:02:05 +00:00
Andre601 3ecca64a3d Allow random to be converted in MiniMOTDConfigMigrator 2024-12-09 03:04:22 +01:00
Andre601 96dcea4e5b Fix admonition box 2024-12-08 13:54:35 +00:00
Andre601 400f4709f5 Add missing ! 2024-12-08 13:52:30 +00:00
Andre601 5d4307128b Use thumbnail + link for better privacy 2024-12-08 13:51:44 +00:00
Andre601 65c96690f6 Use youtube-nocookie domain for iframes 2024-12-08 13:44:04 +00:00
Andre601 483d582cd1 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.2.0' (#377) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/377
2024-12-07 12:02:00 +00:00
Andre601's Bot 6f14e17ae7 Update dependency com.viaversion:viaversion-api to v5.2.0 2024-12-07 12:01:26 +00:00
Andre601 ff32cc1005 Use annotation and (hopefully) improve JS code) 2024-12-07 02:03:29 +01:00
Andre601 bcc18d7738 [Wiki] Add tutorials page 2024-12-05 23:51:20 +01:00
Andre601 629079b438 Remove container image (Is now default) 2024-12-05 01:40:04 +00:00
Andre601 bce03b68a8 Remove container image (Is now default) 2024-12-05 01:39:50 +00:00
Andre601 841c32de0d Update docs and smaller corrections 2024-12-04 23:10:50 +01:00
Andre601 f321ef0162 [Wiki] Add info about favicon creation. 2024-12-04 16:42:51 +00:00
Andre601 eca32d1858 Add video of KasaiSora 2024-12-04 16:26:40 +00:00
Andre601 f2c1f6e491 Update favicons description 2024-12-04 16:19:57 +00:00
Andre601 af31aac07e Merge pull request 'Add support for 'random' in Favicon option' (#376) from feature/add-random-favicon-option into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/376
2024-12-01 19:37:49 +00:00
Andre601 f8db3e7706 Add support for 'random' in Favicon option 2024-12-01 17:31:38 +01:00
Andre601 3d3ea2913c Merge pull request 'Create deploy_wiki.yml' (#375) from feature/deploy-wiki-action into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/375
2024-12-01 15:31:07 +00:00
Andre601 7b7042a856 Merge branch 'master' into feature/deploy-wiki-action 2024-12-01 15:30:06 +00:00
Andre601 c66c4f21f3 Ignore tags (releases) 2024-12-01 15:29:01 +00:00
Andre601 890a3f7b46 Create deploy_wiki.yml 2024-12-01 15:24:54 +00:00
Andre601 73b969bc51 Rename preview-domains to preview_domains 2024-12-01 15:22:52 +00:00
Andre601 55c93d8d59 disable publish_docs for woodpecker 2024-12-01 15:14:33 +00:00
Andre601 e1ed8c1cb2 Disable pr_preview for woodpecker 2024-12-01 15:13:50 +00:00
Andre601 e2a91a461a Create pr_preview.yml 2024-12-01 15:12:34 +00:00
Andre601 8a454004a4 Merge pull request 'Update dependency mkdocs-material to v9.5.47' (#374) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/374
2024-12-01 12:05:13 +00:00
Andre601's Bot 8df862530d Update dependency mkdocs-material to v9.5.47 2024-12-01 12:01:41 +00:00
Andre601 4a1c93fb1b Delete build_wiki.yml 2024-11-29 23:11:30 +00:00
Andre601 e795cf31eb Add Git credentials setup 2024-11-29 13:41:05 +00:00
Andre601 e8d93d064f try ubuntu:act-latest from ghcr.io 2024-11-29 13:35:36 +00:00
Andre601 6a2a90b868 Try node:23-alpine.19 2024-11-29 12:53:43 +00:00
Andre601 9cea1d3841 Try ubuntu 20.04? 2024-11-29 12:48:38 +00:00
Andre601 7453b43d6b Try node:22-bookworm 2024-11-28 23:38:13 +00:00
Andre601 7e30f937bd Try using alpine container image 2024-11-28 23:35:56 +00:00
Andre601 176a8ac42e Use a specific python version 2024-11-28 19:36:17 +00:00
Andre601 f480ff51e1 Try out Forgejo Actions 2024-11-28 19:31:12 +00:00
Andre601 e72b772cb9 Add proper highlighting for mitmotd config 2024-11-28 17:04:11 +01:00
Andre601 c91faa899e Add note about availability of BanPlugins Download 2024-11-27 16:34:14 +00:00
Andre601 e5c6d77e3d Merge pull request 'Update dependency mkdocs-material to v9.5.46' (#372) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/372
2024-11-25 12:14:04 +00:00
Andre601's Bot e8ad2c8266 Update dependency mkdocs-material to v9.5.46 2024-11-25 12:03:01 +00:00
Andre601 d244f2816a Merge pull request 'Update dependency mkdocs-material to v9.5.45' (#371) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/371
2024-11-20 12:06:25 +00:00
Andre601's Bot 73f3172504 Update dependency mkdocs-material to v9.5.45 2024-11-20 12:03:20 +00:00
Andre601 d7c9f73898 Fix typo for code block 2024-11-12 01:33:31 +00:00
Andre601 2b6818180f Merge pull request 'Update dependency mkdocs-material to v9.5.44' (#369) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/369
2024-11-06 12:26:39 +00:00
Andre601's Bot c7c14799e3 Update dependency mkdocs-material to v9.5.44 2024-11-06 12:01:46 +00:00
Andre601 59774347f6 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7.1' (#367) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/367
2024-11-02 12:08:14 +00:00
Andre601 e45f9a1e73 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.1.1' (#368) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/368
2024-11-02 12:07:40 +00:00
Andre601's Bot a44235dc10 Update dependency com.viaversion:viaversion-api to v5.1.1 2024-11-02 12:01:22 +00:00
Andre601's Bot 52569a3588 Update dependency net.william278:papiproxybridge to v1.7.1 2024-11-01 12:01:45 +00:00
Andre601 602a8e27ea Merge pull request 'Update dependency mkdocs-material to v9.5.43' (#366) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/366
2024-10-31 12:14:58 +00:00
Andre601's Bot 81a23953e5 Update dependency mkdocs-material to v9.5.43 2024-10-31 12:01:41 +00:00
Andre601 9daf8f3a3e Delete CHANGELOG.md file 2024-10-30 21:09:21 +00:00
Andre601 3d5b4501e3 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1' (#365) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/365
2024-10-29 12:09:50 +00:00
Andre601's Bot 67047e9877 Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4.1 2024-10-29 12:01:14 +00:00
Andre601 7fcb0e78e3 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.12' (#363) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/363
2024-10-26 12:02:53 +00:00
Andre601 8b8018245e Merge branch 'master' into renovate/ch.qos.logback-logback-classic-1.x 2024-10-26 12:02:40 +00:00
Andre601 b34143d4f5 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.1.0' (#364) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/364
2024-10-26 12:02:25 +00:00
Andre601's Bot a33c096cf4 Update dependency com.viaversion:viaversion-api to v5.1.0 2024-10-26 12:01:27 +00:00
Andre601's Bot 0957edbcd8 Update dependency ch.qos.logback:logback-classic to v1.5.12 2024-10-26 12:01:21 +00:00
Andre601 70adf4e216 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.3' (#361) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/361
2024-10-24 12:10:50 +00:00
Andre601 da42e8c137 Merge pull request 'Update dependency net.william278:papiproxybridge to v1.7' (#362) from renovate/net.william278-papiproxybridge-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/362
2024-10-24 12:10:32 +00:00
Andre601's Bot f4eecda209 Update dependency net.william278:papiproxybridge to v1.7 2024-10-24 12:01:26 +00:00
Andre601's Bot b934d1a856 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.3 2024-10-24 12:01:19 +00:00
Andre601 bbec0aa064 Improve AdvancedBanProvider 2024-10-21 16:43:29 +02:00
Andre601 ba1f620eee SECURITY.md aktualisiert 2024-10-20 22:48:03 +00:00
Andre601 f0281adf8a Merge pull request 'Update dependency mkdocs-material to v9.5.42' (#360) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/360
2024-10-20 12:50:09 +00:00
Andre601's Bot c702f61c21 Update dependency mkdocs-material to v9.5.42 2024-10-20 12:02:03 +00:00
Andre601 dec23e0412 Merge pull request 'Update dependency mkdocs-material to v9.5.41' (#359) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/359
2024-10-16 13:03:17 +00:00
Andre601's Bot 782dcb8382 Update dependency mkdocs-material to v9.5.41 2024-10-16 12:01:17 +00:00
Andre601 e401d1f8c1 Merge pull request 'Update dependency com.viaversion:viaversion-api to v5.0.5' (#358) from renovate/com.viaversion-viaversion-api-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/358
2024-10-15 13:07:25 +00:00
Andre601 5e6654b3ef Merge branch 'master' into renovate/com.viaversion-viaversion-api-5.x 2024-10-15 13:06:30 +00:00
Andre601 25a9e8ef63 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.11' (#357) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/357
2024-10-15 13:06:16 +00:00
Andre601's Bot 558e47a7da Update dependency com.viaversion:viaversion-api to v5.0.5 2024-10-15 12:02:05 +00:00
Andre601's Bot 740896c304 Update dependency ch.qos.logback:logback-classic to v1.5.11 2024-10-15 12:01:56 +00:00
Andre601 62d9aa81a3 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.10' (#356) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/356
2024-10-12 12:03:19 +00:00
Andre601's Bot 7220b633cf Update dependency ch.qos.logback:logback-classic to v1.5.10 2024-10-12 12:01:33 +00:00
Andre601 0908ddad5e Remove unused imports and bump version 2024-10-10 17:01:10 +02:00
Andre601 d1549b1441 delete release-config.ts 2024-10-10 14:58:51 +00:00
Andre601 57f618e7e2 Remove the action (Pointless and confusing to use) 2024-10-10 14:58:29 +00:00
Andre601 911c64f7ad Merge pull request '🎉 Release 5.0.5' (#352) from next-release/master into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/352
2024-10-10 14:50:32 +00:00
oauth fdeeb35fa9 🎉 Release 5.0.5 2024-10-10 12:30:10 +00:00
oauth c2c653e613 Merge branch 'origin/master' into 'next-release/master' 2024-10-10 12:30:10 +00:00
Andre601 8fa7c1593d Merge pull request 'Update dependency mkdocs-material to v9.5.40' (#355) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/355
2024-10-10 12:29:26 +00:00
Andre601's Bot b2dc74951f Update dependency mkdocs-material to v9.5.40 2024-10-10 12:01:17 +00:00
oauth 099c45e4c4 🎉 Release 5.0.5 2024-10-09 12:29:42 +00:00
oauth e38f6648ee Merge branch 'origin/master' into 'next-release/master' 2024-10-09 12:29:42 +00:00
Andre601 2d701aa8a8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.9' (#354) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/354
2024-10-09 12:29:05 +00:00
Andre601's Bot 1f32c22ebf Update dependency ch.qos.logback:logback-classic to v1.5.9 2024-10-09 12:01:45 +00:00
oauth 610d86ad1b 🎉 Release 5.0.5 2024-10-09 11:55:51 +00:00
oauth 658ec8dd74 Merge branch 'origin/master' into 'next-release/master' 2024-10-09 11:55:51 +00:00
Andre601 85b7210e7c Push empty commit to trigger release 2024-10-09 13:55:23 +02:00
Andre601 98b99b37de Merge pull request 'Improve PAPIProxyBridge support' (#353) from feature/improve-papi-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/353
2024-10-09 11:49:41 +00:00
Andre601 bc3aaa4d28 Improve PAPIProxyBridge support 2024-10-09 13:31:34 +02:00
oauth a3d0342f28 🎉 Release 5.0.5 2024-10-09 11:20:46 +00:00
Andre601 6e057422b6 Merge pull request 'Add automatic release action' (#351) from feature/automatic-release-creation into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/351
2024-10-09 11:20:26 +00:00
Andre601 7ee65c6c21 Add useVersionPrefixV to release-config.ts 2024-10-09 13:18:42 +02:00
Andre601 b4b754e483 Update MODRINTH.md 2024-10-08 23:53:00 +00:00
Andre601 b7c0c8a312 Update Mastodon Link 2024-10-08 23:51:52 +00:00
Andre601 cf6006f9d6 Merge branch 'master' into feature/automatic-release-creation 2024-10-06 00:07:49 +02:00
Andre601 6bf44f6208 Fix hover not supporting PlaceholderAPI Placeholders 2024-10-06 00:01:06 +02:00
Andre601 428dd3cd06 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.2' (#350) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/350
2024-10-05 12:12:34 +00:00
Andre601's Bot 871e2efbe2 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.2 2024-10-05 12:01:14 +00:00
Andre601 a5b45e2c82 Add SECURITY.md 2024-10-04 22:54:25 +00:00
Andre601 9feb3dfac6 Bump version 2024-10-02 13:43:45 +02:00
Andre601 5961d0dca0 Don't log errors when fetching servers (+ misc changes) 2024-10-02 13:43:05 +02:00
Andre601 ea0f0f09f4 Add automatic release action 2024-10-02 13:27:46 +02:00
Andre601 3d5d4fcab2 Fix wrong name for AdvancedBan in BanPlugins Addon 2024-10-01 19:58:11 +02:00
Andre601 0763a9b3b4 Fix wrong main class for Paper BanPluginsAddon 2024-10-01 02:26:14 +02:00
Andre601 2d67a89fc2 Merge pull request 'Update dependency mkdocs-material to v9.5.39' (#349) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/349
2024-09-29 12:07:56 +00:00
Andre601's Bot 4207d875f9 Update dependency mkdocs-material to v9.5.39 2024-09-29 12:03:17 +00:00
Andre601 5da420c6c6 Merge pull request 'feature/online-players-setting' (#348) from feature/online-players-setting into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/348
2024-09-27 14:27:47 +00:00
Andre601 1ffa4842c3 Update API docs and bump version to major v5 2024-09-26 16:47:28 +02:00
Andre601 819e194f27 Make Server placeholders return empty String instead of null. 2024-09-26 16:11:38 +02:00
Andre601 269e55b93f Merge branch 'master' into feature/online-players-setting 2024-09-26 15:54:50 +02:00
Andre601 04412f7138 Implement feature to set online player count 2024-09-26 15:54:28 +02:00
Andre601 0fce9d01e1 Merge pull request 'Update dependency mkdocs-material to v9.5.38' (#346) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/346
2024-09-26 13:50:41 +00:00
Andre601's Bot 1c29301635 Update dependency mkdocs-material to v9.5.38 2024-09-26 12:02:06 +00:00
Andre601 8bd7bbb5d7 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.1' (#345) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/345
2024-09-25 12:04:33 +00:00
Andre601 1a99663b59 Merge pull request 'Update dependency mkdocs-material to v9.5.37' (#344) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/344
2024-09-25 12:04:14 +00:00
Andre601's Bot 36e31279b2 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.1 2024-09-25 12:01:31 +00:00
Andre601's Bot 4aa7eba675 Update dependency mkdocs-material to v9.5.37 2024-09-25 12:01:21 +00:00
Andre601 3bbe2d26b8 Merge pull request 'Update dependency com.google.guava:guava to v33.3.1-jre' (#342) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/342
2024-09-24 13:11:35 +00:00
Andre601 782ad838be Merge pull request 'Update dependency org.bstats:bstats-velocity to v3.1.0' (#343) from renovate/org.bstats-bstats-velocity-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/343
2024-09-24 13:11:22 +00:00
Andre601's Bot ceddb26137 Update dependency org.bstats:bstats-velocity to v3.1.0 2024-09-24 12:01:32 +00:00
Andre601's Bot ff044d75c7 Update dependency com.google.guava:guava to v33.3.1-jre 2024-09-24 12:01:25 +00:00
Andre601 8955df695d Merge pull request 'Update dependency org.bstats:bstats-bungeecord to v3.1.0' (#341) from renovate/org.bstats-bstats-bungeecord-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/341
2024-09-23 12:57:03 +00:00
Andre601 8ddcb208f5 Merge pull request 'Update dependency org.bstats:bstats-bukkit to v3.1.0' (#340) from renovate/org.bstats-bstats-bukkit-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/340
2024-09-23 12:56:27 +00:00
Andre601's Bot 95834df89f Update dependency org.bstats:bstats-bungeecord to v3.1.0 2024-09-23 12:01:58 +00:00
Andre601's Bot 2f67f26cbe Update dependency org.bstats:bstats-bukkit to v3.1.0 2024-09-23 12:01:52 +00:00
Andre601 00957f9458 Merge pull request 'Create ${proxy status ...} placeholder.' (#334) from feature/proxy-status-placeholder into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/334
2024-09-22 13:12:42 +00:00
Andre601 2e9e886c48 Merge pull request 'Update dependency mkdocs-material to v9.5.36' (#338) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/338
2024-09-21 12:24:01 +00:00
Andre601's Bot d2d4e48b73 Update dependency mkdocs-material to v9.5.36 2024-09-21 12:01:47 +00:00
Andre601 fe16df27f2 Merge pull request 'Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4' (#337) from renovate/org.apache.httpcomponents.client5-httpclient5-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/337
2024-09-20 15:51:44 +00:00
Andre601's Bot cc29f70dff Update dependency org.apache.httpcomponents.client5:httpclient5 to v5.4 2024-09-20 12:02:38 +00:00
Andre601 e136f7cfaf Merge pull request 'Update dependency mkdocs-material to v9.5.35' (#336) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/336
2024-09-18 12:05:57 +00:00
Andre601's Bot fd52f124fb Update dependency mkdocs-material to v9.5.35 2024-09-18 12:01:38 +00:00
Andre601 5a656cee39 Merge pull request 'Update alpine Docker tag to v3.20.3' (#335) from renovate/alpine-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/335
2024-09-17 14:39:09 +00:00
Andre601's Bot 21a89f9b14 Update alpine Docker tag to v3.20.3 2024-09-17 12:01:40 +00:00
Andre601 9ded4d2d57 Add more placeholders 2024-09-09 14:49:07 +02:00
Andre601 fb64d92879 Create Proxy Placeholder 2024-09-09 02:05:50 +02:00
Andre601 1a4bcae4d1 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.8' (#331) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/331
2024-09-07 12:07:57 +00:00
Andre601's Bot 25ee4da4f4 Update dependency ch.qos.logback:logback-classic to v1.5.8 2024-09-07 12:01:12 +00:00
Andre601 35cb39c35e Merge pull request 'Update dependency mkdocs-material to v9.5.34' (#330) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/330
2024-09-01 14:09:33 +00:00
Andre601's Bot 3a5f232f92 Update dependency mkdocs-material to v9.5.34 2024-09-01 12:03:23 +00:00
Andre601 4ed201fba9 Bump version 2024-08-29 20:31:14 +02:00
Andre601 03835f71d9 Fix local favicon saving using non-lowercased names. 2024-08-29 20:30:44 +02:00
Andre601 480e50e71e .woodpecker/publish_assets.yml aktualisiert 2024-08-29 11:51:38 +00:00
Andre601 39110b2898 Merge pull request 'Update dependency mkdocs-material to v9.5.33' (#329) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/329
2024-08-23 13:08:17 +00:00
Andre601's Bot e8db70e319 Update dependency mkdocs-material to v9.5.33 2024-08-23 12:02:52 +00:00
Andre601 eb907988fb Merge pull request 'Update maven Docker tag to v3.9.9' (#328) from renovate/maven-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/328
2024-08-21 12:39:31 +00:00
Andre601's Bot 95935022b8 Update maven Docker tag to v3.9.9 2024-08-21 12:10:41 +00:00
Andre601 1e70cb0651 Merge pull request 'Update dependency org.bstats:bstats-velocity to v3.0.3' (#327) from renovate/org.bstats-bstats-velocity-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/327
2024-08-20 13:55:27 +00:00
Andre601 1594d062e5 Merge pull request 'Update dependency org.bstats:bstats-bungeecord to v3.0.3' (#326) from renovate/org.bstats-bstats-bungeecord-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/326
2024-08-20 13:55:11 +00:00
Andre601's Bot 04b266f558 Update dependency org.bstats:bstats-velocity to v3.0.3 2024-08-20 12:03:13 +00:00
Andre601's Bot 9989fec809 Update dependency org.bstats:bstats-bungeecord to v3.0.3 2024-08-20 12:03:06 +00:00
Andre601 ab8eabc348 Merge pull request 'Update dependency org.bstats:bstats-bukkit to v3.0.3' (#325) from renovate/org.bstats-bstats-bukkit-3.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/325
2024-08-19 13:54:53 +00:00
Andre601 931b8b5c36 Merge pull request 'Update dependency mkdocs-material to v9.5.32' (#324) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/324
2024-08-19 13:53:45 +00:00
Andre601's Bot 64957ba13c Update dependency org.bstats:bstats-bukkit to v3.0.3 2024-08-19 12:04:55 +00:00
Andre601's Bot a03be990ab Update dependency mkdocs-material to v9.5.32 2024-08-19 12:04:46 +00:00
Andre601 44729495f5 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.7' (#322) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/322
2024-08-19 00:59:33 +00:00
Andre601 9e7500f0cd Merge pull request 'Update dependency com.google.guava:guava to v33.3.0-jre' (#323) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/323
2024-08-17 12:06:21 +00:00
Andre601's Bot d10ff8bdbc Update dependency com.google.guava:guava to v33.3.0-jre 2024-08-17 12:04:11 +00:00
Andre601's Bot f91fc36365 Update dependency ch.qos.logback:logback-classic to v1.5.7 2024-08-16 12:02:51 +00:00
Andre601 84ddff07a2 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.0' (#321) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/321
2024-08-14 12:46:12 +00:00
Andre601's Bot 4a89658cf4 Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.0 2024-08-14 12:31:56 +00:00
Andre601 5daef41031 Fix renovate.json 2024-08-14 12:22:44 +00:00
Andre601 07cc1e8160 Update registry URL for Libby 2024-08-13 12:45:02 +00:00
220 changed files with 7296 additions and 5108 deletions

No files matched your search

+37
View File
@@ -0,0 +1,37 @@
name: "Deploy Wiki"
on:
push:
branches:
- master
tags-ignore:
- "**"
paths:
- ".forgejo/workflows/deploy_wiki.yml"
- "docs/**"
- "domains"
- "properdocs.yml"
- "requirements.txt"
jobs:
deployWiki:
runs-on: codeberg-small
steps:
- name: "Checkout Repository"
uses: https://code.forgejo.org/actions/checkout@v7
with:
token: "${{ secrets.BOT_TOKEN }}"
- name: "Setup Python 3.x"
uses: https://code.forgejo.org/actions/setup-python@v7
with:
python-version: 3.x
- name: "Install Dependencies"
run: "pip install -r requirements.txt"
- name: "Build Website"
run: "properdocs build"
- name: "Deploy Website"
uses: https://code.forgejo.org/actions/git-pages@v2
with:
site: https://asl.andre601.ch
token: ${{ secrets.FORGEJO_TOKEN }}
source: site/
+116
View File
@@ -0,0 +1,116 @@
name: Pull Request Preview
on:
pull_request_target:
types:
- opened
- reopened
- synchronize
paths:
- ".forgejo/workflows/pr_preview.yml"
- "docs/**"
- "properdocs.yml"
- "preview_domains"
- "requirements.txt"
workflow_dispatch:
env:
BRANCH_NAME: "${{ github.event.repository.name }}/${{ github.event.pull_request.number }}"
RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_number }}"
jobs:
createPreview:
runs-on: codeberg-small
steps:
#
# Finding and updating comment in Pull request.
# If not found, have one created instead.
#
- name: "Find Comment"
id: find-comment
uses: https://github.com/peter-evans/find-comment@v4
with:
issue-number: "${{ github.event.pull_request.number }}"
comment-author: "Andre_601-Bot"
- name: "Create or update Comment"
id: comment
uses: https://github.com/peter-evans/create-or-update-comment@v5
with:
body: |-
## Pull request Preview
Creating Preview for Pull request. Please wait...
comment-id: "${{ steps.find-comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
#
# Setup source and target repository.
# Build website and push.
#
- name: "Checkout Source Repository"
uses: https://code.forgejo.org/actions/checkout@v7
with:
token: ${{ secrets.BOT_TOKEN }}
fetch-depth: 0
ref: "${{ github.event.pull_request.head.sha }}"
- name: "Checkout Target Repository"
run: |
git clone https://codeberg.org/Andre601/preview site
cd site
git switch ${{ env.BRANCH_NAME }} 2>/dev/null || git switch -c ${{ env.BRANCH_NAME }}
- name: "Setup Python 3.x"
uses: https://code.forgejo.org/actions/setup-python@v7
with:
python-version: 3.x
- name: "Install Dependencies"
run: "pip install -r requirements.txt"
- name: "Build Website"
run: "properdocs build"
- name: "Commit and Push"
run: |
git config --global user.email "andre_601-bot@noreply.codeberg.org"
git config --global user.name "PR Docs Preview Builder"
mv preview_domains site/.domains
cd site
git remote add upstream https://${{ secrets.BOT_TOKEN }}@codeberg.org/Andre601/preview.git
git add --all
git commit -m "Update Preview for ${{ env.BRANCH_NAME }} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" ))"
git push --set-upstream upstream ${{ env.BRANCH_NAME }} -f
#
# Update comment on success or failure.
#
- name: "Comment Success"
uses: https://github.com/peter-evans/create-or-update-comment@v5
with:
body: |-
## Pull request Preview
Pull request Preview created successfully!
| Name | Link |
|---------|----------------------------------------------------------------------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Preview | https://preview.andre601.ch/@${{ github.event.repository.name }}~${{ github.event.pull_request.number }} |
| Logs | ${{ env.RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
- name: "Comment Failure"
if: ${{ failure() }}
uses: https://github.com/peter-evans/create-or-update-comment@v5
with:
body: |-
## Pull request Preview
Pull request Preview failed! Check the logs for details.
| Name | Link |
|---------|-------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Logs | ${{ env.RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
edit-mode: replace
+35 -5
View File
@@ -16,13 +16,14 @@ body:
label: Platform
description: On what platform do you use the plugin?
options:
- BungeeCord
- Other (Please specify)
- Paper
- Purpur
- Spigot
- Folia
- Velocity
- Waterfall
- Other (Please specify)
- Spigot (DISCONTINUED)
- BungeeCord (DISCONTINUED)
- Waterfall (DISCONTINUED)
validations:
required: true
- type: input
@@ -32,6 +33,35 @@ body:
Please provide the name of the platform (Proxy/Server) you use, if you selected `Other (Please specify)` in the above section.
Leave empty otherwise.
placeholder: SomeProxy
- type: input
attributes:
label: Server/Proxy version
description: |-
Provide the Version of your Server/Proxy.
For Paper and its forks, run `/version` and for Velocity run `/velocity info`
placeholder: This server is running Paper version ...
validations:
required: true
- type: input
attributes:
label: Plugin version
description: |-
Provide the Version of the Plugin.
On Paper and its forks, run `/version AdvancedServerList` and on Velocity, run `/velocity plugins` and find the AdvancedServerList entry.
placeholder: 5.9.0
validations:
required: true
- type: input
attributes:
label: Logs
description: |-
Provide Logs from your Server/Proxy, uploaded to [mclo.gs](https://mclo.gs).
**DO NOT SKIP THIS!**
Skipping this by writing "Not needed", "private", etc. will get your issue closed without warning!
placeholder: 'https://mclo.gs/...'
validations:
required: true
- type: textarea
attributes:
label: What happened?
@@ -49,7 +79,7 @@ body:
placeholder: |-
1. Do this
2. ...
3. Profit!
3. Prof-... Bug!
validations:
required: true
- type: textarea
+1 -1
View File
@@ -98,6 +98,6 @@ Spanish Video by Ajneb97
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg&h=48" alt="revolt" title="Join my Revolt Server">
</a>
<br>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<a href="https://swiss.social/@andre_601" target="_blank">
<img src="https://wsrv.nl/?url=https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg&h=48" alt="revolt" title="Chat with me on Mastodon">
</a>
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

-64
View File
@@ -1,64 +0,0 @@
when:
- event: pull_request
path:
include: [".woodpecker/pr_preview.yml", "docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "andre_601-bot@noreply.codeberg.org"
- git config --global user.name "PR Docs Preview Builder"
steps:
- name: "Clone Preview Repository"
image: alpine:3.18.4
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone https://codeberg.org/Andre601/preview.git site
- chmod -R a+w site
- cd site
- git switch ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST} 2>/dev/null || git switch -c ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST}
- name: "Build Docs"
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
- name: "Commit and Push"
image: alpine:3.18.4
secrets:
- bot_token
commands:
- <<: *setup_git
- mv preview-domains site/.domains
- cd site
- git remote add upstream https://$BOT_TOKEN@codeberg.org/Andre601/preview.git
- git add --all
- git commit -m "Update Preview for ${CI_REPO_NAME}/${CI_COMMIT_PULL_REQUEST} ($( env TZ=Europe/Zurich date +"%d.%m.%Y %Z" )) [SKIP CI]"
- git push --set-upstream upstream ${CI_REPO_NAME,,}/${CI_COMMIT_PULL_REQUEST} -f
- name: "Comment on Success"
image: mcs94/gitea-comment
when:
- status: ["success"]
settings:
gitea_address: https://codeberg.org
gitea_token:
from_secret: BOT_TOKEN
comment: |-
Pull request Preview Ready!
| Name | Value |
|--------|--------------------------------------------------------------------------|
| Commit | ${CI_COMMIT_SHA} |
| Link | https://preview.andre601.ch/@${CI_REPO_NAME,,}~${CI_COMMIT_PULL_REQUEST} |
- name: "Comment on Failure"
image: mcs94/gitea-comment
when:
- status: ["failure"]
settings:
gitea_address: https://codeberg.org
gitea_token:
from_secret: BOT_TOKEN
comment: |-
Pull request Preview **failed**!
Please check the CI logs for details: ${CI_PIPELINE_URL}
+27 -10
View File
@@ -4,29 +4,31 @@ when:
steps:
- name: "Build Jar and Upload"
image: maven:3.9.8-eclipse-temurin-21
secrets:
- modrinth_api_token
- hangar_api_token
- discord_webhook_url
image: maven:3.9.16-eclipse-temurin-25
environment:
CODEBERG_API_TOKEN:
from_secret: cb_token
MODRINTH_API_TOKEN:
from_secret: modrinth_api_token
HANGAR_API_TOKEN:
from_secret: hangar_api_token
DISCORD_WEBHOOK_URL:
from_secret: discord_webhook_url
commands:
- mvn clean install
- cd version-uploader/target
- mv VersionUploader.jar ../../
- cd ../../
- java -jar VersionUploader.jar --all
- name: "Upload Jars to Codeber"
- java -jar VersionUploader.jar upload all
- name: "Upload Jars to Codeberg"
image: woodpeckerci/plugin-gitea-release
settings:
base_url: https://codeberg.org
files:
- "bungeecord/target/AdvancedServerList-*.jar"
- "paper/target/AdvancedServerList-*.jar"
- "velocity/target/AdvancedServerList-*.jar"
- "addons/banplugins/target/AdvancedServerList-*.jar"
- "addons/luckperms/target/AdvancedServerList-*.jar"
api_key:
from_secret: cb_token
- name: "Create Post on Mastodon"
@@ -34,7 +36,7 @@ steps:
when:
- status: ["success"]
settings:
server_url: https://blobfox.coffee
server_url: https://swiss.social
access_token:
from_secret: mastodon_token
status: |-
@@ -43,4 +45,19 @@ steps:
Modrinth - https://modrinth.com/plugin/advancedserverlist
Hangar - https://hangar.papermc.io/Andre_601/AdvancedServerList
Codeberg - https://codeberg.org/Andre601/AdvancedServerList
visibility: public
visibility: public
- name: "Create Post on Bluesky"
image: woodpeckerci/plugin-bluesky-post
when:
- status: ["success"]
settings:
identifier: andre601.ch
app_password:
from_secret: bluesky_app_password
languages: english
text: |-
#AdvancedServerList was updated to ${CI_COMMIT_TAG} and can be downloaded from #Modrinth, #Hangar and #Codeberg!
Modrinth - https://modrinth.com/plugin/advancedserverlist
Hangar - https://hangar.papermc.io/Andre_601/AdvancedServerList
Codeberg - https://codeberg.org/Andre601/AdvancedServerList
-36
View File
@@ -1,36 +0,0 @@
when:
- event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
path:
include: [".woodpecker/publish_docs.yml", "docs/**", "mkdocs.yml", "requirements.txt"]
variables:
setup_git: &setup_git
- apk add git
- git config --global user.email "andre_601-bot@noreply.codeberg.org"
- git config --global user.name "ASL Docs Builder"
steps:
- name: "Clone target Repository"
image: alpine:3.18.4
commands:
- chmod -R a+w .
- <<: *setup_git
- git clone -b pages https://codeberg.org/Andre601/asl-docs.git site
- chmod -R a+w site
- name: "Build Docs"
image: woodpeckerci/plugin-mkdocs:latest
settings:
pip_install_file: requirements.txt
- name: "Commit and Push"
image: alpine:3.18.4
secrets:
- bot_token
commands:
- <<: *setup_git
- mv domains site/.domains
- cd site
- 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
+12 -3
View File
@@ -40,7 +40,7 @@ A Server List Profile is a single YAML file located in the plugin's `profiles` f
Each file has a priority and optional condition. The priority is used to determine what file AdvancedServerList should use first - starting from highest number to lowest - with conditions being used to set when the profile should be used.
Once a profile has been found with a condition returning true - which is the default should there be no condition - will AdvancedServerList use said profile.
> *Read more about [Priority](https://asl.andre601.ch/profiles/#priority) and [Conditions](https://asl.andre601.ch/profiles/#condition)*
> *Read more about [Priority](https://asl.andre601.ch/profiles/options/priority) and [Conditions](https://asl.andre601.ch/profiles/options/condition)*
### Placeholders
@@ -63,7 +63,7 @@ AdvancedServerList soft-depends on the following plugins, meaning their inclusio
| Plugin | Supported Platforms |
|-------------------------------------------------------------------------|----------------------------------------|
| [PlaceholderAPI](https://hangar.papermc.io/HelpChat/PlaceholderAPI) | Paper |
| [PlaceholderAPI](https://modrinth.com/plugin/PlaceholderAPI) | Paper |
| [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) | Paper |
| [PAPIProxyBridge](https://hangar.papermc.io/William278/PAPIProxyBridge) | BungeeCord, Waterfall, Velocity |
| [Maintenance](https://hangar.papermc.io/kennytv/Maintenance) | Paper, BungeeCord, Waterfall, Velocity |
@@ -86,9 +86,18 @@ Below can you find a collection of videos made for my plugin. If you made a vide
<details><summary>Click to show/hide Videos</summary>
<p>
English Video by KasaiSora
[![video thumbnail](https://img.youtube.com/vi/9cU0uUWHOO0/0.jpg)](https://youtube.com/watch?v=9cU0uUWHOO0)
Spanish Video by Ajneb97
[![video thumbnail](https://img.youtube.com/vi/rIbljm_4HVI/0.jpg)](https://youtube.com/watch?v=rIbljm_4HVI)
Indonesian Video by faajrikha
[![video thumbnail](https://img.youtube.com/vi/-p938rOmqy4/0.jpg)](https://www.youtube.com/watch?v=-p938rOmqy4)
German Video by Finni Gamer
[![video thumbnail](https://img.youtube.com/vi/1Kh3cPMDd0c/0.jpg)](https://www.youtube.com/watch?v=1Kh3cPMDd0c)
</p>
</details>
@@ -108,6 +117,6 @@ Spanish Video by Ajneb97
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/revolt-singular_vector.svg" height="48" alt="revolt" title="Join my Revolt Server">
</a>
<br>
<a href="https://blobfox.coffee/@andre_601" target="_blank">
<a href="https://swiss.social/@andre_601" target="_blank">
<img src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/mastodon-singular_vector.svg" height="48" alt="revolt" title="Chat with me on Mastodon">
</a>
+60
View File
@@ -0,0 +1,60 @@
# Supported Versions
To ensure proper safety and support are only certain versions and Platforms of AdvancedServerList maintained and supported.
## Supported Plugin Versions
| Major Version | Supported |
|---------------|-----------|
| v5 | Yes |
| v4 | Yes* |
| v3 | No** |
| v2 | No |
| v1 | No |
\*Only receives support but no updates or bug fixes.
\*\*Support ended on December 31st, 2024.
## Supported Server/Proxy Versions
| Server/Proxy Version* | Supported |
|-----------------------|-----------|
| 26.2 | Yes |
| 26.1.x | Yes |
| 1.21.x | Yes |
| 1.20.x | Yes |
| 1.19.x | No |
| 1.18.x | No |
| 1.17.x | No |
| 1.16.x | No |
| 1.15.x | No |
| 1.14.x | No |
| 1.13.x | No |
| 1.12.x | No |
| 1.11.x | No |
| 1.10.x | No |
| 1.19.x | No |
| 1.8.x | No |
\*Only the latest patch version is actively supported should "Supported" have "Yes".
## Supported Platforms
### Servers
| Server | Supported |
|--------|-----------|
| Spigot | No |
| Paper | Yes |
| Purpur | Yes* |
| Mohist | No |
\*Support hasn't actively been tested, but should work without issues.
### Proxies
| Proxy | Supported |
|------------|-----------|
| BungeeCord | No |
| Waterfall | No |
| Velocity | Yes |
+7 -28
View File
@@ -40,8 +40,8 @@
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@@ -62,30 +62,16 @@
<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.21-R0.1-SNAPSHOT</version>
<version>[26.1.2.build,)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.3.0-SNAPSHOT</version>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
@@ -99,13 +85,13 @@
<dependency>
<groupId>space.arim.libertybans</groupId>
<artifactId>bans-api</artifactId>
<version>1.1.0-RC1</version>
<version>1.1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gitlab.ruany</groupId>
<artifactId>LiteBansAPI</artifactId>
<version>0.5.0</version>
<version>0.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -117,19 +103,12 @@
</dependencies>
<build>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}</finalName>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
</project>
@@ -1,68 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.banplugins.bungeecord;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.banplugins.BanPluginsList;
import net.md_5.bungee.api.plugin.Plugin;
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;
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(BanPluginsList entry : BanPluginsList.values()){
if(!entry.supportsBungeeCord())
continue;
if(getProxy().getPluginManager().getPlugin(entry.getName()) != null){
getLogger().info("Registering Placeholders for " + entry.getName() + "...");
api.addPlaceholderProvider(entry.getPlaceholderProvider());
getLogger().info("Placeholders successfully registered!");
loaded++;
}
}
return loaded;
}
}
@@ -31,32 +31,10 @@ import com.google.common.primitives.UnsignedLongs;
import me.leoko.advancedban.manager.PunishmentManager;
import me.leoko.advancedban.utils.Punishment;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class AdvancedBanProvider implements PunishmentProvider{
private static PunishmentManager getAPI(){
return PunishmentManager.get();
}
private static String noDashesUUID(UUID uuid){
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
}
private static Punishment mute(GenericPlayer player){
return getAPI().getMute(noDashesUUID(player.getUUID()));
}
private static Punishment ban(GenericPlayer player){
return getAPI().getBan(noDashesUUID(player.getUUID()));
}
private static String hexString(long unsigned){
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
}
@Override
public String muted(GenericPlayer player){
return String.valueOf(getAPI().isMuted(noDashesUUID(player.getUUID())));
@@ -136,4 +114,24 @@ public class AdvancedBanProvider implements PunishmentProvider{
return ban.getDuration(fromStart);
}
private PunishmentManager getAPI(){
return PunishmentManager.get();
}
private String noDashesUUID(UUID uuid){
return hexString(uuid.getMostSignificantBits()) + hexString(uuid.getLeastSignificantBits());
}
private Punishment mute(GenericPlayer player){
return getAPI().getMute(noDashesUUID(player.getUUID()));
}
private Punishment ban(GenericPlayer player){
return getAPI().getBan(noDashesUUID(player.getUUID()));
}
private String hexString(long unsigned){
return Strings.padStart(UnsignedLongs.toString(unsigned, 16), 16, '0');
}
}
@@ -1,12 +0,0 @@
name: 'ASLBanPluginsAddon'
author: 'Andre_601'
version: '${plugin.version}'
description: 'AdvancedBan Add-on for AdvancedServerList to add placeholders to use.'
softDepends:
- AdvancedServerList
- AdvancedBan
- LibertyBans
- LiteBans
main: 'ch.andre601.advancedserverlist.banplugins.bungeecord.BungeeCordBanPluginsAddon'
@@ -2,7 +2,7 @@ name: 'ASLBanPluginsAddon'
author: 'Andre_601'
version: '${plugin.version}'
main: 'ch.andre601.advancedserverlist.banplugins.paper.AdvancedBanPlaceholders'
main: 'ch.andre601.advancedserverlist.banplugins.paper.PaperBanPluginsAddon'
api-version: '1.19'
@@ -11,7 +11,7 @@ dependencies:
AdvancedServerList:
required: false
load: BEFORE
AdvancedBans:
AdvancedBan:
required: false
load: BEFORE
LibertyBans:
+112
View File
@@ -0,0 +1,112 @@
<?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>luckperms</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</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://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<!-- Proxy/Server -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.21-R0.4</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.21-R0.4</version>
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>[26.1.2.build,)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
<!-- Plugin APIs -->
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>${api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.luckperms</groupId>
<artifactId>api</artifactId>
<version>5.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-LuckPerms-Addon-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
@@ -0,0 +1,44 @@
package ch.andre601.advancedserverlist.luckperms.paper;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.exceptions.InvalidPlaceholderProviderException;
import ch.andre601.advancedserverlist.luckperms.placeholders.LuckPermsPlaceholder;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import org.bukkit.plugin.java.JavaPlugin;
public class LuckPermsAddon extends JavaPlugin{
@Override
public void onEnable(){
if(!this.getServer().getPluginManager().isPluginEnabled("AdvancedServerList")){
this.getSLF4JLogger().warn("AdvancedServerList not enabled. This plugin is required!");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
if(!this.getServer().getPluginManager().isPluginEnabled("LuckPerms")){
this.getSLF4JLogger().warn("LuckPerms not enabled. This plugin is required!");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
LuckPerms luckPerms;
try{
luckPerms = LuckPermsProvider.get();
}catch(IllegalStateException ex){
this.getSLF4JLogger().error("Unable to obtain LuckPerms API instance! Disabling plugin...");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
this.getSLF4JLogger().info("Registering LuckPerms Placeholder...");
try{
AdvancedServerListAPI.get().addPlaceholderProvider(new LuckPermsPlaceholder(luckPerms));
this.getSLF4JLogger().info("Successfully registered Placeholder!");
}catch(InvalidPlaceholderProviderException ex){
this.getSLF4JLogger().warn("Couldn't register Placeholder. Disabling Plugin...");
this.getServer().getPluginManager().disablePlugin(this);
}
}
}
@@ -0,0 +1,66 @@
package ch.andre601.advancedserverlist.luckperms.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.model.user.User;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import java.util.HashMap;
import java.util.UUID;
public class LuckPermsPlaceholder extends PlaceholderProvider{
private final LuckPerms luckPerms;
private final HashMap<UUID, CacheValue> cache = new HashMap<>();
public LuckPermsPlaceholder(LuckPerms luckPerms){
super("luckperms");
this.luckPerms = luckPerms;
}
@Override
public @Nullable String parsePlaceholder(@NonNull String placholder, @NonNull GenericPlayer player, @NonNull GenericServer server){
if(luckPerms == null)
return "ERR: LuckPerms not available.";
CacheValue cacheValue = cache.get(player.getUUID());
User user;
if(cacheValue == null || cacheValue.expired()){
// Can cause lag if on main thread.
// But the alternative would be a lot more annoying and error-prone.
user = luckPerms.getUserManager().loadUser(player.getUUID()).join();
cache.put(player.getUUID(), new CacheValue(System.currentTimeMillis(), user));
}else{
user = cacheValue.user();
}
if(user == null)
return "ERR: Player not found.";
String[] parts = placholder.split("\\s+");
if(parts.length == 1)
return "ERR: Missing argument for placeholder " + parts[0] + ".";
return switch(parts[0]){
case "hasGroup" -> String.valueOf(
user.getCachedData().getPermissionData().checkPermission("group." + parts[1])
);
case "hasPermission" -> String.valueOf(
user.getCachedData().getPermissionData().checkPermission(parts[1]).asBoolean()
);
case "primaryGroup" -> user.getPrimaryGroup();
default -> null;
};
}
private record CacheValue(long timestamp, User user){
public boolean expired(){
// Expired if current timestamp minus old one is more than 60k milliseconds (1 minute)
return (timestamp < 0L) || System.currentTimeMillis() - timestamp >= 60_000;
}
}
}
@@ -0,0 +1,53 @@
package ch.andre601.advancedserverlist.luckperms.velocity;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.exceptions.InvalidPlaceholderProviderException;
import ch.andre601.advancedserverlist.luckperms.placeholders.LuckPermsPlaceholder;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.proxy.ProxyServer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LuckPermsAddon{
private final ProxyServer proxy;
private final Logger logger = LoggerFactory.getLogger("ASLLuckPermsAddon");
@Inject
public LuckPermsAddon(ProxyServer proxy){
this.proxy = proxy;
}
@Subscribe
public void init(ProxyInitializeEvent event){
if(!proxy.getPluginManager().isLoaded("advancedserverlist")){
logger.warn("AdvancedServerList is not enabled. This plugin is required.");
return;
}
if(!proxy.getPluginManager().isLoaded("luckperms")){
logger.warn("LuckPerms is not enabled. This plugin is required.");
return;
}
LuckPerms luckPerms;
try{
luckPerms = LuckPermsProvider.get();
}catch(IllegalStateException ex){
logger.warn("Unable to obtain LuckPerms API instance. The plugin won't work.");
return;
}
logger.info("Registering LuckPerms Placeholder...");
try{
AdvancedServerListAPI.get().addPlaceholderProvider(new LuckPermsPlaceholder(luckPerms));
logger.info("Successfully registered Placeholder!");
}catch(InvalidPlaceholderProviderException ex){
logger.warn("Unable to register LuckPerms Placeholder! The plugin won't work.");
}
}
}
@@ -0,0 +1,16 @@
name: 'ASLLuckPermsAddon'
author: 'Andre_601'
version: '${plugin.version}'
main: 'ch.andre601.advancedserverlist.luckperms.paper.LuckPermsAddon'
api-version: '1.19'
dependencies:
server:
AdvancedServerList:
required: false
load: BEFORE
LuckPerms:
required: false
load: BEFORE
@@ -0,0 +1,20 @@
{
"id": "aslluckpermsaddon",
"name": "ASLLuckPermsAddon",
"version": "${plugin.version}",
"description": "LuckPerms Add-on for AdvancedServerList to add placeholders to use.",
"authors": [
"Andre_601"
],
"dependencies": [
{
"id": "advancedserverlist",
"optional": true
},
{
"id": "luckperms",
"optional": true
}
],
"main": "ch.andre601.advancedserverlist.luckperms.velocity.LuckPermsAddon"
}
-190
View File
@@ -1,190 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ MIT License
~
~ Copyright (c) 2022-2023 Andre_601
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in all
~ copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
~ SOFTWARE.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>ch.andre601.advancedserverlist</groupId>
<version>parent</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bungeecord</artifactId>
<packaging>jar</packaging>
<version>${plugin.version}</version>
<description>${plugin.description}</description>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.advancedserverlist</groupId>
<artifactId>core</artifactId>
<version>${plugin.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>platform-bungeecord</artifactId>
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<!-- BungeeCord API -->
<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>
<!-- Adventure Library -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>${dependency.adventure-api}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>${dependency.adventure-text-minimessage}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>${dependency.adventure-platform-bungeecord}</version>
<scope>provided</scope>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bungeecord</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<!-- Configurate -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>${dependency.configurate-yaml}</version>
<scope>provided</scope>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>com.github.LeonMangler</groupId>
<artifactId>PremiumVanishAPI</artifactId>
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
<!-- Other -->
<dependency>
<groupId>com.alessiodp.libby</groupId>
<artifactId>libby-bungee</artifactId>
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/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>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>net.byteflux.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.libby</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -1,216 +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.bungeecord;
import ch.andre601.advancedserverlist.bungeecord.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
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.handlers.FaviconHandler;
import com.alessiodp.libby.BungeeLibraryManager;
import com.alessiodp.libby.Library;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.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 final PluginLogger logger = new BungeeLogger(this);
private boolean successfulLoad = false;
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private BungeeAudiences audiences = null;
private BungeeLibraryManager libraryManager = null;
@Override
public void onLoad(){
logger.info("Loading libraries. This may take a while...");
successfulLoad = loadLibs();
if(successfulLoad){
logger.info("Library loading completed successfully!");
}else{
logger.warn("Library loading completed with errors!");
}
}
@Override
public void onEnable(){
if(!successfulLoad){
logger.warn("There were issues during the plugins Loading-phase! Please see the console for possible reasons.");
logger.warn("The plugin won't be enabled to avoid problems.");
return;
}
this.audiences = BungeeAudiences.create(this);
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
}
@Override
public void onDisable(){
core.disable();
}
@Override
public void loadCommands(){
getProxy().getPluginManager().registerCommand(this, new CmdAdvancedServerList(this));
}
@Override
public void loadEvents(){
new JoinEvent(this);
new PingEvent(this);
}
@Override
public void loadMetrics(){
new Metrics(this, 15585).addCustomChart(new SimplePie("profiles",
() -> String.valueOf(core.getFileHandler().getProfiles().size())
));
}
@Override
public void loadFaviconHandler(AdvancedServerList<Favicon> core){
faviconHandler = new FaviconHandler<>(core);
}
@Override
public void clearFaviconCache(){
if(faviconHandler == null)
return;
faviconHandler.cleanCache();
}
@Override
public void downloadLibrary(String groupId, String artifactId, String version){
if(libraryManager == null){
libraryManager = new BungeeLibraryManager(this);
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
}
Library lib = Library.builder()
.groupId(groupId)
.artifactId(artifactId)
.version(version)
.resolveTransitiveDependencies(true)
.build();
libraryManager.loadLibrary(lib);
}
@Override
public AdvancedServerList<Favicon> getCore(){
return core;
}
@Override
public Path getFolderPath(){
return getDataFolder().toPath();
}
@Override
public PluginLogger getPluginLogger(){
return logger;
}
@Override
public FaviconHandler<Favicon> getFaviconHandler(){
if(faviconHandler == null)
faviconHandler = new FaviconHandler<>(core);
return faviconHandler;
}
@Override
public String getPlatformInfo(){
return getProxy().getName() + " " + getProxy().getVersion();
}
@Override
public String getLoader(){
return "bungeecord";
}
@Override
public boolean isPluginEnabled(String plugin){
return getProxy().getPluginManager().getPlugin(plugin) != null;
}
@Override
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
public BungeeAudiences getAudiences(){
return audiences;
}
public int getOnlinePlayers(ServerInfo server){
List<ProxiedPlayer> players = new ArrayList<>(server == null ? getProxy().getPlayers() : server.getPlayers());
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().getPlugin("PremiumVanish") != null){
players.removeIf(BungeeVanishAPI::isInvisible);
}
return players.size();
}
private boolean loadLibs(){
try{
if(libraryManager == null){
libraryManager = new BungeeLibraryManager(this);
libraryManager.addRepository("https://repo.papermc.io/repository/maven-public");
}
libraryManager.configureFromJSON("dependencies.json");
return true;
}catch(Exception ex){
logger.warn("Encountered an Exception while trying to load dependencies.", ex);
return false;
}
}
}
@@ -1,52 +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.bungeecord.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
public class BungeeCmdSender implements CmdSender{
private final CommandSender sender;
private final BungeeAudiences bungeeAudiences;
public BungeeCmdSender(CommandSender sender, BungeeAudiences bungeeAudiences){
this.sender = sender;
this.bungeeAudiences = bungeeAudiences;
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
}
@Override
public void sendMsg(String msg, Object... args){
bungeeAudiences.sender(sender).sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
}
@@ -1,46 +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.bungeecord.commands;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
public class CmdAdvancedServerList extends Command{
private final BungeeCordCore plugin;
public CmdAdvancedServerList(BungeeCordCore plugin){
super("advancedserverlist", "advancedserverlist.command.asl", "asl");
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args){
plugin.getCore().getCommandHandler().handle(new BungeeCmdSender(sender, plugin.getAudiences()), args);
}
}
@@ -1,208 +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.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.impl.BungeePlayerImpl;
import ch.andre601.advancedserverlist.bungeecord.objects.impl.BungeeProxyImpl;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenanceUtil;
import ch.andre601.advancedserverlist.core.compat.papi.PAPIUtil;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.interfaces.events.GenericEventWrapper;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ProxyPingEvent;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePlayerImpl>{
private final BungeeCordCore plugin;
private final ProxyPingEvent event;
private final ServerPing.Protocol protocol;
private final ServerPing ping;
public BungeeEventWrapper(BungeeCordCore plugin, ProxyPingEvent event){
this.plugin = plugin;
this.event = event;
this.protocol = event.getResponse().getVersion();
this.ping = event.getResponse();
}
@Override
public GenericServerListEvent callEvent(ProfileEntry entry){
PreServerListSetEventImpl event = new PreServerListSetEventImpl(entry);
plugin.getProxy().getPluginManager().callEvent(event);
return event;
}
@Override
public void setMaxPlayers(int maxPlayers){
ping.getPlayers().setMax(maxPlayers);
}
@Override
public void setMotd(Component component){
ping.setDescriptionComponent(new TextComponent(BungeeComponentSerializer.get().serialize(component)));
}
@Override
public void hidePlayers(){
ping.setPlayers(null);
}
@Override
public void setPlayerCount(String name){
protocol.setName(name);
protocol.setProtocol(-1);
}
@Override
public void setPlayers(List<String> lines, BungeePlayerImpl player, GenericServer server){
ServerPing.PlayerInfo[] players = new ServerPing.PlayerInfo[lines.size()];
for(int i = 0; i < players.length; i++){
String parsed = ComponentParser.text(lines.get(i))
.modifyText(text -> StringReplacer.replace(text, player, server))
.toString();
ServerPing.PlayerInfo pi = new ServerPing.PlayerInfo(parsed, UUID.randomUUID());
players[i] = pi;
}
if(players.length > 0)
ping.getPlayers().setSample(players);
}
@Override
public void setFavicon(Favicon favicon){
ping.setFavicon(favicon);
}
@Override
public void setDefaultFavicon(){
ping.setFavicon(ping.getFaviconObject());
}
@Override
public void updateEvent(){
this.ping.setVersion(this.protocol);
this.event.setResponse(this.ping);
}
@Override
public boolean isInvalidProtocol(){
return protocol == null;
}
@Override
public boolean isMaintenanceModeActive(){
if(plugin.getProxy().getPluginManager().getPlugin("Maintenance") == null)
return false;
return MaintenanceUtil.get().isMaintenanceEnabled();
}
@Override
public int getProtocolVersion(){
return event.getConnection().getVersion();
}
@Override
public int getOnlinePlayers(){
return plugin.getOnlinePlayers(null);
}
@Override
public int getMaxPlayers(){
return ping.getPlayers().getMax();
}
@Override
public String getPlayerIP(){
return ((InetSocketAddress)event.getConnection().getSocketAddress()).getHostString();
}
@Override
public String parsePAPIPlaceholders(String text, BungeePlayerImpl player){
if(plugin.getProxy().getPluginManager().getPlugin("PAPIProxyBridge") == null)
return text;
if(!PAPIUtil.get().isCompatible())
return text;
String server = PAPIUtil.get().getServer();
if(server == null || server.isEmpty())
return text;
ServerInfo serverInfo = plugin.getProxy().getServerInfo(server);
if(serverInfo == null || serverInfo.getPlayers().isEmpty())
return text;
ProxiedPlayer carrier = PAPIUtil.get().getPlayer(serverInfo.getPlayers());
if(carrier == null)
return text;
return PAPIUtil.get().parse(text, carrier.getUniqueId(), player.getUUID());
}
@Override
public String getVirtualHost(){
return this.resolveHost(event.getConnection().getVirtualHost());
}
@Override
public PluginCore<Favicon> getPlugin(){
return plugin;
}
@Override
public BungeePlayerImpl createPlayer(CachedPlayer player, int protocol){
return new BungeePlayerImpl(player, protocol);
}
@Override
public GenericServer createGenericServer(int playersOnline, int playersMax, String host){
Map<String, ServerInfo> servers = plugin.getProxy().getServers();
return new BungeeProxyImpl(servers, playersOnline, playersMax, host);
}
}
@@ -1,61 +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.bungeecord.listeners;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.bungeecord.commands.BungeeCmdSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
private final BungeeCordCore plugin;
public JoinEvent(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@EventHandler
public void onJoin(PostLoginEvent event){
InetSocketAddress address = (InetSocketAddress)event.getPlayer().getPendingConnection().getSocketAddress();
ProxiedPlayer player = event.getPlayer();
plugin.getCore().getPlayerHandler().addPlayer(address.getHostString(), player.getName(), player.getUniqueId());
if(player.hasPermission("advancedserverlist.admin") || player.hasPermission("advancedserverlist.updatecheck")){
if(plugin.getAudiences() == null || plugin.getCore().getUpdateChecker() == null)
return;
BungeeCmdSender sender = new BungeeCmdSender(player, plugin.getAudiences());
plugin.getCore().getUpdateChecker().performCachedUpdateCheck(sender);
}
}
}
@@ -1,51 +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.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;
public class PingEvent implements Listener{
private final BungeeCordCore plugin;
public PingEvent(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@EventHandler(priority = 90) // Maintenance has Event Priority 80, so we need to be AFTER it.
public void onProxyPing(ProxyPingEvent event){
ProfileEntry entry = PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
plugin.getProxy().getPluginManager().callEvent(new PostServerListSetEvent(entry));
}
}
@@ -1,75 +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.bungeecord.logging;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class BungeeLogger implements PluginLogger{
private final BungeeCordCore plugin;
private final 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
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
}
@Override
public void warn(String msg, Object... args){
logger.warning(String.format(msg, args));
}
@Override
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
}
}
@@ -1,59 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeePlayer;
import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import java.util.UUID;
public class BungeePlayerImpl implements BungeePlayer{
private final String name;
private final int protocol;
private final UUID uuid;
public BungeePlayerImpl(CachedPlayer player, int protocol){
this.name = player.name();
this.protocol = protocol;
this.uuid = player.uuid();
}
@Override
public String getName(){
return name;
}
@Override
public int getProtocol(){
return protocol;
}
@Override
public UUID getUUID(){
return uuid;
}
}
@@ -1,53 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects.impl;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.Map;
public record BungeeProxyImpl(Map<String, ServerInfo> servers, int playersOnline, int playersMax, String host) implements BungeeProxy{
@Override
public Map<String, ServerInfo> getServers(){
return servers;
}
@Override
public int getPlayersOnline(){
return playersOnline;
}
@Override
public int getPlayersMax(){
return playersMax;
}
@Override
public String getHost(){
return host;
}
}
@@ -1,53 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import java.util.Locale;
public class BungeePlayerPlaceholders extends PlaceholderProvider{
private BungeePlayerPlaceholders(){
super("player");
}
public static BungeePlayerPlaceholders init(){
return new BungeePlayerPlaceholders();
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
return switch(placeholder.toLowerCase(Locale.ROOT)){
case "name" -> player.getName();
case "protocol" -> String.valueOf(player.getProtocol());
case "uuid" -> String.valueOf(player.getUUID());
default -> null;
};
}
}
@@ -1,103 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.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 final BungeeCordCore plugin;
private BungeeServerPlaceholders(BungeeCordCore plugin){
super("server");
this.plugin = plugin;
}
public static BungeeServerPlaceholders init(BungeeCordCore plugin){
return new BungeeServerPlaceholders(plugin);
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!(server instanceof BungeeProxy proxy))
return null;
String[] args = placeholder.split("\\s", 2);
return switch(args[0]){
case "playersOnline" -> {
if(args.length >= 2){
String[] servers = args[1].split(",");
int players = 0;
for(String serverName : servers){
if(serverName.isEmpty())
continue;
ServerInfo info = proxy.getServers().get(serverName.strip());
if(info == null)
continue;
players += plugin.getOnlinePlayers(info);
}
yield String.valueOf(players);
}
yield String.valueOf(proxy.getPlayersOnline());
}
case "playersMax" -> {
// ServerInfo doesn't provide the max players that could join, so we won't allow an extra argument
if(args.length >= 2)
yield null;
yield String.valueOf(proxy.getPlayersMax());
}
case "host" -> {
if(args.length > 2)
yield null;
if(args.length == 2 && args[1] != null && !args[1].isEmpty()){
ServerInfo info = proxy.getServers().get(args[1]);
if(info == null)
yield null;
yield String.valueOf(((InetSocketAddress)info.getSocketAddress()).getHostString());
}
yield proxy.getHost();
}
default -> null;
};
}
}
-11
View File
@@ -1,11 +0,0 @@
name: 'AdvancedServerList'
author: 'Andre_601'
version: '${plugin.version}'
description: '${plugin.description}'
softDepends:
- PAPIProxyBridge
- Maintenance
- ServerListPlus
main: 'ch.andre601.advancedserverlist.bungeecord.BungeeCordCore'
@@ -1,28 +0,0 @@
{
"libraries": [
{
"groupId": "net{}kyori",
"artifactId": "adventure-api",
"version": "${dependency.adventure-api}",
"resolveTransitiveDependencies": true
},
{
"groupId": "net{}kyori",
"artifactId": "adventure-text-minimessage",
"version": "${dependency.adventure-text-minimessage}",
"resolveTransitiveDependencies": true
},
{
"groupId": "net{}kyori",
"artifactId": "adventure-platform-bungeecord",
"version": "${dependency.adventure-platform-bungeecord}",
"resolveTransitiveDependencies": true
},
{
"groupId": "org{}spongepowered",
"artifactId": "configurate-yaml",
"version": "${dependency.configurate-yaml}",
"resolveTransitiveDependencies": true
}
]
}
+62 -46
View File
@@ -39,9 +39,11 @@
<version>${plugin.version}</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>5</plugin.config.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.config.version>10</plugin.config.version>
</properties>
<repositories>
@@ -77,9 +79,11 @@
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>1.4.3</version>
<version>1.7.0-b1</version>
<scope>compile</scope>
</dependency>
<!-- Configuration -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
@@ -89,7 +93,7 @@
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-hocon</artifactId>
<version>4.1.2</version>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
@@ -117,7 +121,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.14.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -129,21 +133,48 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.1-jre</version>
<version>33.7.1-jre</version>
<scope>provided</scope>
</dependency>
<!-- Command Framework -->
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-annotations</artifactId>
<version>${dependency.cloud-annotations}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-minecraft-extras</artifactId>
<version>${dependency.cloud-minecraft-extras}</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>net.kyori</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Annotations -->
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.1</version>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>net.william278</groupId>
<artifactId>papiproxybridge</artifactId>
<version>1.6.2</version>
<version>1.8.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>eu.kennytv.maintenance</groupId>
<artifactId>maintenance-api</artifactId>
<version>4.2.1</version>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -152,65 +183,50 @@
<version>3.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.github.miniplaceholders</groupId>
<artifactId>miniplaceholders-api</artifactId>
<version>3.2.0</version>
<scope>provided</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.3</version>
<version>5.14.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Core-${plugin.version}</finalName>
<finalName>AdvancedServerList-Core-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/src/main/resources</directory>
<excludes>
<exclude>char-widths.json.gz</exclude>
</excludes>
</resource>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>char-widths.json.gz</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<version>3.16.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.unascribed</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.expressionparser</shadedPattern>
</relocation>
</relocations>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -28,27 +28,58 @@ package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.commands.*;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenancePlaceholder;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
import ch.andre601.advancedserverlist.core.placeholders.DatePlaceholder;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.conditions.reader.PlaceholderTokenReader;
import ch.andre601.advancedserverlist.core.profiles.conditions.reader.PlaceholderValueReader;
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
import ch.andre601.expressionparser.DefaultExpressionParserEngine;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.annotations.AnnotationParser;
import org.incendo.cloud.description.Description;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.parser.standard.BooleanParser;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.permission.Permission;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
public class AdvancedServerList<F>{
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
List<PlaceholderProvider> providers = new ArrayList<>(Arrays.asList(placeholders));
providers.add(new DatePlaceholder());
return new AdvancedServerList<>(plugin, providers);
}
private final PluginCore<F> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final TextCenterUtil textCenterUtil;
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private final ProfileConditionParser parser = ProfileConditionParser.create();
private final DefaultExpressionParserEngine parser = new DefaultExpressionParserEngine.DefaultBuilder()
.addDefaults()
.addTokenReader(new PlaceholderTokenReader())
.addValueReader(new PlaceholderValueReader())
.build();
private UpdateChecker updateChecker;
@@ -57,69 +88,64 @@ public class AdvancedServerList<F>{
private AdvancedServerList(PluginCore<F> plugin, List<PlaceholderProvider> placeholders){
this.plugin = plugin;
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.textCenterUtil = new TextCenterUtil(this);
plugin.getPluginLogger().info("Registering internal Placeholders...");
plugin.pluginLogger().info("Registering internal Placeholders...");
placeholders.forEach(this::addPlaceholder);
if(plugin.isPluginEnabled("Maintenance")){
plugin.getPluginLogger().info("Found Maintenance Plugin. Registering extra Placeholder...");
addPlaceholder(new MaintenancePlaceholder(this));
}
plugin.getPluginLogger().info("Completed internal Placeholder registration!");
resolveVersion();
plugin().pluginLogger().info("Starting <white>AdvancedServerList v%s</white>...", version);
load();
}
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
public static AdvancedServerListAPI getApi(){
public static AdvancedServerListAPI api(){
return api;
}
public PluginCore<F> getPlugin(){
public PluginCore<F> plugin(){
return plugin;
}
public FileHandler getFileHandler(){
public FileHandler fileHandler(){
return fileHandler;
}
public CommandHandler getCommandHandler(){
return commandHandler;
}
public PlayerHandler getPlayerHandler(){
public PlayerHandler playerHandler(){
return playerHandler;
}
public String getVersion(){
public String version(){
return version;
}
public ProfileConditionParser getParser(){
public DefaultExpressionParserEngine parser(){
return parser;
}
public UpdateChecker getUpdateChecker(){
public UpdateChecker updateChecker(){
return updateChecker;
}
public TextCenterUtil textCenterUtil(){
return textCenterUtil;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving playercache.json file...");
getPlayerHandler().save();
plugin().pluginLogger().info("[-] Saving <white>playercache.json</white> file...");
playerHandler().save();
if(updateChecker != null){
getPlugin().getPluginLogger().info("Disabling Update Checker...");
plugin().pluginLogger().info("[-] Disabling Update Checker...");
updateChecker.disable();
}
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
plugin().pluginLogger().success("AdvancedServerList disabled!");
}
public void clearFaviconCache(){
@@ -127,78 +153,69 @@ public class AdvancedServerList<F>{
}
public void clearPlayerCache(){
getPlayerHandler().clearCache();
playerHandler().clearCache();
}
private void load(){
printBanner();
resolveVersion();
getPlugin().getPluginLogger().info("Starting AdvancedServerList v%s...", version);
getPlugin().getPluginLogger().info("Platform: %s", plugin.getPlatformInfo());
if(getFileHandler().loadConfig()){
getPlugin().getPluginLogger().info("Successfully loaded config.yml!");
}else{
getPlugin().getPluginLogger().warn("Unable to load config.yml! Check previous lines for errors.");
if(!fileHandler().loadConfig()){
plugin().pluginLogger().failure("Unable to load <white>config.yml</white>! Check previous lines for errors.");
return;
}
if(getFileHandler().isOldConfig()){
getPlugin().getPluginLogger().info("Detected old config.yml. Attempting to migrate...");
if(getFileHandler().migrateConfig()){
getPlugin().getPluginLogger().info("Migration completed successfully!");
if(fileHandler().isOldConfig()){
plugin().pluginLogger().info("[-] Detected old <white>config.yml</white>. Attempting to migrate...");
if(fileHandler().migrateConfig()){
plugin().pluginLogger().success("Migration completed successfully!");
}else{
getPlugin().getPluginLogger().warn("Couldn't migrate config.yml! Check previous lines for errors.");
plugin().pluginLogger().failure("Couldn't migrate <white>config.yml</white>! Check previous lines for errors.");
return;
}
}
if(getFileHandler().loadProfiles()){
getPlugin().getPluginLogger().info("Successfully loaded %d profile(s)!", getFileHandler().getProfiles().size());
if(fileHandler().getBool(true, "printBanner")){
printBanner();
}
plugin().pluginLogger().info("Platform: <white>%s</white>", plugin.platformInfo());
plugin().pluginLogger().info("");
if(fileHandler().loadProfiles()){
plugin().pluginLogger().success("Successfully loaded <white>%d</white> profile(s)!", fileHandler().profiles().size());
}else{
getPlugin().getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
plugin().pluginLogger().failure("Unable to load profiles! Check previous lines for errors.");
return;
}
getPlugin().loadFaviconHandler(this);
getPlugin().getPluginLogger().info("Loading Commands...");
plugin.loadCommands();
getPlugin().getPluginLogger().info("Commands loaded!");
getPlugin().getPluginLogger().info("Loading events...");
plugin.loadEvents();
getPlugin().getPluginLogger().info("Events loaded!");
getPlugin().getPluginLogger().info("Loading playercache.json...");
getPlayerHandler().load();
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
plugin.loadMetrics();
getPlugin().getPluginLogger().info("Metrics loaded!");
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
loadCommands();
if(getFileHandler().getBoolean("checkUpdates"))
plugin.loadEvents();
playerHandler().load();
plugin.loadMetrics();
plugin.startScheduler();
plugin().pluginLogger().success("<green>AdvancedServerList is ready!");
if(fileHandler().getBoolean("checkUpdates"))
this.updateChecker = new UpdateChecker(this);
}
private void printBanner(){
getPlugin().getPluginLogger().info(" _____ _");
getPlugin().getPluginLogger().info(" /\\ / ____| |");
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
getPlugin().getPluginLogger().info(" / /\\ \\ \\___ \\| |");
getPlugin().getPluginLogger().info(" / ____ \\ ____) | |____");
getPlugin().getPluginLogger().info("/_/ \\_\\_____/|______|");
getPlugin().getPluginLogger().info("");
plugin().pluginLogger().info("<#3b90ff> __ _______ ___");
plugin().pluginLogger().info("<#3b90ff> /\\ \\ / ____|_| | |");
plugin().pluginLogger().info("<#3b90ff> / \\ \\ | (_(___ | | |");
plugin().pluginLogger().info("<#3b90ff> / /\\ \\ \\ \\___ \\ \\| | |");
plugin().pluginLogger().info("<#3b90ff> / ____ \\ \\ ____) | | |_|____");
plugin().pluginLogger().info("<#3b90ff>/_/_/ \\_\\_\\_____/_/|______|_|");
plugin().pluginLogger().info("");
seasonalText();
}
private void resolveVersion(){
try(InputStream is = getClass().getResourceAsStream("/version.properties")){
try(InputStream stream = getClass().getResourceAsStream("/version.properties")){
Properties properties = new Properties();
properties.load(is);
properties.load(stream);
version = properties.getProperty("version");
}catch(IOException ex){
@@ -207,7 +224,124 @@ public class AdvancedServerList<F>{
}
private void addPlaceholder(PlaceholderProvider placeholderProvider){
getPlugin().getPluginLogger().info("Registering %s Placeholders...", placeholderProvider.getIdentifier());
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
AdvancedServerList.api().addPlaceholderProvider(placeholderProvider);
}
private void loadCommands(){
plugin().loadFaviconHandler(this);
CommandManager<CmdSender> commandManager = plugin().commandManager();
commandManager.registerCommandPostProcessor(new CommandTypePostprocessor());
AnnotationParser<CmdSender> annotationParser = new AnnotationParser<>(commandManager, CmdSender.class);
annotationParser.registerBuilderModifier(
CommandType.class,
(annotation, builder) -> builder.meta(CommandHandler.COMMAND_TYPE, annotation.value())
);
annotationParser.parse(
CmdClearCache.create(this),
CmdHelp.create(commandManager),
CmdMigrate.create(this),
CmdProfiles.create(this),
CmdReload.create(this)
);
for(String option : CmdProfiles.ProfileOption.list()){
commandManager.command(
commandManager.commandBuilder("advancedserverlist", "asl")
.literal("profiles")
.literal("set")
.required(
"profile",
StringParser.stringParser(),
Description.of("The profile to edit."),
SuggestionProvider.suggesting(
fileHandler().profiles().stream()
.map(ServerListProfile::file)
.map(Suggestion::suggestion)
.toList()
)
)
.literal(option)
.optional("value", descriptor(option), description(option))
.commandDescription(Description.of("Sets or resets profile values."))
.handler(context -> CommandHandler.handleSet(this, context))
.meta(CommandHandler.OPTION, option)
.permission(
Permission.anyOf(
Permission.permission("advancedserverlist.admin"),
Permission.permission("advancedserverlist.command.profiles"),
Permission.permission("advancedserverlist.command.profiles.set")
)
)
.meta(CommandHandler.COMMAND_TYPE, CommandType.Type.ALL)
);
}
plugin().pluginLogger().success("Loaded Command <white>/advancedserverlist</white>!");
}
private ParserDescriptor<CmdSender, ?> descriptor(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> BooleanParser.booleanParser();
case "priority" -> IntegerParser.integerParser();
default -> StringParser.greedyStringParser();
};
}
private Description description(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> Description.of(
"Whether this option should be enabled or not. Leave empty to unset it."
);
case "priority" -> Description.of("Priority this Profile should have. Leave empty to reset.");
case "motd", "playercount.hover" -> Description.of(
"Lines to set. Use \\n or <newline> to set a linebreak. Leave empty to reset."
);
default -> Description.of("The Value to use for this option. Leave empty to reset.");
};
}
// Adding some seasonal messages
private void seasonalText(){
LocalDate date = LocalDate.now();
switch(date.getMonth()){
case JANUARY -> {
if(date.getDayOfMonth() == 1){
plugin().pluginLogger().info("Happy new Year!");
plugin().pluginLogger().info("");
}
}
case JUNE -> {
plugin().pluginLogger().info("Happy Pride Month!");
plugin().pluginLogger().info("");
}
case AUGUST -> {
if(date.getDayOfMonth() == 1){
plugin().pluginLogger().info("Happy Birthday Switzerland!");
plugin().pluginLogger().info("");
}
}
case OCTOBER -> {
if(date.getDayOfMonth() == 31){
plugin().pluginLogger().info("Happy Halloween!");
plugin().pluginLogger().info("");
}
}
case DECEMBER -> {
if(date.getDayOfMonth() == 13){
plugin().pluginLogger().info("Happy Birthday Andre_601!");
plugin().pluginLogger().info("");
}else
if(date.getDayOfMonth() > 23 && date.getDayOfMonth() < 27){
plugin().pluginLogger().info("Merry Christmas!");
plugin().pluginLogger().info("");
}
}
}
}
}
@@ -25,13 +25,13 @@
package ch.andre601.advancedserverlist.core.check;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import java.util.concurrent.ThreadFactory;
public class UpdateCheckThread implements ThreadFactory{
@Override
public Thread newThread(@NotNull Runnable r){
public Thread newThread(@NonNull Runnable r){
Thread t = new Thread(r, "AdvancedServerList-UpdateThread");
t.setDaemon(true);
return t;
@@ -28,7 +28,7 @@ package ch.andre601.advancedserverlist.core.check;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.objects.CacheUtil;
import ch.andre601.advancedserverlist.core.objects.ValueCache;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -59,7 +59,7 @@ public class UpdateChecker{
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new UpdateCheckThread());
private final CacheUtil<CompletableFuture<ModrinthVersion>> cache = new CacheUtil<>(Duration.ofMinutes(5));
private final ValueCache<CompletableFuture<ModrinthVersion>> cache = new ValueCache<>(Duration.ofMinutes(5));
private final AdvancedServerList<?> core;
private final PluginLogger logger;
@@ -68,8 +68,8 @@ public class UpdateChecker{
public UpdateChecker(AdvancedServerList<?> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.loader = core.getPlugin().getLoader();
this.logger = core.plugin().pluginLogger();
this.loader = core.plugin().loader();
this.client = HttpClient.newBuilder().executor(Executors.newSingleThreadExecutor(new UpdateCheckThread())).build();
startUpdateChecker();
@@ -88,10 +88,10 @@ public class UpdateChecker{
if(version == null)
return;
int result = version.compare(core.getVersion());
int result = version.compare(core.version());
if(result == -1){
sender.sendPrefixedMsg("<green>A new Version of AdvancedServerList is available!");
sender.sendPrefixedMsg("<green>Your version: <white>%s", core.getVersion());
sender.sendPrefixedMsg("<green>Your version: <white>%s", core.version());
sender.sendPrefixedMsg("<green>Version on Modrinth: <white>%s", version.versionNumber());
sender.sendPrefixedMsg(
"<click:open_url:'https://modrinth.com/plugin/advancedserverlist/version/%s'>" +
@@ -101,8 +101,12 @@ public class UpdateChecker{
);
}else
if(result == 1){
sender.sendPrefixedMsg("You seem to run a newer Version (<white>%</white>) than what is available on Modrinth (<white>%s</white>).", core.getVersion(), version.versionNumber());
sender.sendPrefixedMsg("Are you running a development build?");
sender.sendPrefixedMsg(
"Your version (<white>%</white>) is newer than what is available on Modrinth (<white>%s</white>).",
core.version(),
version.versionNumber()
);
sender.sendPrefixedMsg("Are you using a Development Version?");
}
});
}
@@ -123,24 +127,28 @@ public class UpdateChecker{
private void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Looking for an update...");
logger.info("[-] Looking for an update...");
performUpdateCheck().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. Check previous messages for causes.");
logger.failure("Failed to look for any updates. Check previous messages for causes.");
return;
}
logger.debug(UpdateChecker.class, "Comparing versions...");
int result = version.compare(core.getVersion());
int result = version.compare(core.version());
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()
);
case 0 -> logger.success("You are running the latest version!");
case 1 -> {
logger.info(
"[?] Your version (<white>%s</white>) is newer than what is available on Modrint (<white>%s</white>).",
core.version(),
version.versionNumber()
);
logger.info(" Are you using a Development Version?");
}
}
});
}, 0L, 12L, TimeUnit.HOURS);
@@ -155,7 +163,7 @@ public class UpdateChecker{
logger.debug(UpdateChecker.class, "Checking '%s' for updates...", finalUrl);
if(core.getVersion().equals("UNKNOWN")){
if(core.version().equals("UNKNOWN")){
logger.warn("Cannot perform update check. Plugin version is 'UNKNOWN'!");
return CompletableFuture.completedFuture(null);
}
@@ -165,7 +173,7 @@ public class UpdateChecker{
request = HttpRequest.newBuilder()
.uri(new URI(finalUrl))
.timeout(Duration.ofSeconds(5))
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.getVersion())
.header("User-Agent", "AdvancedServerList-" + loader + "/" + core.version())
.build();
}catch(URISyntaxException ex){
logger.warn("Cannot perform update check. URL '%s' is not a valid URI.", ex, finalUrl);
@@ -185,18 +193,18 @@ public class UpdateChecker{
logger.warn("=======================================================================");
logger.warn("You are running an outdated version of AdvancedServerList!");
logger.warn("");
logger.warn("Your version: %s", core.getVersion());
logger.warn("Modrinth: %s", version.versionNumber());
logger.warn("Your version: <white>%s</white>", core.version());
logger.warn("Modrinth: <white>%s</white>", version.versionNumber());
logger.warn("");
if(!version.isRelease()){
logger.warn("WARNING!");
logger.warn("<bold>WARNING!</bold>");
logger.warn("This is a %s version and may contain breaking changes and/or bugs!", version.versionType());
logger.warn("");
}
logger.warn("Download the latest version from here:");
logger.warn("https://modrinth.com/plugin/advancedserverlist/version/%s", version.id());
logger.warn("<white>https://modrinth.com/plugin/advancedserverlist/version/%s</white>", version.id());
logger.warn("=======================================================================");
}
@@ -0,0 +1,54 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import org.incendo.cloud.annotations.Argument;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;
import org.jspecify.annotations.Nullable;
@Command("advancedserverlist|asl")
@CommandDescription("Main Command of the plugin")
@Permission("advancedserverlist.admin")
@CommandType(CommandType.Type.ALL)
public record CmdClearCache(AdvancedServerList<?> core){
public static CmdClearCache create(AdvancedServerList<?> core){
return new CmdClearCache(core);
}
@Command("clearcache [target]")
@CommandDescription("Cleares the Favicon and/or Player Cache.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.clearcache"})
@CommandType(CommandType.Type.ALL)
public void handle(
CmdSender sender,
@Nullable @Argument(description = "The type of Cache to clean. Defaults to ALL.") CacheTarget target
){
if(target == null)
target = CacheTarget.ALL;
sender.sendPrefixedMsg("Clearing cache...");
if(target == CacheTarget.ALL || target == CacheTarget.FAVICON){
core().clearFaviconCache();
sender.sendPrefixedMsg("Cleared Favicon Cache.");
}
if(target == CacheTarget.ALL || target == CacheTarget.PLAYER){
core().clearPlayerCache();
sender.sendPrefixedMsg("Cleared Player Cache.");
}
sender.sendPrefixedMsg("<green>Cache clearing complete!");
}
public enum CacheTarget{
ALL,
FAVICON,
PLAYER
}
}
@@ -0,0 +1,65 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import net.kyori.adventure.text.format.NamedTextColor;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.annotation.specifier.Greedy;
import org.incendo.cloud.annotations.Argument;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;
import org.incendo.cloud.annotations.suggestion.Suggestions;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.help.result.CommandEntry;
import org.incendo.cloud.minecraft.extras.MinecraftHelp;
import org.jspecify.annotations.Nullable;
import java.util.List;
@Command("advancedserverlist|asl")
@CommandDescription("Main Command of the plugin")
@Permission("advancedserverlist.admin")
@CommandType(CommandType.Type.ALL)
public record CmdHelp(CommandManager<CmdSender> manager, MinecraftHelp<CmdSender> help){
public static CmdHelp create(CommandManager<CmdSender> manager){
MinecraftHelp<CmdSender> help = MinecraftHelp.<CmdSender>builder()
.commandManager(manager)
.audienceProvider(CmdSender::audience)
.commandPrefix("/asl help")
.colors(MinecraftHelp.helpColors(
NamedTextColor.WHITE, NamedTextColor.AQUA, NamedTextColor.WHITE, NamedTextColor.GRAY, NamedTextColor.DARK_GRAY
))
.build();
return new CmdHelp(manager, help);
}
@Command("help [query]")
@CommandDescription("Displays all commands or provides info about a specific one.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.help"})
@CommandType(CommandType.Type.ALL)
public void handle(
CmdSender sender,
@Nullable @Argument(description = "Search Query for a specific command", suggestions = "help") @Greedy String query
){
this.help.queryCommands(query == null ? "" : query, sender);
}
@Suggestions("help")
public List<String> helpQueries(CommandContext<CmdSender> context) {
return this.manager.createHelpHandler()
.queryRootIndex(context.sender())
.entries()
.stream()
.filter(entry -> context.hasPermission(entry.command().commandPermission()))
.filter(entry -> {
CommandType.Type type = entry.command().commandMeta().getOrDefault(CommandHandler.COMMAND_TYPE, CommandType.Type.ALL);
return type == CommandType.Type.ALL || type == CommandType.Type.PLAYER_ONLY && context.sender().isPlayer();
})
.map(CommandEntry::syntax)
.toList();
}
}
@@ -0,0 +1,78 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.migration.minimotd.MiniMOTDConfigMigrator;
import ch.andre601.advancedserverlist.core.migration.serverlistplus.SLPConfigMigrator;
import org.incendo.cloud.annotations.Argument;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;
import org.jspecify.annotations.NonNull;
import java.util.Locale;
@Command("advancedserverlist|asl")
@CommandDescription("Main Command of the plugin")
@Permission("advancedserverlist.admin")
@CommandType(CommandType.Type.ALL)
public record CmdMigrate(AdvancedServerList<?> core){
public static CmdMigrate create(AdvancedServerList<?> core){
return new CmdMigrate(core);
}
@Command("migrate <plugin>")
@CommandDescription("Migrates Profiles from supported Plugins to ASL.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.migrate"})
@CommandType(CommandType.Type.ALL)
public void handle(
CmdSender sender,
@NonNull @Argument(description = "Name of the plugin to migrate from") MigratablePlugin plugin
){
if(plugin == MigratablePlugin.SERVERLISTPLUS){
if(!core().plugin().isPluginEnabled("ServerListPlus")){
sender.sendErrorMsg("<red>ServerListPlus not enabled.");
sender.sendErrorMsg("<red>The plugin needs to be enabled for the migration to work.");
return;
}
sender.sendPrefixedMsg("Migrating from ServerListPlus...");
int migrated = SLPConfigMigrator.migrate(core(), sender);
if(migrated == 0){
sender.sendErrorMsg("<red>Couldn't migrate any profiles from ServerListPlus.");
sender.sendErrorMsg("<red>See the server console for any errors.");
return;
}else{
sender.sendPrefixedMsg("<green>Successfully migrated </green>%d<green> Profile(s)!", migrated);
}
}else
if(plugin == MigratablePlugin.MINIMOTD){
sender.sendPrefixedMsg("Migrating from MiniMOTD...");
if(MiniMOTDConfigMigrator.migrate(core(), sender)){
sender.sendPrefixedMsg("<green>Successfully migrated config from MiniMOTD!");
}else{
sender.sendErrorMsg("<red>Couldn't migrate config from MiniMOTD.");
sender.sendErrorMsg("<red>See the server console for any errors.");
return;
}
}else{
sender.sendErrorMsg("<red>Received invalid Plugin </red>%s<red>!", plugin.toString());
sender.sendErrorMsg("<red>Only the following plugins are supported:");
for(MigratablePlugin pl : MigratablePlugin.values()){
sender.sendErrorMsg("- <click:suggest_command:/asl migrate %s>%s</click>", pl.name().toLowerCase(Locale.ROOT), pl.name().toLowerCase(Locale.ROOT));
}
}
sender.sendPrefixedMsg("<green>Run <white><click:suggest_command:/asl reload>/asl reload</click></white> to load the new Profile(s).");
}
public enum MigratablePlugin{
SERVERLISTPLUS,
MINIMOTD
}
}
@@ -0,0 +1,483 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.interfaces.dialogs.IDialog;
import ch.andre601.advancedserverlist.core.interfaces.dialogs.IDialogList;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.incendo.cloud.annotations.Argument;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;
import org.incendo.cloud.annotations.suggestion.Suggestions;
import org.incendo.cloud.context.CommandInput;
import org.jspecify.annotations.NonNull;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
@Command("advancedserverlist|asl")
@CommandDescription("Main Command of the plugin.")
@Permission("advancedserverlist.admin")
@CommandType(CommandType.Type.ALL)
public record CmdProfiles(AdvancedServerList<?> core){
public static CmdProfiles create(AdvancedServerList<?> core){
return new CmdProfiles(core);
}
@Command("profiles add <name>")
@CommandDescription("Creates a new Profile with default values applied.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.profiles", "advancedserverlist.command.profiles.add"})
@CommandType(CommandType.Type.ALL)
public void add(
CmdSender sender,
@NonNull @Argument(description = "Name of the profile to create.") String name
){
if(name.isEmpty()){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>A profile name needs to be provided.");
return;
}
if(CommandHandler.profile(core(), name) != null){
sender.sendErrorMsg("<red>A profile with the name </red>%s<red> already exists.", name);
return;
}
String file = CommandHandler.profileName(name);
if(core().fileHandler().createFile(file)){
sender.sendPrefixedMsg("<green>Successfully created </green>%s<green>!", file);
sender.sendPrefixedMsg("<green>Use <white><click:suggest_command:/asl reload>/asl reload</click></white> to load the file.");
}else{
sender.sendErrorMsg("<red>Error while creating new profile.");
sender.sendErrorMsg("<red>Check the server console for details.");
}
}
@Command("profiles copy <profile> <name>")
public void copy(
CmdSender sender,
@NonNull @Argument(description = "Name of the profile to copy.", suggestions = "profiles") String profile,
@NonNull @Argument(description = "Name of the copy to have.") String name
){
if(profile.isEmpty() || name.isEmpty()){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>A profile name and name for the copy need to be provided.");
return;
}
String profileName = CommandHandler.profileName(profile);
String copyName = CommandHandler.profileName(name);
ServerListProfile original = CommandHandler.profile(core(), profileName);
if(original == null){
sender.sendErrorMsg("<red>A profile with name </red>%s<red> does not exist.", profile);
return;
}
boolean copyExists = CommandHandler.profile(core(), copyName) != null;
if(copyExists){
sender.sendErrorMsg("<red>A profile with name </red>%s<red> already exists.", name);
return;
}
Path profilePath = core().plugin().folderPath().resolve("profiles").resolve(copyName);
if(!Files.exists(profilePath)){
try{
Files.createFile(profilePath);
}catch(IOException ex){
sender.sendErrorMsg("<red>Encountered an IOException while creating </red>%s<red>.", copyName);
sender.sendErrorMsg("<red>Please see the server console for further details.");
core.plugin().pluginLogger().warn("Encountered IOException while creating file <white>%s</white>", ex, copyName);
return;
}
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.path(profilePath)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(opt -> opt.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.build();
ConfigurationNode node;
try{
node = loader.load();
}catch(IOException ex){
sender.sendErrorMsg("<red>Encountered an IOException while loading file </red>%s<red>.", copyName);
sender.sendErrorMsg("<red>Please see the server console for further details.");
core().plugin().pluginLogger().warn("Encountered IOException while loading file <white>%s</white>.", ex, copyName);
return;
}
try{
node.node("priority").set(original.priority());
node.node("condition").set(original.condition());
node.node("profiles").setList(ProfileEntry.class, original.profiles());
node.set(ProfileEntry.class, original.defaultProfile());
}catch(SerializationException ex){
sender.sendErrorMsg("<red>Encountered a SerializationException while copying values from </red>%s<red> to </red>%s<red>.", profileName, copyName);
sender.sendErrorMsg("<red>Please see the server console for further details.");
core().plugin().pluginLogger().warn("<red>Encountered a SerializationException while copying values from </red>%s<red> to </red>%s<red>.", ex, profileName, copyName);
return;
}
try{
loader.save(node);
sender.sendPrefixedMsg("<green>Successfully created copy of </green>%s<green> as </green>%s<green>!", profileName, copyName);
sender.sendPrefixedMsg("<green>Use <white><click:suggest_command:/asl reload>/asl reload</click></white> to load the file.");
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an IOException while loading file </red>%s<red>!", copyName);
sender.sendErrorMsg("<red>Please see the server console for further details.");
core.plugin().pluginLogger().warn("Encountered an IOException while loading file <white>%s</white>", ex, copyName);
}
}
}
@Command("profiles edit <profile>")
@CommandDescription("Opens a Dialog to edit a specific profile ingame.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.profiles", "advancedserverlist.command.profiles.edit"})
@CommandType(CommandType.Type.PLAYER_ONLY)
public void edit(
CmdSender sender,
@NonNull @Argument(description = "Name of the profile to edit.", suggestions = "profiles") String profile
){
if(!core().plugin().isDialogsSupported()){
sender.sendErrorMsg("Dialogs are not supported on this server or proxy version.");
return;
}
ServerListProfile slp = CommandHandler.profile(core(), profile);
if(slp == null){
sender.sendErrorMsg("<red>A profile with name </red>%s<red> does not exist.", profile);
return;
}
IDialogList.IDialogListBuilder listBuilder = core().plugin().createDialogListBuilder(slp.file());
String warning = """
<gold><bold>WARNING!</bold></gold>
Dialog-based Profile editing is currently an <italic>experimental feature</italic>!
Please create backups of your profiles before using this feature and report any bugs and/or glitches you encounter.""";
listBuilder.appendBody(warning);
listBuilder.appendDialog(
createDialog("Main Settings", warning, slp, slp.defaultProfile(), slp.priority(), slp.condition(), -1)
);
for(int i = 0; i < slp.profiles().size(); i++){
listBuilder.appendDialog(
createDialog("Profiles #" + (i + 1), warning, slp, slp.profiles().get(i), -1, null, i)
);
}
listBuilder.build().show(sender);
}
@Command("profiles info <profile>")
@CommandDescription("Provides info about a specific profile.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.profiles", "advancedserverlist.command.profiles.info"})
@CommandType(CommandType.Type.PLAYER_ONLY)
public void info(
CmdSender sender,
@NonNull @Argument(description = "Name of the profile to view.", suggestions = "profiles") String profile
){
if(profile.isEmpty()){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>A profile name needs to be provided.");
return;
}
ServerListProfile slp = CommandHandler.profile(core(), profile);
if(slp == null){
sender.sendErrorMsg("<red>Unable to find profile with name </red>%s<red>.", profile);
sender.sendErrorMsg("<red>Make sure you typed it correctly.");
return;
}
ProfileOptionsSender optionsSender = new ProfileOptionsSender(slp.file());
optionsSender
.append(
ProfileOptionsSender.OptionStringBuilder.of("Priority", slp.priority())
.option(ProfileOption.PRIORITY)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Condition", slp.condition())
.option(ProfileOption.CONDITION)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Profiles")
.color(slp.profiles().isEmpty() ? ProfileOptionsSender.ColorName.RED : ProfileOptionsSender.ColorName.GREEN)
);
if(!slp.profiles().isEmpty()){
for(int i = 0; i < slp.profiles().size(); i++){
optionsSender.append(
ProfileOptionsSender.OptionStringBuilder.of("#" + (i + 1), profileHover(slp.profiles().get(i)))
.prefix("│ %s─".formatted((i + 1) == slp.profiles().size() ? "└" : "├"))
.color(ProfileOptionsSender.ColorName.AQUA)
);
}
}
ProfileEntry entry = slp.defaultProfile();
optionsSender
.append(
ProfileOptionsSender.OptionStringBuilder.of("MOTD", entry.motd())
.option(ProfileOption.MOTD)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Favicon", entry.favicon())
.option(ProfileOption.FAVICON)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Player count")
.prefix("└─")
.color(ProfileOptionsSender.ColorName.AQUA)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Hide Player count?", entry.hidePlayersEnabled())
.prefix(" ├─")
.option(ProfileOption.PLAYERCOUNT_HIDEPLAYERS)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Hide Player count hover?", entry.hidePlayersHoverEnabled())
.prefix(" ├─")
.option(ProfileOption.PLAYERCOUNT_HIDEPLAYERSHOVER)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Player count hover", entry.players())
.prefix(" ├─")
.option(ProfileOption.PLAYERCOUNT_HOVER)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Player count text", entry.playerCountText())
.prefix(" ├─")
.option(ProfileOption.PLAYERCOUNT_TEXT)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Extra Players")
.prefix(" ├─")
.color(ProfileOptionsSender.ColorName.AQUA)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Enabled?", entry.extraPlayersEnabled())
.prefix(" │ ├─")
.option(ProfileOption.PLAYERCOUNT_EXTRAPLAYERS_ENABLED)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Amount", entry.extraPlayersCount())
.prefix(" │ └─")
.option(ProfileOption.PLAYERCOUNT_EXTRAPLAYERS_AMOUNT)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Max Players")
.prefix(" ├─")
.color(ProfileOptionsSender.ColorName.AQUA)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Enabled?", entry.maxPlayersEnabled())
.prefix(" │ ├─")
.option(ProfileOption.PLAYERCOUNT_MAXPLAYERS_ENABLED)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Amount", entry.maxPlayersCount())
.prefix(" │ └─")
.option(ProfileOption.PLAYERCOUNT_MAXPLAYERS_AMOUNT)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Online Players")
.prefix(" └─")
.color(ProfileOptionsSender.ColorName.AQUA)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Enabled?", entry.onlinePlayersEnabled())
.prefix(" ├─")
.option(ProfileOption.PLAYERCOUNT_ONLINEPLAYERS_ENABLED)
).append(
ProfileOptionsSender.OptionStringBuilder.of("Amount", entry.onlinePlayersCount())
.prefix(" └─")
.option(ProfileOption.PLAYERCOUNT_ONLINEPLAYERS_AMOUNT)
).send(sender);
}
@Command("profiles list")
@CommandDescription("Lists all available profiles with priority, conditions and if they are valid.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.profiles", "advancedserverlist.command.profiles.list"})
@CommandType(CommandType.Type.ALL)
public void list(CmdSender sender){
sender.sendMsg();
sender.sendPrefixedMsg("Available Profiles:");
sender.sendMsg("<dark_grey>|");
List<ServerListProfile> profiles = core().fileHandler().profiles().stream()
.sorted(Comparator.comparingInt(ServerListProfile::priority).reversed())
.toList();
if(profiles.isEmpty()){
sender.sendMsg("<dark_grey></dark_grey> <i>No profiles found.</i>");
}else{
for(int i = 0; i < profiles.size(); i++){
sender.sendMsg(
"<dark_grey>%s</dark_grey> <aqua>" +
"<hover:show_text:\"%s\">" +
"<click:suggest_command:/asl profiles info %s>" +
"%s" +
"</click>" +
"</hover>" +
"</aqua>",
(i + 1) == profiles.size() ? "" : "-",
hover(profiles.get(i)),
profiles.get(i).file(),
profiles.get(i).file()
);
}
}
sender.sendMsg();
sender.sendMsg("<grey><i>Hover</i></grey> = Show details.");
sender.sendMsg("<grey><i>Click</i></grey> = Get Command.");
}
@Suggestions("profiles")
public List<String> profilesSuggestions(CommandInput input){
String name = input.readString();
List<String> profiles = core().fileHandler().profiles().stream()
.map(profile -> profile.file().substring(0, profile.file().lastIndexOf('.')))
.toList();
if(name.isEmpty())
return profiles;
List<String> matches = new ArrayList<>(profiles.size());
for(String str : profiles){
if(str.length() >= name.length() && str.regionMatches(true, 0, name, 0, name.length()))
matches.add(str);
}
return matches;
}
private String hover(ServerListProfile profile){
return """
<grey>Priority: <white>%d</white>
Condition: <white>%s</white>
Valid? %s""".formatted(
profile.priority(),
profile.condition() == null || profile.condition().isEmpty() ? "<i>None</i>" : profile.condition(),
profile.isInvalidProfile() ? "<red>No</red>" : "<green>Yes</green>"
);
}
private String profileHover(ProfileEntry entry){
return """
<grey>MOTD:
%s<reset>
<grey>Favicon: %s<reset>
<grey>Hide Player count? %s
Hide Player count Hover? %s
Player count Hover:
%s<reset>
<grey>Player count Text: %s<reset>
<grey>Extra Players: %s<reset>
<grey>Max Players: %s<reset>
<grey>Online Players: %s""".formatted(
entry.motd() == null || entry.motd().isEmpty() ?
"<i><white>None</white></i>" : String.join("<reset>\n", entry.motd()),
entry.favicon() == null || entry.favicon().isEmpty() ?
"<i><white>None</white></i>" : entry.favicon(),
entry.hidePlayersEnabled().getOrDefault(false) ? "<green>Enabled</green>" : "<red>Disabled</red>",
entry.hidePlayersHoverEnabled().getOrDefault(false) ? "<green>Enabled</green>" : "<red>Disabled</red>",
entry.players().isEmpty() ? "<i><white>None</white></i>" : String.join("<reset>\n", entry.players()),
entry.playerCountText() == null || entry.playerCountText().isEmpty() ?
"<i><white>None</white></i>" : entry.playerCountText(),
entry.extraPlayersEnabled().getOrDefault(false) ? entry.extraPlayersCount() : "<red>Disabled</red>",
entry.maxPlayersEnabled().getOrDefault(false) ? entry.maxPlayersCount() : "<red>Disabled</red>",
entry.onlinePlayersEnabled().getOrDefault(false) ? entry.onlinePlayersCount() : "<red>Disabled</red>"
);
}
private IDialog<?> createDialog(
String title,
String warning,
ServerListProfile slp,
ProfileEntry entry,
int priority,
String condition,
int index
){
IDialog.IDialogBuilder builder = core.plugin().createDialogBuilder(title, slp, index);
builder.appendBody(warning);
if(index < 0){
builder.appendNumberRange(ProfileOption.PRIORITY, "Priority", priority)
.appendTextInput(ProfileOption.CONDITION, "Condition", condition, 100);
}
builder.appendTextbox(ProfileOption.MOTD, "MOTD", entry.motd(), 200, 2)
.appendTextInput(ProfileOption.FAVICON, "Favicon", entry.favicon(), 100)
.appendBoolean(ProfileOption.PLAYERCOUNT_HIDEPLAYERS, "Hide Player Count", entry.hidePlayersEnabled())
.appendBoolean(ProfileOption.PLAYERCOUNT_HIDEPLAYERSHOVER, "Hide Player Count Hover", entry.hidePlayersHoverEnabled())
.appendTextbox(ProfileOption.PLAYERCOUNT_HOVER, "Player Count Hover", entry.players(), 200, 10)
.appendTextInput(ProfileOption.PLAYERCOUNT_TEXT, "Player Count Text", entry.playerCountText(), 100)
.appendBoolean(ProfileOption.PLAYERCOUNT_EXTRAPLAYERS_ENABLED, "Enable Extra Players", entry.extraPlayersEnabled())
.appendTextInput(ProfileOption.PLAYERCOUNT_EXTRAPLAYERS_AMOUNT, "Extra Players Count", entry.extraPlayersCount(), 100)
.appendBoolean(ProfileOption.PLAYERCOUNT_MAXPLAYERS_ENABLED, "Enable Max Players", entry.maxPlayersEnabled())
.appendTextInput(ProfileOption.PLAYERCOUNT_MAXPLAYERS_AMOUNT, "Max Players Count", entry.maxPlayersCount(), 100)
.appendBoolean(ProfileOption.PLAYERCOUNT_ONLINEPLAYERS_ENABLED, "Enable Online Players", entry.onlinePlayersEnabled())
.appendTextInput(ProfileOption.PLAYERCOUNT_ONLINEPLAYERS_AMOUNT, "Online Players Count", entry.onlinePlayersCount(), 100);
return builder.build();
}
public enum ProfileOption{
PRIORITY,
CONDITION,
MOTD,
FAVICON,
PLAYERCOUNT_HIDEPLAYERS,
PLAYERCOUNT_HIDEPLAYERSHOVER,
PLAYERCOUNT_HOVER,
PLAYERCOUNT_TEXT,
PLAYERCOUNT_EXTRAPLAYERS_ENABLED,
PLAYERCOUNT_EXTRAPLAYERS_AMOUNT,
PLAYERCOUNT_MAXPLAYERS_ENABLED,
PLAYERCOUNT_MAXPLAYERS_AMOUNT,
PLAYERCOUNT_ONLINEPLAYERS_ENABLED,
PLAYERCOUNT_ONLINEPLAYERS_AMOUNT;
public static List<String> list(){
return Arrays.stream(values())
.map(ProfileOption::toString)
.toList();
}
public static ProfileOption fromString(String input){
for(ProfileOption option : values()){
if(option.toString().equalsIgnoreCase(input))
return option;
}
return null;
}
@Override
public String toString(){
return this.name().toLowerCase(Locale.ROOT).replace("_", ".");
}
public String toDialogKey(){
return this.name().toLowerCase(Locale.ROOT);
}
}
}
@@ -0,0 +1,44 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;
@Command("advancedserverlist|asl")
@CommandDescription("Main Command of the plugin")
@Permission("advancedserverlist.admin")
@CommandType(CommandType.Type.ALL)
public record CmdReload(AdvancedServerList<?> core){
public static CmdReload create(AdvancedServerList<?> core){
return new CmdReload(core);
}
@Command("reload")
@CommandDescription("Reloads the plugin's main config and its profiles.")
@Permission({"advancedserverlist.admin", "advancedserverlist.command.reload"})
@CommandType(CommandType.Type.ALL)
public void handle(CmdSender sender){
sender.sendPrefixedMsg("Reloading plugin...");
if(core().fileHandler().reloadConfig()){
sender.sendPrefixedMsg("<green>Reloaded </green>config.yml<green>!");
}else{
sender.sendErrorMsg("<red>Encountered an error while reloading the </red>config.yml<red>.");
sender.sendErrorMsg("<red>See the server console for details.");
}
if(core().fileHandler().reloadProfiles()){
sender.sendPrefixedMsg("<green>(Re)loaded <white>%d</white> Profile(s)!", core().fileHandler().profiles().size());
}else{
sender.sendErrorMsg("<red>Encountered errors while (re)loading profiles.");
sender.sendErrorMsg("<red>See the server console for details.");
}
sender.sendPrefixedMsg("<green>Reload complete!");
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,438 +20,329 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.PluginCommand;
import ch.andre601.advancedserverlist.core.migration.minimotd.MiniMOTDConfigMigrator;
import ch.andre601.advancedserverlist.core.migration.serverlistplus.SLPConfigMigrator;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.key.CloudKey;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.*;
public class CommandHandler{
private final List<PluginCommand> subCommands;
public static final CloudKey<CommandType.Type> COMMAND_TYPE = CloudKey.of("command_type", CommandType.Type.class);
public static final CloudKey<String> OPTION = CloudKey.of("profile_option", String.class);
public CommandHandler(AdvancedServerList<?> core){
subCommands = List.of(
new Help(core),
new Reload(core),
new ClearCache(core),
new Migrate(core),
new Profiles(core)
);
}
public List<PluginCommand> getSubCommands(){
return subCommands;
}
public void handle(CmdSender sender, String[] args){
if(args.length == 0){
sender.sendErrorMsg("<red>Too few arguments! Use <grey>/asl help</grey> for a list of commands.");
public static void handleSet(AdvancedServerList<?> core, CommandContext<CmdSender> context){
CmdSender sender = context.sender();
String profile = context.get("profile");
String value = getOptionValue(context.getOrDefault("value", null));
String option = context.command().commandMeta().getOrDefault(OPTION, "");
ServerListProfile slp = profile(core, profile);
if(slp == null){
sender.sendErrorMsg("<red>No profile with name</red> %s <red>found!", profile);
return;
}
for(PluginCommand subCommand : subCommands){
if(subCommand.name().equalsIgnoreCase(args[0])){
if(!sender.hasPermission(subCommand.permission())){
sender.sendErrorMsg(
"<red>You do not have the permission <grey>%s</grey> to execute this command.",
subCommand.permission()
);
return;
int priority = slp.priority();
String condition = slp.condition();
ProfileEntry entry = slp.defaultProfile();
ProfileEntry.Builder builder = slp.defaultProfile().builder();
List<String> oldValues = new ArrayList<>();
List<String> newValues = new ArrayList<>();
switch(CmdProfiles.ProfileOption.fromString(option)){
case PRIORITY -> {
oldValues.add(String.valueOf(slp.priority()));
if(value == null || value.isEmpty()){
priority = 0;
break;
}
subCommand.handle(sender, Arrays.copyOfRange(args, 1, args.length));
try{
priority = Integer.parseInt(value);
newValues.add(String.valueOf(priority));
}catch(NumberFormatException ex){
sender.sendErrorMsg("<red>Invalid value provided. Expected number but got</red> %s", value);
return;
}
}
case CONDITION -> {
oldValues.add(slp.condition());
if(value == null || value.isEmpty()){
condition = "";
break;
}
condition = value;
newValues.add(value);
}
case MOTD -> {
oldValues.addAll(entry.motd());
if(value == null || value.isEmpty()){
builder.motd(Collections.emptyList());
break;
}
String[] lines = value.split("\\\\n|<newline>|<br>");
if(lines.length == 0){
builder.motd(Collections.emptyList());
break;
}
if(lines.length > 1){
if(lines.length > 2)
sender.sendPrefixedMsg("<gold>Found %d Lines for MOTD. Only using first 2 lines...", lines.length);
builder.motd(Arrays.asList(lines));
}else{
builder.motd(Collections.singletonList(lines[0]));
}
newValues.addAll(Arrays.asList(lines));
}
case FAVICON -> {
oldValues.add(entry.favicon());
if(value == null || value.isEmpty()){
builder.favicon("");
break;
}
builder.favicon(value);
newValues.add(value);
}
case PLAYERCOUNT_HIDEPLAYERS -> {
if(!entry.hidePlayersEnabled().isNotSet())
oldValues.add(String.valueOf(entry.hidePlayersEnabled().getOrDefault(false)));
if(value == null || value.isEmpty()){
builder.hidePlayersEnabled(NullBool.NOT_SET);
break;
}
NullBool bool = NullBool.resolve(Boolean.parseBoolean(value));
builder.hidePlayersEnabled(bool);
newValues.add(String.valueOf(bool.getOrDefault(false)));
}
case PLAYERCOUNT_HIDEPLAYERSHOVER -> {
if(!entry.hidePlayersHoverEnabled().isNotSet())
oldValues.add(String.valueOf(entry.hidePlayersHoverEnabled().getOrDefault(false)));
if(value == null || value.isEmpty()){
builder.hidePlayersHoverEnabled(NullBool.NOT_SET);
break;
}
NullBool bool = NullBool.resolve(Boolean.parseBoolean(value));
builder.hidePlayersHoverEnabled(bool);
newValues.add(String.valueOf(bool.getOrDefault(false)));
}
case PLAYERCOUNT_HOVER -> {
oldValues.addAll(entry.players());
if(value == null || value.isEmpty()){
builder.players(Collections.emptyList());
break;
}
String[] lines = value.split("\\\\n|<newline>");
if(lines.length == 0){
builder.players(Collections.emptyList());
break;
}
builder.players(Arrays.asList(lines));
newValues.addAll(Arrays.asList(lines));
}
case PLAYERCOUNT_TEXT -> {
if(!entry.playerCountText().isEmpty())
oldValues.add(entry.playerCountText());
if(value == null || value.isEmpty()){
builder.playerCountText("");
break;
}
builder.playerCountText(value);
newValues.add(value);
}
case PLAYERCOUNT_EXTRAPLAYERS_ENABLED -> {
if(!entry.extraPlayersEnabled().isNotSet())
oldValues.add(String.valueOf(entry.extraPlayersEnabled().getOrDefault(false)));
if(value == null || value.isEmpty()){
builder.extraPlayersEnabled(NullBool.NOT_SET);
break;
}
NullBool bool = NullBool.resolve(Boolean.parseBoolean(value));
builder.extraPlayersEnabled(bool);
newValues.add(String.valueOf(bool.getOrDefault(false)));
}
case PLAYERCOUNT_EXTRAPLAYERS_AMOUNT -> {
if(!entry.extraPlayersCount().isEmpty())
oldValues.add(entry.extraPlayersCount());
if(value == null || value.isEmpty()){
builder.extraPlayersCount("");
break;
}
builder.extraPlayersCount(value);
newValues.add(value);
}
case PLAYERCOUNT_MAXPLAYERS_ENABLED -> {
if(!entry.maxPlayersEnabled().isNotSet())
oldValues.add(String.valueOf(entry.maxPlayersEnabled().getOrDefault(false)));
if(value == null || value.isEmpty()){
builder.maxPlayersEnabled(NullBool.NOT_SET);
break;
}
NullBool bool = NullBool.resolve(Boolean.parseBoolean(value));
builder.maxPlayersEnabled(bool);
newValues.add(String.valueOf(bool.getOrDefault(false)));
}
case PLAYERCOUNT_MAXPLAYERS_AMOUNT -> {
if(!entry.maxPlayersCount().isEmpty())
oldValues.add(entry.extraPlayersCount());
if(value == null || value.isEmpty()){
builder.maxPlayersCount("");
break;
}
builder.maxPlayersCount(value);
newValues.add(value);
}
case PLAYERCOUNT_ONLINEPLAYERS_ENABLED -> {
if(!entry.onlinePlayersEnabled().isNotSet())
oldValues.add(String.valueOf(entry.onlinePlayersEnabled().getOrDefault(false)));
if(value == null || value.isEmpty()){
builder.onlinePlayersEnabled(NullBool.NOT_SET);
break;
}
NullBool bool = NullBool.resolve(Boolean.parseBoolean(value));
builder.onlinePlayersEnabled(bool);
newValues.add(String.valueOf(bool.getOrDefault(false)));
}
case PLAYERCOUNT_ONLINEPLAYERS_AMOUNT -> {
if(!entry.onlinePlayersCount().isEmpty())
oldValues.add(entry.onlinePlayersCount());
if(value == null || value.isEmpty()){
builder.onlinePlayersCount("");
break;
}
builder.onlinePlayersCount(value);
newValues.add(value);
}
case null, default -> {
sender.sendErrorMsg("<red>Unknown option </red>%s<red>!", option);
return;
}
}
sender.sendErrorMsg("<red>Unknown subcommand <grey>%s</grey>. Use <grey>/asl help</grey> for a list of commands.", args[0]);
}
private static class Help extends PluginCommand{
private final AdvancedServerList<?> core;
public Help(AdvancedServerList<?> core){
super("help");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("- Commands. Hover for details.");
for(PluginCommand command : core.getCommandHandler().getSubCommands()){
sender.sendPrefixedMsg("");
if(core.fileHandler().saveProfile(profileName(profile), priority, condition, slp.profiles(), builder.build())){
if(sender.isPlayer()){
sender.sendPrefixedMsg(
"<aqua><hover:show_text:\"%s\">" +
"<click:suggest_command:/asl %s>" +
"/asl <white>%s</white>" +
"</click>" +
"</hover></aqua>",
getCommandHover(command),
command.name(),
command.name()
"<green>Successfully updated <white>[<grey><hover:show_text:\"%s\">%s</hover></grey>]</white>!",
changeValueHover(oldValues, newValues),
option
);
}
}
@Override
public String usage(){
return "<aqua>/asl <white>help</white></aqua>";
}
@Override
public String description(){
return "Shows all available commands.";
}
private String getCommandHover(PluginCommand command){
return String.format(
"""
<grey>Usage: %s
Permission: <white>%s</white>
<white>%s</white>
""",
command.usage(),
command.permission(),
command.description()
);
}
}
private static class Reload extends PluginCommand{
private final AdvancedServerList<?> core;
public Reload(AdvancedServerList<?> core){
super("reload");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("Reloading plugin...");
if(core.getFileHandler().reloadConfig()){
sender.sendPrefixedMsg("<green>Reloaded <grey>config.yml</grey>!");
}else{
sender.sendErrorMsg("<red>Error while reloading <grey>config.yml</grey>!");
}
if(core.getFileHandler().reloadProfiles()){
sender.sendPrefixedMsg("<green>Loaded <grey>%d profile(s)</grey>!", core.getFileHandler().getProfiles().size());
}else{
sender.sendErrorMsg("<red>Error while loading profile(s)!");
}
sender.sendPrefixedMsg("<green>Reload complete!");
}
@Override
public String usage(){
return "<aqua>/asl <white>reload</white></aqua>";
}
@Override
public String description(){
return "Reloads the main config and all profiles.";
}
}
private static class ClearCache extends PluginCommand{
private final AdvancedServerList<?> core;
public ClearCache(AdvancedServerList<?> core){
super("clearcache");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
sender.sendPrefixedMsg("Clearing caches...");
core.clearFaviconCache();
sender.sendPrefixedMsg("<green>Successfully cleared Favicon Cache!");
core.clearPlayerCache();
sender.sendPrefixedMsg("<green>Successfully cleared Player Cache!");
sender.sendPrefixedMsg("<green>Cache clearing complete!");
}
@Override
public String usage(){
return "<aqua>/asl <white>clearcache</white></aqua>";
}
@Override
public String description(){
return "Clears the Favicon and Player Cache.";
}
}
private static class Migrate extends PluginCommand{
private final AdvancedServerList<?> core;
public Migrate(AdvancedServerList<?> core){
super("migrate");
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
if(args.length == 0){
sender.sendErrorMsg("<red>Insufficient arguments! Please provide a plugin to migrate from.");
sender.sendErrorMsg("<red>Available options:");
sender.sendErrorMsg(" - ServerListPlus");
sender.sendErrorMsg(" - MiniMOTD");
return;
}
if(args[0].equalsIgnoreCase("serverlistplus")){
if(!core.getPlugin().isPluginEnabled("ServerListPlus")){
sender.sendErrorMsg("<red>Plugin ServerListPlus is not enabled.");
sender.sendErrorMsg("<red>It needs to be active for the migration to work!");
return;
}
sender.sendPrefixedMsg("<green>Successfully updated <white>[<grey>%s</grey>]</white>:", option);
sender.sendPrefixedMsg("Migrating ServerListPlus configuration file...");
int migrated = SLPConfigMigrator.migrate(core, sender);
if(migrated == 0){
sender.sendErrorMsg("<red>Unable to migrate any ServerListPlus configuration. Check console for details!");
if(oldValues.isEmpty()){
sender.sendMsg("<red>-</red> <white><i>Not set</i></white>");
}else{
sender.sendPrefixedMsg("<green>Migration complete!");
oldValues.forEach(oldValue -> sender.sendMsg("<red>-</red> %s", oldValue));
}
}else
if(args[0].equalsIgnoreCase("minimotd")){
sender.sendPrefixedMsg("Migrating MiniMOTD configuration file...");
if(MiniMOTDConfigMigrator.migrate(core, sender)){
sender.sendPrefixedMsg("<green>Migration complete!");
sender.sendMsg();
if(newValues.isEmpty()){
sender.sendMsg("<green>+</green> <white><i>Reset to default</i></white>");
}else{
sender.sendErrorMsg("<red>Unable to migrate MiniMOTD configuration. Check console for details!");
newValues.forEach(newValue -> sender.sendMsg("<green>+</green> %s", newValue));
}
}else{
sender.sendErrorMsg("<red>Unknown plugin <grey>%s</grey>. Available Options:", args[0]);
sender.sendErrorMsg(" - ServerListPlus");
sender.sendErrorMsg(" - MiniMOTD");
sender.sendMsg();
}
}
@Override
public String usage(){
return "<aqua>/asl <white>migrate <grey>\\<</grey>Plugin<grey>></grey></white></aqua>";
}
@Override
public String description(){
return "Migrates the configuration from supported Plugins to AdvancedServerList.";
sender.sendPrefixedMsg(
"<green>Use <white><click:suggest_command:/asl reload>/asl reload</click></white> to apply changes."
);
}else{
sender.sendErrorMsg("<red>Encountered an IOException while trying to save file</red> %s<red>.", profile);
sender.sendErrorMsg("<red>Check console for details.");
core.plugin().pluginLogger().warn("Encountered IOException while saving file <white>%s.yml</white>", profile);
}
}
private static class Profiles extends PluginCommand{
public static ServerListProfile profile(AdvancedServerList<?> core, String name){
return core.fileHandler().profiles().stream()
.filter(p -> p.file().equalsIgnoreCase(profileName(name)))
.findFirst()
.orElse(null);
}
public static String profileName(String name){
if(name == null || name.isEmpty())
return "";
private final AdvancedServerList<?> core;
String filename = name.toLowerCase(Locale.ROOT);
public Profiles(AdvancedServerList<?> core){
super("profiles");
return filename.endsWith(".yml") ? filename : filename + ".yml";
}
private static String changeValueHover(List<String> oldValues, List<String> newValues){
return """
<red>-</red> %s<reset>
this.core = core;
}
@Override
public void handle(CmdSender sender, String[] args){
if(args.length == 0){
sender.sendErrorMsg("<red>Invalid command usage.");
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
return;
}
switch(args[0].toLowerCase(Locale.ROOT)){
case "list" -> {
sender.sendPrefixedMsg("Available Profiles:");
core.getFileHandler().getProfiles().stream()
.sorted(Comparator.comparingInt(ServerListProfile::priority).reversed())
.forEach(
profile -> sender.sendPrefixedMsg("- <white><hover:show_text:\"%s\">%s</hover></white>", getHover(profile), profile.file())
);
}
case "add" -> {
if(args.length == 1){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>Usage:</red> /asl profiles add <name>");
return;
}
String name = getProfileName(args[1]);
if(core.getFileHandler().getProfiles().stream().anyMatch(profile -> profile.file().equalsIgnoreCase(name))){
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", name);
return;
}
if(core.getFileHandler().createFile(name)){
sender.sendPrefixedMsg("<green>Successfully created</green> %s<green>!", name);
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
}else{
sender.sendErrorMsg("<red>Error while trying to create</red> %s<red>!", name);
sender.sendErrorMsg("<red>Check console for further details.");
}
}
case "copy" -> {
if(args.length < 3){
sender.sendErrorMsg("<red>Insufficient arguments.");
sender.sendErrorMsg("<red>Usage:</red> /asl profiles copy <profile> <name>");
return;
}
String name = getProfileName(args[1]);
String copy = getProfileName(args[2]);
ServerListProfile targetProfile = core.getFileHandler().getProfiles().stream()
.filter(file -> file.file().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
boolean copyExists = core.getFileHandler().getProfiles().stream()
.anyMatch(profile -> profile.file().equals(copy));
if(targetProfile == null){
sender.sendErrorMsg("<red>There is no file with name</red> %s<red>!", name);
return;
}
if(copyExists){
sender.sendErrorMsg("<red>A profile with file name</red> %s <red>already exists!", copy);
return;
}
Path profilePath = core.getPlugin().getFolderPath().resolve("profiles").resolve(copy);
try{
Files.createFile(profilePath);
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an error while creating the file</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for further details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while creating file %s", ex, copy);
return;
}
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.path(profilePath)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(options -> options.serializers(builder -> builder.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.build();
ConfigurationNode node;
try{
node = loader.load();
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an error while loading the file</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for further details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while loading file %s", ex, copy);
return;
}
if(node == null){
sender.sendErrorMsg("Cannot copy</red> %s <red>to</red> %s<red>. ConfigurationNode was null.", name, copy);
return;
}
try{
node.node("priority").set(targetProfile.priority());
node.node("condition").set(targetProfile.condition());
node.node("profiles").setList(ProfileEntry.class, targetProfile.profiles());
node.set(ProfileEntry.class, targetProfile.defaultProfile());
}catch(SerializationException ex){
sender.sendErrorMsg("<red>There was an Error while copying values from</red> %s <red>to</red> %s<red>.", name, copy);
sender.sendErrorMsg("<red>Check console for details.");
core.getPlugin().getPluginLogger().warn("Encountered SerializationException while set values for %s!", ex, copy);
return;
}
try{
loader.save(node);
sender.sendPrefixedMsg("<green>Successfully created copy of</green> %s <green>as</green> %s<green>!", name, copy);
sender.sendPrefixedMsg("<green>Load the file using</green> /asl reload");
}catch(IOException ex){
sender.sendErrorMsg("<red>There was an Error while trying to save</red> %s<red>!", copy);
sender.sendErrorMsg("<red>Check console for details.");
core.getPlugin().getPluginLogger().warn("Encountered IOException while saving ConfigurationNode for %s!", ex, copy);
}
}
default -> {
sender.sendErrorMsg("<red>Unknown argument</red> %s<red>!", args[0]);
sender.sendErrorMsg("<red>Usage:</red> %s", usage());
}
}
}
@Override
public String usage(){
return "<aqua>/asl <white>profiles</white> <grey>\\<" +
"<white>add</white> \\<<white>name</white>> | " +
"<white>copy</white> \\<<white>profile</white>> \\<<white>name</white>> | " +
"<white>list</white>" +
"></grey></aqua>";
}
@Override
public String description(){
return "Creates a new profile, copies one from an existing file, or lists all available profiles.";
}
private String getHover(ServerListProfile profile){
return String.format(
"""
<grey>Priority: <white>%s</white>
Condition: <white>%s</white>
Valid profile: %s
""",
profile.priority(),
profile.condition() == null || profile.condition().isEmpty() ? "<i>None</i>" : profile.condition(),
profile.isInvalidProfile() ? "<red>No</red>" : "<green>Yes</green>"
);
}
private String getProfileName(String name){
String fileName = name.toLowerCase(Locale.ROOT);
return fileName.endsWith(".yml") ? fileName : fileName + ".yml";
}
<green>+</green> %s""".formatted(
oldValues.isEmpty() ? "<i>Not set</i>" : String.join("<reset>\n<red>-</red> ", oldValues),
newValues.isEmpty() ? "<i>Not set</i>" : String.join("<reset>\n<green>+</green> ", newValues)
);
}
private static String getOptionValue(Object obj){
return switch(obj){
case null -> "";
case Boolean bool -> Boolean.toString(bool);
case Integer integer -> Integer.toString(integer);
case String str -> str;
default -> obj.toString();
};
}
}
@@ -0,0 +1,22 @@
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.execution.postprocessor.CommandPostprocessingContext;
import org.incendo.cloud.execution.postprocessor.CommandPostprocessor;
import org.incendo.cloud.services.type.ConsumerService;
public class CommandTypePostprocessor implements CommandPostprocessor<CmdSender>{
@Override
public void accept(@NonNull CommandPostprocessingContext<CmdSender> context){
CmdSender sender = context.commandContext().sender();
CommandType.Type type = context.commandContext().command().commandMeta().get(CommandHandler.COMMAND_TYPE);
if(type == CommandType.Type.ALL || (type == CommandType.Type.PLAYER_ONLY && sender.isPlayer()))
return;
sender.sendErrorMsg("<red>This command can only be executed by players!");
ConsumerService.interrupt();
}
}
@@ -0,0 +1,172 @@
/*
* MIT License
*
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ProfileOptionsSender{
private final List<OptionStringBuilder> builders = new ArrayList<>();
private final String file;
public ProfileOptionsSender(String file){
this.file = file;
}
public ProfileOptionsSender append(OptionStringBuilder builder){
this.builders.add(builder.file(file));
return this;
}
public void send(CmdSender sender){
sender.sendMsg();
sender.sendPrefixedMsg("Profile Info [<white>%s</white>]", file);
for(OptionStringBuilder builder : builders){
sender.sendMsg(builder.build());
}
sender.sendMsg();
sender.sendMsg("[<grey>Hover for info, click for command</grey>]");
sender.sendMsg();
}
public static class OptionStringBuilder{
public static OptionStringBuilder of(String displayName, String hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : hover)
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, List<String> hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : String.join("\n<reset>", hover))
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, NullBool hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || !hover.getOrDefault(false) ? "<red>Disabled</red>" : "<green>Enabled</green>")
.color(hover == null || !hover.getOrDefault(false) ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, int hover){
return new OptionStringBuilder(displayName)
.hover(String.valueOf(hover));
}
public static OptionStringBuilder of(String displayName){
return new OptionStringBuilder(displayName).hover(null);
}
private final String displayName;
private String file = null;
private String prefix = "├─";
private ColorName color = ColorName.AQUA;
private String hover = "<i>Not set</i>";
private CmdProfiles.ProfileOption option = null;
private OptionStringBuilder(String displayName){
this.displayName = displayName;
}
public OptionStringBuilder file(String file){
this.file = file;
return this;
}
public OptionStringBuilder prefix(String prefix){
this.prefix = prefix;
return this;
}
public OptionStringBuilder color(ColorName color){
this.color = color;
return this;
}
public OptionStringBuilder hover(String hover){
this.hover = hover;
return this;
}
public OptionStringBuilder option(CmdProfiles.ProfileOption option){
this.option = option;
return this;
}
public String build(){
StringBuilder builder = new StringBuilder("<grey>")
.append(prefix)
.append(" <white>[")
.append('<')
.append(color)
.append('>');
if(hover != null && !hover.isEmpty()){
builder.append("<hover:show_text:\"")
.append(hover)
.append("\">");
}
if(option != null && file != null && !file.isEmpty()){
builder.append("<click:suggest_command:/asl profiles set ")
.append(file)
.append(" ")
.append(option)
.append(" >");
}
builder.append(displayName);
if(option != null && file != null && !file.isEmpty())
builder.append("</click>");
if(hover != null && !hover.isEmpty())
builder.append("</hover>");
builder.append("</")
.append(color)
.append(">]</white></grey>");
return builder.toString();
}
}
public enum ColorName{
RED,
GREEN,
AQUA;
@Override
public String toString(){
return this.name().toLowerCase(Locale.ROOT);
}
}
}
@@ -4,7 +4,10 @@ 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 org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public class MaintenancePlaceholder extends PlaceholderProvider{
private final AdvancedServerList<?> plugin;
@@ -15,8 +18,8 @@ public class MaintenancePlaceholder extends PlaceholderProvider{
this.plugin = plugin;
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!placeholder.equals("maintenanceEnabled") || !plugin.getPlugin().isPluginEnabled("Maintenance"))
public @Nullable String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!placeholder.equals("maintenanceEnabled") || !plugin.plugin().isPluginEnabled("Maintenance"))
return null;
return String.valueOf(MaintenanceUtil.get().isMaintenanceEnabled());
@@ -0,0 +1,11 @@
package ch.andre601.advancedserverlist.core.compat.miniplaceholders;
import io.github.miniplaceholders.api.MiniPlaceholders;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
public class MiniPlaceholdersUtil{
public static TagResolver tagResolvers(){
return MiniPlaceholders.globalPlaceholders();
}
}
@@ -25,22 +25,24 @@
package ch.andre601.advancedserverlist.core.compat.papi;
import ch.andre601.advancedserverlist.core.objects.CacheUtil;
import ch.andre601.advancedserverlist.core.objects.ValueCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.william278.papiproxybridge.api.PlaceholderAPI;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class PAPIUtil{
private static PAPIUtil instance;
private final CacheUtil<String> cache = new CacheUtil<>(Duration.ofSeconds(5));
private final ValueCache<CompletableFuture<Set<String>>> serversCache = new ValueCache<>(Duration.ofSeconds(10));
private final Cache<CacheKey, CompletableFuture<String>> textCache = CacheBuilder.newBuilder()
.expireAfterWrite(Duration.ofSeconds(10))
.build();
private final PlaceholderAPI papi;
private PAPIUtil(){
@@ -66,38 +68,27 @@ public class PAPIUtil{
}
public String getServer(){
return cache.get(() -> {
List<String> servers;
try{
Set<String> value = papi.getServers().getNow(null);
if(value == null)
return null;
servers = List.copyOf(value);
}catch(CancellationException | CompletionException ex){
return null;
}
if(servers == null || servers.isEmpty())
return null;
return servers.get(0);
});
Set<String> values = serversCache.get(papi::getServers).getNow(Collections.emptySet());
if(values.isEmpty())
return null;
return List.copyOf(values).getFirst();
}
public <P> P getPlayer(Collection<P> players){
if(players.isEmpty())
return null;
return List.copyOf(players).get(0);
return List.copyOf(players).getFirst();
}
public String parse(String text, UUID carrier, UUID player){
try{
return papi.formatPlaceholders(text, carrier, player).getNow(text);
}catch(IllegalArgumentException | CancellationException | CompletionException ex){
return textCache.get(new CacheKey(player, text), () -> papi.formatPlaceholders(text, carrier, player)).getNow(text);
}catch(ExecutionException ex){
return text;
}
}
private record CacheKey(UUID uuid, String text){}
}
@@ -36,32 +36,36 @@ import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileManager;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import java.util.List;
public class PingEventHandler{
public static <F, P extends GenericPlayer> ProfileEntry handleEvent(GenericEventWrapper<F, P> event){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
event.plugin().pluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
if(event.isInvalidProtocol()){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Not handling event. Protocol was invalid.");
event.plugin().pluginLogger().debug(PingEventHandler.class, "Not handling event. Protocol was invalid.");
return null;
}
PluginCore<F> plugin = event.getPlugin();
String host = event.getVirtualHost();
PluginLogger logger = plugin.getPluginLogger();
PluginCore<F> plugin = event.plugin();
String host = event.virtualHost();
PluginLogger logger = plugin.pluginLogger();
logger.debug(PingEventHandler.class, "Protocol valid. Continue handling...");
int online = event.getOnlinePlayers();
int max = event.getMaxPlayers();
int online = event.onlinePlayers();
int max = event.maxPlayers();
P player = event.createPlayer(
plugin.getCore().getPlayerHandler().getCachedPlayer(event.getPlayerIP()),
event.getProtocolVersion()
plugin.core().playerHandler().getCachedPlayer(event.playerIP()),
event.protocolVersion()
);
GenericServer server = event.createGenericServer(online, max, host);
GenericServer server = event.createServer(online, max, host);
ServerListProfile profile = ProfileManager.resolveProfile(plugin.getCore(), player, server);
ServerListProfile profile = ProfileManager.resolveProfile(plugin.core(), player, server);
if(profile == null){
logger.debugWarn(PingEventHandler.class, "Server List Profile couldn't be resolved properly. Cancelling event handling...");
@@ -70,91 +74,142 @@ public class PingEventHandler{
logger.debug(PingEventHandler.class, "Received valid Server List Profile. Calling PreServerListSetEvent...");
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
if(e == null || e.isCancelled()){
GenericServerListEvent slEvent = event.callEvent(ProfileManager.merge(profile));
if(slEvent == null || slEvent.isCancelled()){
logger.debug(PingEventHandler.class, "PreServerListSetEvent was cancelled. Stopping ping handling...");
return null;
}
logger.debug(PingEventHandler.class, "PreServerListSetEvent completed. Proceeding with ping handling...");
ProfileEntry entry = e.getEntry();
ProfileEntry entry = slEvent.getEntry();
if(entry.isInvalid()){
logger.debugWarn(PingEventHandler.class, "No valid ProfileEntry retrieved. Cancelling ping handling...");
return null;
}
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
if(ProfileManager.checkOption(entry.onlinePlayersEnabled()) && ignoreMaintenance(event, "onlinePlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> onlinePlayers -> enabled' option is true. Trying to apply '%s'...", entry.onlinePlayersCount());
String onlinePlayers = ComponentParser.text(entry.onlinePlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.applyMMTags(event.plugin())
.toString();
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
event.setMaxPlayers(max);
try{
online = onlinePlayers == null ? online : Integer.parseInt(onlinePlayers);
event.onlinePlayers(online);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> onlinePlayers -> amount' is not a valid Number!");
}
}
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
boolean extraPlayersEnabled = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayersEnabled && ignoreMaintenance(event, "extraPlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> enabled' option is true. Trying to apply '%s'...", entry.extraPlayersCount());
String extraPlayers = ComponentParser.text(entry.extraPlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.applyMMTags(event.plugin())
.toString();
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
event.setMaxPlayers(max);
try{
max = online + (extraPlayers == null ? 0 : Integer.parseInt(extraPlayers));
logger.debug(PingEventHandler.class, "'playerCount -> extraPlayers -> amount' is a valid number. Applying it...");
event.maxPlayers(max);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> extraPlayers -> amount' is not a valid Number!");
}
}
GenericServer finalServer = event.createGenericServer(online, max, host);
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayersEnabled && ignoreMaintenance(event, "maxPlayers")){
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> enabled' option is true. Trying to apply '%s'...", entry.maxPlayersCount());
String maxPlayers = ComponentParser.text(entry.maxPlayersCount())
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.applyMMTags(event.plugin())
.toString();
try{
max = maxPlayers == null ? 0 : Integer.parseInt(maxPlayers);
logger.debug(PingEventHandler.class, "'playerCount -> maxPlayers -> amount' is a valid number. Applying it...");
event.maxPlayers(max);
}catch(NumberFormatException ex){
logger.warn("Option 'playerCount -> maxPlayers -> amount' is not a valid Number!");
}
}
GenericServer finalServer = event.createServer(online, max, host);
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
logger.debug(PingEventHandler.class, "'motd' option present. Applying ['%s']...", String.join("', '", entry.motd()));
event.setMotd(
ComponentParser.list(entry.motd())
List<Component> motd = entry.motd().stream()
.map(line -> ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.modifyText(text -> plugin.core().textCenterUtil().getCenteredText(text))
.applyMMTags(event.plugin())
.toComponent()
);
)
.toList();
event.motd(Component.join(JoinConfiguration.separator(Component.newline()), motd));
}
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
if(hidePlayers && ignoreMaintenance(event, "hidePlayers") && ignoreMaintenance(event, "hidePlayersHover")){
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayers' enabled. Hiding player count...");
event.hidePlayers();
}
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
logger.debug(PingEventHandler.class, "'playerCount -> text' option set. Applying '%s'...", entry.playerCountText());
event.setPlayerCount(
event.playerCount(
ComponentParser.text(entry.playerCountText())
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.applyMMTags(event.plugin())
.toString()
);
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
boolean hidePlayersHover = ProfileManager.checkOption(entry.hidePlayersHoverEnabled());
if(hidePlayersHover){
logger.debug(PingEventHandler.class, "'playerCount -> hidePlayersHover' option set. Hiding Player Hover...");
event.playersHidden();
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && !hidePlayersHover && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying ['%s']...", String.join("', '", entry.players()));
event.setPlayers(entry.players(), player, server);
event.players(entry.players(), player, server);
}
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
logger.debug(PingEventHandler.class, "'favicon' option set. Resolving '%s'...", entry.favicon());
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
String faviconString = StringReplacer.modifier(entry.favicon())
.modify(text -> StringReplacer.replace(text, player, server))
.modify(text -> event.parsePAPIPlaceholders(text, player))
.asString();
F favicon = plugin.getFaviconHandler().getFavicon(faviconString);
F favicon = plugin.faviconHandler().favicon(faviconString);
if(favicon == null){
logger.debugWarn(PingEventHandler.class, "Favicon was invalid or not yet resolved! Using default favicon of Server/Proxy...");
event.setDefaultFavicon();
event.defaultFavicon();
}else{
logger.debug(PingEventHandler.class, "Applying favicon...");
event.setFavicon(favicon);
event.favicon(favicon);
}
}
@@ -168,6 +223,6 @@ public class PingEventHandler{
if(!event.isMaintenanceModeActive())
return true;
return !event.getPlugin().getCore().getFileHandler().getBool(true, "disableDuringMaintenance", option);
return !event.plugin().core().fileHandler().getBool(true, "disableDuringMaintenance", option);
}
}
@@ -46,13 +46,64 @@ public class ConfigMigrator{
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, fourToFive())
.addVersion(LATEST, nineToTen())
.addVersion(9, eightToNine())
.addVersion(8, sevenToEight())
.addVersion(7, sixToSeven())
.addVersion(6, fiveToSix())
.addVersion(5, fourToFive())
.addVersion(4, threeToFour())
.addVersion(3, twoToThree())
.addVersion(2, oneToTwo())
.build();
}
public static ConfigurationTransformation nineToTen(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("faviconStrategy"), TransformAction.rename("faviconResizeStrategy"))
.build();
}
public static ConfigurationTransformation eightToNine(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("faviconStrategy").set("resize");
return null;
})
.build();
}
public static ConfigurationTransformation sevenToEight(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
value.node("hidePlayersHover").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation sixToSeven(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("printBanner").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation fiveToSix(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path("disableDuringMaintenance"), (path, value) -> {
value.node("onlinePlayers").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation fourToFive(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
@@ -111,7 +162,7 @@ public class ConfigMigrator{
versioned.apply(node);
final int endVersion = versioned.version(node);
if(startVersion < endVersion)
logger.info("Migrated config.yml from v" + startVersion + " to v" + endVersion);
logger.success("Successfully migrated config from <white>v%d</white> to <white>v%d</white>", startVersion, endVersion);
}
return node;
@@ -32,6 +32,7 @@ import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.profile.ProfileSerializer;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
@@ -46,6 +47,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
public class FileHandler{
@@ -61,19 +63,27 @@ public class FileHandler{
public FileHandler(AdvancedServerList<?> core){
this.plugin = core;
this.logger = core.getPlugin().getPluginLogger();
this.logger = core.plugin().pluginLogger();
this.config = core.getPlugin().getFolderPath().resolve("config.yml");
this.profilesFolder = core.getPlugin().getFolderPath().resolve("profiles");
this.config = core.plugin().folderPath().resolve("config.yml");
this.profilesFolder = core.plugin().folderPath().resolve("profiles");
}
public List<ServerListProfile> getProfiles(){
public List<ServerListProfile> profiles(){
return profiles;
}
public ServerListProfile profile(String file){
for(ServerListProfile profile : profiles){
if(profile.file().equalsIgnoreCase(file))
return profile;
}
return null;
}
public boolean loadConfig(){
logger.info("Loading config.yml...");
File folder = plugin.getPlugin().getFolderPath().toFile();
File folder = plugin.plugin().folderPath().toFile();
if(!folder.exists() && !folder.mkdirs()){
logger.warn("Couldn't create folder for plugin. Is it missing Write permissions?");
return false;
@@ -87,7 +97,7 @@ public class FileHandler{
}
Files.copy(stream, config);
logger.info("Created new config.yml!");
logger.success("Created new config.yml!");
}catch(IOException ex){
logger.warn("Cannot create config.yml for plugin.", ex);
return false;
@@ -98,7 +108,7 @@ public class FileHandler{
}
public boolean loadProfiles(){
logger.info("Loading profiles...");
logger.info("[-] Loading profiles...");
if(createFile("default.yml")){
return reloadProfiles();
@@ -107,9 +117,51 @@ public class FileHandler{
}
}
public boolean saveProfile(String file, int priority, String condition, List<ProfileEntry> profiles, ProfileEntry defaultProfile){
String filename = file.toLowerCase(Locale.ROOT);
Path filePath = profilesFolder.resolve(filename.endsWith(".yml") ? filename : filename + ".yml");
if(!Files.exists(filePath)){
logger.warn("Cannot find profile with file name '<white>%s</white>'", filename);
return false;
}
YamlConfigurationLoader loader = YamlConfigurationLoader.builder()
.defaultOptions(opts -> opts.serializers(build -> build.register(ProfileEntry.class, ProfileSerializer.INSTANCE)))
.path(filePath)
.nodeStyle(NodeStyle.BLOCK)
.build();
ConfigurationNode node;
try{
node = loader.load();
}catch(IOException ex){
logger.warn("Encountered an IOException while loading file '<white>%s</white>'", ex, filename);
return false;
}
if(node == null)
return false;
try{
node.node("priority").set(priority);
node.node("condition").set(condition);
node.node("profiles").setList(ProfileEntry.class, profiles);
node.set(ProfileEntry.class, defaultProfile);
loader.save(node);
return true;
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while saving file '<white>%s</white>'", ex, filename);
return false;
}catch(IOException ex){
logger.warn("Encountered an IOException while saving file '<white>%s</white>'", ex, filename);
return false;
}
}
public boolean createFile(String name){
if(Files.notExists(profilesFolder) && profilesFolder.toFile().mkdirs()){
logger.info("Successfully created profiles folder.");
logger.debugSuccess(FileHandler.class, "Successfully created profiles folder.");
}
File file = new File(profilesFolder.toFile(), name);
@@ -126,7 +178,7 @@ public class FileHandler{
Files.copy(stream, profilesFolder.resolve(name));
return true;
}catch(IOException ex){
logger.warn("Encountered IOException while trying to create file %s", ex, name);
logger.warn("Encountered IOException while trying to create file <white>%s</white>", ex, name);
return false;
}
}
@@ -160,7 +212,7 @@ public class FileHandler{
File[] files = profilesFolder.toFile().listFiles(((dir, name) -> name.endsWith(".yml")));
if(files == null || files.length == 0){
logger.warn("Cannot load files from profiles folder! No valid YAML files present.");
logger.failure("Cannot load files from profiles folder! No valid YAML files present.");
return false;
}
@@ -170,11 +222,11 @@ public class FileHandler{
continue;
profiles.add(ServerListProfile.Builder.resolve(file.getName(), tmp, logger).build());
logger.info("Loaded '%s'!", file.getName());
logger.debugSuccess(FileHandler.class, "Loaded '<white>%s</white>'!", file.getName());
}
if(profiles.isEmpty()){
logger.warn("Couldn't load any profile from profiles folder!");
logger.failure("Couldn't load any profile from profiles folder!");
return false;
}
@@ -191,7 +243,7 @@ public class FileHandler{
try{
return loader.load();
}catch(IOException ex){
logger.warn("Cannot load '%s' due to an IOException!", ex, path.toFile().getName());
logger.warn("Cannot load '<white>%s</white>' due to an IOException!", ex, path.toFile().getName());
return null;
}
}
@@ -218,11 +270,11 @@ public class FileHandler{
}
private boolean makeBackup(){
logger.info("Making backup of old config.yml...");
logger.info("[-] Making backup of old config.yml...");
File backups = plugin.getPlugin().getFolderPath().resolve("backups").toFile();
File backups = plugin.plugin().folderPath().resolve("backups").toFile();
if(!backups.exists() && !backups.mkdirs()){
logger.warn("Cannot create backups folder for migration!");
logger.failure("Cannot create backups folder for migration!");
return false;
}
@@ -231,16 +283,16 @@ public class FileHandler{
File configBackup = new File(backups, "config_" + date.replace(":", "_") + ".yml");
try{
if(!configBackup.exists() && !configBackup.createNewFile()){
logger.warn("Cannot create backup file for config.yml!");
logger.failure("Cannot create backup file for config.yml!");
return false;
}
Files.copy(config, configBackup.toPath(), StandardCopyOption.REPLACE_EXISTING);
logger.info("Saved backup as '%s'!", configBackup.getName());
logger.success("Saved backup as '<white>%s</white>'!", configBackup.getName());
return true;
}catch(IOException ex){
logger.warn("Encountered IOException while trying to create a backup.", ex);
logger.failure("Encountered IOException while trying to create a backup.", ex);
return false;
}
}
@@ -27,10 +27,18 @@ package ch.andre601.advancedserverlist.core.interfaces;
public interface PluginLogger{
default void debugSuccess(Class<?> clazz, String msg, Object... args){
debug(clazz, "[<green>✓</green>] " + msg, args);
}
void debug(Class<?> clazz, String msg, Object... args);
void debugWarn(Class<?> clazz, String msg, Object... args);
default void success(String msg, Object... args){
info("[<green>✓</green>] " + msg, args);
}
void info(String msg, Object... args);
void warn(String msg, Object... args);
@@ -38,4 +46,8 @@ public interface PluginLogger{
void warn(String msg, Throwable throwable);
void warn(String msg, Throwable throwable, Object... args);
default void failure(String msg, Object... args){
warn("[<red>x</red>] " + msg, args);
}
}
@@ -25,12 +25,12 @@
package ch.andre601.advancedserverlist.core.interfaces.commands;
import net.kyori.adventure.audience.Audience;
public interface CmdSender{
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>] ";
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>] ";
boolean hasPermission(String permission);
String prefix = "<grey>[<aqua>ASL</aqua>] ";
String errorPrefix = "<grey>[<red>ASL</red>] ";
void sendMsg(String msg, Object... args);
@@ -45,4 +45,8 @@ public interface CmdSender{
default void sendErrorMsg(String msg, Object... args){
sendMsg(errorPrefix + msg, args);
}
Audience audience();
boolean isPlayer();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,17 +20,15 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.listeners;
package ch.andre601.advancedserverlist.core.interfaces.commands;
import ch.andre601.advancedserverlist.api.bungeecord.events.PreServerListSetEvent;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
public class PreServerListSetEventImpl extends PreServerListSetEvent{
public interface CommandManagerInterface<S>{
CommandManager<CmdSender> commandHandler();
public PreServerListSetEventImpl(ProfileEntry entry){
super(entry);
}
SenderMapper<S, CmdSender> senderMapper();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,32 +20,22 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.commands;
import java.util.Locale;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public abstract class PluginCommand{
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface CommandType{
Type value();
private final String argument;
public PluginCommand(String argument){
this.argument = argument;
enum Type{
ALL,
PLAYER_ONLY
}
public String name(){
return argument;
}
public String permission(){
return "advancedserverlist.command." + name().toLowerCase(Locale.ROOT);
}
public abstract void handle(CmdSender sender, String[] args);
public abstract String usage();
public abstract String description();
}
@@ -26,16 +26,19 @@
package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.dialogs.IDialog;
import ch.andre601.advancedserverlist.core.interfaces.dialogs.IDialogList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import org.incendo.cloud.CommandManager;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
public interface PluginCore<F>{
void loadCommands();
void loadEvents();
void loadMetrics();
@@ -46,26 +49,36 @@ public interface PluginCore<F>{
void downloadLibrary(String groupId, String artifactId, String version);
AdvancedServerList<F> getCore();
void startScheduler();
Path getFolderPath();
AdvancedServerList<F> core();
PluginLogger getPluginLogger();
Path folderPath();
FaviconHandler<F> getFaviconHandler();
PluginLogger pluginLogger();
String getPlatformInfo();
FaviconHandler<F> faviconHandler();
String getLoader();
CommandManager<CmdSender> commandManager();
String platformInfo();
String loader();
boolean isPluginEnabled(String plugin);
boolean isDialogsSupported();
F createFavicon(BufferedImage image) throws Exception;
IDialogList.IDialogListBuilder createDialogListBuilder(String title);
IDialog.IDialogBuilder createDialogBuilder(String title, ServerListProfile profile, int profilesPosition);
default boolean isDebugEnabled(){
if(getCore() == null)
if(core() == null)
return false;
return getCore().getFileHandler().getBoolean("debug");
return core().fileHandler().getBoolean("debug");
}
}
@@ -0,0 +1,24 @@
package ch.andre601.advancedserverlist.core.interfaces.dialogs;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.core.commands.CmdProfiles;
import java.util.List;
public interface IDialog<T>{
T createDialog();
interface IDialogBuilder{
IDialogBuilder appendBody(String body);
IDialogBuilder appendTextInput(CmdProfiles.ProfileOption option, String title, String initValue, int maxLength);
IDialogBuilder appendTextbox(CmdProfiles.ProfileOption option, String title, List<String> initValue, int maxLength, int rows);
IDialogBuilder appendNumberRange(CmdProfiles.ProfileOption option, String title, int initValue);
IDialogBuilder appendBoolean(CmdProfiles.ProfileOption option, String title, NullBool initValue);
IDialog<?> build();
}
}
@@ -0,0 +1,16 @@
package ch.andre601.advancedserverlist.core.interfaces.dialogs;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
public interface IDialogList{
void show(CmdSender sender);
interface IDialogListBuilder{
IDialogListBuilder appendBody(String body);
IDialogListBuilder appendDialog(IDialog<?> dialog);
IDialogList build();
}
}
@@ -40,19 +40,23 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
GenericServerListEvent callEvent(ProfileEntry entry);
void setMaxPlayers(int maxPlayers);
void maxPlayers(int maxPlayers);
void setMotd(Component component);
void onlinePlayers(int onlinePlayers);
void motd(Component component);
void hidePlayers();
void setPlayerCount(String name);
void playerCount(String name);
void setPlayers(List<String> players, P player, GenericServer server);
void players(List<String> players, P player, GenericServer server);
void setFavicon(F favicon);
void playersHidden();
void setDefaultFavicon();
void favicon(F favicon);
void defaultFavicon();
void updateEvent();
@@ -60,23 +64,23 @@ public interface GenericEventWrapper<F, P extends GenericPlayer>{
boolean isMaintenanceModeActive();
int getProtocolVersion();
int protocolVersion();
int getOnlinePlayers();
int onlinePlayers();
int getMaxPlayers();
int maxPlayers();
String getPlayerIP();
String playerIP();
String parsePAPIPlaceholders(String text, P player);
String getVirtualHost();
String virtualHost();
PluginCore<F> getPlugin();
PluginCore<F> plugin();
P createPlayer(CachedPlayer player, int protocol);
GenericServer createGenericServer(int playersOnline, int playersMax, String host);
GenericServer createServer(int playersOnline, int playersMax, String host);
default String resolveHost(InetSocketAddress address){
return address == null ? null : address.getHostString();
@@ -49,14 +49,16 @@ import java.util.List;
public class MiniMOTDConfigMigrator{
public static boolean migrate(AdvancedServerList<?> core, CmdSender sender){
core.getPlugin().downloadLibrary("org.spongepowered", "configurate-hocon", "4.1.2");
sender.sendMsg("Loading Configurate-Hocon library. This may take a while...");
core.plugin().downloadLibrary("org.spongepowered", "configurate-hocon", "4.1.2");
sender.sendMsg("<green>Library loaded!");
PluginLogger logger = core.getPlugin().getPluginLogger();
String folder = core.getPlugin().getLoader().equals("velocity") ? "minimotd-velocity" : "MiniMOTD";
PluginLogger logger = core.plugin().pluginLogger();
String folder = core.plugin().loader().equals("velocity") ? "minimotd-velocity" : "MiniMOTD";
Path mainConf = core.getPlugin().getFolderPath().getParent().resolve(folder).resolve("main.conf");
Path mainConf = core.plugin().folderPath().getParent().resolve(folder).resolve("main.conf");
if(!Files.exists(mainConf)){
logger.warn("[Migrator - MiniMOTD] Cannot find a main.conf file in /plugins/%s/ folder.", folder);
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot find a main.conf file in <white>/plugins/%s/</white> folder.", folder);
sender.sendErrorMsg(" -> <red>No main.conf file found.");
return false;
}
@@ -76,13 +78,13 @@ public class MiniMOTDConfigMigrator{
config = node.get(MiniMOTDConfig.class);
}catch(IOException ex){
logger.warn("[Migrator - MiniMOTD] Encountered IOException while loading main.conf file.", ex);
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered IOException while loading main.conf file.", ex);
sender.sendErrorMsg(" -> <red>IOException while loading</red> main.conf <red>file.");
return false;
}
if(config == null){
logger.warn("[Migrator - MiniMOTD] Retrieved main.conf file returned null.");
logger.warn("[<white>Migrator - MiniMOTD</white>] Retrieved main.conf file returned null.");
sender.sendErrorMsg(" -> <red>Received invalid</red> main.conf <red>file.");
return false;
}
@@ -98,7 +100,7 @@ public class MiniMOTDConfigMigrator{
if(config.motdEnabled()){
if(config.motds().size() == 1){
applyMotd(profileBuilder, config.motds().get(0));
applyMotd(profileBuilder, config.motds().getFirst());
}else
if(config.motds().size() > 1){
for(int i = 0; i < config.motds().size(); i++){
@@ -109,15 +111,15 @@ public class MiniMOTDConfigMigrator{
if(config.iconEnabled()){
if(config.motds().size() == 1){
MiniMOTDConfig.Motd motd = config.motds().get(0);
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
MiniMOTDConfig.Motd motd = config.motds().getFirst();
if(!motd.icon().isEmpty()){
profileBuilder.favicon(motd.icon());
}
}else
if(config.motds().size() > 1){
for(int i = 0; i < config.motds().size(); i++){
MiniMOTDConfig.Motd motd = config.motds().get(i);
if(!motd.icon().isEmpty() && !motd.icon().equalsIgnoreCase("random")){
if(!motd.icon().isEmpty()){
profilesBuilders.get(i).favicon(motd.icon());
}
}
@@ -135,9 +137,9 @@ public class MiniMOTDConfigMigrator{
profileBuilder.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(xMoreEnabled)
.extraPlayersCount(xMore)
.extraPlayersCount(String.valueOf(xMore))
.maxPlayersEnabled(maxPlayersEnabled)
.maxPlayersCount(maxPlayers);
.maxPlayersCount(String.valueOf(maxPlayers));
}
ProfileEntry entry = profileBuilder.build();
@@ -147,14 +149,14 @@ public class MiniMOTDConfigMigrator{
boolean profilesInvalid = profiles.isEmpty() || profiles.stream().allMatch(ProfileEntry::isInvalid);
if(entry.isInvalid() && profilesInvalid){
logger.warn("[Migrator - MiniMOTD] Main ProfileEntry was invalid and profiles were empty.");
logger.warn("[<white>Migrator - MiniMOTD</white>] Main ProfileEntry was invalid and profiles were empty.");
sender.sendErrorMsg(" -> <red>Received invalid configuration.");
return false;
}
Path profile = core.getPlugin().getFolderPath().resolve("profiles").resolve("minimotd_migrated.yml");
Path profile = core.plugin().folderPath().resolve("profiles").resolve("minimotd_migrated.yml");
if(Files.exists(profile)){
logger.warn("[Migrator - MiniMOTD] Cannot create new file minimotd_migrated.yml. One with the same name is already present.");
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot create new file minimotd_migrated.yml. One with the same name is already present.");
sender.sendErrorMsg(" -> <red>File</red> minimotd_migrated.yml <red>already present.");
return false;
@@ -163,7 +165,7 @@ public class MiniMOTDConfigMigrator{
try{
Files.createFile(profile);
}catch(IOException ex){
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to create file minimotd_migrated.yml.", ex);
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to create file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File creation error.");
return false;
@@ -180,14 +182,14 @@ public class MiniMOTDConfigMigrator{
try{
migrated = yamlLoader.load();
}catch(IOException ex){
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to load file minimotd_migrated.yml.", ex);
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to load file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File loading error.");
return false;
}
if(migrated == null){
logger.warn("[Migrator - MiniMOTD] Cannot migrate Configuration. ConfigurationNode was null.");
logger.warn("[<white>Migrator - MiniMOTD</white>] Cannot migrate Configuration. ConfigurationNode was null.");
sender.sendErrorMsg(" -> <red>File loading error.");
return false;
@@ -202,7 +204,7 @@ public class MiniMOTDConfigMigrator{
migrated.set(entry);
}catch(SerializationException ex){
logger.warn("[Migrator - MiniMOTD] Encountered a SerializationException while setting values.", ex);
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered a SerializationException while setting values.", ex);
sender.sendErrorMsg(" -> <red>Error while updating file</red> minimotd_migrated.yml<red>.");
return false;
@@ -214,7 +216,7 @@ public class MiniMOTDConfigMigrator{
return true;
}catch(IOException ex){
logger.warn("[Migrator - MiniMOTD] Encountered an IOException while trying to save new file minimotd_migrated.yml.", ex);
logger.warn("[<white>Migrator - MiniMOTD</white>] Encountered an IOException while trying to save new file minimotd_migrated.yml.", ex);
sender.sendErrorMsg(" -> <red>File saving error.");
return false;
@@ -59,26 +59,55 @@ public class SLPConfigMigrator{
"(?<end>#[a-fA-F0-9]{6})" + // Ending color
"%" +
"(?<text>.+?)" + // Text
"%gradient%");
"%gradient%"
);
private static final Map<String, String> STATIC_REPLACEMENTS = Map.of(
"%player%", "${player name}",
"%uuid%", "${player uuid}",
"%_uuid_%", "${player uuid}",
"%online%", "${server playersOnline}",
"%max%", "${server playersMax}");
"%max%", "${server playersMax}"
);
private static final Map<String, String> COLOR_TO_MINIMESSAGE_TAG = new HashMap<>(){{
// Color Codes.
put("a", "<green>");
put("b", "<aqua>");
put("c", "<red>");
put("d", "<light_purple>");
put("e", "<yellow>");
put("f", "<white>");
put("0", "<black>");
put("1", "<dark_blue>");
put("2", "<dark_green>");
put("3", "<dark_aqua>");
put("4", "<dark_red>");
put("5", "<dark_purple>");
put("6", "<gold>");
put("7", "<grey>");
put("8", "<dark_grey>");
put("9", "<blue>");
// Formatting Codes
put("k", "<obfuscated>");
put("l", "<bold>");
put("m", "<strikethrough>");
put("n", "<underlined>");
put("o", "<italic>");
put("r", "<reset>");
}};
public static int migrate(AdvancedServerList<?> core, CmdSender sender){
ServerListPlusCore slpCore = ServerListPlusCore.getInstance();
PluginLogger logger = core.getPlugin().getPluginLogger();
PluginLogger logger = core.plugin().pluginLogger();
if(slpCore == null){
logger.warn("[Migrator - ServerListPlus] Cannot migrate ServerListPlus config. ServerListPlus is not active!");
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate ServerListPlus config. ServerListPlus is not active!");
return 0;
}
ServerStatusConf conf = slpCore.getConf(ServerStatusConf.class);
if(conf == null){
logger.warn("[Migrator - ServerListPlus] Cannot migrate ServerListPlus configuration. Received configuration was null.");
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate ServerListPlus configuration. Received configuration was null.");
return 0;
}
@@ -99,9 +128,9 @@ public class SLPConfigMigrator{
}
private static int parseConf(AdvancedServerList<?> core, CmdSender sender, PersonalizedStatusConf.StatusConf conf, Type type){
PluginLogger logger = core.getPlugin().getPluginLogger();
PluginLogger logger = core.plugin().pluginLogger();
if(conf == null){
logger.info("[Migrator - ServerListPlus] No StatusConf found for type %s. Skipping...", type.getName());
logger.info("[<white>Migrator - ServerListPlus</white>] No StatusConf found for type <white>%s</white>. Skipping...", type.getName());
sender.sendPrefixedMsg(" -> Not found! Skipping...");
return 0;
@@ -129,7 +158,7 @@ public class SLPConfigMigrator{
apply(motds, builder, profiles, ProfileEntry.Builder::motd);
apply(favicons, builder, profiles, ProfileEntry.Builder::favicon);
apply(hovers, builder, profiles, ProfileEntry.Builder::players);
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(count));
apply(maxPlayers, builder, profiles, (build, count) -> build.maxPlayersEnabled(NullBool.TRUE).maxPlayersCount(String.valueOf(count)));
apply(playerCount, builder, profiles, ProfileEntry.Builder::playerCountText);
builder.hidePlayersEnabled(hidePlayers);
@@ -141,15 +170,15 @@ public class SLPConfigMigrator{
boolean profilesInvalid = profileEntries.isEmpty() || profileEntries.stream().anyMatch(ProfileEntry::isInvalid);
if(entry.isInvalid() && profilesInvalid){
logger.warn("[Migrator - ServerListPlus] Unable to parse ServerListPlus configuration of type %s. Generated ProfileEntry was invalid.", type.getName());
logger.warn("[<white>Migrator - ServerListPlus</white>] Unable to parse ServerListPlus configuration of type <white>%s</white>. Generated ProfileEntry was invalid.", type.getName());
sender.sendErrorMsg(" -> <red>Received invalid Configuration.");
return 0;
}
Path profile = core.getPlugin().getFolderPath().resolve("profiles").resolve(type.getFile());
Path profile = core.plugin().folderPath().resolve("profiles").resolve(type.getFile());
if(Files.exists(profile)){
logger.warn("[Migrator - ServerListPlus] Cannot create new file %s. One with the same name is already present", type.getFile());
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot create new file <white>%s</white>. One with the same name is already present", type.getFile());
sender.sendErrorMsg(" -> <red>File</red> %s <red>already present.", type.getFile());
return 0;
@@ -158,7 +187,7 @@ public class SLPConfigMigrator{
try{
Files.createFile(profile);
}catch(IOException ex){
logger.warn("[Migrator - ServerListPlus] Encountered an IOException while trying to create file %s.", ex, type.getFile());
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to create file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File creation error.");
return 0;
@@ -175,14 +204,14 @@ public class SLPConfigMigrator{
try{
node = loader.load();
}catch(IOException ex){
logger.warn("[Migrator - ServerListPlus] Encountered an IOException while trying to load file %s.", ex, type.getFile());
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to load file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File loading error.");
return 0;
}
if(node == null){
logger.warn("[Migrator - ServerListPlus] Cannot migrate Configuration of type %s. ConfigurationNode was null.", type.getName());
logger.warn("[<white>Migrator - ServerListPlus</white>] Cannot migrate Configuration of type <white>%s</white>. ConfigurationNode was null.", type.getName());
sender.sendErrorMsg(" -> <red>File loading error.");
return 0;
@@ -194,9 +223,7 @@ public class SLPConfigMigrator{
if(type == Type.PERSONALIZED){
node.node("condition")
.set("${player name} != \"" +
core.getFileHandler().getString("Anonymous", "unknownPlayer", "name") +
"\"");
.set("${player name} != \"" + core.fileHandler().getString("Anonymous", "unknownPlayer", "name") + "\"");
}else
if(type == Type.BANNED){
node.node("condition")
@@ -209,7 +236,7 @@ public class SLPConfigMigrator{
node.set(entry);
}catch(SerializationException ex){
logger.warn("[Migrator - ServerListPlus] Encountered a SerializationException while setting values.", ex);
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered a SerializationException while setting values.", ex);
sender.sendErrorMsg(" -> <red>Error while updating file</red> %s<red>.", type.getFile());
return 0;
@@ -221,7 +248,7 @@ public class SLPConfigMigrator{
return 1;
}catch(IOException ex){
logger.warn("[Migrator - ServerListPlus] Encountered an IOException while trying to save new file %s.", ex, type.getFile());
logger.warn("[<white>Migrator - ServerListPlus</white>] Encountered an IOException while trying to save new file <white>%s</white>.", ex, type.getFile());
sender.sendErrorMsg(" -> <red>File saving error.");
return 0;
@@ -372,32 +399,11 @@ public class SLPConfigMigrator{
if(colorCodeMatcher.find()){
builder.setLength(0);
do{
String color = colorCodeMatcher.group("color").toLowerCase(Locale.ROOT);
switch(color){
case "a" -> colorCodeMatcher.appendReplacement(builder, "<green>");
case "b" -> colorCodeMatcher.appendReplacement(builder, "<aqua>");
case "c" -> colorCodeMatcher.appendReplacement(builder, "<red>");
case "d" -> colorCodeMatcher.appendReplacement(builder, "<light_purple>");
case "e" -> colorCodeMatcher.appendReplacement(builder, "<yellow>");
case "f" -> colorCodeMatcher.appendReplacement(builder, "<white>");
case "k" -> colorCodeMatcher.appendReplacement(builder, "<obfuscated>");
case "l" -> colorCodeMatcher.appendReplacement(builder, "<bold>");
case "m" -> colorCodeMatcher.appendReplacement(builder, "<strikethrough>");
case "n" -> colorCodeMatcher.appendReplacement(builder, "<underlined>");
case "o" -> colorCodeMatcher.appendReplacement(builder, "<italic>");
case "r" -> colorCodeMatcher.appendReplacement(builder, "<reset>");
case "0" -> colorCodeMatcher.appendReplacement(builder, "<black>");
case "1" -> colorCodeMatcher.appendReplacement(builder, "<dark_blue>");
case "2" -> colorCodeMatcher.appendReplacement(builder, "<dark_green>");
case "3" -> colorCodeMatcher.appendReplacement(builder, "<dark_aqua>");
case "4" -> colorCodeMatcher.appendReplacement(builder, "<dark_red>");
case "5" -> colorCodeMatcher.appendReplacement(builder, "<dark_purple>");
case "6" -> colorCodeMatcher.appendReplacement(builder, "<gold>");
case "7" -> colorCodeMatcher.appendReplacement(builder, "<grey>");
case "8" -> colorCodeMatcher.appendReplacement(builder, "<dark_grey>");
case "9" -> colorCodeMatcher.appendReplacement(builder, "<blue>");
// This one shouldn't be reachable given the pattern, but you never know...
default -> colorCodeMatcher.appendReplacement(builder, "&" + color);
for(Map.Entry<String, String> colorCodes : COLOR_TO_MINIMESSAGE_TAG.entrySet()){
if(!colorCodeMatcher.group("color").equalsIgnoreCase(colorCodes.getKey()))
continue;
colorCodeMatcher.appendReplacement(builder, colorCodes.getValue());
}
}while(colorCodeMatcher.find());
@@ -28,12 +28,12 @@ package ch.andre601.advancedserverlist.core.objects;
import java.time.Duration;
import java.util.function.Supplier;
public class CacheUtil<T>{
public class ValueCache<T>{
private final Duration duration;
private CacheValue<T> cache = null;
public CacheUtil(Duration duration){
public ValueCache(Duration duration){
this.duration = duration;
}
@@ -25,11 +25,13 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.compat.miniplaceholders.MiniPlaceholdersUtil;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.List;
import java.util.function.Function;
public class ComponentParser{
@@ -52,12 +54,24 @@ public class ComponentParser{
return new ComponentParser(text);
}
public static ComponentParser list(List<String> lines){
return new ComponentParser(String.join("\n", lines));
public static ComponentParser textFormatted(String text, Object... args){
return text(String.format(text, args));
}
public ComponentParser modifyText(Function<String, String> function){
this.text = function.apply(text);
return this;
}
public ComponentParser applyMMTags(PluginCore<?> plugin){
if(!plugin.isPluginEnabled("MiniPlaceholders"))
return this;
TagResolver resolver = MiniPlaceholdersUtil.tagResolvers();
Component component = mm.deserialize(this.text, resolver);
this.text = mm.serialize(component);
return this;
}
@@ -65,8 +79,16 @@ public class ComponentParser{
return mm.deserialize(text);
}
public static String toMMString(Component component){
return mm.serialize(component);
}
@Override
public String toString(){
return legacy.serialize(toComponent());
}
public String toStringStriped(){
return mm.stripTags(text);
}
}
@@ -0,0 +1,136 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.flattener.FlattenerListener;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;
public class TextCenterUtil{
private final ComponentFlattener COMPONENT_FLATTENER = ComponentFlattener.textOnly();
private final double MAX_WIDTH = 270.0; // Max width of the MOTD
private final int SPACE_WIDTH = 4;
private final Map<String, FontInfo> charWidths;
public TextCenterUtil(AdvancedServerList<?> plugin){
charWidths = loadFontWidths(plugin);
}
public String getCenteredText(String text){
if(!text.toLowerCase(Locale.ROOT).startsWith("<center>"))
return text;
if(getDefault() == null)
return text;
text = text.substring("<center>".length());
TextFlattenerListener listener = new TextFlattenerListener(this);
COMPONENT_FLATTENER.flatten(ComponentParser.text(text).toComponent(), listener);
double width = listener.getWidth();
if(width >= MAX_WIDTH)
return text;
return createSpaces(width) + text;
}
private double getCharWidth(int codePoint, boolean isBold, String fontName){
FontInfo font = charWidths.getOrDefault(fontName, getDefault());
if(font == null)
return -1.0;
int index = Arrays.binarySearch(font.codePoints, codePoint);
if(index < 0){
return isBold ? 7.0 : 6.0;
}else{
return isBold ? font.advanceBf[index] : font.advance[index];
}
}
private FontInfo getDefault(){
return charWidths.get("minecraft:default");
}
private String createSpaces(double length){
double remainder = MAX_WIDTH - length;
int padding = (int)Math.max(0, Math.floor(remainder / 2.0) - 1);
return " ".repeat(Math.floorDiv(padding, SPACE_WIDTH));
}
private Map<String, FontInfo> loadFontWidths(AdvancedServerList<?> plugin){
try(InputStream stream = plugin.getClass().getResourceAsStream("/char-widths.json.gz")){
if(stream == null){
plugin.plugin().pluginLogger().warn("Internal char-widths.json.gz couldn't be retrieved.");
plugin.plugin().pluginLogger().warn("The <center> Placeholder won't work.");
return new HashMap<>();
}
GZIPInputStream gzipStream = new GZIPInputStream(stream);
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipStream));
return new Gson().fromJson(reader, new TypeToken<Map<String, FontInfo>>(){}.getType());
}catch(IOException ex){
plugin.plugin().pluginLogger().warn("Encountered IOException while loading font widths.");
plugin.plugin().pluginLogger().warn("The <center> Placeholder won't work.");
plugin.plugin().pluginLogger().warn("Cause: <white>%s</white>", ex.getMessage());
return new HashMap<>();
}
}
private static class TextFlattenerListener implements FlattenerListener{
private double width = 0.0;
private boolean isBold = false;
private String font = "minecraft:default";
private final TextCenterUtil instance;
public TextFlattenerListener(TextCenterUtil instance){
this.instance = instance;
}
@Override
public void pushStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = true;
if(style.font() != null)
font = style.font().asString();
}
@Override
public void component(@NotNull String text){
for(int i = 0; i < text.length(); i++){
width += instance.getCharWidth(text.codePointAt(i), isBold, font);
}
}
@Override
public void popStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = false;
}
public double getWidth(){
return width;
}
}
private record FontInfo(int[] codePoints, float[] advance, float[] advanceBf){}
}
@@ -0,0 +1,81 @@
package ch.andre601.advancedserverlist.core.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.function.Function;
public class DatePlaceholder extends PlaceholderProvider{
public DatePlaceholder(){
super("date");
}
@Override
public @Nullable String parsePlaceholder(@NonNull String placeholder, @NonNull GenericPlayer player, @NonNull GenericServer server){
String[] args = placeholder.split("\\s+");
return switch(args[0]){
case "current" -> {
String format = "dd/MM/yyyy";
if(args.length > 1){
format = format(Arrays.copyOfRange(args, 1, args.length));
}
try{
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
yield dateFormat.format(new Date());
}catch(IllegalArgumentException ex){
yield "ERR: Invalid Date pattern " + format;
}
}
case "isBefore" -> compareDates(args, integer -> integer < 0);
case "isExactly" -> compareDates(args, integer -> integer == 0);
case "isAfter" -> compareDates(args, integer -> integer > 0);
default -> null;
};
}
private String format(String... args){
if(args.length == 0)
return "dd/MM/yyyy";
String format = String.join(" ", args);
if(format.trim().isEmpty()){
return "dd/MM/yyyy";
}else{
return format.trim();
}
}
private String compareDates(String[] args, Function<Integer, Boolean> function){
if(args.length == 1)
return "ERR: No Date provided!";
String targetDateStr = args[1];
String format = "dd/MM/yyyy";
if(args.length > 2){
format = format(Arrays.copyOfRange(args, 2, args.length));
}
SimpleDateFormat dateFormat;
try{
dateFormat = new SimpleDateFormat(format);
Date targetDate = dateFormat.parse(targetDateStr);
int diff = new Date().compareTo(targetDate);
return String.valueOf(function.apply(diff));
}catch(IllegalArgumentException ex){
return "ERR: Invalid Date format provided!";
}catch(ParseException ex){
return "ERR: Received invalid Date " + targetDateStr;
}
}
}
@@ -46,18 +46,27 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
return true;
ParseWarnCollector collector = new ParseWarnCollector(condition);
PluginLogger logger = core.getPlugin().getPluginLogger();
PluginLogger logger = core.plugin().pluginLogger();
boolean result = core.getParser().evaluate(condition, player, server, collector);
boolean result;
try{
result = core.parser().compileToBoolean(condition, collector, player, server);
}catch(Exception ex){
logger.warn("Encountered an Exception while parsing condition '%s'. Cause: %s", condition, ex.getMessage());
if(core.fileHandler().getBool(false, "debug"))
logger.warn("Stacktrace:", ex);
return false;
}
if(collector.hasWarnings()){
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
logger.warn("Encountered <white>%d</white> Error(s) while parsing condition for file '<white>%s</white>':", collector.getWarnings().size(), file);
for(ParseWarnCollector.Context context : collector.getWarnings()){
logger.warn(" - At position %s:", context.position() == -1 ? "Unknown" : context.position());
logger.warn(" %s", condition);
logger.warn(" ".repeat(context.position() + 4) + "^");
logger.warn(" -> %s", context.message());
logger.warn(" - At position <white>%s</white>:", context.position() == -1 ? "<italic>Unknown</italic>" : context.position());
logger.warn(" <white>%s</white>", condition);
logger.warn(" ".repeat(context.position() + 3) + "<red>^</red>");
logger.warn(" <grey>-></grey> %s", context.message());
}
}
@@ -70,7 +79,7 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
}
if(profiles.size() == 1)
return profiles.get(0); // No need to run a random for 1 profile.
return profiles.getFirst(); // No need to run a random for 1 profile.
synchronized(random){
return profiles.get(random.nextInt(profiles.size()));
@@ -146,7 +155,7 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
try{
this.profiles = node.node("profiles").getList(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the profiles entry for %s", ex, fileName);
logger.warn("Encountered a SerializationException while resolving the profiles entry for <white>%s</white>", ex, fileName);
}
return this;
@@ -159,7 +168,7 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
try{
this.defaultProfile = node.get(ProfileEntry.class);
}catch(SerializationException ex){
logger.warn("Encountered a SerializationException while resolving the global profile for %s", ex, fileName);
logger.warn("Encountered a SerializationException while resolving the global profile for <white>%s</white>", ex, fileName);
}
return this;
}
@@ -1,82 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.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 boolean evaluate(String text, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
ExpressionTemplate result = parser.parse(tokenizer.parse(text, player, server, collector), collector);
if(result == null)
return false;
return result.returnBooleanExpression().evaluate();
}
@Override
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()));
}
}
}
@@ -1,48 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.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);
}
@@ -1,85 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.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;
}
}
@@ -23,27 +23,46 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.reader;
package ch.andre601.advancedserverlist.core.profiles.conditions.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.conditions.tokens.PlaceholderToken;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.tokens.Token;
import ch.andre601.expressionparser.tokens.readers.TokenReader;
import java.text.ParsePosition;
public class PlaceholderTokenReader extends CustomTokenReader{
public class PlaceholderTokenReader extends TokenReader{
public PlaceholderTokenReader(int priority){
super(priority);
public PlaceholderTokenReader(){
super(-20);
}
@Override
public Token read(String text, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
public Token read(String text, ParsePosition position, ParseWarnCollector collector, Object... args){
GenericPlayer player = null;
GenericServer server = null;
for(Object arg : args){
if(arg instanceof GenericPlayer pl){
player = pl;
}else
if(arg instanceof GenericServer srv){
server = srv;
}
}
if(player == null || server == null){
collector.appendWarning(position.getIndex(), "Received null GenericPlayer or GenericServer instance.");
return null;
}
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;
@@ -23,9 +23,9 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.reader;
package ch.andre601.advancedserverlist.core.profiles.conditions.reader;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.advancedserverlist.core.profiles.conditions.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.parsers.ExpressionTemplateParser;
import ch.andre601.expressionparser.parsers.ValueReader;
@@ -37,8 +37,8 @@ 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);
if(tokens.getFirst() instanceof PlaceholderToken){
PlaceholderToken token = (PlaceholderToken)tokens.removeFirst();
return token.getValue();
}
return null;
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens;
package ch.andre601.advancedserverlist.core.profiles.conditions.tokens;
import ch.andre601.expressionparser.expressions.ToBooleanExpression;
import ch.andre601.expressionparser.expressions.ToDoubleExpression;
@@ -1,28 +1,3 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.handlers;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
@@ -42,10 +17,12 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
public class FaviconHandler<F>{
@@ -55,147 +32,338 @@ public class FaviconHandler<F>{
private final ThreadPoolExecutor faviconThreadPool;
private final Cache<String, CompletableFuture<F>> faviconCache;
private final Map<String, F> localFavicons = new HashMap<>();
private final Random random = new Random();
private final HttpClient client = HttpClient.newHttpClient();
private final Map<String, FaviconPair<F>> localFavicons = new HashMap<>();
public FaviconHandler(AdvancedServerList<F> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.faviconThreadPool = createFaviconThreadPool();
this.logger = core.plugin().pluginLogger();
this.faviconThreadPool = createThreadPool();
this.faviconCache = CacheBuilder.newBuilder()
.expireAfterWrite(core.getFileHandler().getLong(1, 1, "faviconCacheTime"), TimeUnit.MINUTES)
.build();
.expireAfterWrite(core.fileHandler().getLong(1, 1, "faviconCacheTime"), TimeUnit.MINUTES)
.build();
loadLocalFavicons();
}
public F getFavicon(String input){
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT).split("\\.")[0])){
return localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]);
public F favicon(String input){
if(localFavicons.containsKey(input.toLowerCase(Locale.ROOT))){
logger.debug(FaviconHandler.class, "Returning local Favicon '%s'.", input);
return localFavicons.get(input.toLowerCase(Locale.ROOT)).favicon();
}
try{
return faviconCache.get(input, () -> getFuture(input)).getNow(null);
}catch(ExecutionException ex){
logger.warn("Received ExecutionException while retrieving Favicon for '%s'.", ex, input);
return null;
if(input.equalsIgnoreCase("random")){
logger.debug(FaviconHandler.class, "Returning random local Favicon.");
FaviconPair<F> pair = randomFavicon();
if(pair == null){
logger.warn("Cannot return random Favicon. Make sure PNGs are available in the Favicons folder!");
return null;
}
return pair.favicon();
}
CompletableFuture<F> favicon = faviconCache.getIfPresent(input);
if(favicon != null)
return favicon.getNow(null);
logger.debug(FaviconHandler.class, "Processing '%s'", input);
if(input.contains(";")){
String[] parts = input.split(";");
logger.debug(FaviconHandler.class, "Handling multi-part Favicon: ['%s']", String.join("', '", parts));
favicon = CompletableFuture.supplyAsync(() -> {
List<BufferedImage> images = new ArrayList<>();
Arrays.stream(parts).forEach(part -> {
logger.debug(FaviconHandler.class, "Creating BufferedImage for part '%s'...", part);
images.add(create(part));
});
if(images.isEmpty()){
logger.debugWarn(FaviconHandler.class, "Unable to create Multi-part Favicon. List was empty.");
return null;
}
return composeFavicon(images);
}, faviconThreadPool);
}else{
logger.debug(FaviconHandler.class, "Handling Favicon input '%s'...", input);
favicon = CompletableFuture.supplyAsync(() -> {
logger.debug(FaviconHandler.class, "Creating BufferedImage for '%s'...", input);
BufferedImage image = create(input);
if(image == null){
logger.warn("Cannot create Favicon for '%s'. BufferedImage was null!", input);
return null;
}
return createFavicon(image);
}, faviconThreadPool);
}
faviconCache.put(input, favicon);
return favicon.getNow(null);
}
public void cleanCache(){
localFavicons.clear();
faviconCache.invalidateAll();
loadLocalFavicons();
}
private CompletableFuture<F> getFuture(String input){
private F composeFavicon(List<BufferedImage> images){
logger.debug(FaviconHandler.class, "Composing Favicon out of %d part(s)...", images.size());
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
String strategy = core.fileHandler().getString("resize", "faviconStrategy");
int layer = 0;
for(BufferedImage img : images){
layer++;
logger.debug(FaviconHandler.class, "Applying layer %d...", layer);
if(img == null){
logger.debugWarn(FaviconHandler.class, "Layer %d was null! Skipping...", layer);
continue;
}
switch(strategy.toLowerCase(Locale.ROOT)){
case "center" -> {
int height = img.getHeight();
int width = img.getWidth();
int posHeight = 0;
int posWidth = 0;
if(height != 64){
posHeight = (64 - height) / 2;
}
// 64 - 128 = -64
if(width != 64){
posWidth = (64 - width) / 2;
}
graphics.drawImage(img, posWidth, posHeight, img.getWidth(), img.getHeight(), null);
}
case "none" -> graphics.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);
default -> graphics.drawImage(img, 0, 0, 64, 64, null);
}
logger.debug(FaviconHandler.class, "Applied layer %d!", layer);
}
graphics.dispose();
logger.debug(FaviconHandler.class, "Image Composing complete! Creating Favicon instance...");
return createFavicon(image);
}
private BufferedImage create(String input){
if(input.toLowerCase(Locale.ROOT).startsWith("https://")){
logger.debug(FaviconHandler.class, "Resolving URL '%s'...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, input), this.faviconThreadPool);
logger.debug(FaviconHandler.class, "Handling URL '%s'...", input);
return fromURL(input);
}else
if(input.equalsIgnoreCase("random")){
logger.debug(FaviconHandler.class, "Returning random local Favicon...");
FaviconPair<F> pair = randomFavicon();
return pair == null ? null : pair.image();
}else
if(input.toLowerCase(Locale.ROOT).endsWith(".png")){
logger.debug(FaviconHandler.class, "Resolving image file '%s'...", input);
return CompletableFuture.completedFuture(localFavicons.get(input.toLowerCase(Locale.ROOT).split("\\.")[0]));
logger.debug(FaviconHandler.class, "Returning local Favicon '%s'...", input);
FaviconPair<F> pair = localFavicons.get(input.toLowerCase(Locale.ROOT));
return pair == null ? null : pair.image();
}else{
logger.debug(FaviconHandler.class, "Resolving Name/UUID as https://mc-heads.net/avatar/%s/64...", input);
return CompletableFuture.supplyAsync(() -> fromURL(core, "https://mc-heads.net/avatar/" + input + "/64"), this.faviconThreadPool);
logger.debug(FaviconHandler.class, "Handling Player Name/UUID '%s'...", input);
return fromURL("https://mc-heads.net/avatar/" + input + "/64");
}
}
private FaviconPair<F> randomFavicon(){
if(localFavicons.isEmpty())
return null;
List<FaviconPair<F>> favicons = new ArrayList<>(localFavicons.values());
if(favicons.isEmpty())
return null;
if(favicons.size() == 1)
return favicons.getFirst();
synchronized(random){
return favicons.get(random.nextInt(favicons.size()));
}
}
private void loadLocalFavicons(){
this.localFavicons.clear();
logger.info("Loading local image files as Favicons...");
logger.info("[-] Loading local images as Favicons...");
Path folder = core.getPlugin().getFolderPath().resolve("favicons");
Path folder = core.plugin().folderPath().resolve("favicons");
if(!Files.exists(folder)){
try{
Files.createDirectories(folder);
logger.info("Created favicons folder.");
logger.debugSuccess(FaviconHandler.class, "Created favicons folder");
}catch(IOException ex){
logger.warn("Cannot create favicons folder. Encountered an IOException.", ex);
logger.warn("Encountered IOException while creating favicons folder.", ex);
return;
}
}
try(Stream<Path> pathStream = Files.list(folder)){
pathStream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
try(Stream<Path> stream = Files.list(folder)){
stream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
logger.success("Loaded <white>%s</white> local Favicon(s).", localFavicons.size());
}catch(IOException ex){
logger.warn("Cannot load files from Favicons folder.", ex);
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered IOException while loading local favicons.", ex);
}else{
logger.warn("Encountered IOException while loading local favicons. Reason: %s", ex.getMessage());
}
}
}
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());
BufferedImage image = createBufferedImage(stream);
if(image == null)
return;
}
localFavicons.put(path.getFileName().toString().split("\\.")[0], favicon);
logger.info("Loaded file '%s' as Favicon.", path.getFileName().toString());
F favicon = core.plugin().createFavicon(image);
if(favicon == null)
return;
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), new FaviconPair<>(image, favicon));
}catch(IOException ex){
logger.warn("Cannot create Favicon from file '%s'. Encountered IOException.", ex);
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered IOException while creating a Favicon from '%s'.", ex, path.getFileName().toString());
}else{
logger.warn("Encountered IOException while creating a Favicon from '%s'. Reason: %s", path.getFileName().toString(), ex.getMessage());
}
}catch(Exception ex){
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered Exception while creating a Favicon from '%s'.", ex, path.getFileName().toString());
}else{
logger.warn("Encountered Exception while creating a Favicon from '%s'. Reason: %s", path.getFileName().toString(), ex.getMessage());
}
}
}
private F fromURL(AdvancedServerList<F> core, String url){
private BufferedImage fromURL(String url){
try{
logger.debug(FaviconHandler.class, "Creating Request for URL '%s'...", url);
logger.debug(FaviconHandler.class, "Creating request for URL '%s'...", url);
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(url))
.header("User-Agent", "AdvancedServerList-" + core.getPlugin().getLoader() + "/" + core.getVersion())
.build();
.uri(new URI(url))
.header("User-Agent", "AdvancedServerList-" + core.plugin().loader() + "/" + core.version())
.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 createBufferedImage(stream);
}catch(IOException ex){
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered IOException while performing a web request for '%s'.", ex, url);
}else{
logger.warn("Encountered IOException while performing a web request for '%'. Reason: %s", url, ex.getMessage());
}
return null;
}catch(InterruptedException ex){
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered an InterruptedException while performing a web request for '%s'.", ex, url);
}else{
logger.warn("Encountered an InterruptedException while performing a web request for '%s'. Reason: %s", url, ex.getMessage());
}
return null;
}
}catch(URISyntaxException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an IOException.", ex, url);
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered an URISyntaxException while performing a web request for '%s'.", ex, url);
}else{
logger.warn("Encountered an URISyntaxException while performing a web request for '%s'. Reason: %s", url, ex.getMessage());
}
return null;
}
}
private F createFavicon(InputStream stream){
private BufferedImage createBufferedImage(InputStream stream){
logger.debug(FaviconHandler.class, "Creating BufferedImage from InputStream...");
try{
logger.debug(FaviconHandler.class, "Creating BufferedImage from InputStream...");
BufferedImage original = ImageIO.read(stream);
if(original == null){
logger.warn("Cannot create Favicon. Received null BufferedImage.");
logger.warn("Cannot create Favicon. Received a null BufferedImage!");
return null;
}
// Don't waste resources resizing images already having right size.
if(original.getWidth() == 64 && original.getHeight() == 64){
logger.debug(FaviconHandler.class, "BufferedImage is 64x64 pixels. No resizing needed.");
return core.getPlugin().createFavicon(original);
logger.debug(FaviconHandler.class, "Check image size for possible resizing...");
if(original.getHeight() == 64 && original.getWidth() == 64){
logger.debug(FaviconHandler.class, "Image is 64x64. No resizing needed!");
return original;
}
logger.debug(FaviconHandler.class, "Resizing image to 64x64 pixels...");
logger.debug(FaviconHandler.class, "Applying Favicon resize strategy...");
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = image.createGraphics();
Graphics2D graphics = image.createGraphics();
graphics2D.drawImage(original, 0, 0, 64, 64, null);
graphics2D.dispose();
String resizeMode = core.fileHandler().getString("resize", "faviconStrategy");
switch(resizeMode.toLowerCase(Locale.ROOT)){
case "center" -> {
int height = original.getHeight();
int width = original.getWidth();
int posHeight = 0;
int posWidth = 0;
if(height != 64){
posHeight = (64 - height) / 2;
}
if(width != 64){
posWidth = (64 - width) / 2;
}
graphics.drawImage(original, posWidth, posHeight, original.getWidth(), original.getHeight(), null);
}
case "none" -> graphics.drawImage(original, 0, 0, original.getWidth(), original.getHeight(), null);
default -> graphics.drawImage(original, 0, 0, 64, 64, null);
}
logger.debug(FaviconHandler.class, "Image resized! Returning Favicon...");
return core.getPlugin().createFavicon(image);
}catch(Exception ex){
logger.warn("Unable to create Favicon. Received Exception.", ex);
graphics.dispose();
logger.debug(FaviconHandler.class, "Image resized. Returning it...");
return image;
}catch(IOException ex){
logger.warn("Encountered an IOException while processing Favicon!", ex);
return null;
}
}
private ThreadPoolExecutor createFaviconThreadPool(){
private F createFavicon(BufferedImage image){
try{
return core.plugin().createFavicon(image);
}catch(Exception ex){
if(core.fileHandler().getBool(false, "debug")){
logger.warn("Encountered an Exception while trying to create a Favicon instance.", ex);
}else{
logger.warn("Encountered an Exception while trying to create a Favicon instance. Reason: %s", ex.getMessage());
}
return null;
}
}
private ThreadPoolExecutor createThreadPool(){
return new ThreadPoolExecutor(3, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024), r -> {
Thread t = new Thread(r, "AdvancedServerList-FaviconThread");
t.setDaemon(true);
return t;
});
}
private record FaviconPair<F>(BufferedImage image, F favicon){}
}
@@ -61,8 +61,8 @@ public class PlayerHandler{
public PlayerHandler(AdvancedServerList<?> core){
this.core = core;
this.logger = core.getPlugin().getPluginLogger();
this.cache = core.getPlugin().getFolderPath().resolve("playercache.json");
this.logger = core.plugin().pluginLogger();
this.cache = core.plugin().folderPath().resolve("playercache.json");
}
public void load(){
@@ -71,7 +71,7 @@ public class PlayerHandler{
return;
}
if(core.getFileHandler().getBoolean("disableCache")){
if(core.fileHandler().getBoolean("disableCache")){
logger.info("'disableCache' is set to true. Skipping playercache.json loading...");
return;
}
@@ -79,54 +79,52 @@ public class PlayerHandler{
try(BufferedReader reader = Files.newBufferedReader(cache)){
cachedPlayers = gson.fromJson(reader, listType);
}catch(IOException ex){
logger.warn("Encountered IOException while reading the playercache.json file!", ex);
logger.warn("Encountered IOException while reading the <white>playercache.json</white> file!", ex);
return;
}catch(JsonIOException | JsonSyntaxException ex){
logger.warn("Encountered JsonSyntaxException while parsing playercache.json file!", ex);
logger.warn("Encountered JsonSyntaxException while parsing <white>playercache.json</white> file!", ex);
return;
}
// In case Gson messes up... I guess.
if(cachedPlayers == null){
logger.warn("Couldn't load players from playercache.json file. Is the JSON valid?");
logger.warn("Couldn't load players from <white>playercache.json</white> file. Is the JSON valid?");
// Create new ArrayList instance to avoid further issues.
cachedPlayers = new ArrayList<>();
return;
}
logger.info("Loaded %d players into cache!", cachedPlayers.size());
logger.success("Loaded <white>%d</white> players into cache!", cachedPlayers.size());
}
public void save(){
if(cachedPlayers.isEmpty()){
logger.info("No players in cache to save. Skipping...");
logger.debug(PlayerHandler.class, "No players in cache to save. Skipping...");
return;
}
if(core.getFileHandler().getBoolean("disableCache")){
logger.info("'disable_cache' is set to true. Skipping saving of cached players...");
if(core.fileHandler().getBoolean("disableCache")){
logger.debug(PlayerHandler.class, "[-] 'disable_cache' is set to true. Not saving cached players.");
return;
}
try(BufferedWriter writer = Files.newBufferedWriter(cache, StandardCharsets.UTF_8)){
gson.toJson(cachedPlayers, listType, writer);
logger.info("Successfully saved playercache.json file.");
logger.success("Successfully saved <white>playercache.json</white> file.");
}catch(IOException ex){
logger.warn("Encountered IOException while saving cached players to playercache.json!", ex);
logger.failure("Encountered IOException while saving cached players to <white>playercache.json</white>!", ex);
}
}
public void addPlayer(String ip, String name, UUID uuid){
if(contains(ip) || core.getFileHandler().getBoolean("disableCache"))
if(contains(ip) || core.fileHandler().getBoolean("disableCache"))
return;
cachedPlayers.add(new CachedPlayer(ip, name, uuid));
}
public CachedPlayer getCachedPlayer(String key){
if(!contains(key) || core.getFileHandler().getBoolean("disableCache"))
if(!contains(key) || core.fileHandler().getBoolean("disableCache"))
return getDefaultPlayer();
for(CachedPlayer player : cachedPlayers){
@@ -166,8 +164,8 @@ public class PlayerHandler{
return (defaultPlayer = new CachedPlayer(
"0.0.0.0",
core.getFileHandler().getString("Anonymous", "unknownPlayer", "name"),
convertToUUID(core.getFileHandler().getString(defaultUUID.toString(), "unknownPlayer", "uuid"))
core.fileHandler().getString("Anonymous", "unknownPlayer", "name"),
convertToUUID(core.fileHandler().getString(defaultUUID.toString(), "unknownPlayer", "uuid"))
));
}
@@ -55,15 +55,30 @@ public class ProfileManager{
NullBool hidePlayersEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersEnabled);
NullBool extraPlayersEnabled = resolve(defEntry, entry, ProfileEntry::extraPlayersEnabled);
NullBool maxPlayersEnabled = resolve(defEntry, entry, ProfileEntry::maxPlayersEnabled);
Integer extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
Integer maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
NullBool onlinePlayersEnabled = resolve(defEntry, entry, ProfileEntry::onlinePlayersEnabled);
NullBool hidePlayersHoverEnabled = resolve(defEntry, entry, ProfileEntry::hidePlayersHoverEnabled);
String extraPlayersCount = resolve(defEntry, entry, ProfileEntry::extraPlayersCount);
String maxPlayersCount = resolve(defEntry, entry, ProfileEntry::maxPlayersCount);
String onlinePlayersCount = resolve(defEntry, entry, ProfileEntry::onlinePlayersCount);
return new ProfileEntry(motd, players, playerCountText, favicon, hidePlayersEnabled, extraPlayersEnabled,
maxPlayersEnabled, extraPlayersCount, maxPlayersCount);
return new ProfileEntry.Builder()
.motd(motd)
.players(players)
.playerCountText(playerCountText)
.favicon(favicon)
.hidePlayersEnabled(hidePlayersEnabled)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.onlinePlayersEnabled(onlinePlayersEnabled)
.hidePlayersHoverEnabled(hidePlayersHoverEnabled)
.extraPlayersCount(extraPlayersCount)
.maxPlayersCount(maxPlayersCount)
.onlinePlayersCount(onlinePlayersCount)
.build();
}
public static ServerListProfile resolveProfile(AdvancedServerList<?> core, GenericPlayer player, GenericServer server){
for(ServerListProfile profile : core.getFileHandler().getProfiles()){
for(ServerListProfile profile : core.fileHandler().profiles()){
if(profile.isInvalidProfile())
continue;
@@ -82,8 +97,11 @@ public class ProfileManager{
NullBool hidePlayers = resolveNullBool(node, "playerCount", "hidePlayers");
NullBool extraPlayersEnabled = resolveNullBool(node, "playerCount", "extraPlayers", "enabled");
NullBool maxPlayersEnabled = resolveNullBool(node, "playerCount", "maxPlayers", "enabled");
Integer extraPlayers = resolveNullableInt(node, "playerCount", "extraPlayers", "amount");
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
NullBool onlinePlayersEnabled = resolveNullBool(node, "playerCount", "onlinePlayers", "enabled");
NullBool hidePlayersHoverEnabled = resolveNullBool(node, "playerCount", "hidePlayersHover");
String extraPlayers = resolveNullableString(node, "playerCount", "extraPlayers", "amount");
String maxPlayers = resolveNullableString(node, "playerCount", "maxPlayers", "amount");
String onlinePlayers = resolveNullableString(node, "playerCount", "onlinePlayers", "amount");
return new ProfileEntry.Builder()
.motd(motd)
@@ -93,26 +111,22 @@ public class ProfileManager{
.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.onlinePlayersEnabled(onlinePlayersEnabled)
.hidePlayersHoverEnabled(hidePlayersHoverEnabled)
.extraPlayersCount(extraPlayers)
.maxPlayersCount(maxPlayers)
.onlinePlayersCount(onlinePlayers)
.build();
}
public static boolean checkOption(Object obj){
if(obj == null)
return false;
return switch(obj){
case List<?> list -> !list.isEmpty(); // Check if list isn't empty
case String str -> !str.isEmpty(); // Check if String is not empty
case NullBool nb -> nb.getOrDefault(false); // Return NullBool's value
case null, default -> false;
};
if(obj instanceof List<?> list){
return !list.isEmpty(); // Check if list isn't empty
}else
if(obj instanceof String str){
return !str.isEmpty(); // Check if String is not empty
}else
if(obj instanceof NullBool nb){
return nb.getOrDefault(false); // Return NullBool's value
}
return false;
}
private static <T> T resolve(ProfileEntry defProfile, ProfileEntry profile, Function<ProfileEntry, T> function){
@@ -137,10 +151,10 @@ public class ProfileManager{
return NullBool.resolve(node.node(path).getBoolean());
}
private static Integer resolveNullableInt(ConfigurationNode node, Object... path){
private static String resolveNullableString(ConfigurationNode node, Object... path){
if(node.node(path).virtual())
return null;
return node.node(path).getInt();
return node.node(path).getString();
}
}
@@ -53,9 +53,12 @@ public class ProfileSerializer implements TypeSerializer<ProfileEntry>{
node.node("playerCount", "text").set(profile.playerCountText());
node.node("favicon").set(profile.favicon());
node.node("playerCount", "hidePlayers").set(profile.hidePlayersEnabled().getOrDefault(false));
node.node("playerCount", "hidePlayersHover").set(profile.hidePlayersHoverEnabled().getOrDefault(false));
node.node("playerCount", "extraPlayers", "enabled").set(profile.extraPlayersEnabled().getOrDefault(false));
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? 0 : profile.extraPlayersCount());
node.node("playerCount", "extraPlayers", "amount").set((profile.extraPlayersCount() == null) ? "0" : profile.extraPlayersCount());
node.node("playerCount", "maxPlayers", "enabled").set(profile.maxPlayersEnabled().getOrDefault(false));
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? 0 : profile.maxPlayersCount());
node.node("playerCount", "maxPlayers", "amount").set((profile.maxPlayersCount() == null) ? "0" : profile.maxPlayersCount());
node.node("playerCount", "onlinePlayers", "enabled").set(profile.onlinePlayersEnabled().getOrDefault(false));
node.node("playerCount", "onlinePlayers", "amount").set(profile.onlinePlayersCount() == null ? "0" : profile.onlinePlayersCount());
}
}
@@ -30,13 +30,18 @@ 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.advancedserverlist.core.profiles.conditions.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import java.text.ParsePosition;
import java.util.function.Function;
public class StringReplacer{
public static StringModifier modifier(String text){
return new StringModifier(text);
}
public static String replace(String input, GenericPlayer player, GenericServer server){
if(input == null)
return null;
@@ -63,7 +68,7 @@ public class StringReplacer{
}
private static String parsePlaceholder0(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
AdvancedServerListAPI api = AdvancedServerList.getApi();
AdvancedServerListAPI api = AdvancedServerList.api();
int index = position.getIndex();
StringBuilder identifier = new StringBuilder();
@@ -72,6 +77,9 @@ public class StringReplacer{
boolean identified = false;
boolean invalid = true;
int placeholderStart = position.getIndex() - 1;
int valueStart = position.getIndex() - 1;
char[] chars = input.substring(index).toCharArray();
for(final char c : chars){
index++;
@@ -83,6 +91,7 @@ public class StringReplacer{
if(c == ' ' && !identified){
identified = true;
valueStart = index + 1;
continue;
}
@@ -98,10 +107,6 @@ public class StringReplacer{
StringBuilder raw = new StringBuilder();
// Condition parsing needs one extra increase of index... for some reason
if(collector != null)
index++;
position.setIndex(index);
if(invalid){
@@ -111,7 +116,7 @@ public class StringReplacer{
raw.append(' ').append(valuesStr);
if(collector != null)
collector.appendWarningFormatted(index, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
collector.appendWarningFormatted(index, "Placeholder '<white>%s</white>' does not have a closing bracket (})", raw.toString());
return raw.toString();
}
@@ -126,7 +131,7 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(index, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
collector.appendWarningFormatted(placeholderStart, "Placeholder '<white>%s</white>' does not have any available PlaceholderProvider", raw.toString());
return raw.toString();
}
@@ -141,11 +146,29 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(index, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
collector.appendWarningFormatted(valueStart, "Placeholder '<white>%s</white>' has an invalid value String '<white>%s</white>'", raw.toString(), valuesStr);
return raw.toString();
}
return replacement;
}
public static class StringModifier{
private String value;
public StringModifier(String value){
this.value = value;
}
public StringModifier modify(Function<String, String> function){
this.value = function.apply(value);
return this;
}
public String asString(){
return value;
}
}
}
Binary file not shown.
+33
View File
@@ -48,6 +48,14 @@ checkUpdates: true
#
debug: false
#
# Should the "ASL" ASCI art be displayed on plugin startup?
# Setting this to false will hide the banner.
#
# Default: true
#
printBanner: true
#
# Sets how long Favicons should be cached. Value is in minutes with the lowest possible value being 1.
#
@@ -58,6 +66,19 @@ debug: false
#
faviconCacheTime: 1
#
# Sets how AdvancedServerList should handle the size and positioning of images for favicons.
#
# Available options:
#
# - resize: Resizes the image to 64x64 pixels if it isn't these dimensions already.
# - center: Doesn't resize the image, but instead tries to center it as good as possible in a 64x64 area.
# - none: Doesn't resize the image and leaves it positioned at x 0 and y 0 (top-left) of the 64x64 area.
#
# Setting any not listed option or leaving this blank/removing it sets the option to resize.
#
faviconResizeStrategy: 'resize'
#
# Options to disable while the Maintenance Plugin is present and Maintenance Mode is active.
#
@@ -84,6 +105,12 @@ disableDuringMaintenance:
#
hidePlayers: true
#
# Whether hiding player list on hover should be disabled while Maintenance mode is active.
#
# Default: true
#
hidePlayersHover: true
#
# Whether player count text changing should be disabled while Maintenance mode is active.
#
# Default: true
@@ -107,6 +134,12 @@ disableDuringMaintenance:
# Default: true
#
maxPlayers: true
#
# Whether the online players feature should be disabled while Maintenance mode is active.
#
# Default: true
#
onlinePlayers: true
#
# DO NOT EDIT!
+75 -29
View File
@@ -2,7 +2,7 @@
# Set the priority of this profile.
# If there are multiple profiles (files) will they be sorted by priority, starting with highest.
#
# Read more: https://asl.andre601.ch/profiles/#priority
# Read more: https://asl.andre601.ch/profiles/options/priority/
#
priority: 0
@@ -10,11 +10,11 @@ priority: 0
# Set condition(s) that should return true to display this profile.
# This allows you to create profiles to only show for specific scenarios (i.e. player is banned).
#
# Multiple conditions can be chaing with the keywords 'and', 'or', or their counterparts '&&' and '||'.
# 'AND'/'&&' and 'OR'/'||' can be used to chain together multiple conditions.
#
# No condition or an empty condition will be treated as true by default.
# Removing the condition option or setting it to an empty String will be treated as a true condition being returned.
#
# Read more: https://asl.andre601.ch/profiles/#condition
# Read more: https://asl.andre601.ch/profiles/options/condition
#
condition: ''
@@ -30,7 +30,7 @@ condition: ''
#
# 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
# Read more: https://asl.andre601.ch/profiles/options/profiles
#
profiles:
- motd: ['<aqua>Line A', '<gold>Line B']
@@ -40,14 +40,17 @@ profiles:
#
# Set the "Message of the day" to display.
# This option supports RGB colors for 1.16+ Servers and clients, including gradients using MiniMessage's <gradient>
# option.
# This option supports RGB colors for 1.16+ Servers and clients. More advanced MiniMessage features such as <gradient>
# can be used for further styling the text.
#
# <center> can be put at the start of a line to have AdvancedServerList automatically center the text as good as
# possible.
#
# Only the first two lines will be considered and any additional one is ignored.
#
# When not present or empty (motd: []), no MOTD will be set.
#
# Read more: https://asl.andre601.ch/profiles/#motd
# Read more: https://asl.andre601.ch/profiles/options/motd
#
motd:
- '<grey>First Line'
@@ -55,28 +58,36 @@ motd:
#
# Set the Favicon (image on the left of a server entry) to display.
# This option supports three types of inputs:
# This option supports three types of input:
#
# 1. Name, including .png extension, pointing to an image located in the plugin's favicons folder.
# 2. 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.
# 1. Filename, including the .png extension, matching a filename in the favicons folder of the plugin.
# - 'random' can be used to have AdvancedServerList select a random image from the favicons folder every time
# the server is pinged.
# 3. URL pointing to an image.
# 4. Player name, UUID or a placeholder that returns either.
# - 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.
# Any image below or above 64x64 pixels will be resized according to the faviconResizeMode option in the config.yml.
#
# If not present or empty (favicon: ''), defaults to not modifying the favicon.
#
# Read more: https://asl.andre601.ch/profiles/#favicon
# Read more: https://asl.andre601.ch/profiles/options/favicon
#
# "The favicon isn't showing!"
# This is a side effect of using either URLs or player names/UUIDs for the favicon.
# These types require AdvancedServerList to create a new favicon object from scratch. This action takes a significant
# amount of time, which can cause the server to show with a huge ping.
# To avoid this is this action performed asynchronously. This means that the plugin doesn't wait for the favicon to
# be created before continuing, which can result in no favicon being available when it is done handling the ping.
# This should only happen for the first ping of a player and subsequent pings should display the favicon, if the
# pings are done within the configured cache time (See 'faviconCacheTime' in the config.yml).
#
favicon: ''
#
# Contains options for modifying the player count (Text displaying <online>/<max>).
#
# Read more: https://asl.andre601.ch/profiles/#playercount
# Read more: https://asl.andre601.ch/profiles/options/playercount
#
playerCount:
#
@@ -86,17 +97,26 @@ playerCount:
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#hideplayers
# Read more: https://asl.andre601.ch/profiles/options/playercount/hideplayers
#
hidePlayers: false
#
# Set whether the List of players is shown when hovering over the player count.
# Setting this to true will also make the plugin ignore the hover option below.
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/options/playercount/hideplayershover
#
hidePlayersHover: false
#
# Set the lines shown when the player hovers over the player count.
# Unlike the MOTD option does this one only support basic color and formatting codes. Any RGB colors will be
# downsampled to the nearest matching color.
# down-sampled to the nearest matching color.
#
# If not present or empty (hover: []), defaults to not modifying the hover.
#
# Read more: https://asl.andre601.ch/profiles/#hover
# Read more: https://asl.andre601.ch/profiles/options/playercount/hover
#
hover:
- '<aqua>Line 1'
@@ -110,7 +130,7 @@ playerCount:
#
# If not present or empty (text: ''), defaults to not modifying the text.
#
# Read more: https://asl.andre601.ch/profiles/#text
# Read more: https://asl.andre601.ch/profiles/options/playercount/text
#
text: ''
#
@@ -119,7 +139,7 @@ playerCount:
#
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers
# Read more: https://asl.andre601.ch/profiles/options/playercount/extraplayers
#
extraPlayers:
#
@@ -129,18 +149,19 @@ playerCount:
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-enabled
# Read more: https://asl.andre601.ch/profiles/options/playercount/extraplayers#enabled
#
enabled: false
#
# Set the number that should be added to the online player count to then use as the new max player count.
# Placeholders resolving to numbers can be used here.
#
# Example: Setting this to 1 will result in ${server playersMax} displaying 11 while 10 players are online,
# 9 when 8 are online and so on.
#
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#extraplayers-amount
# Read more: https://asl.andre601.ch/profiles/options/playercount/extraplayers#amount
#
amount: 0
#
@@ -148,7 +169,7 @@ playerCount:
#
# Using this feature will modify the ${server playersMax} placeholder, except for usage in the condition option.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers
# Read more: https://asl.andre601.ch/profiles/options/playercount/maxplayers
#
maxPlayers:
#
@@ -157,14 +178,39 @@ playerCount:
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-enabled
# Read more: https://asl.andre601.ch/profiles/options/playercount/maxplayers#enabled
#
enabled: false
#
# Set the number that should be used as the new max players count.
# Placeholders resolving to numbers can be used here.
#
# If not present, defaults to 0.
#
# Read more: https://asl.andre601.ch/profiles/#maxplayers-amount
# Read more: https://asl.andre601.ch/profiles/options/playercount/maxplayers#amount
#
amount: 0
#
# The onlinePlayers feature allows to set a number to use as the online player count to display.
#
# Read more: https://asl.andre601.ch/profiles/options/playercount/onlineplayers
#
onlinePlayers:
#
# Set whether the onlinePlayers feature should be enabled or not.
# When set to true, the max player count will be set to the 'amount' value.
#
# If not present, defaults to false.
#
# Read more: https://asl.andre601.ch/profiles/options/playercount/onlineplayers#enabled
#
enabled: false
#
# Set the number that should be used as the new online players count.
# Placeholders resolving to numbers can be used here.
#
# If not present, defaults to current online player count.
#
# Read more: https://asl.andre601.ch/profiles/options/playercount/onlineplayers#amount
#
amount: 0
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
@@ -23,29 +23,37 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.expressionparser.DefaultExpressionParserEngine;
import ch.andre601.expressionparser.ParseWarnCollector;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ExpressionParserTests{
private final ProfileConditionParser parser = ProfileConditionParser.create();
private final DefaultExpressionParserEngine parser = DefaultExpressionParserEngine.createDefault();
private final DummyPluginLogger logger = new DummyPluginLogger();
private final Map<String, Boolean> testValuesMap = getTestMap();
private final TestPlayer player = new TestPlayer();
private final TestServer server = new TestServer();
@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());
boolean result = parser.evaluate(values.getKey(), null, null, collector);
boolean result = parser.compileToBoolean(values.getKey(), collector, player, server);
logger.info("Result (Output, Expected?): %b, %b", result, (result == values.getValue()));
assertEquals(result, values.getValue());
@@ -66,4 +74,38 @@ public class ExpressionParserTests{
"false or 100 < 10", false
);
}
private static class TestPlayer implements GenericPlayer{
@Override
public @NonNull String getName(){
return "Lorem";
}
@Override
public int getProtocol(){
return 1;
}
@Override
public @NonNull UUID getUUID(){
return UUID.randomUUID();
}
}
private static class TestServer implements GenericServer{
@Override
public int getPlayersOnline(){
return 10;
}
@Override
public int getPlayersMax(){
return 20;
}
@Override
public @Nullable String getHost(){
return "play.example.com";
}
}
}
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import com.unascribed.flexver.FlexVerComparator;
import org.junit.jupiter.api.Test;
+15
View File
@@ -0,0 +1,15 @@
def on_pre_page_macros(env):
footer = """
{% if page.meta and page.meta.api %}
{% include 'api_docs/constructor_summaries.md' %}
{% include 'api_docs/nested_class_summaries.md' %}
{% include 'api_docs/enum_summaries.md' %}
{% include 'api_docs/method_summaries.md' %}
{% include 'api_docs/constructor_details.md' %}
{% include 'api_docs/enum_details.md' %}
{% include 'api_docs/method_details.md' %}
{% endif %}
"""
env.markdown += footer
+23
View File
@@ -0,0 +1,23 @@
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
from re import Match
def on_page_markdown(
markdown: str, *, page: Page, config: MkDocsConfig, files: Files
):
def replace(match: Match):
platform = match.group(1)
if platform == "paper": return "[:fontawesome-solid-paper-plane:](https://papermc.io){ .md-button .md-button--icon title=\"PaperMC\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "bungee": return "[:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "velocity": return "[:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "proxies": return "[:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" } [:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
elif platform == "all": return "[:fontawesome-solid-paper-plane:](https://papermc.io){ .md-button .md-button--icon title=\"PaperMC\" target=\"_blank\" rel=\"noopener\" } [:simple-spigotmc:](https://spigotmc.org){ .md-button .md-button--icon title=\"BungeeCord\" target=\"_blank\" rel=\"noopener\" } [:simple-velocity:](https://velocitypowered.com){ .md-button .md-button--icon title=\"Velocity\" target=\"_blank\" rel=\"noopener\" }"
else: return platform
return re.sub(
r"<!-- icon:(paper|bungee|velocity|proxies|all) -->",
replace, markdown, flags = re.I | re.M
)
+1 -1
View File
@@ -17,7 +17,7 @@
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
def on_page_markdown(
-35
View File
@@ -1,35 +0,0 @@
{% extends "base.html" %}
{% import "api-objects/info-template.html" as info %}
{% block content %}
{% include "partials/content.html" %}
{% if page.meta %}
<!--
Object summaries
-->
{% if page.meta.constructors %}
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.classes %}
{{ info.summary('Class Summary', page.meta.classes, details_type='class', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.summary('Enum Constant Summary', page.meta.enums, details_type='enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods or page.meta.inherits %}
{{ info.summary('Method Summary', page.meta.methods, page.meta.inherits, details_type='method', defaults=page.meta.defaults) }}
{% endif %}
<!--
Detailed object info
-->
{% if page.meta.constructors %}
{{ info.info('Constructor Detail', page.meta.constructors, 'constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.info('Enum Constant Detail', page.meta.enums, 'enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods %}
{{ info.info('Method Detail', page.meta.methods, 'method', defaults=page.meta.defaults)}}
{% endif %}
{% endif %}
{% endblock %}
@@ -1,228 +0,0 @@
{% macro summary(title, summaries, inherits, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
{% if summaries %}
<table>
<thead>
<tr>
{% if details_type and details_type == "method" %}
<th>Modifier and Type</th>
{% endif %}
<th>{{ details_type | capitalize() }}</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for summary in summaries %}
<tr>
{% set modifiers = namespace(name = "") %}
{% for attribute in summary.attributes %}
{% set modifiers.name = modifiers.name ~ attribute %}
{% if loop.revindex > 0 %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
{% endfor %}
{% if modifiers.name %}{% set modifiers.name = modifiers.name ~ " " %}{% endif %}
{% if summary.type and summary.type.name %}
{% set modifiers.name = modifiers.name ~ summary.type.name %}
{% elif defaults and defaults.type and defaults.type.name %}
{% set modifiers.name = modifiers.name ~ defaults.type.name %}
{% else %}
{% set modifiers.name = modifiers.name ~ "void" %}
{% endif %}
{% set desc = "" %}
{% if summary.deprecated %}
{% set desc = "<api__deprecated></api__deprecated><br>" ~ summary.deprecated.split("<br>")[0] %}
{% elif summary.description %}
{% set desc = summary.description.split("<br>")[0] %}
{% endif %}
{% set final_name = namespace(name = "") %}
{% if details_type and details_type == "enum" %}
{% set final_name.name = summary.name | upper() %}
{% else %}
{% set final_name.name = summary.name ~ "(" %}
{% endif %}
{% for parameter in summary.parameters %}
{% set final_name.name = final_name.name ~ parameter.type %}
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
{% if details_type and details_type == "method" %}
{% if modifiers.name %}
<td><code>{{ modifiers.name }}</code></td>
{% else %}
<td></td>
{% endif %}
{% endif %}
<td>
{% if summary.link %}
<a href="{{ summary.link }}"><code>{{ final_name.name | e}}</code></a>
{% else %}
<a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}"><code>{{ final_name.name | e}}</code></a>
{% endif %}
</td>
<td>{{ desc }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if inherits %}
{% for classpath, inherit in inherits.items() %}
<table>
<thead>
<tr>
<th>Methods inherited from <a href="{{ inherit.link }}"><code>{{ classpath }}</code></a></th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% for inh in inherit.list %}
<a href="{{ inherit.link }}#{{ inh | lower() | replace(' ', '-') | e }}">
<code>{{- inh | e -}}</code>
</a>
{%- if loop.revindex > 1 %}, {% endif -%}
{% endfor %}
</td>
</tr>
</tbody>
</table>
{% endfor %}
{% endif %}
</div>
</div>
{%- endmacro %}
{% macro info(title, details, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
{% for detail in details %}
<div class="api-detail">
{% set final_name = namespace(name = "") %}
{% if details_type == "enum" %}
{% set final_name.name = detail.name | upper() %}
{% else %}
{% set final_name.name = detail.name ~ "(" %}
{% endif %}
{% for parameter in detail.parameters %}
{% set final_name.name = final_name.name ~ parameter.type %}
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
<h3 id="{{ final_name.name | lower() | replace(' ', '-') | e }}">
{% if detail.deprecated %}
<api__deprecated></api__deprecated>
{% endif %}
{% for attribute in detail.attributes %}
<api__{{- attribute -}}></api__{{- attribute -}}>
{% endfor %}
{% if enum %}
<api__static></api__static> <api__final></api__final>
{% endif %}
{% if detail.type and details_type == "method" %}
{% if detail.type.link %}
<a href="{{ detail.type.link }}" class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</span>
{% endif %}
{% elif defaults and defaults.type and details_type == "method" %}
{% if defaults.type.link %}
<a href="{{ defaults.type.link }}" class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') }}</span>
{% endif %}
{% elif details_type == "method" %}
<span class="api-type__primitive">void</span>
{% endif %}
<code>{{ final_name.name | e }}</code><a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}" class="headerlink" title="Permanent link"></a>
</h3>
{% if detail.deprecated %}
<div class="admonition deprecated">
<div class="admonition-title">Deprecation Warning</div>
<p>
{{ detail.deprecated }}
</p>
</div>
{% endif %}
{% if detail.description %}
<p class="api-detail__description">
{{ detail.description }}
</p>
{% endif %}
{% if detail.parameters %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-parameters">
Parameters:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-parameters" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for parameter in detail.parameters %}
<li>
{% for attribute in parameter.attribute %}
<api__{{- attribute -}}></api__{{- attribute -}}>
{% endfor %}
<code>{{ parameter.type | e }}: {{ parameter.name }}</code>{% if parameter.description %} - {{ parameter.description }}{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% if detail.returns %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-returns">
Returns:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-returns" class="headerlink" title="Permanent link"></a>
</h4>
<p class="api-detail__description">
{{ detail.returns }}
</p>
{% endif %}
{% if detail.throws %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-throws">
Throws:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-throws" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for throw in detail.throws %}
<li>
<code>{{ throw.name }}</code>{% if throw.description %} - {{ throw.description }}{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% if seealso %}
<h4 id="{{ detail.name | lower() | replace(' ', '-') | e }}-see-also">
See also:<a href="#{{ detail.name | lower() | replace(' ', '-') | e }}-see-also" class="headerlink" title="Permanent link"></a>
</h4>
<ul>
{% for see in detail.seealso %}
<li>
<a href="{{ see.link }}"><code>{{ see.name }}</code></a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
{%- endmacro %}
@@ -0,0 +1,61 @@
{% if page.meta.constructors %}
## Constructor Details
{% for constructor in page.meta.constructors %}
<div class="api-detail" markdown>
{% set name = namespace(text = constructor.name ~ "(") %}
{% for parameter in constructor.parameters %}
{% set name.text = name.text ~ parameter.type %}
{% if loop.revindex > 1 %}{% set name.text = name.text ~ ", " %}{% endif %}
{% endfor %}
{% set name.text = name.text ~ ")" %}
{% if constructor.deprecated %}
{% set name.text = "<api__deprecated></api__deprecated> " ~ name.text %}
{% endif %}
{% for attribute in constructor.attributes %}
{% set name.text = "<api__{{- attribute -}}></api__{{- attribute -}}> " ~ name.text %}
{% endfor %}
### {{ name.text | e }} { #{{ constructor.name | lower() | replace(' ', '-') | e }} }
{% if constructor.deprecated %}
/// deprecated | Deprecation Warning
{{ constructor.deprecated }}
///
{% endif %}
{% if constructor.description %}
<p class="api-detail__description">
{{ constructor.description }}
</p>
{% endif %}
{% if constructor.parameters %}
#### Parameters: { #{{ constructor.name | lower() | replace(' ', '-') | e }}-parameters }
{% for parameter in constructor.parameters %}
- {% for attribute in parameter.attributes %}<api__{{- attribute -}}></api__{{- attribute -}}>{% endfor %} `{{ parameter.type | e}}: {{ parameter.name }}`{% if parameter.description %} - {{ parameter.description }}{% endif %}
{% endfor %}
{% endif %}
{% if constructor.seealso %}
#### See also: { #{{ constructor.name | lower() | replace(' ', '-') | e }}-see-also }
<div class="api-detail__description" markdown>
{% for see in constructor.seealso %}
- [`{{ see.name }}`]({{ see.link }})
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,14 @@
{% if page.meta.constructors %}
## Constructor Summary
| Constructor | Description |
|-------------|-------------|{% for constructor in page.meta.constructors %}
| [`{{ constructor.name }}({% for parameter in constructor.parameters -%}
{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}
{%- endfor %})`](#{{ constructor.name | lower() }}) | {% if constructor.deprecated -%}
<api__deprecated></api__deprecated> {{ constructor.deprecated.split("\n")[0] }}
{%- elif constructor.description -%}
{{ constructor.description.split("\n")[0] }}
{%- endif %} |
{%- endfor %}
{% endif %}
+32
View File
@@ -0,0 +1,32 @@
{% if page.meta.enums %}
## Enum Constant Details
{% for enum in page.meta.enums %}
<div class="api-detail" markdown>
{% set modifiers = namespace(text = "<api__static></api__static> <api__final></api__final> ") %}
{% if enum.deprecated %}
{% set modifiers.text = "<api__deprecated></api__deprecated> " ~ modifiers.text %}
{% endif %}
### {{ modifiers.text }} `{{ enum.name | upper() }}` { #{{ enum.name | lower() | replace(' ', '-') | e }} }
{% if enum.deprecated %}
/// deprecated | Deprecation Warning
{{ enum.deprecated }}
///
{% endif %}
{% if enum.description %}
<div class="api-detail__description" markdown>
{{ enum.description }}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,8 @@
{% if page.meta.enums %}
## Enum Constant Summary
| Enum | Description |
|------|-------------|{% for enum in page.meta.enums %}
| [`{{ enum.name | upper() }}`](#{{ enum.name | lower() }}) | {{ enum.description.split("\n")[0] }} |
{%- endfor %}
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
{% macro render_name(method) -%}
{{ method.name }}({% for parameter in method.parameters %}{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}{% endfor %})
{%- endmacro %}
+109
View File
@@ -0,0 +1,109 @@
{% if page.meta.methods %}
## Method Details
{% for method in page.meta.methods %}
<div class="api-detail" markdown>
{% set modifiers = namespace(text = "") %}
{% if method.deprecated %}
{% set modifiers.text = "<api__deprecated></api__deprecated> " %}
{% endif %}
{% for attribute in method.attributes %}
{% set modifiers.text = modifiers.text ~ "<api__" ~ attribute ~ "></api__" ~ attribute ~ ">" %}
{% if loop.revindex > 0 %}{% set modifiers.text = modifiers.text ~ " " %}{% endif %}
{% endfor %}
{% if modifiers.text %}{% set modifiers.text = modifiers.text ~ " " %}{% endif %}
{% set method_type = "" %}
{% if method.type %}
{% if method.type.link %}
{% set method_type = '[' ~ method.type.name|default('void')|e ~ '](' ~ method.type.link ~ '){ .api-type__' ~ method.type.type|default('primitive') ~ '} ' %}
{% else %}
{% set method_type = '<span class="api-type__' ~ method.type.type|default('primitive') ~ '">' ~ method.type.name|default('void')|e ~ '</span> ' %}
{% endif %}
{% elif page.meta.defaults and page.meta.defaults.type %}
{% if page.meta.defaults.type.link %}
{% set method_type = '[' ~ page.meta.defaults.type.name|default('void')|e ~ '](' ~ page.meta.defaults.type.link ~ '){ .api-type__' ~ page.meta.defaults.type.type|default('primitive') ~ '} ' %}
{% else %}
{% set method_type = '<span class="api-type__' ~ page.meta.defaults.type.type|default('primitive') ~ '">' ~ page.meta.defaults.type.name|default('void')|e ~ '</span> ' %}
{% endif %}
{% else %}
{% set method_type = '<span class="api-type__primitive">void</span> ' %}
{% endif %}
{% set name = namespace(text = method.name ~ "(") %}
{% for parameter in method.parameters %}
{% set name.text = name.text ~ parameter.type %}
{% if loop.revindex > 1 %}{% set name.text = name.text ~ ", " %}{% endif %}
{% endfor %}
{% set name.text = name.text ~ ")" %}
### {{ modifiers.text }} {{ method_type }} `{{ name.text }}` { #{{ method.name | lower() | replace(' ', '-') | e }} }
{% if method.deprecated %}
/// deprecated | Deprecation Warning
{{ method.deprecated }}
///
{% endif %}
{% if method.description %}
<div class="api-detail__description" markdown>
{{ method.description }}
</div>
{% endif %}
{% if method.parameters %}
#### Parameters: { #{{ method.name | lower() | replace(' ', '-') | e }}-parameters }
<div class="api-detail__description" markdown>
{% for parameter in method.parameters %}
- {% for attribute in parameter.attributes %}<api__{{- attribute -}}></api__{{- attribute -}}>{% endfor %} `{{ parameter.type | e}}: {{ parameter.name }}`{% if parameter.description %} - {{ parameter.description }}{% endif %}
{% endfor %}
</div>
{% endif %}
{% if method.returns %}
#### Returns: { #{{ method.name | lower() | replace(' ', '-') | e }}-returns }
<div class="api-detail__description" markdown>
{{ method.returns }}
</div>
{% endif %}
{% if method.throws %}
#### Throws: { #{{ method.name | lower() | replace(' ', '-') | e }}-throws }
<div class="api-detail__description" markdown>
{% for throw in method.throws %}
- `{{ throw.name }}`{% if throw.description %} - {{ throw.description }}{% endif %}
{% endfor %}
</div>
{% endif %}
{% if method.seealso %}
#### See also: { #{{ method.name | lower() | replace(' ', '-') | e }}-see-also }
<div class="api-detail__description" markdown>
{% for see in method.seealso %}
- [`{{ see.name }}`]({{ see.link }})
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
@@ -0,0 +1,31 @@
{% if page.meta.methods or page.meta.inherits %}
## Method Summary
{% if page.meta.methods %}
| Modifier and Type | Method | Description |
|-------------------|--------|-------------|{% for method in page.meta.methods %}
| `{% if method.attributes -%}
{% for attribute in method.attributes -%}
{{ attribute }}{% if loop.revindex > 0 %} {% endif %}
{%- endfor %} {%- endif %}{% if method.type and method.type.name -%}
{{ method.type.name }}
{%- elif page.meta.defaults and page.meta.defaults.type and page.meta.defaults.type.name -%}
{{ page.meta.defaults.type.name }}
{%- else -%}void{%- endif %}` | [`{{ method.name }}({% for parameter in method.parameters -%}
{{ parameter.type }}{% if loop.revindex > 1 %}, {% endif %}
{%- endfor %})`](#{{ method.name | lower() }}) | {% if method.deprecated -%}
<api__deprecated></api__deprecated> {{ method.deprecated.split("\n")[0] }}
{%- elif method.description -%}
{{ method.description.split("\n")[0] }}
{%- endif %} |
{%- endfor %}
{% endif %}
{% if page.meta.inherits %}
{% for classpath, inherit in page.meta.inherits.items() %}
| Methods inherited from [`{{ classpath }}`]({{ inherit.link }}) |
|----------------------------------------------------------------|
| {% for entry in inherit.list -%}[`{{ entry.name | e }}`]({{ inherit.link }}#{{ entry.link | lower() | replace(' ', '-') | e }}){% if loop.revindex > 1 %}, {% endif %}{% endfor %} |
{% endfor %}
{% endif %}
{% endif %}
@@ -0,0 +1,11 @@
{% if page.meta.classes %}
## Nested Class Summary
| Modifier and Type | Class | Description |
|-------------------|-------|-------------|{% for class in page.meta.classes %}
| `{% if class.attributes -%}
{% for attribute in class.attributes -%}
{{ attribute }}{% if loop.revindex > 1 %} {% endif %}
{%- endfor %} {%- endif %}{{ class.type }}` | [`{{ class.name }}`]({{ class.link }}) | {{ class.description.split("\n")[0] }} |
{%- endfor %}
{% endif %}
Loaded 100 of 220 files, more files were not shown because too many files have changed in this diff. Show more