Compare commits

...
41 Commits
Author SHA1 Message Date
Andre601 571f9f6b38 Add support for SayanVanish 2024-12-29 01:24:55 +01:00
Andre601 6d7fbb8c25 Merge pull request 'Update API reference' (#393) from feature/update-api-reference into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/393
2024-12-25 00:58:11 +00:00
Andre601 d3d83e5e11 Update ProfileEntry index page 2024-12-25 00:46:43 +00:00
Andre601 82fb9c90f4 Update API reference 2024-12-25 00:39:03 +00:00
Andre601 6841a5a6e0 Undo componentlogger changes on velocity 2024-12-24 22:27:26 +01:00
Andre601 6f41cd4e3a Use a fallback logger for velocity versions without ComponentLoggers 2024-12-24 22:05:56 +01:00
Andre601 379f36832e Use snippet links 2024-12-24 21:45:01 +01:00
Andre601 5d8a39cd22 Update config example in getting-started 2024-12-24 21:43:39 +01:00
Andre601 9dba820840 Reduce flood of messages on Startup + make ASL banner hidable.
(I really don't get why people get upset about a few lines of text... Won't make the Log file like 10GB bigger or smth...)
2024-12-24 21:41:39 +01:00
Andre601 58712ca5c5 Merge pull request 'Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0' (#392) from renovate/dependency.adventure-text-serializer-legacy into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/392
2024-12-24 12:04:13 +00:00
Andre601's Bot e19e942799 Update dependency net.kyori:adventure-text-serializer-legacy to v4.18.0 2024-12-24 12:01:21 +00:00
Andre601 03434130c4 Update dependency net.kyori:adventure-text-minimessage to v4.18.0 2024-12-23 13:20:48 +01:00
Andre601 99df25551a Merge pull request 'Update dependency net.kyori:adventure-api to v4.18.0' (#390) from renovate/dependency.adventure-api into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/390
2024-12-23 12:14:32 +00:00
Andre601's Bot 4f31e4ce6f Update dependency net.kyori:adventure-api to v4.18.0 2024-12-23 12:01:35 +00:00
Andre601 ba097c538d Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.15' (#389) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/389
2024-12-22 13:03:31 +00:00
Andre601's Bot aa52435591 Update dependency ch.qos.logback:logback-classic to v1.5.15 2024-12-22 12:01:59 +00:00
Andre601 f44194d24f Update docs 2024-12-21 02:21:33 +01:00
Andre601 0e2d760ea6 Upload center_text_example.jpg 2024-12-20 13:31:42 +00:00
Andre601 c1e7e6b3ff Merge pull request 'Add support for centering MOTD lines' (#388) from feature/motd-center-feature into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/388
2024-12-20 13:24:41 +00:00
Andre601 96d383a5a1 Merge branch 'master' into feature/motd-center-feature 2024-12-20 13:24:11 +00:00
Andre601 79ba7877bf Bump version and add docs 2024-12-20 13:46:53 +01:00
Andre601 86b9aaa7c6 Add support for centering MOTD lines 2024-12-20 13:40:11 +01:00
Andre601 0cb3c036af Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.14' (#387) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/387
2024-12-20 12:11:41 +00:00
Andre601's Bot b1f7b75e2d Update dependency ch.qos.logback:logback-classic to v1.5.14 2024-12-20 12:01:15 +00:00
Andre601 e9bc72c165 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.13' (#386) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/386
2024-12-19 12:02:24 +00:00
Andre601's Bot 93203249fe Update dependency ch.qos.logback:logback-classic to v1.5.13 2024-12-19 12:01:11 +00:00
Andre601 2523ccb425 Merge pull request 'Update dependency com.google.guava:guava to v33.4.0-jre' (#384) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/384
2024-12-17 12:04:55 +00:00
Andre601 94972dad31 Merge pull request 'Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4' (#383) from renovate/org.junit.jupiter-junit-jupiter-engine-5.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/383
2024-12-17 12:04:39 +00:00
Andre601's Bot f8ac310259 Update dependency com.google.guava:guava to v33.4.0-jre 2024-12-17 12:01:48 +00:00
Andre601's Bot 5d8f5d81ed Update dependency org.junit.jupiter:junit-jupiter-engine to v5.11.4 2024-12-17 12:01:40 +00:00
Andre601 3111d7933d Merge pull request 'Move Migration pages to sub-pages' (#382) from docs/move-migration-pages into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/382
2024-12-16 21:42:31 +00:00
Andre601 55f7e17d34 Fix typo. 2024-12-16 21:42:14 +00:00
Andre601 0e88a50deb Move Migration pages to sub-pages 2024-12-16 22:38:55 +01:00
Andre601 83f351de6d Try github.run_number variable 2024-12-16 19:42:19 +00:00
Andre601 b96d1cb1a9 Merge pull request 'Update dependency mkdocs-material to v9.5.49' (#381) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/381
2024-12-16 12:04:47 +00:00
Andre601's Bot 517ff1df82 Update dependency mkdocs-material to v9.5.49 2024-12-16 12:01:18 +00:00
Andre601 e8c7c4ee18 Merge pull request 'Update Wiki Announcement' (#380) from feature/wiki-update-announcement into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/380
2024-12-13 14:15:21 +00:00
Andre601 da44eac70e Fix typos 2024-12-13 14:05:41 +00:00
Andre601 e85c121ee4 Add missing .svg 2024-12-13 13:58:10 +00:00
Andre601 0c175999fc Update announcement 2024-12-13 13:57:32 +00:00
Andre601 9c3f237f6d Use ruby for hocon highlighting 2024-12-11 20:42:52 +01:00
57 changed files with 622 additions and 362 deletions

No files matched your search

+6 -5
View File
@@ -16,6 +16,7 @@ on:
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:
@@ -91,7 +92,7 @@ jobs:
|---------|----------------------------------------------------------------------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Preview | https://preview.andre601.ch/@${{ github.event.repository.name }}~${{ github.event.pull_request.number }} |
| Logs | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
| Logs | ${{ env.RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
@@ -105,10 +106,10 @@ jobs:
Pull request Preview failed! Check the logs for details.
| Name | Link |
|---------|-------------------------------------------------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Logs | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
| Name | Link |
|---------|-------------------------------------------|
| Commit | ${{ github.event.pull_request.head.sha }} |
| Logs | ${{ RUN_URL }} |
comment-id: "${{ steps.comment.outputs.comment-id }}"
issue-number: "${{ github.event.pull_request.number }}"
token: "${{ secrets.BOT_TOKEN }}"
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

+16
View File
@@ -49,6 +49,10 @@
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
</repository>
</repositories>
<dependencies>
@@ -124,6 +128,18 @@
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-bungeecord</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<!-- Other -->
<dependency>
@@ -47,6 +47,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import org.sayandev.sayanvanish.bungeecord.api.SayanVanishBungeeAPI;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
@@ -55,6 +56,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
@@ -71,12 +73,13 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
@Override
public void onLoad(){
logger.info("Loading libraries. This may take a while...");
// Using getLogger() here, because PluginLogger requires MiniMessage, which isn't loaded at this stage.
getLogger().info("Loading libraries. This may take a while...");
successfulLoad = loadLibs();
if(successfulLoad){
logger.info("Library loading completed successfully!");
getLogger().info("Library loading completed successfully!");
}else{
logger.warn("Library loading completed with errors!");
getLogger().warning("Library loading completed with errors!");
}
}
@@ -84,7 +87,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
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.");
logger.warn("Aborting further enabling of the plugin to avoid errors.");
return;
}
@@ -97,11 +100,13 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
public void onDisable(){
core.disable();
getProxy().getScheduler().cancel(this);
audiences.close();
}
@Override
public void loadCommands(){
getProxy().getPluginManager().registerCommand(this, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
@@ -206,6 +211,9 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().getPlugin("PremiumVanish") != null){
players.removeIf(BungeeVanishAPI::isInvisible);
}else // Do the same if SayanVanish is enabled.
if(getProxy().getPluginManager().getPlugin("SayanVanish") != null){
players.removeIf(player -> SayanVanishBungeeAPI.getInstance().isVanished(player.getUniqueId()));
}
return players.size();
@@ -226,7 +234,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
return true;
}catch(Exception ex){
logger.warn("Encountered an Exception while trying to load dependencies.", ex);
getLogger().log(Level.WARNING, "Encountered an Exception while trying to load dependencies.", ex);
return false;
}
}
@@ -27,6 +27,7 @@ package ch.andre601.advancedserverlist.bungeecord.logging;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -55,21 +56,21 @@ public class BungeeLogger implements PluginLogger{
@Override
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
logger.info(ComponentParser.textFormatted(msg, args).toStringStriped());
}
@Override
public void warn(String msg, Object... args){
logger.warning(String.format(msg, args));
logger.warning(ComponentParser.textFormatted(msg, args).toStringStriped());
}
@Override
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
logger.log(Level.WARNING, ComponentParser.text(msg).toStringStriped(), throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
logger.log(Level.WARNING, ComponentParser.textFormatted(msg, args).toStringStriped(), throwable);
}
}
+15 -3
View File
@@ -41,7 +41,7 @@
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>6</plugin.config.version>
<plugin.config.version>7</plugin.config.version>
</properties>
<repositories>
@@ -80,6 +80,8 @@
<version>1.5.0</version>
<scope>compile</scope>
</dependency>
<!-- Configuration -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
@@ -129,7 +131,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.3.1-jre</version>
<version>33.4.0-jre</version>
<scope>provided</scope>
</dependency>
@@ -157,7 +159,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.3</version>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -168,6 +170,16 @@
<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>
@@ -32,6 +32,7 @@ import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenancePlaceholder;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
@@ -47,6 +48,8 @@ public class AdvancedServerList<F>{
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final TextCenterUtil textCenterUtil;
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private final ProfileConditionParser parser = ProfileConditionParser.create();
@@ -59,18 +62,18 @@ public class AdvancedServerList<F>{
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.textCenterUtil = new TextCenterUtil(this);
plugin.getPluginLogger().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();
getPlugin().getPluginLogger().info("Starting <white>AdvancedServerList v%s</white>...", version);
load();
}
@@ -110,16 +113,20 @@ public class AdvancedServerList<F>{
return updateChecker;
}
public TextCenterUtil getTextCenterUtil(){
return textCenterUtil;
}
public void disable(){
getPlugin().getPluginLogger().info("Saving playercache.json file...");
getPlugin().getPluginLogger().info("[-] Saving <white>playercache.json</white> file...");
getPlayerHandler().save();
if(updateChecker != null){
getPlugin().getPluginLogger().info("Disabling Update Checker...");
getPlugin().getPluginLogger().info("[-] Disabling Update Checker...");
updateChecker.disable();
}
getPlugin().getPluginLogger().info("AdvancedServerList disabled!");
getPlugin().getPluginLogger().success("AdvancedServerList disabled!");
}
public void clearFaviconCache(){
@@ -131,70 +138,56 @@ public class AdvancedServerList<F>{
}
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(!getFileHandler().loadConfig()){
getPlugin().getPluginLogger().failure("Unable to load <white>config.yml</white>! Check previous lines for errors.");
return;
}
if(getFileHandler().isOldConfig()){
getPlugin().getPluginLogger().info("Detected old config.yml. Attempting to migrate...");
getPlugin().getPluginLogger().info("[-] Detected old <white>config.yml</white>. Attempting to migrate...");
if(getFileHandler().migrateConfig()){
getPlugin().getPluginLogger().info("Migration completed successfully!");
getPlugin().getPluginLogger().success("Migration completed successfully!");
}else{
getPlugin().getPluginLogger().warn("Couldn't migrate config.yml! Check previous lines for errors.");
getPlugin().getPluginLogger().failure("Couldn't migrate <white>config.yml</white>! Check previous lines for errors.");
return;
}
}
if(getFileHandler().getBool(true, "printBanner")){
printBanner();
}
getPlugin().getPluginLogger().info("Platform: <white>%s</white>", plugin.getPlatformInfo());
getPlugin().getPluginLogger().info("");
if(getFileHandler().loadProfiles()){
getPlugin().getPluginLogger().info("Successfully loaded %d profile(s)!", getFileHandler().getProfiles().size());
getPlugin().getPluginLogger().success("Successfully loaded <white>%d</white> profile(s)!", getFileHandler().getProfiles().size());
}else{
getPlugin().getPluginLogger().warn("Unable to load profiles! Check previous lines for errors.");
getPlugin().getPluginLogger().failure("Unable to load profiles! Check previous lines for errors.");
return;
}
getPlugin().loadFaviconHandler(this);
getPlugin().getPluginLogger().info("Loading Commands...");
plugin.loadCommands();
getPlugin().getPluginLogger().info("Commands loaded!");
getPlugin().getPluginLogger().info("Loading events...");
plugin.loadEvents();
getPlugin().getPluginLogger().info("Events loaded!");
getPlugin().getPluginLogger().info("Loading playercache.json...");
getPlayerHandler().load();
getPlugin().getPluginLogger().info("Loading bStats metrics. Disable it in the global config under /plugins/bstats/");
plugin.loadMetrics();
getPlugin().getPluginLogger().info("Metrics loaded!");
getPlugin().getPluginLogger().info("Enabling Schedulers...");
plugin.startScheduler();
getPlugin().getPluginLogger().info("Schedulers enabled.");
getPlugin().getPluginLogger().info("AdvancedServerList is ready!");
getPlugin().getPluginLogger().success("<green>AdvancedServerList is ready!");
if(getFileHandler().getBoolean("checkUpdates"))
this.updateChecker = new UpdateChecker(this);
}
private void printBanner(){
getPlugin().getPluginLogger().info(" _____ _");
getPlugin().getPluginLogger().info(" /\\ / ____| |");
getPlugin().getPluginLogger().info(" / \\ | (___ | |");
getPlugin().getPluginLogger().info(" / /\\ \\ \\___ \\| |");
getPlugin().getPluginLogger().info(" / ____ \\ ____) | |____");
getPlugin().getPluginLogger().info("/_/ \\_\\_____/|______|");
getPlugin().getPluginLogger().info("<#3b90ff> __ _______ ___");
getPlugin().getPluginLogger().info("<#3b90ff> /\\ \\ / ____|_| | |");
getPlugin().getPluginLogger().info("<#3b90ff> / \\ \\ | (_(___ | | |");
getPlugin().getPluginLogger().info("<#3b90ff> / /\\ \\ \\ \\___ \\ \\| | |");
getPlugin().getPluginLogger().info("<#3b90ff> / ____ \\ \\ ____) | | |_|____");
getPlugin().getPluginLogger().info("<#3b90ff>/_/_/ \\_\\_\\_____/_/|______|_|");
getPlugin().getPluginLogger().info("");
}
@@ -211,7 +204,6 @@ public class AdvancedServerList<F>{
}
private void addPlaceholder(PlaceholderProvider placeholderProvider){
getPlugin().getPluginLogger().info("Registering %s Placeholders...", placeholderProvider.getIdentifier());
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
}
}
@@ -123,11 +123,11 @@ public class UpdateChecker{
private void startUpdateChecker(){
executor.scheduleAtFixedRate(() -> {
logger.info("Looking for an update...");
logger.info("[-] Looking for an update...");
performUpdateCheck().whenComplete((version, throwable) -> {
if(version == null || throwable != null){
logger.warn("Failed to look for any updates. Check previous messages for causes.");
logger.failure("Failed to look for any updates. Check previous messages for causes.");
return;
}
@@ -136,9 +136,9 @@ public class UpdateChecker{
int result = version.compare(core.getVersion());
switch(result){
case -1 -> printUpdateBanner(version);
case 0 -> logger.info("You are running the latest version!");
case 0 -> logger.success("You are running the latest version!");
case 1 -> logger.info(
"Your version (%s) seems to be newer than the latest release (%s). Are you running a dev build?",
"[?] Your version (<white>%s</white>) seems to be newer than the latest release (<white>%s</white>). Are you running a dev build?",
core.getVersion(), version.versionNumber()
);
}
@@ -185,18 +185,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.getVersion());
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("=======================================================================");
}
@@ -360,7 +360,7 @@ public class CommandHandler{
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);
core.getPlugin().getPluginLogger().warn("Encountered IOException while creating file <white>%s</white>", ex, copy);
return;
}
@@ -378,7 +378,7 @@ public class CommandHandler{
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);
core.getPlugin().getPluginLogger().warn("Encountered IOException while loading file <white>%s</white>", ex, copy);
return;
}
@@ -398,7 +398,7 @@ public class CommandHandler{
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);
core.getPlugin().getPluginLogger().warn("Encountered SerializationException while set values for <white>%s</white>!", ex, copy);
return;
}
@@ -410,7 +410,7 @@ public class CommandHandler{
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);
core.getPlugin().getPluginLogger().warn("Encountered IOException while saving ConfigurationNode for <white>%s</white>!", ex, copy);
}
}
default -> {
@@ -36,6 +36,10 @@ 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{
@@ -138,14 +142,18 @@ public class PingEventHandler{
GenericServer finalServer = event.createGenericServer(online, max, host);
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
logger.debug(PingEventHandler.class, "'motd' option present. Applying '%s'...", String.join("\\n", entry.motd()));
logger.debug(PingEventHandler.class, "'motd' option present. Applying ['%s']...", String.join("', '", entry.motd()));
event.setMotd(
ComponentParser.list(entry.motd())
List<Component> motd = entry.motd().stream()
.map(line -> ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, finalServer))
.modifyText(text -> event.parsePAPIPlaceholders(text, player))
.modifyText(text -> plugin.getCore().getTextCenterUtil().getCenteredText(text))
.toComponent()
);
)
.toList();
event.setMotd(Component.join(JoinConfiguration.separator(Component.newline()), motd));
}
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
@@ -168,7 +176,7 @@ public class PingEventHandler{
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying '%s'...", String.join("\\n", entry.players()));
logger.debug(PingEventHandler.class, "'playerCount -> hover' option set. Applying ['%s']...", String.join("', '", entry.players()));
event.setPlayers(entry.players(), player, server);
}
@@ -46,7 +46,8 @@ public class ConfigMigrator{
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, fiveToSix())
.addVersion(LATEST, sixToSeven())
.addVersion(6, fiveToSix())
.addVersion(5, fourToFive())
.addVersion(4, threeToFour())
.addVersion(3, twoToThree())
@@ -54,6 +55,16 @@ public class ConfigMigrator{
.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) -> {
@@ -122,7 +133,7 @@ public class ConfigMigrator{
versioned.apply(node);
final int endVersion = versioned.version(node);
if(startVersion < endVersion)
logger.info("Migrated config.yml from v" + startVersion + " to v" + endVersion);
logger.success("Successfully migrated config from <white>v%d</white> to <white>v%d</white>", startVersion, endVersion);
}
return node;
@@ -72,7 +72,6 @@ public class FileHandler{
}
public boolean loadConfig(){
logger.info("Loading config.yml...");
File folder = plugin.getPlugin().getFolderPath().toFile();
if(!folder.exists() && !folder.mkdirs()){
logger.warn("Couldn't create folder for plugin. Is it missing Write permissions?");
@@ -87,7 +86,7 @@ public class FileHandler{
}
Files.copy(stream, config);
logger.info("Created new config.yml!");
logger.success("Created new config.yml!");
}catch(IOException ex){
logger.warn("Cannot create config.yml for plugin.", ex);
return false;
@@ -98,7 +97,7 @@ public class FileHandler{
}
public boolean loadProfiles(){
logger.info("Loading profiles...");
logger.info("[-] Loading profiles...");
if(createFile("default.yml")){
return reloadProfiles();
@@ -109,7 +108,7 @@ public class FileHandler{
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 +125,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 +159,7 @@ public class FileHandler{
File[] files = profilesFolder.toFile().listFiles(((dir, name) -> name.endsWith(".yml")));
if(files == null || files.length == 0){
logger.warn("Cannot load files from profiles folder! No valid YAML files present.");
logger.failure("Cannot load files from profiles folder! No valid YAML files present.");
return false;
}
@@ -170,11 +169,11 @@ public class FileHandler{
continue;
profiles.add(ServerListProfile.Builder.resolve(file.getName(), tmp, logger).build());
logger.info("Loaded '%s'!", file.getName());
logger.debugSuccess(FileHandler.class, "Loaded '<white>%s</white>'!", file.getName());
}
if(profiles.isEmpty()){
logger.warn("Couldn't load any profile from profiles folder!");
logger.failure("Couldn't load any profile from profiles folder!");
return false;
}
@@ -191,7 +190,7 @@ public class FileHandler{
try{
return loader.load();
}catch(IOException ex){
logger.warn("Cannot load '%s' due to an IOException!", ex, path.toFile().getName());
logger.warn("Cannot load '<white>%s</white>' due to an IOException!", ex, path.toFile().getName());
return null;
}
}
@@ -218,11 +217,11 @@ public class FileHandler{
}
private boolean makeBackup(){
logger.info("Making backup of old config.yml...");
logger.info("[-] Making backup of old config.yml...");
File backups = plugin.getPlugin().getFolderPath().resolve("backups").toFile();
if(!backups.exists() && !backups.mkdirs()){
logger.warn("Cannot create backups folder for migration!");
logger.failure("Cannot create backups folder for migration!");
return false;
}
@@ -231,16 +230,16 @@ public class FileHandler{
File configBackup = new File(backups, "config_" + date.replace(":", "_") + ".yml");
try{
if(!configBackup.exists() && !configBackup.createNewFile()){
logger.warn("Cannot create backup file for config.yml!");
logger.failure("Cannot create backup file for config.yml!");
return false;
}
Files.copy(config, configBackup.toPath(), StandardCopyOption.REPLACE_EXISTING);
logger.info("Saved backup as '%s'!", configBackup.getName());
logger.success("Saved backup as '<white>%s</white>'!", configBackup.getName());
return true;
}catch(IOException ex){
logger.warn("Encountered IOException while trying to create a backup.", ex);
logger.failure("Encountered IOException while trying to create a backup.", ex);
return false;
}
}
@@ -27,10 +27,18 @@ package ch.andre601.advancedserverlist.core.interfaces;
public interface PluginLogger{
default void debugSuccess(Class<?> clazz, String msg, Object... args){
debug(clazz, "[<green>✓</green>] " + msg, args);
}
void debug(Class<?> clazz, String msg, Object... args);
void debugWarn(Class<?> clazz, String msg, Object... args);
default void success(String msg, Object... args){
info("[<green>✓</green>] " + msg, args);
}
void info(String msg, Object... args);
void warn(String msg, Object... args);
@@ -38,4 +46,8 @@ public interface PluginLogger{
void warn(String msg, Throwable throwable);
void warn(String msg, Throwable throwable, Object... args);
default void failure(String msg, Object... args){
warn("[<red>x</red>] " + msg, args);
}
}
@@ -56,7 +56,7 @@ public class MiniMOTDConfigMigrator{
Path mainConf = core.getPlugin().getFolderPath().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 +76,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;
}
@@ -147,14 +147,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");
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 +163,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 +180,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 +202,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 +214,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();
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;
}
@@ -101,7 +130,7 @@ public class SLPConfigMigrator{
private static int parseConf(AdvancedServerList<?> core, CmdSender sender, PersonalizedStatusConf.StatusConf conf, Type type){
PluginLogger logger = core.getPlugin().getPluginLogger();
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;
@@ -141,7 +170,7 @@ 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;
@@ -149,7 +178,7 @@ public class SLPConfigMigrator{
Path profile = core.getPlugin().getFolderPath().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.getFileHandler().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());
@@ -29,7 +29,6 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import java.util.List;
import java.util.function.Function;
public class ComponentParser{
@@ -52,12 +51,13 @@ public class ComponentParser{
return new ComponentParser(text);
}
public static ComponentParser list(List<String> lines){
return new ComponentParser(String.join("\n", lines));
public static ComponentParser textFormatted(String text, Object... args){
return text(String.format(text, args));
}
public ComponentParser modifyText(Function<String, String> function){
this.text = function.apply(text);
return this;
}
@@ -73,4 +73,8 @@ public class ComponentParser{
public String toString(){
return legacy.serialize(toComponent());
}
public String toStringStriped(){
return mm.stripTags(text);
}
}
@@ -0,0 +1,136 @@
package ch.andre601.advancedserverlist.core.parsing;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.flattener.FlattenerListener;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPInputStream;
public class TextCenterUtil{
private final ComponentFlattener COMPONENT_FLATTENER = ComponentFlattener.textOnly();
private final double MAX_WIDTH = 270.0; // Max width of the MOTD
private final int SPACE_WIDTH = 4;
private final Map<String, FontInfo> charWidths;
public TextCenterUtil(AdvancedServerList<?> plugin){
charWidths = loadFontWidths(plugin);
}
public String getCenteredText(String text){
if(!text.toLowerCase(Locale.ROOT).startsWith("<center>"))
return text;
if(getDefault() == null)
return text;
text = text.substring("<center>".length());
TextFlattenerListener listener = new TextFlattenerListener(this);
COMPONENT_FLATTENER.flatten(ComponentParser.text(text).toComponent(), listener);
double width = listener.getWidth();
if(width >= MAX_WIDTH)
return text;
return createSpaces(width) + text;
}
private double getCharWidth(int codePoint, boolean isBold, String fontName){
FontInfo font = charWidths.getOrDefault(fontName, getDefault());
if(font == null)
return -1.0;
int index = Arrays.binarySearch(font.codePoints, codePoint);
if(index < 0){
return isBold ? 7.0 : 6.0;
}else{
return isBold ? font.advanceBf[index] : font.advance[index];
}
}
private FontInfo getDefault(){
return charWidths.get("minecraft:default");
}
private String createSpaces(double length){
double remainder = MAX_WIDTH - length;
int padding = (int)Math.max(0, Math.floor(remainder / 2.0) - 1);
return " ".repeat(Math.floorDiv(padding, SPACE_WIDTH));
}
private Map<String, FontInfo> loadFontWidths(AdvancedServerList<?> plugin){
try(InputStream stream = plugin.getClass().getResourceAsStream("/char-widths.json.gz")){
if(stream == null){
plugin.getPlugin().getPluginLogger().warn("Internal char-widths.json.gz couldn't be retrieved.");
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
return new HashMap<>();
}
GZIPInputStream gzipStream = new GZIPInputStream(stream);
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipStream));
return new Gson().fromJson(reader, new TypeToken<Map<String, FontInfo>>(){}.getType());
}catch(IOException ex){
plugin.getPlugin().getPluginLogger().warn("Encountered IOException while loading font widths.");
plugin.getPlugin().getPluginLogger().warn("The <center> Placeholder won't work.");
plugin.getPlugin().getPluginLogger().warn("Cause: <white>%s</white>", ex.getMessage());
return new HashMap<>();
}
}
private static class TextFlattenerListener implements FlattenerListener{
private double width = 0.0;
private boolean isBold = false;
private String font = "minecraft:default";
private final TextCenterUtil instance;
public TextFlattenerListener(TextCenterUtil instance){
this.instance = instance;
}
@Override
public void pushStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = true;
if(style.font() != null)
font = style.font().asString();
}
@Override
public void component(@NotNull String text){
for(int i = 0; i < text.length(); i++){
width += instance.getCharWidth(text.codePointAt(i), isBold, font);
}
}
@Override
public void popStyle(@NotNull Style style){
if(style.hasDecoration(TextDecoration.BOLD))
isBold = false;
}
public double getWidth(){
return width;
}
}
private record FontInfo(int[] codePoints, float[] advance, float[] advanceBf){}
}
@@ -51,13 +51,13 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
boolean result = core.getParser().evaluate(condition, player, server, collector);
if(collector.hasWarnings()){
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
logger.warn("Encountered <white>%d</white> Error(s) while parsing condition for file '<white>%s</white>':", collector.getWarnings().size(), file);
for(ParseWarnCollector.Context context : collector.getWarnings()){
logger.warn(" - At position %s:", context.position() == -1 ? "Unknown" : context.position());
logger.warn(" %s", condition);
logger.warn(" ".repeat(context.position() + 3) + "^");
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());
}
}
@@ -146,7 +146,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 +159,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;
}
@@ -91,7 +91,7 @@ public class FaviconHandler<F>{
logger.debug(FaviconHandler.class, "Getting Favicon image from cache...");
return faviconCache.get(input, () -> getFuture(input)).getNow(null);
}catch(ExecutionException ex){
logger.warn("Received ExecutionException while retrieving Favicon for '%s'.", ex, input);
logger.warn("Received ExecutionException while retrieving Favicon for '<white>%s</white>'.", ex, input);
return null;
}
}
@@ -137,15 +137,15 @@ public class FaviconHandler<F>{
private void loadLocalFavicons(){
this.localFavicons.clear();
logger.info("Loading local image files as Favicons...");
logger.info("[-] Loading local image files as Favicons...");
Path folder = core.getPlugin().getFolderPath().resolve("favicons");
if(!Files.exists(folder)){
try{
Files.createDirectories(folder);
logger.info("Created favicons folder.");
logger.debugSuccess(FaviconHandler.class, "Created favicons folder.");
}catch(IOException ex){
logger.warn("Cannot create favicons folder. Encountered an IOException.", ex);
logger.failure("Cannot create favicons folder. Encountered an IOException.", ex);
return;
}
}
@@ -154,8 +154,10 @@ public class FaviconHandler<F>{
pathStream.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".png"))
.forEach(this::loadFile);
logger.success("Loaded <white>%d</white> local Favicons.", localFavicons.size());
}catch(IOException ex){
logger.warn("Cannot load files from Favicons folder.", ex);
logger.failure("Cannot load files from favicons folder.", ex);
}
}
@@ -163,14 +165,14 @@ public class FaviconHandler<F>{
try(InputStream stream = Files.newInputStream(path)){
F favicon = createFavicon(stream);
if(favicon == null){
logger.warn("Cannot create Favicon from file '%s'. Received Favicon was null.", path.getFileName().toString());
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Received Favicon was null.", path.getFileName().toString());
return;
}
localFavicons.put(path.getFileName().toString().toLowerCase(Locale.ROOT), favicon);
logger.info("Loaded file '%s' as Favicon.", path.getFileName().toString());
logger.debugSuccess(FaviconHandler.class, "Loaded file '<white>%s</white>' as Favicon.", path.getFileName().toString());
}catch(IOException ex){
logger.warn("Cannot create Favicon from file '%s'. Encountered IOException.", ex);
logger.failure("Cannot create Favicon from file '<white>%s</white>'. Encountered IOException.", ex);
}
}
@@ -185,11 +187,11 @@ public class FaviconHandler<F>{
try(InputStream stream = client.send(request, HttpResponse.BodyHandlers.ofInputStream()).body()){
return createFavicon(stream);
}catch(InterruptedException | IOException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an Exception.", ex, url);
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered an Exception.", ex, url);
return null;
}
}catch(URISyntaxException ex){
logger.warn("Cannot create Favicon from URL '%s'. Encountered an IOException.", ex, url);
logger.warn("Cannot create Favicon from URL '<white>%s</white>'. Encountered a URISyntaxException.", ex, url);
return null;
}
}
@@ -79,40 +79,40 @@ 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...");
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);
}
}
@@ -111,7 +111,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 +126,7 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
collector.appendWarningFormatted(placeholderStart, "Placeholder '<white>%s</white>' does not have any available PlaceholderProvider", raw.toString());
return raw.toString();
}
@@ -141,7 +141,7 @@ public class StringReplacer{
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(valueStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
collector.appendWarningFormatted(valueStart, "Placeholder '<white>%s</white>' has an invalid value String '<white>%s</white>'", raw.toString(), valuesStr);
return raw.toString();
}
Binary file not shown.
+8
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.
#
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.expressionparser.ParseWarnCollector;
@@ -23,7 +23,7 @@
*
*/
package ch.andre601.advancedserverlist.test;
package ch.andre601.advancedserverlist.core;
import com.unascribed.flexver.FlexVerComparator;
import org.junit.jupiter.api.Test;
+1 -1
View File
@@ -17,7 +17,7 @@
import re
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
def on_page_markdown(
+3 -2
View File
@@ -1,6 +1,7 @@
{% extends "base.html" %}
{% block announce %}
<span class="twemoji">{% include ".icons/octicons/info-24.svg" %}</span>
<b>NEW:</b> Added a <a href="{{ base_url | url }}/getting-started/tutorials">Tutorial Section</a> to the Wiki!
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
Celebrating <a href="https://andre601.ch/blog/2024/12-13-history-of-asl/" target="_blank" rel="nofollow"><b>25,000 downloads!</b></a> Thank you!
<span class="twemoji">{% include ".icons/material/party-popper.svg" %}</span>
{% endblock %}
@@ -13,14 +13,16 @@ constructors:
methods:
- name: 'extraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#setextraplayersenabled(nullbool)"><code>disable extra Players</code></a>.
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: 'Integer'
type: 'String'
attribute:
- 'nullable'
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
@@ -73,7 +75,9 @@ methods:
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
- name: 'maxPlayersCount'
description: |
Sets the number of max players allowed to join this server.<br>
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#maxplayersenabled(nullbool)">disable max Players</a>.
@@ -122,7 +126,11 @@ methods:
- name: 'onlinePlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#onlineplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the online player count. Alternatively <a href="#onlineplayersenabled(nullbool)">disable online Players</a>.
parameters:
- name: 'onlinePlayersCount'
description: 'The number of online players to set.'
@@ -43,13 +43,18 @@ constructors:
attributes:
- notnull
- name: 'extraPlayersCount'
description: 'The number to add to the online players for the max players number.'
type: Integer
description: 'The number to add to the online Players for the extra Players.'
type: String
attributes:
- nullable
- name: 'maxPlayersCount'
description: 'The number to use for the max players count.'
type: Integer
description: 'The number to set for the max Players count.'
type: String
attributes:
- nullable
- name: 'onlinePlayersCount'
description: 'The number to set for the Online Players count.'
type: String
attributes:
- nullable
seealso:
@@ -76,6 +81,7 @@ methods:
<li><a href="#maxplayersenabled()"><code>maxPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#extraplayerscount()"><code>extraPlayersCount</code></a>: <code>null</code></li>
<li><a href="#maxplayerscount()"><code>maxPlayersCount</code></a>: <code>null</code></li>
<li><a href="#onlineplayerscount()"><code>onlinePlayersCount</code></a>: <code>null</code></li>
</ul>
returns: 'New ProfileEntry instance with empty/null values defined'
attributes:
@@ -164,12 +170,12 @@ methods:
type: 'object'
link: '../../objects/nullbool/'
- name: 'extraPlayersCount'
description: 'Gets the currently set number of extra players to use by this ProfileEntry. May be <code>null</code>.'
returns: 'Possibly-null integer number of extra players used by this ProfileEntry.'
description: 'Gets the currently set number of extra players of this ProfileEntry.'
returns: 'The current number of extra players used by this ProfileEntry.'
attributes:
- nullable
type:
name: 'Integer'
name: 'String'
type: 'object'
- name: 'maxPlayersCount'
description: 'Gets the currently set number of max players of this ProfileEntry.'
@@ -177,7 +183,15 @@ methods:
attributes:
- nullable
type:
name: 'Integer'
name: 'String'
type: 'object'
- name: 'onlinePlayersCount'
description: 'Gets the currently set number of online players of this ProfileEntry.'
returns: 'The current number of online players used by this ProfileEntry.'
attributes:
- nullable
type:
name: 'String'
type: 'object'
- name: 'isInvalid'
description: |
+11
View File
@@ -44,4 +44,15 @@
.md-source__repository .md-source__facts {
animation: facts .25s ease-in;
}
.md-nav--secondary li.md-nav__item > .md-nav__link {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
}
.md-banner__inner.md-grid.md-typeset {
text-align: center;
}
+15 -4
View File
@@ -41,10 +41,7 @@ AdvancedServerList is available on the following places (Please note the current
</div>
[modrinth]: https://modrinth.com/plugin/advancedserverlist
[codeberg]: https://codeberg.org/Andre601/AdvancedServerList
[spigot]: https://www.spigotmc.org/resources/102910/
[hangar]: https://hangar.papermc.io/Andre_601/AdvancedServerList
The plugin is available for Paper, BungeeCord, Waterfall and Velocity, and has been tested on these platforms. It may support additional forks, but this is not guaranteed.
@@ -424,6 +421,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.
#
@@ -483,6 +488,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!
@@ -490,7 +501,7 @@ disableDuringMaintenance:
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
config-version: 5
configVersion: 7
```
///
+43
View File
@@ -50,6 +50,12 @@ AdvancedServerList supports the following platforms:
----
A simple guide on how to get started with AdvancedServerList.
----
**Other Pages:**
- [:octicons-project-roadmap-24: Tutorials](getting-started/tutorials.md)
- [:octicons-rel-file-path-24: **Commands**](commands/index.md)
@@ -62,6 +68,14 @@ AdvancedServerList supports the following platforms:
----
Pages containing information about the Server List Profile System and all its available options.
----
**Other Pages:**
- [:octicons-file-code-24: Expressions](profiles/expressions.md)
- [:octicons-pencil-24: Formatting](profiles/formatting.md)
- [:material-percent: Placeholders](profiles/placeholders.md)
- [:octicons-list-unordered-24: **Examples**](examples/index.md)
@@ -74,12 +88,35 @@ AdvancedServerList supports the following platforms:
----
Pages explaining how to migrate from one version of the plugin to another.
----
**Other Pages:**
- Plugins
- [:octicons-arrow-right-24: MiniMOTD](migration/plugins/minimotd.md)
- [:octicons-arrow-right-24: ServerListPlus](migration/plugins/serverlistplus.md)
- Versions
- [:octicons-arrow-right-24: v3.8.0 to v3.9.0](migration/versions/v3.8.0-to-v3.9.0.md)
- [:octicons-arrow-right-24: v3.7.0 to v3.8.0](migration/versions/v3.7.0-to-v3.8.0.md)
- [:octicons-arrow-right-24: < v3.7.0 to v3.7.0](migration/versions/pre-v3.7.0-to-v3.7.0.md)
- [:octicons-arrow-right-24: v1.9.0 to v1.10.0](migration/versions/v1.9.0-to-v1.10.0.md)
- [:octicons-arrow-right-24: v1.5.3 to v1.6.0](migration/versions/v1.5.3-to-v1.6.0.md)
- [:octicons-command-palette-24: **API**](api/index.md)
----
Pages all about the API of AdvancedServerList.
----
**Other Pages:**
- [:octicons-log-24: Changelog](api/changelog.md)
- [:octicons-link-external-24: Javadocs](api/javadocs.md)
- [:simple-codeberg: Source Code](api/source.md)
- [:octicons-file-code-24: Reference](api/reference/index.md)
- [:octicons-plus-circle-24: **Addons**](addons/index.md)
@@ -87,6 +124,12 @@ AdvancedServerList supports the following platforms:
Pages listing 1st-party and 3rd-party add-ons for AdvancedServerList.
----
**Other Pages:**
- [:octicons-stop-24: BanPlugins Addon](addons/banplugins.md)
- [:material-percent: **PlaceholderAPI**](placeholderapi/index.md)
----
+7 -7
View File
@@ -11,13 +11,13 @@ These pages may include important information about the migration process and wh
<div class="grid cards" markdown>
- [**MiniMOTD**](minimotd.md)
- [**MiniMOTD**](plugins/minimotd.md)
----
Migrate from the Plugin [MiniMOTD](https://github.com/jpenilla/MiniMOTD){ target="_blank" rel="nofollow" }
- [**ServerListPlus**](serverlistplus.md)
- [**ServerListPlus**](plugins/serverlistplus.md)
----
@@ -32,31 +32,31 @@ These guides are only for the Server List Profile files, as the config.yml gets
<div class="grid cards" markdown>
- [**v3.8.0 to v3.9.0**](v3_8_0-to-v3_9_0.md)
- [**v3.8.0 to v3.9.0**](versions/v3.8.0-to-v3.9.0.md)
----
Migrate from version 3.8.0 to 3.9.0.
- [**v3.7.0 to v3.8.0**](v3_7_0-to-v3_8_0.md)
- [**v3.7.0 to v3.8.0**](versions/v3.7.0-to-v3.8.0.md)
----
Migrating from version 3.7.0 to 3.8.0.
- [**< v3.7.0 to v3.7.0**](pre-v3_7_0-to-v3_7_0.md)
- [**< v3.7.0 to v3.7.0**](versions/pre-v3.7.0-to-v3.7.0.md)
----
Migrate from any version prior to 3.7.0 to 3.7.0 or newer.
- [**v1.9.0 to v1.10.0**](v1_9_0-to-v1_10_0.md)
- [**v1.9.0 to v1.10.0**](versions/v1.9.0-to-v1.10.0.md)
----
Migrate from version 1.9.0 to 1.10.0.
- [**v1.5.3 to v1.6.0**](v1_5_3-to-v1_6_0.md)
- [**v1.5.3 to v1.6.0**](versions/v1.5.3-to-v1.6.0.md)
----
@@ -11,14 +11,14 @@ Version `4.10.0` added support for migrating your existing `main.conf` configura
## How to Migrate
Execute the command [`/asl migrate minimotd`](../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
Execute the command [`/asl migrate minimotd`](../../commands/index.md#migrate) to start the migration process. Make sure the `main.conf` file is present in `/plugins/MiniMOTD/` (`minimotd-velocity` on Velocity).
## Example
Below can you find a full example of a `main.conf` file and the corresponding migrated files from AdvancedServerList:
/// tab | :octicons-file-code-24: main.conf
```lighty
```ruby
icon-enabled=true
motd-enabled=true
motds=[
@@ -48,7 +48,7 @@ The following Favicon options get converted into an equivalent one:
## How to Migrate
Execute the command [`/asl migrate serverlistplus`](../commands/index.md#migrate) to start the migration process. Make sure that ServerListPlus is present and enabled.
Execute the command [`/asl migrate serverlistplus`](../../commands/index.md#migrate) to start the migration process. Make sure that ServerListPlus is present and enabled.
## Example
@@ -5,7 +5,7 @@ icon: octicons/arrow-right-24
# < v3.7.0 to v3.7.0
Version 3.7.0 of AdvancedServerList brought significant changes to its conditions system.
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../profiles/index.md#condition) option should now be used instead.
Namely, the `conditions` option is now deprecated and planned for removal in a future release of the Plugin, and the new [`condition`](../../profiles/index.md#condition) option should now be used instead.
## Migration
+2
View File
@@ -91,6 +91,8 @@ motd:
## Motd
<!-- admo:tip Start a line with <code>&lt;center&gt;</code> to have it centered. -->
The `motd` option allows you to alter the "Message of the day" that is being displayed on a server in the multiplayer screen.
Please see the [Formatting](formatting.md) for all supported formatting options.
+19 -7
View File
@@ -68,6 +68,18 @@ extra:
plugins:
- search
- glightbox
- redirects:
redirect_maps:
# Plugin Migration Pages
'migration/minimotd.md': 'migration/plugins/minimotd.md'
'migration/serverlistplus.md': 'migration/plugins/serverlistplus.md'
#
# Version Migration Pages
'migration/v3_8_0-to-v3_9_0.md': 'migration/versions/v3.8.0-to-v3.9.0.md'
'migration/v3_7_0-to-v3_8_0.md': 'migration/versions/v3.7.0-to-v3.8.0.md'
'migration/pre-v3_7_0-to-v3_7_0.md': 'migration/versions/pre-v3.7.0-to-v3.7.0.md'
'migration/v1_9_0-to-v1_10_0.md': 'migration/versions/v1.9.0-to-v1.10.0.md'
'migration/v1_5_3-to-v1_6_0.md': 'migration/versions/v1.5.3-to-v1.6.0.md'
- pagenav-generator
markdown_extensions:
@@ -123,14 +135,14 @@ nav:
- Migration:
- migration/index.md
- Other Plugins:
- MiniMOTD: migration/minimotd.md
- ServerListPlus: migration/serverlistplus.md
- MiniMOTD: migration/plugins/minimotd.md
- ServerListPlus: migration/plugins/serverlistplus.md
- AdvancedServerList:
- v3.8.0 to v3.9.0: migration/v3_8_0-to-v3_9_0.md
- v3.7.0 to v3.8.0: migration/v3_7_0-to-v3_8_0.md
- '< v3.7.0 to v3.7.0': migration/pre-v3_7_0-to-v3_7_0.md
- v1.9.0 to v1.10.0: migration/v1_9_0-to-v1_10_0.md
- v1.5.3 to v1.6.0: migration/v1_5_3-to-v1_6_0.md
- v3.8.0 to v3.9.0: migration/versions/v3.8.0-to-v3.9.0.md
- v3.7.0 to v3.8.0: migration/versions/v3.7.0-to-v3.8.0.md
- '< v3.7.0 to v3.7.0': migration/versions/pre-v3.7.0-to-v3.7.0.md
- v1.9.0 to v1.10.0: migration/versions/v1.9.0-to-v1.10.0.md
- v1.5.3 to v1.6.0: migration/versions/v1.5.3-to-v1.6.0.md
- API:
- api/index.md
- Changelog: api/changelog.md
+10
View File
@@ -118,6 +118,16 @@
<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>
@@ -67,18 +67,6 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
@Override
public void onEnable(){
try{
Class.forName("io.papermc.paper.configuration.ConfigurationLoaders");
}catch(ClassNotFoundException ignored){
try{
// Above class only exists since 1.19+. This is a fallback to see if an older version is used.
Class.forName("com.destroystokyo.paper.PaperConfig");
}catch(ClassNotFoundException ex){
printNoPaperWarning();
return;
}
}
this.core = AdvancedServerList.init(this, new PaperPlayerPlaceholders(), new PaperServerPlaceholders(this));
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
@@ -101,9 +89,9 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
@Override
public void loadCommands(){
if(getServer().getCommandMap().register("asl", new CmdAdvancedServerList(this))){
getPluginLogger().info("Registered /advancedserverlist:advancedserverlist");
getPluginLogger().success("Registered <white>/advancedserverlist:advancedserverlist</white>!");
}else{
getPluginLogger().info("Registered /asl:advancedserverlist");
getPluginLogger().success("Registered <white>/asl:advancedserverlist</white>!");
}
}
@@ -225,27 +213,6 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
return players.size();
}
private void printNoPaperWarning(){
getPluginLogger().warn("======================================================================================");
getPluginLogger().warn("THIS SERVER DOES NOT USE PAPER OR A COMPATIBLE FORK!");
getPluginLogger().warn("");
getPluginLogger().warn("AdvancedServerList 3.6.0 has dropped support for Spigot-based servers.");
getPluginLogger().warn("This means that only servers using Paper or a Paper-compatible fork may work.");
getPluginLogger().warn("");
getPluginLogger().warn("Reasons for this removal:");
getPluginLogger().warn(" - Reliance on a different plugin for core functionalities.");
getPluginLogger().warn(" - Bad dependency loading limited to MavenCentral only.");
getPluginLogger().warn("");
getPluginLogger().warn("Please consider switching to Paper or one of the Paper-compatible forks to benefit");
getPluginLogger().warn("from overall performance improvements amongst other things.");
getPluginLogger().warn("");
getPluginLogger().warn("Disabling AdvancedServerList. If you believe this is an error, report it on");
getPluginLogger().warn("Codeberg: https://codeberg.org/Andre601/AdvancedServerList");
getPluginLogger().warn("======================================================================================");
Bukkit.getPluginManager().disablePlugin(this);
}
private String getNewVersion(){
ServerBuildInfo info = ServerBuildInfo.buildInfo();
@@ -255,7 +222,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
OptionalInt build = info.buildNumber();
if(build.isEmpty())
return String.format("%s (%s, Version: %s)", name, id, version);
return String.format("%s (ID: %s, Version: %s)", name, id, version);
return String.format("%s (ID: %s, Version: %s, Build: %d)", name, id, version, build.getAsInt());
}
@@ -56,14 +56,12 @@ public class LoadEvent implements Listener{
plugin.getPluginLogger().warn("======================================================================================");
plugin.getPluginLogger().warn("SERVER RELOAD DETECTED!");
plugin.getPluginLogger().warn("");
plugin.getPluginLogger().warn("AdvancedServerList has detected your server has been reloaded using the /reload");
plugin.getPluginLogger().warn("command or the Bukkit.reload() method call.");
plugin.getPluginLogger().warn("A server reload has been detected by AdvancedServerList, meaning either the /reload");
plugin.getPluginLogger().warn("command or Bukkit.reload() was executed.");
plugin.getPluginLogger().warn("");
plugin.getPluginLogger().warn("DO NOT RELOAD THE SERVER. ALWAYS RESTART IT!");
plugin.getPluginLogger().warn("");
plugin.getPluginLogger().warn("Plugins may not work as expected when reloading a server, causing breaking issues.");
plugin.getPluginLogger().warn("AdvancedServerList *should* work, but any support for issues with it will be denied if");
plugin.getPluginLogger().warn("a server reload was detected!");
plugin.getPluginLogger().warn("YOU WILL GET NO SUPPORT FOR THE PLUGIN FOR ANY ISSUES YOU ENCOUNTER AFTER A SERVER");
plugin.getPluginLogger().warn("RELOAD!");
plugin.getPluginLogger().warn("ALWAYS RESTART YOUR SERVER. NEVER RELOAD IT!");
plugin.getPluginLogger().warn("======================================================================================");
}
}
@@ -26,19 +26,18 @@
package ch.andre601.advancedserverlist.paper.logging;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.paper.PaperCore;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
public class PaperLogger implements PluginLogger{
private final PaperCore plugin;
private final Logger logger;
private final ComponentLogger logger;
public PaperLogger(PaperCore plugin){
this.plugin = plugin;
this.logger = plugin.getLogger();
this.logger = plugin.getComponentLogger();
}
@Override
@@ -55,21 +54,21 @@ public class PaperLogger implements PluginLogger{
@Override
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
logger.info(ComponentParser.textFormatted("<grey>" + msg, args).toComponent());
}
@Override
public void warn(String msg, Object... args){
logger.warning(String.format(msg, args));
logger.warn(ComponentParser.textFormatted("<yellow>" + msg, args).toComponent());
}
@Override
public void warn(String msg, Throwable throwable){
logger.log(Level.WARNING, msg, throwable);
logger.warn(ComponentParser.text("<yellow>" + msg).toComponent(), throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.log(Level.WARNING, String.format(msg, args), throwable);
logger.warn(ComponentParser.textFormatted("<yellow>" + msg, args).toComponent(), throwable);
}
}
@@ -36,7 +36,7 @@ public class PaperPlayerImpl implements BukkitPlayer{
private final OfflinePlayer player;
private final String name;
private int protocol;
private final int protocol;
private final UUID uuid;
private boolean playedBefore = false;
@@ -46,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class PAPIPlaceholders extends PlaceholderExpansion{
@@ -114,9 +115,9 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
BukkitServer finalServer = new PaperServerImpl(plugin.getWorldCache().worlds(), online, max, host);
return switch(identifier.toLowerCase(Locale.ROOT)){
case "motd" -> getOption(entry.motd(), pl, player, finalServer);
case "motd" -> getOption(entry.motd(), pl, player, finalServer, true);
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer);
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer, false);
case "playercount_text" -> getOption(entry.playerCountText(), pl, player, finalServer);
case "playercount_extraplayers" -> extraPlayers == null ? "null" : String.valueOf(extraPlayers);
case "playercount_maxplayers" -> maxPlayers == null ? "null" : String.valueOf(maxPlayers);
@@ -136,14 +137,23 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
}
private String getOption(String str, Player pl, BukkitPlayer player, BukkitServer server){
return getOption(Collections.singletonList(str), pl, player, server);
return getOption(Collections.singletonList(str), pl, player, server, false);
}
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server){
return ComponentParser.list(list)
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
.toString();
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server, boolean isMotd){
return list.stream()
.map(line -> ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, server))
.modifyText(text -> PlaceholderAPI.setPlaceholders(pl, text))
.modifyText(text -> {
if(isMotd)
return plugin.getCore().getTextCenterUtil().getCenteredText(text);
return text;
})
.toString()
)
.collect(Collectors.joining("\n"));
}
private Integer parseNumberOption(String option, Player pl, BukkitPlayer player, BukkitServer server){
+1 -10
View File
@@ -5,7 +5,7 @@ description: '${plugin.description}'
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
api-version: '1.19'
api-version: '1.20'
folia-supported: true
@@ -24,15 +24,6 @@ dependencies:
load: BEFORE
required: false
# The below stuff is NOT used by Paper plugin.
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [help|reload]'
aliases:
- 'asl'
permission: 'advancedserverlist.admin'
# This is actually supported(?)
permissions:
advancedserverlist.*:
-58
View File
@@ -1,58 +0,0 @@
#
# This file is kept for Folia support.
#
name: 'AdvancedServerList'
author: 'Andre_601'
version: '${plugin.version}'
description: '${plugin.description}'
main: 'ch.andre601.advancedserverlist.paper.PaperCore'
api-version: '1.19'
folia-supported: true
libraries:
- 'org.spongepowered:configurate-yaml:4.1.2'
- 'net.kyori:adventure-text-serializer-legacy:4.12.0'
- 'com.squareup.okhttp3:okhttp:4.10.0'
softdepend:
- 'PlaceholderAPI'
- 'Maintenance'
commands:
advancedserverlist:
description: 'Main command of AdvancedServerList'
usage: '/<command> [help|reload|clearCache]'
aliases:
- 'asl'
permission: 'advancedserverlist.admin'
permissions:
advancedserverlist.*:
description: 'Grants access to all permissions'
default: op
children:
- 'advancedserverlist.admin'
advancedserverlist.admin:
description: 'Grants access to all permissions'
default: op
children:
- 'advancedserverlist.command.*'
advancedserverlist.command.*:
description: 'Grants access to all commands'
default: op
children:
- 'advancedserverlist.command.help'
- 'advancedserverlist.command.reload'
advancedserverlist.command.help:
description: 'Grants access to /asl help'
default: op
advancedserverlist.command.reload:
description: 'Grants access to /asl reload'
default: op
advancedserverlist.command.clearcache:
description: 'Clears the Player and Favicon cache'
default: op
+4 -4
View File
@@ -37,14 +37,14 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.version>5.1.2</plugin.version>
<plugin.version>5.3.0</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<api.version>4.0.0</api.version>
<dependency.adventure-api>4.17.0</dependency.adventure-api>
<dependency.adventure-text-minimessage>4.17.0</dependency.adventure-text-minimessage>
<dependency.adventure-text-serializer-legacy>4.17.0</dependency.adventure-text-serializer-legacy>
<dependency.adventure-api>4.18.0</dependency.adventure-api>
<dependency.adventure-text-minimessage>4.18.0</dependency.adventure-text-minimessage>
<dependency.adventure-text-serializer-legacy>4.18.0</dependency.adventure-text-serializer-legacy>
<dependency.adventure-platform-bungeecord>4.3.4</dependency.adventure-platform-bungeecord>
<dependency.configurate-yaml>4.1.2</dependency.configurate-yaml>
+2 -1
View File
@@ -1,3 +1,4 @@
mkdocs-material==9.5.48
mkdocs-material==9.5.49
mkdocs-glightbox==0.4.0
mkdocs-redirects==1.2.2
git+https://github.com/Andre601/mkdocs-pagenav-generator
+17 -1
View File
@@ -48,6 +48,10 @@
<id>velocity-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
</repository>
</repositories>
<dependencies>
@@ -68,7 +72,7 @@
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.1.2-SNAPSHOT</version>
<version>3.4.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -95,6 +99,18 @@
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-velocity</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<!-- Other -->
<dependency>
@@ -51,10 +51,10 @@ import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.scheduler.ScheduledTask;
import com.velocitypowered.api.util.Favicon;
import de.myzelyam.api.vanish.VelocityVanishAPI;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bstats.charts.SimplePie;
import org.bstats.velocity.Metrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sayandev.sayanvanish.velocity.api.SayanVanishVelocityAPI;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
@@ -67,10 +67,11 @@ import java.util.concurrent.TimeUnit;
public class VelocityCore implements PluginCore<Favicon>{
private final Logger logger = LoggerFactory.getLogger("AdvancedServerList");
private final Map<String, ServerPing> fetchedServers = new ConcurrentHashMap<>();
private final PluginLogger pluginLogger;
private final ComponentLogger logger;
private final ProxyServer proxy;
private final Path path;
private final Metrics.Factory metrics;
@@ -84,7 +85,9 @@ public class VelocityCore implements PluginCore<Favicon>{
@Inject
public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
this.pluginLogger = new VelocityLogger(this, this.logger);
ComponentLogger logger = ComponentLogger.logger("AdvancedServerList");
this.pluginLogger = new VelocityLogger(this, logger);
this.logger = logger;
this.proxy = proxy;
this.path = path;
@@ -112,6 +115,7 @@ public class VelocityCore implements PluginCore<Favicon>{
.build();
getProxy().getCommandManager().register(command, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
@@ -223,6 +227,9 @@ public class VelocityCore implements PluginCore<Favicon>{
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().isLoaded("premiumvanish")){
players.removeIf(VelocityVanishAPI::isInvisible);
}else // Do the same if SayanVanish is enabled.
if(getProxy().getPluginManager().isLoaded("sayanvanish")){
players.removeIf(player -> SayanVanishVelocityAPI.getInstance().isVanished(player.getUniqueId()));
}
return players.size();
@@ -26,15 +26,16 @@
package ch.andre601.advancedserverlist.velocity.logging;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import org.slf4j.Logger;
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
public class VelocityLogger implements PluginLogger{
private final VelocityCore plugin;
private final Logger logger;
private final ComponentLogger logger;
public VelocityLogger(VelocityCore plugin, Logger logger){
public VelocityLogger(VelocityCore plugin, ComponentLogger logger){
this.plugin = plugin;
this.logger = logger;
}
@@ -53,21 +54,21 @@ public class VelocityLogger implements PluginLogger{
@Override
public void info(String msg, Object... args){
logger.info(String.format(msg, args));
logger.info(ComponentParser.textFormatted("<grey>" + msg, args).toComponent());
}
@Override
public void warn(String msg, Object... args){
logger.warn(String.format(msg, args));
logger.warn(ComponentParser.textFormatted(msg, args).toComponent());
}
@Override
public void warn(String msg, Throwable throwable){
logger.warn(msg, throwable);
logger.warn(ComponentParser.text(msg).toComponent(), throwable);
}
@Override
public void warn(String msg, Throwable throwable, Object... args){
logger.warn(String.format(msg, args), throwable);
logger.warn(ComponentParser.textFormatted(msg, args).toComponent(), throwable);
}
}
+1 -1
View File
@@ -52,7 +52,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.12</version>
<version>1.5.15</version>
<scope>compile</scope>
</dependency>
<dependency>