Compare commits

...
57 Commits
Author SHA1 Message Date
Andre601 de7d011216 Fix cloud-paper not being compiled into project 2025-02-06 13:45:21 +01:00
Andre601 4a2cb2078d Compile the bungee cloud dependency and make enum public. 2025-02-05 21:28:56 +01:00
Andre601 05381bd538 Rename CommandHandler to CommandManagerInterface 2025-02-04 23:17:05 +01:00
Andre601 51e561f2ba Use records instead of classes for Player implementations 2025-02-04 23:11:30 +01:00
Andre601 71a3bddc62 Remove no longer existing overrides and update docs 2025-02-04 22:16:09 +01:00
Andre601 3eeffd5520 Merge pull request 'Use Cloud for Command handling' (#400) from feature/cloud-command-system into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/400
2025-02-04 20:40:40 +00:00
Andre601 3590e4fa12 Merge pull request 'Update dependency mkdocs-material to v9.6.2' (#405) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/405
2025-02-04 12:54:04 +00:00
Andre601's Bot e1e7907d0f Update dependency mkdocs-material to v9.6.2 2025-02-04 12:02:22 +00:00
Andre601 1e8f71092c Update ExpressionParser 2025-02-04 02:33:47 +01:00
Andre601 1c12180fe3 Merge branch 'master' into feature/cloud-command-system 2025-02-03 17:54:42 +01:00
Andre601 7a41e27788 Merge pull request 'Use MkDocs macros plugin for API reference generation' (#398) from feature/docs/better-autogen-apidocs into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/398
2025-02-03 16:48:20 +00:00
Andre601 ddfc8763c4 Bump Sayanvanish to 1.6.4 and add it as addon to wiki 2025-02-03 14:28:38 +01:00
Andre601 086905ad53 Upate dependencies and saynvanish Repo URL 2025-02-03 14:09:49 +01:00
Andre601 4526e91e0f Add SayanVanish as third-party addon to the docs 2025-02-03 01:19:06 +01:00
Andre601 cfb74b277e Revert updating SayanVanishAPI to 1.6.3 to fix it being fully broken... 2025-02-02 14:40:43 +01:00
Andre601 d7c3a7d756 Merge pull request 'Update all non-major dependencies' (#403) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/403
2025-02-02 12:46:28 +00:00
Andre601's Bot 36c6af0a43 Update all non-major dependencies 2025-02-02 12:03:48 +00:00
Andre601 f9df11c9f8 Add Build ID on Jenkins Builds. 2025-02-01 23:09:38 +01:00
Andre601 8f42b63733 Merge pull request 'Update all non-major dependencies' (#402) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/402
2025-01-31 12:06:35 +00:00
Andre601's Bot 10604f4064 Update all non-major dependencies 2025-01-31 12:03:20 +00:00
Andre601 7a574513af Merge pull request 'Update dependency com.google.code.gson:gson to v2.12.0' (#401) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/401
2025-01-30 12:10:52 +00:00
Andre601's Bot deeea1578d Update dependency com.google.code.gson:gson to v2.12.0 2025-01-30 12:02:28 +00:00
Andre601 ac379b1668 Refactor some stuff 2025-01-30 02:12:04 +01:00
Andre601 c636764f4b Update default config in getting-started.md 2025-01-28 16:13:33 +00:00
Andre601 a823aebafd Exclude kyori in minecraft-extras dependency 2025-01-27 22:37:47 +01:00
Andre601 dd4c3c0eb3 Improve shading of dependencies 2025-01-27 22:32:37 +01:00
Andre601 23afe54e29 No need to use sublist (Is truncated in API) 2025-01-26 02:05:02 +01:00
Andre601 fab3731cf4 Update value change hover 2025-01-26 01:57:01 +01:00
Andre601 49a782d560 Fix broken inherits list for docs 2025-01-25 15:35:00 +00:00
Andre601 cdac325e71 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-25 15:24:16 +00:00
Andre601 88f4278f3f Implement different value types per option 2025-01-25 15:14:06 +01:00
Andre601 de4617e450 Display old and new value on setting 2025-01-24 23:52:41 +01:00
Andre601 4c4573b1e0 Add class to create Options list + /asl profiles set command 2025-01-23 23:39:11 +01:00
Andre601 f74f3ef766 Small restructure 2025-01-22 13:38:51 +01:00
Andre601 806a920d32 Update commands.md 2025-01-22 13:34:38 +01:00
Andre601 c9db8cbc97 Improve info structure a bit 2025-01-22 13:25:06 +01:00
Andre601 3e3cd112ec Change PlayerOnly to CommandType and use enum values 2025-01-22 03:05:53 +01:00
Andre601 fcc7d7c6b6 A loooooooot of work...
Yes, this was absolute pain to make, thanks for asking.
2025-01-22 02:51:15 +01:00
Andre601 cb31fc6f5a Use markdown for entries 2025-01-20 22:11:49 +01:00
Andre601 b26a614f87 Fix issues with Annotationa + add /asl profiles info {profile} 2025-01-20 17:21:35 +01:00
Andre601 eb6f4180bf Implement BungeeCord and Paper Command Handler 2025-01-19 21:13:02 +01:00
Andre601 02d6b1958b Add command alias + remove requiredSender declaration 2025-01-19 19:36:18 +01:00
Andre601 bf3c979819 Use Annotations for commands 2025-01-19 16:49:05 +01:00
Andre601 b5af4b9c47 Use Cloud for Command handling 2025-01-18 23:12:10 +01:00
Andre601 6b9cff2945 Merge pull request 'Update dependency mkdocs-material to v9.5.50' (#399) from renovate/all-minor-patch into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/399
2025-01-18 12:16:39 +00:00
Andre601's Bot d17549ee68 Update dependency mkdocs-material to v9.5.50 2025-01-18 12:01:47 +00:00
Andre601 8b73eb3c8c Change PAPI Placeholder behaviour + new placeholders 2025-01-16 02:27:31 +01:00
Andre601 1ee9ae473d Remove api-doc.html 2025-01-13 23:40:04 +01:00
Andre601 37006063cf Add macros plugin to requirements.txt 2025-01-13 23:37:53 +01:00
Andre601 76d97de029 Update API reference pages 2025-01-13 23:36:27 +01:00
Andre601 cd8f6f4c22 Merge branch 'master' into feature/docs/better-autogen-apidocs 2025-01-13 22:32:13 +01:00
Andre601 ce14274e4c Remove PlaceholderAPI page link 2025-01-12 15:34:31 +01:00
Andre601 a5d777f4f1 Restructure Wiki 2025-01-12 15:32:09 +01:00
Andre601 f94e578694 Update formatting.md 2025-01-10 15:28:57 +01:00
Andre601 4ff55ddf28 First work on some templates 2025-01-08 02:13:35 +01:00
Andre601 7c441e6ab5 Update SECURITY.md 2025-01-07 13:36:47 +00:00
Andre601 17d0802e41 Add MkDocs Macros Plugin 2024-12-28 16:14:10 +01:00
87 changed files with 2787 additions and 1744 deletions

No files matched your search

+2 -2
View File
@@ -8,12 +8,12 @@ To ensure proper safety and support are only certain versions and Platforms of A
|---------------|-----------|
| v5 | Yes |
| v4 | Yes* |
| v3 | Yes** |
| v3 | No** |
| v2 | No |
| v1 | No |
\*Only receives support but no updates or bug fixes.
\*\*Support ends at the end of 2024.
\*\*Support ended on December 31st, 2024.
## Supported Server/Proxy Versions
+3 -10
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>
@@ -117,19 +117,12 @@
</dependencies>
<build>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}</finalName>
<finalName>AdvancedServerList-BanPlugins-Addon-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
</project>
+48 -34
View File
@@ -40,8 +40,9 @@
<description>${plugin.description}</description>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
@@ -51,7 +52,7 @@
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
<url>https://repo.sayandev.org/releases/</url>
</repository>
</repositories>
@@ -131,13 +132,13 @@
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<version>1.6.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-bungeecord</artifactId>
<version>1.6.1</version>
<version>1.6.4</version>
<scope>provided</scope>
</dependency>
@@ -148,10 +149,16 @@
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-bungee</artifactId>
<version>${dependency.cloud-bungee}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}</finalName>
<finalName>AdvancedServerList-BungeeCord-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -159,44 +166,51 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>net.byteflux.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.libby</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.libby</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.expressionparser</shadedPattern>
</relocation>
<relocation>
<pattern>com.unascribed.flexver</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>org.incendo.cloud</pattern>
<shadedPattern>ch.andre601.advancedserverlist.bungeecord.depends.cloud</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
@@ -25,15 +25,16 @@
package ch.andre601.advancedserverlist.bungeecord;
import ch.andre601.advancedserverlist.bungeecord.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.bungeecord.listeners.JoinEvent;
import ch.andre601.advancedserverlist.bungeecord.listeners.PingEvent;
import ch.andre601.advancedserverlist.bungeecord.commands.BungeeCommandManagerInterface;
import ch.andre601.advancedserverlist.bungeecord.listeners.PlayerJoinEventListener;
import ch.andre601.advancedserverlist.bungeecord.listeners.ProxyPingEventListener;
import ch.andre601.advancedserverlist.bungeecord.logging.BungeeLogger;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeePlayerPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeProxyPlaceholders;
import ch.andre601.advancedserverlist.bungeecord.objects.placeholders.BungeeServerPlaceholders;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import com.alessiodp.libby.BungeeLibraryManager;
@@ -47,6 +48,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import org.incendo.cloud.CommandManager;
import org.sayandev.sayanvanish.bungeecord.api.SayanVanishBungeeAPI;
import java.awt.image.BufferedImage;
@@ -68,6 +70,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
private BungeeAudiences audiences = null;
private BungeeCommandManagerInterface handler;
private BungeeLibraryManager libraryManager = null;
@@ -92,6 +95,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
}
this.audiences = BungeeAudiences.create(this);
this.handler = new BungeeCommandManagerInterface(this);
this.core = AdvancedServerList.init(this,
BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this), BungeeProxyPlaceholders.init(this));
}
@@ -103,16 +107,10 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
audiences.close();
}
@Override
public void loadCommands(){
getProxy().getPluginManager().registerCommand(this, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
public void loadEvents(){
new JoinEvent(this);
new PingEvent(this);
new PlayerJoinEventListener(this);
new ProxyPingEventListener(this);
}
@Override
@@ -181,6 +179,11 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
return faviconHandler;
}
@Override
public CommandManager<CmdSender> getCommandManager(){
return handler.commandHandler();
}
@Override
public String getPlatformInfo(){
return getProxy().getName() + " " + getProxy().getVersion();
@@ -27,8 +27,10 @@ package ch.andre601.advancedserverlist.bungeecord.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class BungeeCmdSender implements CmdSender{
@@ -40,13 +42,22 @@ public class BungeeCmdSender implements CmdSender{
this.bungeeAudiences = bungeeAudiences;
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
}
@Override
public void sendMsg(String msg, Object... args){
bungeeAudiences.sender(sender).sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
@Override
public Audience audience(){
return bungeeAudiences.sender(sender);
}
@Override
public boolean isPlayer(){
return sender instanceof ProxiedPlayer;
}
public CommandSender sender(){
return sender;
}
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,27 +20,41 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.bungeecord.commands;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandManagerInterface;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.bungee.BungeeCommandManager;
import org.incendo.cloud.execution.ExecutionCoordinator;
public class CmdAdvancedServerList extends Command{
public class BungeeCommandManagerInterface implements CommandManagerInterface<CommandSender>{
private final BungeeCordCore plugin;
public CmdAdvancedServerList(BungeeCordCore plugin){
super("advancedserverlist", "advancedserverlist.command.asl", "asl");
public BungeeCommandManagerInterface(BungeeCordCore plugin){
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args){
plugin.getCore().getCommandHandler().handle(new BungeeCmdSender(sender, plugin.getAudiences()), args);
public CommandManager<CmdSender> commandHandler(){
return new BungeeCommandManager<>(
plugin,
ExecutionCoordinator.asyncCoordinator(),
senderMapper()
);
}
@Override
public SenderMapper<CommandSender, CmdSender> senderMapper(){
return SenderMapper.create(
cmdSender -> new BungeeCmdSender(cmdSender, plugin.getAudiences()),
sender -> ((BungeeCmdSender)sender).sender()
);
}
}
@@ -34,10 +34,10 @@ import net.md_5.bungee.event.EventHandler;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
public class PlayerJoinEventListener implements Listener{
private final BungeeCordCore plugin;
public JoinEvent(BungeeCordCore plugin){
public PlayerJoinEventListener(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@@ -33,11 +33,11 @@ import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public class PingEvent implements Listener{
public class ProxyPingEventListener implements Listener{
private final BungeeCordCore plugin;
public PingEvent(BungeeCordCore plugin){
public ProxyPingEventListener(BungeeCordCore plugin){
this.plugin = plugin;
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@@ -30,21 +30,11 @@ import ch.andre601.advancedserverlist.core.objects.CachedPlayer;
import java.util.UUID;
public class BungeePlayerImpl implements BungeePlayer{
private final String name;
private final int protocol;
private final UUID uuid;
public BungeePlayerImpl(CachedPlayer player, int protocol){
this.name = player.name();
this.protocol = protocol;
this.uuid = player.uuid();
}
public record BungeePlayerImpl(CachedPlayer player, int protocol) implements BungeePlayer{
@Override
public String getName(){
return name;
return player.name();
}
@Override
@@ -54,6 +44,6 @@ public class BungeePlayerImpl implements BungeePlayer{
@Override
public UUID getUUID(){
return uuid;
return player.uuid();
}
}
+28 -39
View File
@@ -39,8 +39,10 @@
<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>
<plugin.config.version>8</plugin.config.version>
</properties>
@@ -77,7 +79,7 @@
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>1.5.0</version>
<version>1.6.0</version>
<scope>compile</scope>
</dependency>
@@ -119,7 +121,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.12.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -134,6 +136,24 @@
<version>33.4.0-jre</version>
<scope>provided</scope>
</dependency>
<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>
<!-- Plugins -->
<dependency>
@@ -165,7 +185,7 @@
</dependencies>
<build>
<finalName>AdvancedServerList-Core-${plugin.version}</finalName>
<finalName>AdvancedServerList-Core-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -187,42 +207,11 @@
<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>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.unascribed</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.core.depends.expressionparser</shadedPattern>
</relocation>
</relocations>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -31,10 +31,24 @@ import ch.andre601.advancedserverlist.core.check.UpdateChecker;
import ch.andre601.advancedserverlist.core.commands.CommandHandler;
import ch.andre601.advancedserverlist.core.compat.maintenance.MaintenancePlaceholder;
import ch.andre601.advancedserverlist.core.file.FileHandler;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandType;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.parsing.TextCenterUtil;
import ch.andre601.advancedserverlist.core.profiles.ServerListProfile;
import ch.andre601.advancedserverlist.core.profiles.conditions.ProfileConditionParser;
import ch.andre601.advancedserverlist.core.profiles.handlers.PlayerHandler;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.annotations.AnnotationParser;
import org.incendo.cloud.description.Description;
import org.incendo.cloud.injection.ParameterInjector;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.parser.standard.BooleanParser;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.permission.Permission;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.io.IOException;
import java.io.InputStream;
@@ -44,9 +58,12 @@ import java.util.Properties;
public class AdvancedServerList<F>{
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
private final PluginCore<F> plugin;
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final TextCenterUtil textCenterUtil;
@@ -60,7 +77,6 @@ public class AdvancedServerList<F>{
private AdvancedServerList(PluginCore<F> plugin, List<PlaceholderProvider> placeholders){
this.plugin = plugin;
this.fileHandler = new FileHandler(this);
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
this.textCenterUtil = new TextCenterUtil(this);
@@ -77,10 +93,6 @@ public class AdvancedServerList<F>{
load();
}
public static <F> AdvancedServerList<F> init(PluginCore<F> plugin, PlaceholderProvider... placeholders){
return new AdvancedServerList<>(plugin, Arrays.asList(placeholders));
}
public static AdvancedServerListAPI getApi(){
return api;
}
@@ -93,10 +105,6 @@ public class AdvancedServerList<F>{
return fileHandler;
}
public CommandHandler getCommandHandler(){
return commandHandler;
}
public PlayerHandler getPlayerHandler(){
return playerHandler;
}
@@ -167,9 +175,8 @@ public class AdvancedServerList<F>{
return;
}
getPlugin().loadFaviconHandler(this);
plugin.loadCommands();
loadCommands();
plugin.loadEvents();
getPlayerHandler().load();
plugin.loadMetrics();
@@ -206,4 +213,74 @@ public class AdvancedServerList<F>{
private void addPlaceholder(PlaceholderProvider placeholderProvider){
AdvancedServerList.getApi().addPlaceholderProvider(placeholderProvider);
}
private void loadCommands(){
getPlugin().loadFaviconHandler(this);
CommandManager<CmdSender> commandManager = plugin.getCommandManager();
commandManager.parameterInjectorRegistry().registerInjector(AdvancedServerList.class, ParameterInjector.constantInjector(this));
AnnotationParser<CmdSender> annotationParser = new AnnotationParser<>(commandManager, CmdSender.class);
annotationParser.registerBuilderModifier(
CommandType.class,
(annotation, builder) -> builder.meta(CommandHandler.COMMAND_TYPE, annotation.value())
);
annotationParser.parse(new CommandHandler(commandManager));
for(String option : CommandHandler.PROFILE_OPTIONS){
commandManager.command(
commandManager.commandBuilder("advancedserverlist", "asl")
.literal("profiles")
.literal("set")
.required(
"profile",
StringParser.stringParser(),
Description.of("The profile to edit."),
SuggestionProvider.suggesting(
getFileHandler().getProfiles().stream()
.map(ServerListProfile::file)
.map(Suggestion::suggestion)
.toList()
)
)
.literal(option)
.optional("value", descriptor(option), description(option))
.commandDescription(Description.of("Sets or resets profile values."))
.handler(context -> CommandHandler.handleSet(this, context))
.meta(CommandHandler.OPTION, option)
.permission(
Permission.anyOf(
Permission.permission("advancedserverlist.admin"),
Permission.permission("advancedserverlist.command.profiles")
)
)
);
}
getPlugin().getPluginLogger().success("Loaded Command <white>/advancedserverlist</white>!");
}
private ParserDescriptor<CmdSender, ?> descriptor(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> BooleanParser.booleanParser();
case "priority" -> IntegerParser.integerParser();
default -> StringParser.greedyStringParser();
};
}
private Description description(String option){
return switch(option){
case "playercount.hideplayers", "playercount.hideplayershover", "playercount.extraplayers.enabled",
"playercount.maxplayers.enabled", "playercount.onlineplayers.enabled" -> Description.of(
"Whether this option should be enabled or not. Leave empty to unset it."
);
case "priority" -> Description.of("Priority this Profile should have. Leave empty to reset.");
case "motd", "playercount.hover" -> Description.of(
"Lines to set. Use \\n or <newline> to set a linebreak. Leave empty to reset."
);
default -> Description.of("The Value to use for this option. Leave empty to reset.");
};
}
}
@@ -101,8 +101,12 @@ public class UpdateChecker{
);
}else
if(result == 1){
sender.sendPrefixedMsg("You seem to run a newer Version (<white>%</white>) than what is available on Modrinth (<white>%s</white>).", core.getVersion(), version.versionNumber());
sender.sendPrefixedMsg("Are you running a development build?");
sender.sendPrefixedMsg(
"Your version (<white>%</white>) is newer than what is available on Modrinth (<white>%s</white>).",
core.getVersion(),
version.versionNumber()
);
sender.sendPrefixedMsg("Are you using a Development Version?");
}
});
}
@@ -137,10 +141,14 @@ public class UpdateChecker{
switch(result){
case -1 -> printUpdateBanner(version);
case 0 -> logger.success("You are running the latest version!");
case 1 -> logger.info(
"[?] Your version (<white>%s</white>) seems to be newer than the latest release (<white>%s</white>). Are you running a dev build?",
core.getVersion(), version.versionNumber()
);
case 1 -> {
logger.info(
"[?] Your version (<white>%s</white>) is newer than what is available on Modrint (<white>%s</white>).",
core.getVersion(),
version.versionNumber()
);
logger.info(" Are you using a Development Version?");
}
}
});
}, 0L, 12L, TimeUnit.HOURS);
File diff suppressed because it is too large. Load diff
@@ -1,110 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package ch.andre601.advancedserverlist.core.commands;
import java.util.ArrayList;
import java.util.List;
public class CommandStringBuilder{
private final List<CommandPart> commandParts = new ArrayList<>();
public CommandStringBuilder(String subcommand, String description){
appendText("<hover:show_text:\"<grey>" + description + "</grey>\"><white>" + subcommand + "</white></hover>");
}
public CommandStringBuilder appendArgument(Argument argument){
this.commandParts.add(argument);
return this;
}
public CommandStringBuilder appendText(String text){
this.commandParts.add(new Text(text));
return this;
}
public CommandStringBuilder appendLiteralArgument(String name, String description){
return appendText("<hover:show_text:\"<grey>" + description + "</grey>\"><white>" + name + "</white></hover>");
}
public CommandStringBuilder appendSpace(){
return appendText(" ");
}
public String build(){
StringBuilder builder = new StringBuilder("<aqua>/asl ");
for(CommandPart part : commandParts){
builder.append(part.build());
}
builder.append("</aqua>"); // Closing the first color tag.
return builder.toString();
}
public static class ArgumentBuilder{
private final String name;
private String description = "No description provided.";
private boolean required = false;
public ArgumentBuilder(String name){
this.name = name;
}
public ArgumentBuilder description(String description){
this.description = description;
return this;
}
public ArgumentBuilder required(){
this.required = true;
return this;
}
public Argument build(){
return new Argument(name, description, required);
}
}
private record Text(String text) implements CommandPart{
@Override
public String build(){
return text();
}
}
private record Argument(String name, String description, boolean required) implements CommandPart{
@Override
public String build(){
return "<hover:show_text:\"<grey>" + description() + "</grey>\">" +
"<grey>" + (required() ? "\\<" : "[") + "<white>" + name() + "</white>" + (required() ? ">" : "]") +
"</grey></hover>";
}
}
private interface CommandPart{
String build();
}
}
@@ -0,0 +1,172 @@
/*
* MIT License
*
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package ch.andre601.advancedserverlist.core.commands;
import ch.andre601.advancedserverlist.api.objects.NullBool;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class ProfileOptionsSender{
private final List<OptionStringBuilder> builders = new ArrayList<>();
private final String file;
public ProfileOptionsSender(String file){
this.file = file;
}
public ProfileOptionsSender append(OptionStringBuilder builder){
this.builders.add(builder.file(file));
return this;
}
public void send(CmdSender sender){
sender.sendMsg();
sender.sendPrefixedMsg("Profile Info [<white>%s</white>]", file);
for(OptionStringBuilder builder : builders){
sender.sendMsg(builder.build());
}
sender.sendMsg();
sender.sendMsg("[<grey>Hover for info, click for command</grey>]");
sender.sendMsg();
}
public static class OptionStringBuilder{
public static OptionStringBuilder of(String displayName, String hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : hover)
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, List<String> hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || hover.isEmpty() ? "<i>Not set</i>" : String.join("\n<reset>", hover))
.color(hover == null || hover.isEmpty() ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, NullBool hover){
return new OptionStringBuilder(displayName)
.hover(hover == null || !hover.getOrDefault(false) ? "<red>Disabled</red>" : "<green>Enabled</green>")
.color(hover == null || !hover.getOrDefault(false) ? ColorName.RED : ColorName.GREEN);
}
public static OptionStringBuilder of(String displayName, int hover){
return new OptionStringBuilder(displayName)
.hover(String.valueOf(hover));
}
public static OptionStringBuilder of(String displayName){
return new OptionStringBuilder(displayName).hover(null);
}
private final String displayName;
private String file = null;
private String prefix = "├─";
private ColorName color = ColorName.AQUA;
private String hover = "<i>Not set</i>";
private String option = null;
private OptionStringBuilder(String displayName){
this.displayName = displayName;
}
public OptionStringBuilder file(String file){
this.file = file;
return this;
}
public OptionStringBuilder prefix(String prefix){
this.prefix = prefix;
return this;
}
public OptionStringBuilder color(ColorName color){
this.color = color;
return this;
}
public OptionStringBuilder hover(String hover){
this.hover = hover;
return this;
}
public OptionStringBuilder option(String option){
this.option = option;
return this;
}
public String build(){
StringBuilder builder = new StringBuilder("<grey>")
.append(prefix)
.append(" <white>[")
.append('<')
.append(color)
.append('>');
if(hover != null && !hover.isEmpty()){
builder.append("<hover:show_text:\"")
.append(hover)
.append("\">");
}
if(option != null && !option.isEmpty() && file != null && !file.isEmpty()){
builder.append("<click:suggest_command:/asl profiles set ")
.append(file)
.append(" ")
.append(option)
.append(" >");
}
builder.append(displayName);
if(option != null && !option.isEmpty())
builder.append("</click>");
if(hover != null && !hover.isEmpty())
builder.append("</hover>");
builder.append("</")
.append(color)
.append(">]</white></grey>");
return builder.toString();
}
}
enum ColorName{
RED,
GREEN,
AQUA;
@Override
public String toString(){
return this.name().toLowerCase(Locale.ROOT);
}
}
}
@@ -25,12 +25,12 @@
package ch.andre601.advancedserverlist.core.interfaces.commands;
import net.kyori.adventure.audience.Audience;
public interface CmdSender{
String prefix = "<grey>[<gradient:aqua:white>AdvancedServerList</gradient>] ";
String errorPrefix = "<grey>[<gradient:dark_red:red>AdvancedServerList</gradient>] ";
boolean hasPermission(String permission);
String prefix = "<grey>[<aqua>ASL</aqua>] ";
String errorPrefix = "<grey>[<red>ASL</red>] ";
void sendMsg(String msg, Object... args);
@@ -45,4 +45,8 @@ public interface CmdSender{
default void sendErrorMsg(String msg, Object... args){
sendMsg(errorPrefix + msg, args);
}
Audience audience();
boolean isPlayer();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,24 +20,15 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.velocity.commands;
package ch.andre601.advancedserverlist.core.interfaces.commands;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import com.velocitypowered.api.command.SimpleCommand;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
public class CmdAdvancedServerList implements SimpleCommand{
public interface CommandManagerInterface<S>{
CommandManager<CmdSender> commandHandler();
private final VelocityCore plugin;
public CmdAdvancedServerList(VelocityCore plugin){
this.plugin = plugin;
}
@Override
public void execute(Invocation invocation){
plugin.getCore().getCommandHandler().handle(new VelocityCmdSender(invocation.source()), invocation.arguments());
}
SenderMapper<S, CmdSender> senderMapper();
}
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2022-2023 Andre_601
* Copyright (c) 2022-2025 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,32 +20,22 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.interfaces.commands;
import java.util.Locale;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public abstract class PluginCommand{
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface CommandType{
Type value();
private final String name;
public PluginCommand(String name){
this.name = name;
enum Type{
ALL,
PLAYER_ONLY
}
public String name(){
return name;
}
public String permission(){
return "advancedserverlist.command." + name().toLowerCase(Locale.ROOT);
}
public abstract void handle(CmdSender sender, String[] args);
public abstract String usage();
public abstract String description();
}
@@ -27,15 +27,15 @@ package ch.andre601.advancedserverlist.core.interfaces.core;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import org.incendo.cloud.CommandManager;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
public interface PluginCore<F>{
void loadCommands();
void loadEvents();
void loadMetrics();
@@ -56,6 +56,8 @@ public interface PluginCore<F>{
FaviconHandler<F> getFaviconHandler();
CommandManager<CmdSender> getCommandManager();
String getPlatformInfo();
String getLoader();
+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
-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 %}
<p class="api-detail__description">
{{ enum.description }}
</p>
{% 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 %}
File renamed without changes.
+10 -2
View File
@@ -13,7 +13,7 @@ These Addons are made by Andre601 and available together with the plugin downloa
<div class="grid cards" markdown>
- [**BanPlugins**](banplugins.md)
- [**BanPlugins**](first-party/banplugins.md)
----
@@ -25,4 +25,12 @@ These Addons are made by Andre601 and available together with the plugin downloa
Third-party addons made by other people not working on AdvancedServerList.
*Currently no entries*
<div class="grid cards" markdown>
- [**SayanVanish**](third-party/sayanvanish.md)
----
SayanVanish adds additional placeholders to the Velocity version of AdvancedServerList to use.
</div>
+39
View File
@@ -0,0 +1,39 @@
---
icon: octicons/eye-closed-24
---
# SayanVanish
The plugin [SayanVanish]{ target="_blank" rel="nofollow" } is hooking into AdvancedServerList to provide placeholders of its own to be used in conditions and text options.
## Placeholders
/// tab | :fontawesome-solid-paper-plane: Paper
[:octicons-file-code-24: Source][source-paper]
| Placeholder | Description |
|----------------------------------|--------------------------------------------------------------------------------------------|
| `${sayanvanish vanished}` | Returns true or false based on if the player is vanished. |
| `${sayanvanish level}` | Returns the vanish level of the player. |
| `${sayanvanish count}` | Returns the number of online players that are vanished. |
| `${sayanvanish online_here}` | Returns the number of online players on the same server that aren't vanished. |
| `${sayanvanish online_total}` | Returns the number of online players on the entire network that aren't vanished.^[1](#n1)^ |
| `${sayanvanish online_<server>}` | Returns the number of online players on `<server>` that aren't vanished.^[1](#n1)^ |
<small>^1^{ #n1 } Only works when Proxy mode is enabled and will otherwise return `PROXY_MODE IS NOT ENABLED!`</small>
///
/// tab | :fontawesome-solid-paper-plane: Velocity
[:octicons-file-code-24: Source][source-velocity]
| Placeholder | Description |
|----------------------------------|----------------------------------------------------------------------------------|
| `${sayanvanish vanished}` | Returns true or false based on if the player is vanished. |
| `${sayanvanish level}` | Returns the vanish level of the player. |
| `${sayanvanish count}` | Returns the number of online players that are vanished. |
| `${sayanvanish online_total}` | Returns the number of online players on the entire network that aren't vanished. |
| `${sayanvanish online_<server>}` | Returns the number of online players on `<server>` that aren't vanished. |
///
[SayanVanish]: https://modrinth.com/plugin/sayanvanish
[source-paper]: https://github.com/Syrent/SayanVanish/blob/ffd740832fd914c6462c41917a91f575f43ee778/sayanvanish-bukkit/src/main/kotlin/org/sayandev/sayanvanish/bukkit/feature/features/hook/FeatureHookAdvancedServerList.kt
[source-velocity]: https://github.com/Syrent/SayanVanish/blob/585279bf5480542858a9d3d91cfc4d844982aa0f/sayanvanish-proxy/sayanvanish-proxy-velocity/src/main/kotlin/org/sayandev/sayanvanish/velocity/feature/features/hook/FeatureHookAdvancedServerList.kt
+183
View File
@@ -0,0 +1,183 @@
---
icon: octicons/plus-circle-24
---
AdvancedServerList allows you to add your own Placeholders to be useable through its `${identifier value}` format.
The benefit of this method over alternatives such as using PlaceholderAPI placeholders is availability and the fact that these placeholders can be used within the [`condition` option](../profiles/index.md#condition) of the plugin.
Adding your own placeholder is relatively easy and only requires the main API module to be used in your dependencies, unless you need platform-specific values (Explained later on).
## Create your PlaceholderProvider class
AdvancedServerList's placeholder system uses a dedicated [`PlaceholderProvider`](reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md) class where the placeholder gets defined and its values parsed.
In order to add your own, you'll need to first create a new class and make it extend the `PlaceholderProvider` class:
```java title="MyPlaceholder.java"
public class MyPlaceholder extends PlaceholderProvider {
}
```
Your IDE should now report issues, namely a missing method to override and a missing Constructor to match the extended class' one. Your IDE should allow you to easily implement those, if not, then manually add the constructor with a `String` argument and the `public String parsePlaceholder` method with `String`, [`GenericPlayer`](reference/api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) and [`GenericServer`](reference/api/ch.andre601.advancedserverlist.api/objects/genericserver.md) arguments:
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder(String identifier) {
super(identifier); // (1)
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
return null;
}
}
```
1. It is recommended to replace the Constructor with a No-Args Constructor and set the placeholder name directly in the `super` call:
```java
public MyPlaceholder() {
super("myplaceholder");
}
```
## Parsing placeholders
To now parse your placeholders, all you need to do is edit the `parsePlaceholder` method.
AdvancedServerList calls this method whenever it finds a matching identifier of a PlaceholderProvider, with the `String` argument being the actual value after the identifier and the `GenericPlayer` and `GenericServer` arguments holding the Player and server values respectively.
As an example, assuming you simply want to return `Hello` for the placeholder `${myplaceholder sayHello}`, this would be the code for it:
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder() {
super("myplaceholder");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if (placeholder.equals("sayHello")) {
return "Hello";
}
return null; // (1)
}
}
```
1. Returning `null` tells AdvancedServerList that the placeholder was invalid, making it return the placeholder unchanged, while also reporting an error, if used in `condition`.
## Registering the Placeholder
The final step now would be to register your placeholder for AdvancedServerList to use.
To do this, obtain an instance of the [`AdvancedServerListAPI`](reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md) through its static `get()` method and then call `addPlaceholderProvider(PlaceholderProvider)` through it:
/// tab | :fontawesome-solid-paper-plane: Paper Example
```java title="MyPlugin.java"
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
getLogger().info("Hooked into AdvancedServerList!");
}
}
```
///
/// tab | :octicons-git-merge-24: BungeeCord Example
```java title="MyPlugin.java"
public class MyPlugin extends Plugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
getLogger().info("Hooked into AdvancedServerList!");
}
}
```
///
/// tab | :fontawesome-solid-paper-plane: Velocity Example
```java title="MyPlugin.java"
@Plugin(
id = "myplugin",
version = "1.0.0",
authors = {"You?"},
dependencies = {
@Dependency(id = "advancedserverlist")
}
)
public class MyPlugin {
private final ProxyServer proxy;
private final Logger logger;
@Inject
public MyPlugin(ProxyServer proxy, Logger logger) {
this.proxy = proxy;
this.logger = logger;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholder());
logger.info("Hooked into AdvancedServerList!");
}
}
```
///
## You're done
Your Placeholders should now be registered successfully if they check the following:
- The provided identifier is not `null` nor empty.
- The provided identifier does not contain spaces.
- The provided identifier is not already registered in the API.
## Note on `GenericPlayer` and `GenericServer`
The different platform APIs of AdvancedServerList provide extended versions of the `GenericPlayer` and `GenericServer` instances used, providing additional methods otherwise not available.
Should you want to use these specific instances will you need to add the platform API as an additional dependency to your project and then cast the `GenericPlayer` and/or `GenericServer` instance to the platform specific version.
Below is an example using the `platform-bukkit` API (This assumes your plugin is one running on Paper):
```java { title="MyPlaceholder.java" .annotate }
public class MyPlaceholder extends PlaceholderProvider {
public MyPlaceholder() {
super("myplaceholder");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if (!(player instanceof BukkitPlayer bukkitPlayer)) {
return null; // (1)
}
return switch (placeholder) {
case "playedBefore" -> String.valueOf(bukkitPlayer.hasPlayedBefore());
case "whitelisted" -> String.valueOf(bukkitPlayer.isWhitelisted());
case "banned" -> String.valueOf(bukkitPlayer.isBanned());
default -> null;
};
}
}
```
1. Depending on the Java version you use will you need to alter the code:
```java
if (!(player instanceof BukkitPlayer)) {
return null;
}
// You need to cast it separately.
BukkitPlayer bukkitPlayer = (BukkitPlayer) player;
// ...use bukkitPlayer here.
```
+14 -14
View File
@@ -14,7 +14,7 @@ They are ordered newest to oldest.
- New setter method added to [`ProfileEntry.Builder`][profileentry.builder] class:
- [`hidePlayersHoverEnabled(NullBool)`][hidePlayersHoverEnabled]
[hidePlayersHoverEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayershoverenabled(nullbool)
[hidePlayersHoverEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayershoverenabled
## v4.0.0 { #v4.0.0 }
@@ -30,8 +30,8 @@ They are ordered newest to oldest.
- [`onlinePlayersCount(String)`][onlinePlayersCount]
- [`onlinePlayersEnabled(NullBool)`][onlinePlayersEnabled]
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount(string)
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled(nullbool)
[onlinePlayersCount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayerscount
[onlinePlayersEnabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#onlineplayersenabled
## v3.3.0 { #v3.3.0 }
@@ -62,15 +62,15 @@ They are ordered newest to oldest.
- [`playerCountText(String)`][playercounttext]
- [`players(List<String>)`][players]
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount(string)
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled(nullbool)
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon(string)
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled(nullbool)
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount(string)
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayersenabled(nullbool)
[motd]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#motd(list<string>)
[playercounttext]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#playercounttext(string)
[players]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#players(list<string>)
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayersenabled
[motd]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#motd
[playercounttext]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#playercounttext
[players]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#players
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.0-changed }
@@ -137,8 +137,8 @@ They are ordered newest to oldest.
- `setExtraPlayerEnabled(Integer)` in `ProfileEntry.Builder` - Typo in method name.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled()
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount()
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayersenabled
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#maxplayerscount
[profileentry.builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
+12 -116
View File
@@ -84,127 +84,23 @@ dependencies {
```
///
## Adding your own Placeholders
## Tutorials
<!-- admo:info This requires the main api module -->
Dedicated pages to explain aspects of the API are available:
The API allows you to add your own placeholders which would be available through the `${<identifier> <values>}` placeholder Pattern in a Server List profile.
<div class="grid cards" markdown>
To add your own placeholders, follow these steps:
- [:octicons-plus-circle-24: Adding Placeholders](adding-placeholders.md)
- [:octicons-broadcast-24: Listening for Events](listening-for-events.md)
### 1. Create a Placeholder class
</div>
You should first create a new class and make it extend the abstract [`PlaceholderProvider`][placeholderprovider]. This class includes a constructor and a method you need to add, so do that:
```java { .annotate title="Creating PlaceholderProvider class" }
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders(String identifier) {
super(identifier); // (1)
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
return null;
}
}
```
1. It is recommended to replace this constructor with a no-args Constructor and have the placeholder name set in the `super` directly:
```java
public MyPlaceholders() {
super("myplaceholders");
}
```
The [`parsePlaceholder(String, GenericPlayer, GenericServer)`][parseplaceholder] method is used by AdvancedServerList to replace a matching placeholder with a value.
What you return is completely up to you. Just keep in mind that returning `null` will be treated as an invalid placeholder by AdvancedServerList, resulting in the placeholder being returned as-is without any changes.
[placeholderprovider]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
[parseplaceholder]: reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md#parseplaceholder(string,-genericplayer,-genericserver)
/// details | Example of final class
type: example
```java title="MyPlaceholders.java"
public class MyPlaceholders extends PlaceholderProvider {
public MyPlaceholders() {
super("myplaceholders");
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server) {
if(placeholder.equalsIgnoreCase("hello"))
return "Hello " + player.getName();
return null;
}
}
```
///
### 2. Register the Placeholders
Next step should be to register the placeholder. To achieve this, first obtain an instance of the [`AdvancedServerListAPI`][advancedserverlistapi] by using the static [`get()`][get] method. After that call [`addPlaceholderProvider(PlaceholderProvider placeholderProvider)`][addplaceholderprovider].
Your code may look similar to this:
```java title="Registering PlaceholderProvider class"
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
AdvancedServerListAPI api = AdvancedServerListAPI.get();
api.addPlaceholderProvider(new MyPlaceholders());
}
}
```
[advancedserverlistapi]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
[get]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#get()
[addplaceholderprovider]: reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)
This should register your PlaceholderExpansion as long as it is valid, meaning that the identifier...
- ...is not `null`
- ...is not containing spaces
- ...is not using a name already registered in the API
### 3. Declare AdvancedServerList as (soft)depend
## Declare AdvancedServerList as (soft)depend
The final thing you should make sure is to define AdvancedServerList as a depend or soft-depend for your plugin, to make sure it loads after AdvancedServerList.
Below are example setups for Spigot, Paper, BungeeCord and Velocity:
/// tab | :simple-spigotmc: Spigot
//// tab | Softdepend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
softdepend:
- AdvancedServerList
```
////
//// tab | Depend
```yaml title="plugin.yml"
name: "MyPlugin"
author: "author"
version: "1.0.0"
main: "com.example.plugin.ExamplePlugin"
depend:
- AdvancedServerList
```
////
///
/// tab | :fontawesome-solid-paper-plane: Paper
//// tab | Softdepend
```yaml title="paper-plugin.yml"
@@ -377,10 +273,10 @@ The event offers the following methods:
Please check the server/proxy's documentation on how to listen for events with your plugin.
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry(profileentry)
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled()
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled(boolean)
[getentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry
[setentry]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setentry
[iscancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#iscancelled
[setcancelled]: reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#setcancelled
### PostServerListSetEvent
@@ -401,4 +297,4 @@ A convenience method ([`builder()`][builder()]) exists to create a `Builder` ins
This allows you to customize the Server list using your plugin. Just keep in mind that other plugins may also do the same, overriding your changes.
[builder]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
[builder()]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#builder()
[builder()]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md#builder
+65
View File
@@ -0,0 +1,65 @@
---
icon: octicons/broadcast-24
---
AdvancedServerList provides some events that your plugin can listen to.
These events are structurally the same across all platforms, yet still require the usage of Platform-specific APIs due to how some events are registered and handled on some platforms.
The plugin currently offers the following events:
<div class="grid cards" markdown>
- [PreServerListSetEvent](#preserverlistsetevent)
- [PostServerListSetEvent](#postserverlistsetevent)
</div>
## PreServerListSetEvent
This event is executed before AdvancedServerList tries to modify the player list.
### Methods { #preserverlistsetevent-methods }
The following methods are available to use:
| Method | Description |
|--------------------------|--------------------------------------------------------------------------------|
| `getEntry()` | Returns the [`ProfileEntry`][profileentry] that AdvancedServerList should use. |
| `setEntry(ProfileEntry)` | Sets the [`ProfileEntry`][profileentry] that should be used. |
| `isCancelled()` | Returns wether this event was cancelled or not. |
| `setCancelled(boolean)` | Sets the event's cancelled state. |
### Notes { #preserverlistsetevent-notes }
- Providing `null` as the `ProfileEntry` for `setEntry(ProfileEntry)` is not allowed. Also, a copy of the provided `ProfileEntry` is made and used.
## PostServerListSetEvent
This event is executed after AdvancedServerList completed the server list modifications.
### Methods { #postserverlistsetevent-methods }
| Method | Description |
|--------------------------|--------------------------------------------------------------------------|
| `getEntry()` | Returns the [`ProfileEntry`][profileentry] that AdvancedServerList used. |
### Notes { #postserverlistsetevent-notes }
- The returned `ProfileEntry` is not an actual representation of what is being displayed to the player and rather an instance of values the plugin received.
The returned value may also be `null` should the Ping Event be cancelled due to things such as an invalid Protocol or the [`PreServerListSetEvent`](#preserverlistsetevent) being cancelled.
## Registering the Events
To register an event, please refer to our platforms documentation on how to do this.
## What is a ProfileEntry?
Both events provide and use a so called [`ProfileEntry`][profileentry].
The `ProfileEntry` is a record, representing the values of a [Server List Profile](../profiles/index.md), meaning all values you can set in the profile configuration (Except condition and priority) will be available as a `ProfileEntry`.
It is important to note, that the `ProfileEntry` can be a representation of the [`profiles` option](../profiles/index.md#profiles), the global options or a mixture of both.
If you want to create your own instance, you'll need to use the [`ProfileEntry.Builder` class](reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md) as the `ProfileEntry` is unmodifiable.
A convenience method in the form of `builder()` exists to create a Builder instance of the ProfileEntry with its values already pre-set.
[profileentry]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
@@ -1,10 +1,10 @@
---
template: api-doc.html
api: true
methods:
- name: 'get'
description: |
Retrieve the instance used of this API.<br>
Retrieve the instance used of this API.
If no instance has been made so far will a new one be created.
returns: 'Instance of this API.'
attributes:
@@ -14,38 +14,38 @@ methods:
type: 'object'
- name: 'addPlaceholderProvider'
description: |
Adds the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to the list, if it passes the following checks:<br>
<ul>
<li>Provided PlaceholderProvider instance is not null.</li>
<li>The identifier is not null nor empty.</li>
<li>The identifier does not contain any spaces.</li>
<li>A PlaceholderProvider with the same identifier doesn't exist already.</li>
</ul>
Not passing any of the above checks results in a <a href="./../exceptions/invalidplaceholderproviderexception/"><code>InvalidPlaceholderProviderException</code></a> being thrown.
Adds the provided [`PlaceholderAPIProvider`](placeholderprovider.md) to the list, if it passes the following checks:
- Provided PlaceholderProvider instance is not null.
- The identifier is not null nor empty.
- The identifier does not contain any spaces.
- A PlaceholderProvider with the same identifier doesn't exist already.
Not passing any of the above checks results in a [`InvalidPlaceholderProviderException`](exceptions/invalidplaceholderproviderexception.md) being thrown.
parameters:
- name: 'placeholderProvider'
description: 'The <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> to add.'
description: 'The [`PlaceholderProvider`](placeholderprovider.md) to add.'
type: PlaceholderProvider
attributes:
- notnull
throws:
- name: 'InvalidPlaceholderProviderException'
description: 'When the provided <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a> is null, has a null or empty identifier, the identifier contains spaces, or another PlaceholderProvider with the same identifier is already in use.'
description: 'When the provided [`PlaceholderProvider`](placeholderprovider.md) is null, has a null or empty identifier, the identifier contains spaces, or another PlaceholderProvider with the same identifier is already in use.'
type:
name: 'void'
- name: 'retrievePlaceholderProvider'
description: 'Retrieves the <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> associated with the provided identifier, or <code>null</code> should no such entry exist.'
description: 'Retrieves the [`PlaceholderProvider`](placeholderprovider.md) associated with the provided identifier, or `null` should no such entry exist.'
parameters:
- name: 'identifier'
description: 'The identifier to find a matching <a href="./../placeholderprovider/"><code>PlaceholderProvider</code></a> for.'
description: 'The identifier to find a matching [`PlaceholderProvider`](placeholderprovider.md) for.'
type: String
returns: 'Possibly-null <a href="./../placeholderprovider/"><code>PlaceholderProvider</code> instance</a>.'
returns: 'Possibly-null [`PlaceholderProvider` instance](placeholderprovider.md).'
attributes:
- nullable
type:
name: PlaceholderProvider
type: object
link: './../placeholderprovider'
link: 'placeholderprovider.md'
---
# <api__class></api__class> AdvancedServerListAPI
@@ -1,27 +1,27 @@
---
template: api-doc.html
api: true
methods:
- name: 'getEntry'
description: 'Gets the <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> currently set.'
description: 'Gets the [`ProfileEntry`](../profiles/profileentry/index.md) currently set.'
returns: The currently used ProfileEntry.
type:
name: ProfileEntry
type: object
link: '../../profiles/profileentry/'
link: '../profiles/profileentry/index.md'
- name: 'setEntry'
description: |-
Sets the new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.<br>
This may not be <code>null</code>.
Sets the new [`ProfileEntry`](../profiles/profileentry/index.md) to use.
This may not be `null`.
parameters:
- name: 'entry'
description: 'The new <a href="../../profiles/profileentry/"><code>ProfileEntry</code></a> to use.'
description: 'The new [`ProfileEntry`](../profiles/profileentry/index.md) to use.'
type: ProfileEntry
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'When the provided ProfileEntry is <code>null</code>'
description: 'When the provided ProfileEntry is `null`'
type:
name: 'void'
- name: 'isCancelled'
@@ -1,5 +1,5 @@
---
template: 'api-doc.html'
api: true
constructors:
- name: 'InvalidPlaceholderProviderException'
@@ -1,12 +1,12 @@
---
template: api-doc.html
api: true
methods:
- name: 'getName'
description: |
Returns the name of the player.<br>
Note that on Spigot, Paper and other forks can the name differ from the one cached by AdvancedServerList, if the plugin was able to retrieve an OfflinePlayer instance from the server. On BungeeCord and Velocity will the returned String always be the name from the cache.<br>
<br>
Returns the name of the player.
Note that on Spigot, Paper and other forks can the name differ from the one cached by AdvancedServerList, if the plugin was able to retrieve an OfflinePlayer instance from the server. On BungeeCord and Velocity will the returned String always be the name from the cache.
Name may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by the plugin.
returns: 'String representing the player''s name'
type:
@@ -14,15 +14,15 @@ methods:
type: object
- name: 'getProtocol'
description: |
Returns the protocol ID the player is using.<br>
Returns the protocol ID the player is using.
The protocol ID is an integer used by Minecraft to determine what version a server or client is running.
returns: 'Integer representing the protocol version of this player.'
type:
name: int
- name: 'getUUID'
description: |
Returns the unique ID associated with this player.<br>
<br>
Returns the unique ID associated with this player.
UUID may be whatever has been defined in AdvancedServerList's config.yml, should the player not be cached yet by AdvancedServerList.
returns: 'UUID of the player'
type:
@@ -37,6 +37,6 @@ The different variants of AdvancedServerList implement this into their own class
The following values will always be present, no matter the platform this interface is used on:
- [Name of the Player](#getname())
- [Protocol version of the Player](#getprotocol())
- [UUID of the Player](#getuuid())
- [Name of the Player](#getname)
- [Protocol version of the Player](#getprotocol)
- [UUID of the Player](#getuuid)
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getPlayersOnline'
@@ -1,23 +1,23 @@
---
template: api-doc.html
api: true
enums:
- name: 'true'
description: 'Boolean value <code>true</code>'
description: 'Boolean value `true`'
- name: 'false'
description: 'Boolean value <code>false</code>'
description: 'Boolean value `false`'
- name: 'not_set'
description: 'Boolean value <code>null</code>'
description: 'Boolean value `null`'
methods:
- name: 'resolve'
description: |
Returns a NullBool instance based on the provided <code>Boolean</code> value.<br>
In case of <code>null</code> being provided will <a href="#not_set"><code>NullBool.NOT_SET</code></a> be returned, otherwise will the corresponding NullBool instance matching the Boolean value be returned.
returns: 'NullBool instance based on the provided <code>Boolean</code> value.'
Returns a NullBool instance based on the provided `Boolean` value.
In case of `null` being provided will [`NullBool.NOT_SET`](#not_set) be returned, otherwise will the corresponding NullBool instance matching the Boolean value be returned.
returns: 'NullBool instance based on the provided `Boolean` value.'
parameters:
- name: 'bool'
description: 'The <code>Boolean</code> value to receive a NullBool instance for.'
description: 'The `Boolean` value to receive a NullBool instance for.'
type: Boolean
attributes:
- nullable
@@ -27,19 +27,19 @@ methods:
name: 'NullBool'
type: 'object'
- name: 'isNotSet'
description: 'Returns whether the NullBool is <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
returns: 'True if the instance is <a href="#not_set"><code>NullBool.NOT_SET</code></a>, otherwise false.'
description: 'Returns whether the NullBool is [`NullBool.NOT_SET`](#not_set)'
returns: 'True if the instance is [`NullBool.NOT_SET`](#not_set), otherwise false.'
type:
name: 'boolean'
type: 'primitive'
- name: 'getOrDefault'
description: |
Gets the corresponding boolean value associated with the NullBool instance.<br>
In the case of NullBool <a href="#isnotset()">not being set</a> will the provided default value be returned.
Gets the corresponding boolean value associated with the NullBool instance.
In the case of NullBool [not being set](#isnotset) will the provided default value be returned.
returns: 'True or false depending on the NullBool instance and the provided default value.'
parameters:
- name: 'def'
description: 'The default boolean value to return should the NullBool instance be <a href="#not_set"><code>NullBool.NOT_SET</code></a>.'
description: 'The default boolean value to return should the NullBool instance be [`NullBool.NOT_SET`](#not_set).'
type: boolean
type:
name: 'boolean'
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PlaceholderProvider'
@@ -8,27 +8,27 @@ constructors:
- name: 'identifier'
description: 'The identifier to use for the placeholder. Cannot be empty.'
type: String
attribute:
attributes:
- notnull
methods:
- name: 'parsePlaceholder'
description: |
Method called by AdvancedServerList's StringReplacer class to replace any appearances of <code>${&lt;identifier&gt; &lt;placeholder&gt;}</code> with whatever value a matching PlaceholderProvider may return.<br>
<br>
Returning <code>null</code> will be treated as an invalid placeholder by the plugin, making it return the placeholder as-is without any changes.
Method called by AdvancedServerList's StringReplacer class to replace any appearances of `${<identifier> <placeholder> with whatever value a matching PlaceholderProvider may return.
Returning `null` will be treated as an invalid placeholder by the plugin, making it return the placeholder as-is without any changes.
parameters:
- name: 'placeholder'
type: String
description: 'The part of the Placeholder that comes after the identifier and before the closing curly bracket.'
- name: 'player'
type: GenericPlayer
description: 'The <a href="./../objects/genericplayer/"><code>GenericPlayer</code> instance</a> used.'
description: 'The [`GenericPlayer` instance](objects/genericplayer.md) used.'
- name: 'server'
type: GenericServer
description: 'The <a href="./../objects/genericserver/"><code>GenericServer</code> instance</a> used.'
description: 'The [`GenericServer` instance](objects/genericserver.md) used.'
returns: 'Possibly-parsed or possibly-null String to replace the placeholder with.'
attribute:
attributes:
- nullable
- abstract
type:
@@ -47,4 +47,4 @@ methods:
Abstract class that is used to provide your own Placeholder patterns for AdvancedServerList to parse.
In order for your class to be considered a valid PlaceholderProvider will you need to set the `identifier` to a non-null, non-empty value without having any spaces in it.
Once set, use [`AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)`](advancedserverlistapi.md#addplaceholderprovider(placeholderprovider)) to register your class for AdvancedServerList to use.
Once set, use [`AdvancedServerListAPI#addPlaceholderProvider(PlaceholderProvider)`](advancedserverlistapi.md#addplaceholderprovider) to register your class for AdvancedServerList to use.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
defaults:
type:
@@ -13,199 +13,199 @@ constructors:
methods:
- name: 'extraPlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#setextraplayersenabled(nullbool)"><code>disable extra Players</code></a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`extraPlayersEnabled()`](index.md#extraplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the max player count. Alternatively [disable extra Players](#extraplayersenabled).
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
- name: 'extraPlayersEnabled'
description: |
Sets whether the extra players feature should be enabled or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets whether the extra players feature should be enabled or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.
description: Thrown by the `CheckUtil` in case `null` has been provided as parameter.
- name: 'favicon'
description: |
Sets the value to use for the favicon.<br>
Sets the value to use for the favicon.
The following values are supported:
<ul>
<li>URL to a valid PNG file.</li>
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
<li><code>${player uuid}</code> to display the avatar of the player.
</ul>
Set to an empty String or <code>null</code> to not alter the Favicon.
- URL to a valid PNG file
- File name (with `.png` extension) matching a file saved in the favicons folder of AdvancedServerList
- `${player uuid}` to display the avatar of the player
Set to an empty String or `null` to not alter the Favicon.
parameters:
- name: 'favicon'
description: 'The favicon to set.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the Favicon has been set. Useful for chaining.'
- name: 'hidePlayersEnabled'
description: |
Sets whether the player count should be hidden or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets whether the player count should be hidden or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'hidePlayersHoverEnabled'
description: |
Sets ehther the Hover List of online Players should be hidden or not.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
Sets ehther the Hover List of online Players should be hidden or not.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
parameters:
- name: 'hidePlayersHoverEnabled'
description: 'Whether the online players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'maxPlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#maxplayersenabled(nullbool)">disable max Players</a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`maxPlayersEnabled(NullBool)`](#maxplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the max player count. Alternatively [disable max Players](#maxplayersenabled).
parameters:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: 'Integer'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the max player count has been set. Useful for chaining.'
- name: 'maxPlayersEnabled'
description: |
Sets whether the max players feature should be enabled.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should maxPlayersEnabled be null.
Sets whether the max players feature should be enabled.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should maxPlayersEnabled be null.
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'motd'
description: |
Sets a new MOTD to use.<br>
<br>
Set to an empty list to not change the MOTD.<br>
Only the first two entries of the list will be considered and any additional ones discarded.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided motd list be null.
Sets a new MOTD to use.
Set to an empty list to not change the MOTD.
Only the first two entries of the list will be considered and any additional ones discarded.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should the provided motd list be null.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the motd has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'onlinePlayersCount'
description: |
Sets the value to resolve into a number by AdvancedServerList.<br>
Strings not resolving into valid numbers will be treated as this option not being set.<br>
<br>
This option has no effect when <a href="#onlineplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the online player count. Alternatively <a href="#onlineplayersenabled(nullbool)">disable online Players</a>.
Sets the value to resolve into a number by AdvancedServerList.
Strings not resolving into valid numbers will be treated as this option not being set.
This option has no effect when [`onlinePlayersEnabled(NullBool)`](#onlineplayersenabled) is set to [`NullBool.FALSE`](../../objects/nullbool.md#false) or [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set).
Set this to `null` to not alter the online player count. Alternatively [disable online Players.](#onlineplayersenabled).
parameters:
- name: 'onlinePlayersCount'
description: 'The number of online players to set.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the max player count has been set. Useful for chaining.'
- name: 'onlinePlayersEnabled'
description: |
Sets whether the online players feature should be enabled.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should onlinePlayersEnabled be null.
Sets whether the online players feature should be enabled.
Set to [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set) to not set this.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should onlinePlayersEnabled be null.
parameters:
- name: 'onlinePlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'playerCountText'
description: |
Sets the text to override the player count with.<br>
<br>
Set to an empty String or <code>null</code> to not alter the player count text.
Set to an empty String or `null` to not alter the player count text.
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: 'String'
attribute:
attributes:
- 'nullable'
returns: 'This Builder after the player count text has been set. Useful for chaining.'
- name: 'players'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Sets the players (lines) to use for the hover.
Set to an empty list to not change the hover text.
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided okayersmotd list be null.
An `IllegalArgumentException` may be thrown by the `CheckUtil` should the provided okayersmotd list be null.
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
attributes:
- 'notnull'
returns: 'This Builder after the players have been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
description: 'Thrown by the `CheckUtil` in case `null` has been provided as parameter.'
- name: 'build'
description: 'Creates a new <a href="./.."><code>ProfileEntry</code> instance</a> with the values set in this Builder.'
returns: 'New <a href="./.."><code>ProfileEntry</code> instance</a>.'
description: 'Creates a new [`ProfileEntry` instance](index.md) with the values set in this Builder.'
returns: 'New [`ProfileEntry` instance](index.md).'
type:
name: 'ProfileEntry'
type: 'object'
link: './..'
link: 'index.md'
---
# <api__class></api__class> Builder
@@ -1,11 +1,11 @@
---
template: api-doc.html
api: true
constructors:
- name: 'ProfileEntry'
description: |
Creates a new instance of a ProfileEntry with the given values.<br>
It's recommended to use the <a href="./builder/"><code>Builder</code> class</a> for a more convenient configuration of the Settings.
Creates a new instance of a ProfileEntry with the given values.
It's recommended to use the [`Builder` class](builder.md) for a more convenient configuration of the Settings.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
@@ -64,32 +64,31 @@ constructors:
- nullable
seealso:
- name: 'ProfileEntry.Builder'
link: './builder/'
link: 'builder.md'
classes:
- name: 'Builder'
description: 'Builder class to create a new ProfileEntry instance.'
type: 'static class'
link: 'builder/'
link: 'builder.md'
methods:
- name: 'empty'
description: |
Creates an "empty" PlayerEntry with the following values set:<br>
<ul>
<li><a href="#motd()"><code>motd</code></a>: Empty List</li>
<li><a href="#players()"><code>players</code></a>: Empty List</li>
<li><a href="#playercounttext()"><code>playerCountText</code></a>: Empty String</li>
<li><a href="#favicon()"><code>favicon</code></a>: Empty String</li>
<li><a href="#hideplayersenabled()"><code>hidePlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
<li><a href="#extraplayersenabled()"><code>extraPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a></li>
<li><a href="#maxplayersenabled()"><code>maxPlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#onlineplayersenabled()"><code>onlinePlayersEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#hideplayershoverenabled()"><code>hidePlayersHoverEnabled</code></a>: <a href="../../objects/nullbool/#not_set"><code>NullBoo.NOT_SET</code></a></li>
<li><a href="#extraplayerscount()"><code>extraPlayersCount</code></a>: <code>null</code></li>
<li><a href="#maxplayerscount()"><code>maxPlayersCount</code></a>: <code>null</code></li>
<li><a href="#onlineplayerscount()"><code>onlinePlayersCount</code></a>: <code>null</code></li>
</ul>
Creates an "empty" PlayerEntry with the following values set:
- [`motd`](#motd): Empty List
- [`players`](#players): Empty List
- [`playerCountText`](#playercounttext): Empty String
- [`favicon`](#favicon): Empty String
- [`hidePlayersEnabled`](#hideplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`extraPlayersEnabled`](#extraplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`maxPlayersEnabled`](#maxplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`onlinePlayersEnabled`](#onlineplayersenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`hidePlayersHoverEnabled`](#hideplayershoverenabled): [`NullBool.NOT_SET`](../../objects/nullbool.md#not_set)
- [`extraPlayersCount`](#extraplayerscount): `null`
- [`maxPlayersCount`](#maxplayerscount): `null`
- [`onlinePlayersCount`](#onlineplayerscount): `null`
returns: 'New ProfileEntry instance with empty/null values defined'
attributes:
- static
@@ -98,26 +97,32 @@ methods:
type: 'object'
- name: 'copy'
description: |
Creates a copy of this ProfileEntry instance.<br>
<br>
This is simply a convenience method to not have to call <a href="#builder()"><code>builder()</code></a><code>.</code><a href="./builder/#build()"><code>build()</code></a>.<br>
If you want to modify the ProfileEntry <a href="#builder()"><code>builder()</code></a> is preferred.
Creates a copy of this ProfileEntry instance.
This is a convenience method that avoids using [`builder()`](#builder) first followed by [`ProfileEntry.Builder.build()`](builder.md#build):
```java
ProfileEntry entry = ProfileEntry.empty(); // Obtain ProfileEntry
// Both do the same
ProfileEntry newEntry1 = entry.builder().build();
ProfileEntry newEntry2 = entry.copy();
```
returns: 'A copy of this ProfileEntry instance.'
seealso:
- name: 'builder()'
link: '#builder()'
link: '#builder'
type:
name: 'ProfileEntry'
type: 'object'
- name: 'builder'
description: |
Creates a <a href="./builder/"><code>Builder</code> instance</a> with the values from this ProfileEntry set.<br>
Creates a [`Builder` instance](builder.md) with the values from this ProfileEntry set.
Use this method if you would like to modify the ProfileEntry.
returns: 'A new <a href="./builder/"><code>Builder</code> instance</a> with the values of this ProfileEntry set.'
returns: 'A new [`Builder` instance](builder.md) with the values of this ProfileEntry set.'
type:
name: 'Builder'
type: 'object'
link: './builder/'
link: 'builder.md'
- name: 'motd'
description: 'Gets the currently set MOTD of this ProfileEntry.'
returns: 'The current MOTD used by this ProfileEntry.'
@@ -138,64 +143,63 @@ methods:
type: 'object'
- name: 'favicon'
description: |
Gets the currently set favicon of this ProfileEntry.<br>
Gets the currently set favicon of this ProfileEntry.
Note that the favicon usually is and supports one of the following options:
<ul>
<li>URL to a valid PNG file</li>
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList</li>
<li><code>${player uuid}</code> to display the avatar of the player</li>
</ul>
- URL to a valid PNG file
- File name (with `.png` extension) matching a file saved in the favicons folder of AdvancedServerList
- `${player uuid}` to display the avatar of the player
returns: 'The current favicon used by this ProfileEntry.'
type:
name: 'String'
type: 'object'
- name: 'hidePlayersEnabled'
description: |
Whether the player count should be hidden or not in this ProfileEntry.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the player count should be hidden or not in this ProfileEntry.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the player count should be hidden or not in this ProfileEntry.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'extraPlayersEnabled'
description: |
Whether the extra players feature should be used or not in this ProfileEntry.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the extra players feature should be used or not in this ProfileEntry.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the extra players feature should be used or not in this ProfileEntry.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'maxPlayersEnabled'
description: |
Whether the max players feature should be used or not.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the max players feature should be used or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the max players feature should be used or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'onlinePlayersEnabled'
description: |
Whether the online players feature should be used or not.<br>
To get the actual boolean value, append <a href="../../objects/nullbool/#getordefault(boolean)"><code>getOrDefault(boolean)</code></a>.
Whether the online players feature should be used or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
returns: 'Whether the online players feature should be used or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'hidePlayersHoverEnabled'
description: |
Whether the Hover List of online players should be hidden or not.<br>
To get the actual boolean value, use <a href="../../objects/nullbool/#getordefault()"><code>getOrDefault(boolean)</code></a> of the returned <a href="../../objects/nullbool"><code>NullBool</code></a>.<br>
<br>
When true, this option will force the <a href="#players()"><code>players()</code></a> list to be ignored.
Whether the Hover List of online players should be hidden or not.
To get the actual boolean value, append [`getOrDefault(boolean)`](../../objects/nullbool.md#getordefault).
When true, this option will force the [`players()`](#players) list to be ignored.
returns: 'Whether the Hover List of online players should be hidden or not.'
type:
name: 'NullBool'
type: 'object'
link: '../../objects/nullbool/'
link: '../../objects/nullbool.md'
- name: 'extraPlayersCount'
description: 'Gets the currently set number of extra players of this ProfileEntry.'
returns: 'The current number of extra players used by this ProfileEntry.'
@@ -222,15 +226,15 @@ methods:
type: 'object'
- name: 'isInvalid'
description: |
Whether this ProfileEntry is considered invalid or not.<br>
Whether this ProfileEntry is considered invalid or not.
The ProfileEntry is considered invalid if all the following is true:
<ul>
<li><a href="#motd()"><code>motd()</code></a> is empty.</li>
<li><a href="#players()"><code>players()</code></a> is empty.</li>
<li><a href="#playercounttext()"><code>playerCountText()</code></a> is null/empty <b>and</b> <a href="#hideplayersenabled()"><code>hidePlayersEnabled()</code></a> is <code>false</code>.</li>
<li><a href="#favicon()"><code>favicon()</code></a> is null/empty.</li>
</ul>
As long as one of the above is <b>not</b> true is this ProfileEntry considered valid and <code>false</code> will be returned.
- [`motd()`](#motd) is empty.
- [`players()`](#players) is empty.
- [`playerCountText()`](#playercounttext) is null/empty **and** [`hidePlayersEnabled()`](#hideplayersenabled) is `false`.
- [`favicon()`](#favicon) is null/empty.
As long as one of the above is **not** true is this ProfileEntry considered valid and `false` will be returned.
returns: 'Whether this ProfileEntry is invalid or not.'
type:
name: 'boolean'
@@ -242,4 +246,4 @@ methods:
This record represents the content found in a server list profile YAML file.
The content may come from either the "profiles" list, the options in the file itself (global options) or a mix of both.
This class is immutable. Use [`builder()`](#builder()) to get a [`Builder` instance](builder.md) with the values of this class added.
This class is immutable. Use [`builder()`](#builder) to get a [`Builder` instance](builder.md) with the values of this class added.
@@ -1,20 +1,20 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
methods:
- name: 'getHandlerList'
description: 'Static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList</code></a> getter. Required by Paper.'
returns: 'The static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList instance</code></a> of this event.'
description: 'Static [`HandlerList`](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html){ target="_blank" rel="nofollow" } getter. Required by Paper.'
returns: 'The static [`HandlerList` instance](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html){ target="_blank" rel="nofollow" } of this event.'
attributes:
- static
type:
@@ -22,9 +22,9 @@ methods:
type: 'object'
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -32,18 +32,19 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
inherits:
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- 'getHandlers()'
- name: 'getHandlers()'
link: 'getHandlers()'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -9,7 +9,7 @@ constructors:
methods:
- name: 'getHandlerList'
returns: 'Static <code>HandlerList</code> instance.'
returns: 'Static `HandlerList` instance.'
attributes:
- static
type:
@@ -18,19 +18,24 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- 'getHandlers()'
- name: 'getHandlers()'
link: 'getHandlers()'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getPlayer'
@@ -10,24 +10,24 @@ methods:
type: 'object'
- name: 'hasPlayedBefore'
description: |
Returns whether this player has played on the server before.<br>
<br>
Returns whether this player has played on the server before.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player has played on the server before.'
type:
name: 'boolean'
- name: 'isBanned'
description: |
Returns whether this player has been banned from the server.<br>
<br>
Returns whether this player has been banned from the server.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player has been banned from the server.'
type:
name: 'boolean'
- name: 'isWhitelisted'
description: |
Returns whether this player is whitelisted on the server.<br>
<br>
Returns whether this player is whitelisted on the server.
The returned boolean may be inaccurate if AdvancedServerList was unable to obtain a valid OfflinePlayer instance.
returns: 'Boolean indicating whether this player is whitelisted on the server.'
type:
@@ -35,16 +35,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> BukkitPlayer
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the SpigotMC/Paper server implementation of AdvancedServerList.
This interface includes a [`OfflinePlayer` instance](#getplayer()) obtained from the server the plugin runs on alongside some getters to get if the player [has played on the server before](#hasplayedbefore()), [is banned](#isbanned()) or [is whitelisted](#iswhitelisted()). These options actually require a proper OfflinePlayer instance to be present or will otherwise default to `false`.
This interface includes a [`OfflinePlayer` instance](#getplayer) obtained from the server the plugin runs on alongside some getters to get if the player [has played on the server before](#hasplayedbefore), [is banned](#isbanned) or [is whitelisted](#iswhitelisted). These options actually require a proper OfflinePlayer instance to be present or will otherwise default to `false`.
This class is useful for cases where you want to use the OfflinePlayer. Simply cast the GenericPlayer instance to a SpigotPlayer (Granted that it actually is an instance of it to begin with).
@@ -1,9 +1,9 @@
---
template: api-doc.html
api: true
methods:
- name: 'getWorlds'
description: 'Returns a <code>Map&lt;String, World&gt;</code> where the key is the name of the World and the value the world of the server.'
description: 'Returns a `Map<String, World>` where the key is the name of the World and the value the world of the server.'
returns: 'Possibly-empty Map containing pairs of Strings and Worlds.'
type:
name: 'Map<String, World>'
@@ -11,16 +11,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> BukkitServer
Spigot/Paper specific instance of a [`GenericServer`](../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md).
This interface includes a [Map of Worlds](#getworlds()) the server currently has.
This interface includes a [Map of Worlds](#getworlds) the server currently has.
This interface is useful for cases where you want to get the worlds of the Server itself, by simply casting your GenericServer instance to a BukkitServer one. Make sure to do proper instanceof checks first before attempting to cast.
@@ -1,12 +1,12 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
@@ -14,9 +14,9 @@ constructors:
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -24,12 +24,12 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -10,15 +10,19 @@ constructors:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,13 +1,16 @@
---
template: api-doc.html
api: true
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> BungeePlayer
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getServers'
@@ -11,11 +11,14 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> BungeeProxy
@@ -1,12 +1,12 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
description: 'The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
@@ -14,9 +14,9 @@ constructors:
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md) that was used during the PingEvent handling.
The returned value may be `null` should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the [`PreServerListSetEvent`](preserverlistsetevent.md) has been cancelled).
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
@@ -24,12 +24,12 @@ methods:
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
link: '../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The provided [`ProfileEntry`](#getentry) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
constructors:
- name: 'PreServerListSetEvent'
@@ -9,15 +9,19 @@ constructors:
inherits:
'ch.andre601.advancedserverlist.api.events.GenericServerListEvent':
link: '../../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent/'
link: '../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md'
list:
- 'getEntry()'
- 'setEntry(ProfileEntry)'
- 'isCancelled()'
- 'setCancelled(boolean)'
- name: 'getEntry()'
link: 'getentry'
- name: 'setEntry(ProfileEntry)'
link: 'setentry'
- name: 'isCancelled()'
link: 'iscancelled'
- name: 'setCancelled(boolean)'
link: 'setcancelled'
---
# <api__class></api__class> PreServerListSetEvent
Called **before** AdvancedServerList modifies the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry()) will be the one used for the server list.
The provided [`ProfileEntry`](../../../api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md#getentry) will be the one used for the server list.
@@ -1,9 +1,9 @@
---
template: api-doc.html
api: true
methods:
- name: 'getVersion'
description: 'Returns the <a href="../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/#getprotocol()">protocol version</a> of the player in a readable MC version format (i.e. 1.19.3).'
description: 'Returns the [protocol version](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md#getprotocol) of the player in a readable MC version format (i.e. 1.19.3).'
returns: 'The readable MC version the player uses.'
type:
name: 'String'
@@ -11,16 +11,19 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericPlayer':
link: '../../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md'
list:
- 'getName()'
- 'getProtocol()'
- 'getUUID()'
- name: 'getName()'
link: 'getname'
- name: 'getProtocol()'
link: 'getprotocol'
- name: 'getUUID()'
link: 'getuuid'
---
# <api__interface></api__interface> VelocityPlayer
[`GenericPlayer` instance](../../../api/ch.andre601.advancedserverlist.api/objects/genericplayer.md) for the Velocity proxy implementation of AdvancedServerList.
Provides a [`getVersion()` method](#getversion()) to get the MC version used as a readable String (i.e. 1.19.3) rather than just the protocol version.
Provides a [`getVersion()` method](#getversion) to get the MC version used as a readable String (i.e. 1.19.3) rather than just the protocol version.
To get an instance of this class from a GenericPlayer instance, simply cast it to a VelocityPlayer (Granted that the GenericPlayer instance actually is a VelocityPlayer instance).
@@ -1,5 +1,5 @@
---
template: api-doc.html
api: true
methods:
- name: 'getServers'
@@ -11,11 +11,14 @@ methods:
inherits:
'ch.andre601.advancedserverlist.api.objects.GenericServer':
link: '../../../api/objects/genericserver/'
link: '../../../api/ch.andre601.advancedserverlist.api/objects/genericserver.md'
list:
- 'getPlayersOnline()'
- 'getPlayersMax()'
- 'getHost()'
- name: 'getPlayersOnline()'
link: 'getplayersonline'
- name: 'getPlayersMax()'
link: 'getplayersmax'
- name: 'getHost()'
link: 'gethost'
---
# <api__interface></api__interface> VelocityProxy
+1 -1
View File
@@ -54,7 +54,7 @@ There are 5 frontmatter options, each following a specific structure:
- [`Constructors`](#constructors)
- [`Nested Classes`](#nested-classes)
- [`Enum Constants`](#enum constants)
- [`Enum Constants`](#enum-constants)
- [`Methods`](#methods)
- [`Inherits`](#inherits)
+22 -12
View File
@@ -9,21 +9,24 @@ The main command is `/advancedserverlist` but an alias called `/asl` is also reg
## Permissions
The main permission is `advancedserverlist.admin` for all commands, but you can also grant access to specific commands using `advancedserverlist.command.<subcommand>` instead (i.e. `advancedserverlist.command.help` to grant access to [`/asl help`](#help)).
The main permission is `advancedserverlist.admin` for all commands, but you can also grant access to specific commands using `advancedserverlist.command.<subcommand>` instead (i.e. `advancedserverlist.command.help` to grant access to [`/asl help [query]`](#help)).
## Subcommands
The following subcommands are available (Subcommands are case-insensitive):
- [`help`](#help)
- [`help [query]`](#help)
- [`reload`](#reload)
- [`clearCache`](#clearcache)
- [`migrate <plugin>`](#migrate)
- [`profiles <add <profile> | copy <profile> <name> | list>`](#profiles)
- [`profiles {add <name> | copy <profile> <name> | info <profile> | list | set <profile> <option> [value]}`](#profiles)
### `help`
### `help [query]` { #help }
**Permission:** `advancedserverlist.command.help`
**Permission:** `advancedserverlist.command.help`
**Arguments:**
- `[query]` - Optional search query to receive help info from.
Shows a list of all available [subcommands](#subcommands) for AdvancedServerList.
@@ -47,8 +50,7 @@ Clears the currently cached favicons and players.
### `migrate <plugin>` { #migrate }
**Permission:** `advancedserverlist.command.migrate`
**Permission:** `advancedserverlist.command.migrate`
**Arguments:**
- `<plugin>` - The plugin to migrate from.
@@ -58,14 +60,22 @@ Check the [Migration Page](../migration/index.md) for a list of supported plugin
----
### `profiles <add <profile> | copy <profile> <name> | list>` { #profiles }
**Permission:** `advancedserverlist.command.profiles`
### `profiles {add <profile> | copy <profile> <name> | info <profile> | list | set <profile> <option> [value]}` { #profiles }
**Permission:** `advancedserverlist.command.profiles`
**Arguments:**
- `add <profile>` - Creates a new profile with name `<profile>` using the default profile values.
- `copy <profile> <name>` - Creates a copy of `<profile>` and saves it as `<name>`.
- `add <profile>` - Creates a new profile using the default profile values.
- `<profile>` - Name of the profile to use.
- `copy <profile> <name>` - Creates a copy of an existing profile.
- `<profile>` - Name of the profile to copy from.
- `<name>` - Name of the copy to have.
- `info <profile>` - Returns information of a profile. Only executable by players.
- `<profile>` - Name of the profile to fetch info from.
- `list` - Lists all loaded profiles. The entries have hover text for extra info.
- `set <profile> <option> [value]` - Edits values of a profile. Requires [`/asl reload`](#reload) to apply changes.
- `<profile>` - Name of the profile to edit.
- `<option>` - The option to edit.
- `[value]` - The new value to set. Leave empty to reset to the default.
Creates, copies or shows profiles in AdvancedServerList.
+2 -2
View File
@@ -106,7 +106,7 @@ The plugin also supports these additional plugins. They are all optional.
</div>
[addon]: ../addons/banplugins.md
[addon]: ../addons/first-party/banplugins.md
## 2. Installation { #installation }
@@ -516,7 +516,7 @@ disableDuringMaintenance:
# This is used internally to determine if the config needs to be migrated.
# Changing or even removing this option could result in your config being broken.
#
configVersion: 7
configVersion: 8
```
///
+6 -7
View File
@@ -113,6 +113,8 @@ AdvancedServerList supports the following platforms:
**Other Pages:**
- [:octicons-plus-circle-24: Adding Placeholders](api/adding-placeholders.md)
- [:octicons-broadcast-24: Listening for Events](api/listening-for-events.md)
- [:octicons-log-24: Changelog](api/changelog.md)
- [:octicons-link-external-24: Javadocs](api/javadocs.md)
- [:simple-codeberg: Source Code](api/source.md)
@@ -128,12 +130,9 @@ AdvancedServerList supports the following platforms:
**Other Pages:**
- [:octicons-stop-24: BanPlugins Addon](addons/banplugins.md)
- [:material-percent: **PlaceholderAPI**](placeholderapi/index.md)
----
Information about available placeholders to use in PlaceholderAPI and how to use placeholders from other plugins in AdvancedServerList using PlaceholderAPI.
- First Party
- [:octicons-stop-24: BanPlugins Addon](addons/first-party/banplugins.md)
- Third Party
- [:octicons-eye-closed-24: SayanVanish](addons/third-party/sayanvanish.md)
</div>
-33
View File
@@ -1,33 +0,0 @@
---
icon: material/percent
---
# PlaceholderAPI Placeholder support
AdvancedServerList provides support for [PlaceholderAPI] placeholders to be used, while also providing its own set of placeholders.
## Own placeholders
The below listed placeholders can be used through PlaceholderAPI in other plugins.
Note that the values depend on the player it is used for, as AdvancedServerList will try and get a matching [Server List Profile](../profiles/index.md) to display values from.
| Placeholder | Description |
|----------------------------------|--------------------------------------------------------------------------------------------------------|
| `%asl_favicon%` | Gives the value of `favicon` from a matching Profile. |
| `%asl_motd%` | Gives the value of `motd` in the matching Profile as a single String. |
| `%asl_playercount_extraplayers%` | Gives the value of `playerCount -> extraPlayers -> amount` from a matching Profile. Can return `null`. |
| `%asl_playercount_hover%` | Gives the value of `playerCount -> hover` from a matching Profile as a single String. |
| `%asl_playercount_maxplayers%` | Gives the value of `playerCount -> maxPlayers -> amount` from a matching profile. Can return `null`. |
| `%asl_playercount_text%` | Gives the value of `playerCount -> text` from a matching Profile. |
| `%asl_server_playersmax%` | Gives the output of `${server playersMax}` |
## Using Placeholders in Server List profiles
You can use any PlaceholderAPI placeholder in a server list profile, if the following conditions are met:
- The placeholder does not require the player to be online.
- [PAPIProxyBridge] is installed alongside AdvancedServerList, if used on a Proxy.
To use a placeholder, simply use its default `%identifier_parameters%` format.
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
+32 -27
View File
@@ -33,7 +33,7 @@ The following cases are considered literal values:
Any number is considered an expression, meaning the below examples are considered valid:
/// example | Examples
```shell
```ruby
0
1000
-7
@@ -53,7 +53,7 @@ To avoid this is it very important to always surround Strings with single or dou
///
/// example | Examples
```shell
```ruby
"Hello World!"
""
```
@@ -68,7 +68,7 @@ Strings `true` and `false` are treated as boolean literals.
Any [placeholder](placeholders.md) is a valid expression.
/// example | Examples
```shell
```ruby
${player protocol}
${player name}
@@ -83,40 +83,45 @@ ${server host}
The following binary operators can be used for boolean evaluation:
| Operator | True if |
|---------------|-------------------------------------------------------------------------------------------------------------|
| `and` / `&&` | Both expressions return true. |
| `or` / `\|\|` | Either expression returns true. |
| `==` / `=` | Both expressions are equal (Case sensitive). |
| `=~` / `~` | Both expressions are equal (Not Case sensitive). |
| `!=` | Both expressions are not equal (Case sensitive). |
| `!~` | Both expressions are not equal (Not case sensitive). |
| `\|-` | Left expression starts with right expression. |
| `-\|` | Left expression ends with right expression. |
| `<_` | Left expression contains right expression. |
| `<` | Left expression is less than the right expression. Strings use their text length as number. |
| `<=` | Left expression is less than, or equal to, the right expression. Strings use their text length as number. |
| `>` | Left expression is larger than the right expression. Strings use their text length as number. |
| `>=` | Left expression is larger than, or equal to, the right expression. Strings use their text length as number. |
| Operator | True if | Case Sensitive? |
|---------------|-------------------------------------------------------------------------------|-----------------|
| `and` / `&&` | Both expressions return true. | No |
| `or` / `\|\|` | Either expression returns true. | No |
| `==` / `=` | Both expressions are equal (Case sensitive). | Yes |
| `=~` / `~` | Both expressions are equal (Not Case sensitive). | No |
| `!=` | Both expressions are not equal (Case sensitive). | Yes |
| `!~` | Both expressions are not equal (Not case sensitive). | No |
| `\|-` | Left expression starts with right expression (Case sensitive). | Yes |
| `\|~` | Left expression starts with right expression (Not case sensitive). | No |
| `-\|` | Left expression ends with right expression (Case sensitive). | Yes |
| `~\|` | Left expression ends with right expression (Not case sensitive). | No |
| `<_` | Left expression contains right expression (Case sensitive). | Yes |
| `<~` | Left expression contains right expression (Not case sensitive). | No |
| `<` | Left expression is less than the right expression.^[1](#n1)^ | No |
| `<=` | Left expression is less than, or equal to, the right expression.^[1](#n1)^ | No |
| `>` | Left expression is larger than the right expression.^[1](#n1)^ | No |
| `>=` | Left expression is larger than, or equal to, the right expression.^[1](#n1)^ | No |
These additional binary operators can also be used to perform certain actions:
| Operator | Semantic |
|----------|-----------------------------------------------------------------------------|
| `.` | Concatenates (merges) two Strings |
| `+` | Adds two numbers. Strings use their text length as number. |
| `-` | Subtracts one number from another. Strings use their text length as number. |
| `*` | Multiplies two numbers. Strings use their text length as number. |
| `/` | Divides one number by another. Strings use their text length as number. |
| Operator | Semantic |
|----------|----------------------------------------------|
| `.` | Concatenates (merges) two Strings |
| `+` | Adds two numbers.^[1](#n1)^ |
| `-` | Subtracts one number from another.^[1](#n1)^ |
| `*` | Multiplies two numbers.^[1](#n1)^ |
| `/` | Divides one number by another.^[1](#n1)^ |
/// example | Examples
```shell
```ruby
${player name} != "Anonymous"
763 > ${player protocol} > 758
${player hasPlayedBefore} and ${player isBanned} == "false"
```
///
<small>^1^{ #n1 } In case of text will the text length be used to compare against.</small>
### Parenthesis
`( <expression> )` is a valid expression.
@@ -127,7 +132,7 @@ Parenthesis can be used to prevent ambiguities.
`!` can be used to negate boolean expressions.
/// example | Examples
```shell
```ruby
!${player isWhitelisted}
```
///
+86 -47
View File
@@ -4,69 +4,108 @@ icon: octicons/pencil-24
# Formatting
AdvancedServerList utilizes the [MiniMessage] text formatting to allow colors, formatting codes, gradients, etc. for the text options `motd`, `playerCount -> hover` and `playerCount -> text`.
You can find a collection of available tags on the library's [Format] page. Please make sure to see the [Unsupported Formatting](#unsupported-formatting) section below for tags with no support.
This page explains specific points of formatting in AdvancedServerList, be it [text formatting](#text-formatting) or special quirks of [YAML formatting](#yaml-formatting).
If you have questions, don't hesitate to join the [M.O.S.S. Discord][discord] and ask in the `#asl-support` channel.
## Why no legacy colors (`&`/`§` codes) support?
## Text Formatting
### The tl;dr
AdvancedServerList uses the [MiniMessage Text Formatting][minimessage] for all formatting of text options ([`motd`](index.md#motd), [`playerCount -> hover`](index.md#hover) and [`playerCount -> text`](index.md#text)).
It supports all available [formatting tags][tags] with a [few exceptions and limitations](#exceptions-and-limitations).
MiniMessage tags are overall more readable while also allowing a lot more ways of formatting, with Legacy colors becoming an unreadable mess the more complex your formatting is.
### The long explanation
Legacy colors are a mess to read. This becomes especially evident with gradients using RGB color support.
As an example is here the text `Hello World` made into a Gradient with starting color `#084CFB` and end color `#ADF3FD` both in Legacy Color (Using `&` character) and MiniMessage format:
/// tab | Legacy Color Codes
```
&#084CFBH&#195DFBe&#296DFBl&#3A7EFCl&#4A8FFCo &#6BB0FCW&#7CC1FCo&#8CD2FDr&#9DE2FDl&#ADF3FDd
```
/// note
Please note that the available tags in MiniMessage depend heavily on the version used on the Server or Proxy.
While AdvancedServerList downloads MiniMessage for BungeeCord, is it using the built-in version on Paper and Velocity. Due to this could the version used be older than the one the plugin is compiled against.
///
/// tab | MiniMessage
```
<gradient:#084CFB:#ADF3FD>Hello World</gradient>
```
///
[minimessage]: https://docs.advntr.dev/minimessage/index.html
[tags]: https://docs.advntr.dev/minimessage/format.html
This becomes even more difficult to work with if you want to add text formatting to only parts of the text.
Assuming you want to make `World` be bold, with legacy colors, you would need to add `&l` before every character of the word, as colors reset any formatting applied. In MiniMessage all you need to do is put `<bold>` before the word and `</bold>` after it.
### Why MiniMessage and not `&`/`§`? { #why-minimessage }
Another benefit for gradients in particular is, that MiniMessage allows more than one color to be set for the gradient, i.e. you can set three colors for a start, middle and end color.
The reason to only support MiniMessage and not the so-called legacy color and formatting codes can be boiled down to 3 specific reasons:
## Web Editor
1. **MiniMessage tags are more clear on what they do.**
`<aqua>` makes it clear that it colors the text while `&b` is not as clear on that matter.
2. **MiniMessage allows easier combination of color and formatting codes.**
MiniMessage "remembers" what colors and formatting you applied, meaning if you close a tag and a previous one was set before it, that will continue.
/// details | Example
type: example
Below is a comparison of the same text made in MiniMessage and Color codes.
//// tab | MiniMessage
```
<aqua>Hello <green><bold>World! <red>How</bold> are</red> you?
```
////
//// tab | Color Codes
```
# We add &c after "How" to avoid a "bold space"
&bHello &a&lWorld! &c&lHow&c are &ayou?
```
////
///
3. **MiniMessage adds easier support for advanced features (RGB colors, gradients, etc.)**
With MiniMessage is it significantly more easy to use more advanced features such as gradients, rgb colors and similar.
While legacy colors have a form of RGB support is the format weird to look at and gradients become a mess. This is even worse when including bold for specific characters.
/// details | Example
type: example
Below is an example of a Gradient starting at `#084CFB` (:octicons-dot-fill-24:{ style="color: #084CFB;" }) and ending at `#ADF3FD` (:octicons-dot-fill-24:{ style="color: #ADF3FD;" }).
//// tab | MiniMessage
```
<gradient:#084CFB:#ADF3FD>Hello World!</gradient>
```
////
//// tab | Color Codes
```
&#084CFBH&#195DFBe&#296DFBl&#3A7EFCl&#4A8FFCo &#6BB0FCW&#7CC1FCo&#8CD2FDr&#9DE2FDl&#ADF3FDd
```
////
///
The Adventure team offers an [Online Web tool][webviewer]{ target="_blank" rel="nofollow" } that allows you to create the right MiniMessage tags while also having a preview.
Just visit the page and make sure to select `Server List` at the top to have a preview in a server list.
In general is MiniMessage a lot easier to manage and read as legacy color codes, as their appearance is more distinct from normal text.
## YAML Formatting
### Exceptions and Limitations
It is recommended to always surround your text with single or double quotes. This avoids situations where the YAML parses sees a specific character and treats it as a special YAML feature.
This is especially the case with MiniMessage tags, where `<` can be seen as the start of a so-called scolar value.
Due to the situation MiniMessage is used in are not all of its features available to use.
Below is a list of all features that cannot be used by AdvancedServerList, or can only be used by it under specific conditions.
Should you be using single quotes inside the text itself - i.e. for words such as `you're` - will you either need to surround the text with double quotes, or change the single quote in the word to two single quotes (`you're` becomes `you''re`).
| Feature | Tag | Supported? |
|---------------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| RGB Colors | `<#rrggbb>` | Only works properly on `motd` and will be downsampled to the closest named color for the other options. |
| RGB Gradients | `<gradient:#rrggbb:#rrggbb>` | Only works properly on `motd` and will be downsampled to the closest named color for the other options. |
| Click Actions | `<click:_type_:_value_>` | Tag will be rendered, but clicking the text won't do anything. |
| Hover Actions | `<hover:_type_:_value_>` | Tag will be rendered, but hovering the text won't show anything. |
| Insertions | `<insertion:_value_>` | Tag will be rendered, but clicking the text won't do anything. |
| Font | `<font:_font_>` | May work with the default fonts (`default`, `alt` and `uniform`) and with custom ones should the client already have it. |
| Selector | `<selector:_sel_>` | Tag will be rendered, but clicking the text won't do anything. |
| Score | `<score:_name_:_objective_>` | Will not render due to requiring the player to be on the server. |
| Pride | `<pride[:_flag_]>` | Only works if the server (Paper) or Proxy (Velocity) use `v4.18.0` of MiniMessage. BungeeCord is unaffected due to downloading it. |
## Unsupported Formatting
## Yaml Formatting
### Non-functional Tags
YAML has some special quirks that require attention when editing the file.
Such quirks include features such as...
While MiniMessage will parse most, if not all tags, will not all work.
The following list of tags will do nothing, or only work under specific circumstances:
- Reading `~` and `null` as literal null values.
- Reading `>` and `|` as multi-line indicators.
| Tag | Note |
|---------------|------------------------------------------------------------------------------------------------------|
| `<click>` | |
| `<hover>` | |
| `<insertion>` | |
| `<font>` | May work if either a default MC font is used, or the player has a resourcepack with the font loaded. |
| `<selector>` | |
| `<score>` | |
To avoid this should you always surround text values with single (`'`) or double quotes (`"`) to force the YAML parser to see those as Strings.
### Non-supported RGB
/// note | Note on Single quotes inside text
Using single quotes, the YAML parser may get confused when the text itself also contains a single quote.
As an example `'You're banned'` would mess up the value because the `'` in `You're` is understood as the end of the String.
Only the `motd` option supports RGB colors. Every other option allowing MiniMessage format may only support the default colors provided by Minecraft (`<aqua>`, `<yellow>`, etc) with RGB colors being downsampled to their next supported option.
To avoid this issue, do one of the following:
[MiniMessage]: https://docs.advntr.dev/minimessage/index.html
[Format]: https://docs.advntr.dev/minimessage/format.html
[webviewer]: https://webui.advntr.dev/
- Surround the text with Double quotes instead of Single quotes (`"You're banned"`)
- Use two single quotes (`''`) inside the text every time you want to display a single quote character (`'You''re banned'`)
///
+68 -43
View File
@@ -5,7 +5,7 @@ icon: material/percent
# Placeholders
AdvancedServerList provides a set of pre-made placeholders using the `${<identifier> <placeholder>}` format adobted from BungeeTabListPlus.
It also has built-in [PlaceholderAPI support](#placeholderapi) for Spigot and Paper Servers and since v2 can even allow you to [add your own placeholders](#custom-placeholders) by using its [API](../api/index.md).
It also has built-in [PlaceholderAPI support](#placeholderapi) for Spigot and Paper Servers and since v2 can even allow you to [add your own placeholders](#adding-your-own-placeholders) by using its [API](../api/index.md).
## Built-in Placeholders
@@ -15,43 +15,39 @@ The following placeholders are available in AdvancedServerList itself. Please no
These placeholders use the player who pinged the server, to return values. They may require the player to be cached in order to work.
| Placeholder | Description | Platforms | Cached Player required?[^1] |
|-----------------------------|-----------------------------------------------------------------|--------------|-----------------------------|
| `${player name}` | The name of the player. | All | Yes[^2] |
| `${player protocol}` | The protocol version of the player. | All | No |
| `${player uuid}` | The UUID of the player. | All | Yes[^3] |
| `${player version}` | The protocol version of the player as readable MC version. | Velocity | No |
| `${player hasPlayedBefore}` | Boolean for whether the player has played on the server before. | Paper | Yes |
| `${player isBanned}` | Boolean for whether the player has been banned from the server. | Paper | Yes |
| `${player isWhitelisted}` | Boolean for whether the player is whitelisted on the server. | Paper | Yes |
| Placeholder | Description | Platforms | Cached Player required?^[1](#player-n1)^ |
|-----------------------------|-----------------------------------------------------------------|--------------|------------------------------------------|
| `${player name}` | The name of the player. | All | Yes^[2](#player-n2)^ |
| `${player protocol}` | The protocol version of the player. | All | No |
| `${player uuid}` | The UUID of the player. | All | Yes^[3](#player-n3)^ |
| `${player version}` | The protocol version of the player as readable MC version. | Velocity | No |
| `${player hasPlayedBefore}` | Boolean for whether the player has played on the server before. | Paper | Yes |
| `${player isBanned}` | Boolean for whether the player has been banned from the server. | Paper | Yes |
| `${player isWhitelisted}` | Boolean for whether the player is whitelisted on the server. | Paper | Yes |
[^1]:
Whether this placeholder requires the player to have joined before while AdvancedServerList was running.
When `disableCache` is enabled will these placeholders not work.
[^2]: Will default to whatever name has been provided in the `unknownPlayer -> name` option of the config.yml, when the player isn't cached yet.
[^3]: Will default to whatever name has been provided in the `unknownPlayer -> uuid` option of the config.yml, when the player isn't cached yet.
<small>^1^{ #player-n1 } When `Yes` is set, requires the player to have joined before while AdvancedServerList was running. Placeholder will not work when `disableCache` is true.</small>
<small>^2^{ #player-n2 } Will default to the value provided in `unknownPlayer -> name` of the config.yml, should the player not be cached yet.</small>
<small>^3^{ #player-n3 } Will default to the value provided in `unknownPlayer -> uuid` of the config.yml, should the player not be cached yet.</small>
### Server
These placeholders use values given by the server/proxy AdvancedServerList runs on.
| Placeholder | Description | Platforms |
|------------------------------|------------------------------------------------------------|-----------|
| `${server playersOnline}` | The number of players online on this proxy/server.[^4] | All |
| `${server playersMax}` | The total number of players that can join this server.[^5] | All |
| `${server host}` | The domain/IP the player pinged.[^6] | All |
| `${server whitelistEnabled}` | Whether the whitelist is enabled or not. | Paper |
| Placeholder | Description | Platforms |
|------------------------------|-------------------------------------------------------------------------|-----------|
| `${server playersOnline}` | The number of players online on this proxy/server.^[1](#server-n1)^ | All |
| `${server playersMax}` | The total number of players that can join this server.^[2](#server-n2)^ | All |
| `${server host}` | The domain/IP the player pinged.^[3](#server-n3)^ | All |
| `${server whitelistEnabled}` | Whether the whitelist is enabled or not. | Paper |
[^4]:
A comma-separated list of world (On Paper) or Server (On BungeeCord/Velocity) names can be provided to display the added numbers of players in these worlds/servers.
**Example:** `${server playersOnline lobby1,lobby2}` will display the collective numbers of players in the servers `lobby1` and `lobby2`.
Using the [onlinePlayers' `amount`](index.md#onlineplayers-amount) option will modify the output of this placeholder, except when used in [`condition`](index.md#condition).
[^5]:
Using either the [extraPlayers' `amount`](index.md#extraplayers-amount) or [maxPlayers' `amount`](index.md#maxplayers-amount) option will make this placeholder return the modified max players count.
Only exception to this rule is when the placeholder is used in the [`condition`](index.md#condition) option in which case it returns the actual max player count of the proxy/server.
[^6]:
An optional server name can be provided to display the IP/Domain associated with that server. This only works on BungeeCord or Velocity.
**Example:** `${server host survival}` would display the IP/Domain associated with the `survival` server.
<small>^1^{ #server-n1 } You can provide a comma-separated list of world or server names (based on platform) to return the collective count of players on these worlds/servers.
Additionally, when using [`playerCount -> onlinePlayers`](index.md#onlineplayers) will this placeholder return the modified online players count, except when used within the [`condition`](index.md#condition) option.</small>
<small>^2^{ #server-n2 } When using either [`playerCount -> extraPlayers`](index.md#extraplayers) or [`playerCount -> maxPlayers`](index.md#maxplayers) will this placeholder return the modified max players count, except when used within the [`condition`](index.md#condition) option.</small>
<small>^3^{ #server-n3 } An optional server name may be provided to display the IP/Domain associated with said server. This only works for the BungeeCord and Velocity version of the plugin.</small>
### Proxy
@@ -61,14 +57,14 @@ These placeholders are only available on the BungeeCord and Velocity versions of
Servers are pinged every 10 seconds by the plugin and cached for that time period.
///
| Placeholders | Description | Default[^7] |
|------------------------------|-------------------------------------------------------------------|-------------|
| `${proxy status <name>}` | Returns `online` or `offline` based on the Server's availability. | `offline` |
| `${proxy motd <name>}` | Returns the Server's MOTD as MiniMessage String. | `none` |
| `${proxy players <name>}` | Returns the number of online Players on the Server. | `0` |
| `${proxy maxPlayers <name>}` | Returns the max number of Players allowed to join the Server. | `0` |
| Placeholders | Description | Default^[1](#proxy-n1)^ |
|------------------------------|-------------------------------------------------------------------|-------------------------|
| `${proxy status <name>}` | Returns `online` or `offline` based on the Server's availability. | `offline` |
| `${proxy motd <name>}` | Returns the Server's MOTD as MiniMessage String. | `none` |
| `${proxy players <name>}` | Returns the number of online Players on the Server. | `0` |
| `${proxy maxPlayers <name>}` | Returns the max number of Players allowed to join the Server. | `0` |
[^7]: The default value returned, should the Server or parts of it not be available.
<small>^1^{ #proxy-n1 } The default value returned, should the Server or parts of it not be available.</small>
### Maintenance
@@ -78,13 +74,42 @@ These placeholders require the [Maintenance](https://hangar.papermc.io/kennytv/M
|-------------------------------------|----------------------------------------------------------------|
| `${maintenance maintenanceEnabled}` | Returns whether the Global maintenance mode is enabled or not. |
## Adding your own Placeholders
Thanks to the API of AdvancedServerList are you able to add your own Placeholders that can be used using the `${identifier value}` pattern.
To learn how to do this, head over to the [API page](../api/index.md) to learn more.
## PlaceholderAPI
Please visit the [PlaceholderAPI page](../placeholderapi/index.md) for how AdvancedServerList works with PlaceholderAPI.
### Own Placeholders
## Custom Placeholders
The Paper version of AdvancedServerList provides the following placeholders to use through PlaceholderAPI.
Since version 2 of AdvancedServerList are developers able to provide their own placeholders to be used in a server list profile.
The format follows the same one as the [built-in placeholders](#built-in-placeholders), meaning it is `${<identifier> <placeholder>}`.
/// info
AdvancedServerList uses the same logic to determine the value to return for a player as it does when selecting a Server List Profile.
///
If you're a developer and want to integrate your own placeholders into AdvancedServerList, read about it [here](../api/index.md).
| Placeholder | Description | Default^[1](#papi-n1)^ |
|--------------------------------------|-----------------------------------------------------------------------------------|------------------------|
| `%asl_favicon%` | Value of `favicon` when present. | `(empty string)` |
| `%asl_motd%` | Value of `motd` when present. | `(empty string)` |
| `%asl_playercount_extraplayers%` | Value of `playerCount -> extraPlayers -> amount`. | `(empty string)` |
| `%asl_playercount_hideplayers%` | Returns wether `playerCount -> hidePlayers` is enabled or not. | `false` |
| `%asl_playercount_hideplayershover%` | Returns wether `playerCount -> hidePlayersHover` is enabled or not. | `false` |
| `%asl_playercount_hover%` | Value of `playerCount -> hover`. | `(empty string)` |
| `%asl_playercount_maxplayers%` | Value of `playerCount -> maxPlayers -> amount` | `(empty string)` |
| `%asl_playercount_onlineplayers%` | Value of `playerCount -> onlinePlayers -> amount` | `(empty string)` |
| `%asl_playercount_text%` | Value of `playerCount -> text` | `(empty string)` |
| `%asl_playersmax%` | Returns the max players based on currently set maxPlayers or extraPlayers values. | `(empty string)` |
<small>^1^{ #papi-n1 } The default value is returned when the option in the chosen profile is either not set, or `null`.</small>
### Other Placeholders
Placeholders from PlaceholderAPI Expansions can be used in AdvancedServerList using the default `%identifier_value%` format.
PlaceholderAPI placeholders can be used both on the Server (Paper) and on the proxy (BungeeCord, Velocity) version of AdvancedServerList.
However, the Proxy version requires the usage of [PAPIProxyBridge] to function properly.
Placeholders can also not be used within the [`condition`](index.md#condition) option of a Server List Profile.
+17 -2
View File
@@ -80,11 +80,21 @@ plugins:
'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'
#
# PlaceholderAPI page
'placeholderapi/index.md': 'profiles/placeholders.md#own-placeholders'
#
# Addons page
'addons/banplugins.md': 'addons/first-party/banplugins.md'
- pagenav-generator
- macros:
include_dir: docs/.overrides
module_name: docs/.hooks/api_docs
markdown_extensions:
- markdown.extensions.toc:
permalink: true
toc_depth: 3
- markdown.extensions.attr_list:
- markdown.extensions.footnotes:
- markdown.extensions.md_in_html:
@@ -115,6 +125,7 @@ markdown_extensions:
- pymdownx.blocks.tab:
alternate_style: true
- pymdownx.blocks.details:
- pymdownx.caret:
hooks:
- docs/.hooks/badges.py
@@ -145,6 +156,8 @@ nav:
- v1.5.3 to v1.6.0: migration/versions/v1.5.3-to-v1.6.0.md
- API:
- api/index.md
- Adding Placeholders: api/adding-placeholders.md
- Listening for Events: api/listening-for-events.md
- Changelog: api/changelog.md
- Javadocs: api/javadocs.md
- Source Code: api/source.md
@@ -196,5 +209,7 @@ nav:
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/objects/velocityproxy.md
- Addons:
- addons/index.md
- BanPlugins: addons/banplugins.md
- PlaceholderAPI: placeholderapi/index.md
- First-party:
- BanPlugins: addons/first-party/banplugins.md
- Third-party:
- SayanVanish: addons/third-party/sayanvanish.md
+46 -35
View File
@@ -39,8 +39,9 @@
<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>
<repositories>
@@ -77,7 +78,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -110,10 +111,16 @@
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-paper</artifactId>
<version>${dependency.cloud-paper}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Paper-${plugin.version}</finalName>
<finalName>AdvancedServerList-Paper-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -131,47 +138,51 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>16</release>
</configuration>
</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.paper.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.libby</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.libby</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.expressionparser</shadedPattern>
</relocation>
<relocation>
<pattern>com.unascribed.flexver</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>org.incendo.cloud</pattern>
<shadedPattern>ch.andre601.advancedserverlist.paper.depends.cloud</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
@@ -27,10 +27,11 @@ package ch.andre601.advancedserverlist.paper;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import ch.andre601.advancedserverlist.paper.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.paper.listeners.LoadEvent;
import ch.andre601.advancedserverlist.paper.commands.PaperCommandManagerInterface;
import ch.andre601.advancedserverlist.paper.listeners.ServerLoadEventListener;
import ch.andre601.advancedserverlist.paper.logging.PaperLogger;
import ch.andre601.advancedserverlist.paper.objects.WorldCache;
import ch.andre601.advancedserverlist.paper.objects.placeholders.PAPIPlaceholders;
@@ -47,6 +48,7 @@ import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.CachedServerIcon;
import org.incendo.cloud.CommandManager;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
@@ -58,6 +60,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
private final PluginLogger logger = new PaperLogger(this);
private PaperCommandManagerInterface commandHandler;
private AdvancedServerList<CachedServerIcon> core;
private FaviconHandler<CachedServerIcon> faviconHandler = null;
private PAPIPlaceholders papiPlaceholders = null;
@@ -67,6 +70,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
@Override
public void onEnable(){
this.commandHandler = new PaperCommandManagerInterface(this);
this.core = AdvancedServerList.init(this, new PaperPlayerPlaceholders(), new PaperServerPlaceholders(this));
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
@@ -86,18 +90,9 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
getCore().disable();
}
@Override
public void loadCommands(){
if(getServer().getCommandMap().register("asl", new CmdAdvancedServerList(this))){
getPluginLogger().success("Registered <white>/advancedserverlist:advancedserverlist</white>!");
}else{
getPluginLogger().success("Registered <white>/asl:advancedserverlist</white>!");
}
}
@Override
public void loadEvents(){
new LoadEvent(this);
new ServerLoadEventListener(this);
}
@Override
@@ -165,6 +160,11 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
return faviconHandler;
}
@Override
public CommandManager<CmdSender> getCommandManager(){
return commandHandler.commandHandler();
}
@Override
public String getPlatformInfo(){
try{
@@ -27,23 +27,50 @@ package ch.andre601.advancedserverlist.paper.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import net.kyori.adventure.audience.Audience;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@SuppressWarnings("UnstableApiUsage")
public class PaperCmdSender implements CmdSender{
private final CommandSender sender;
private final CommandSourceStack commandSourceStack;
public PaperCmdSender(CommandSender sender){
this.sender = sender;
this(sender, null);
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
public PaperCmdSender(CommandSourceStack commandSourceStack){
this(commandSourceStack.getSender(), commandSourceStack);
}
private PaperCmdSender(CommandSender sender, CommandSourceStack commandSourceStack){
this.sender = sender;
this.commandSourceStack = commandSourceStack;
}
@Override
public void sendMsg(String msg, Object... args){
sender.sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
@Override
public Audience audience(){
return sender();
}
@Override
public boolean isPlayer(){
return sender() instanceof Player;
}
public CommandSender sender(){
return sender;
}
public CommandSourceStack getCommandSourceStack(){
return commandSourceStack;
}
}
@@ -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,35 +20,40 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.paper.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandManagerInterface;
import ch.andre601.advancedserverlist.paper.PaperCore;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.paper.PaperCommandManager;
import java.util.Collections;
public class CmdAdvancedServerList extends Command{
@SuppressWarnings("UnstableApiUsage")
public class PaperCommandManagerInterface implements CommandManagerInterface<CommandSourceStack>{
private final PaperCore plugin;
public CmdAdvancedServerList(PaperCore plugin){
super(
"advancedserverlist",
"Main command of the plugin",
"/asl [reload|help|clearCache]",
Collections.singletonList("asl")
);
public PaperCommandManagerInterface(PaperCore plugin){
this.plugin = plugin;
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String s, @NotNull String[] args){
plugin.getCore().getCommandHandler().handle(new PaperCmdSender(sender), args);
return true;
public CommandManager<CmdSender> commandHandler(){
return PaperCommandManager.builder(senderMapper())
.executionCoordinator(ExecutionCoordinator.asyncCoordinator())
.buildOnEnable(plugin);
}
@Override
public SenderMapper<CommandSourceStack, CmdSender> senderMapper(){
return SenderMapper.create(
PaperCmdSender::new,
sender -> ((PaperCmdSender)sender).getCommandSourceStack()
);
}
}
@@ -35,11 +35,11 @@ import org.bukkit.event.player.PlayerJoinEvent;
import java.net.InetSocketAddress;
public class JoinEvent implements Listener{
public class PlayerJoinEventListener implements Listener{
private final PaperCore plugin;
public JoinEvent(PaperCore plugin){
public PlayerJoinEventListener(PaperCore plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@@ -34,11 +34,11 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class PingEvent implements Listener{
public class ServerListPingEventListener implements Listener{
private final PaperCore plugin;
public PingEvent(PaperCore plugin){
public ServerListPingEventListener(PaperCore plugin){
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@@ -31,20 +31,20 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerLoadEvent;
public class LoadEvent implements Listener{
public class ServerLoadEventListener implements Listener{
private final PaperCore plugin;
public LoadEvent(PaperCore plugin){
public ServerLoadEventListener(PaperCore plugin){
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onLoad(ServerLoadEvent event){
new JoinEvent(plugin);
new PingEvent(plugin);
new WorldEvents(plugin);
new PlayerJoinEventListener(plugin);
new ServerListPingEventListener(plugin);
new WorldEventsListener(plugin);
// Load currently loaded worlds into the WorldCache
Bukkit.getWorlds().forEach(world -> plugin.getWorldCache().addWorld(world));
@@ -31,11 +31,11 @@ import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
public class WorldEvents implements Listener{
public class WorldEventsListener implements Listener{
private final PaperCore plugin;
public WorldEvents(PaperCore plugin){
public WorldEventsListener(PaperCore plugin){
this.plugin = plugin;
}
@@ -31,36 +31,11 @@ import org.bukkit.OfflinePlayer;
import java.util.UUID;
public class PaperPlayerImpl implements BukkitPlayer{
private final OfflinePlayer player;
private final String name;
private final int protocol;
private final UUID uuid;
private boolean playedBefore = false;
private boolean banned = false;
private boolean whitelisted = false;
public PaperPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol){
this.player = player;
this.name = player == null ? cachedPlayer.name() : player.getName();
this.protocol = protocol;
this.uuid = player == null ? cachedPlayer.uuid() : player.getUniqueId();
if(player == null)
return;
this.playedBefore = player.hasPlayedBefore();
this.banned = player.isBanned();
this.whitelisted = player.isWhitelisted();
}
public record PaperPlayerImpl(OfflinePlayer player, CachedPlayer cachedPlayer, int protocol) implements BukkitPlayer{
@Override
public String getName(){
return name;
return player == null ? cachedPlayer.name() : player.getName();
}
@Override
@@ -70,7 +45,7 @@ public class PaperPlayerImpl implements BukkitPlayer{
@Override
public UUID getUUID(){
return uuid;
return player == null ? cachedPlayer.uuid() : player.getUniqueId();
}
@Override
@@ -80,16 +55,16 @@ public class PaperPlayerImpl implements BukkitPlayer{
@Override
public boolean hasPlayedBefore(){
return playedBefore;
return player != null && player.hasPlayedBefore();
}
@Override
public boolean isBanned(){
return banned;
return player != null && player.isBanned();
}
@Override
public boolean isWhitelisted(){
return whitelisted;
return player != null && player.isWhitelisted();
}
}
@@ -115,13 +115,15 @@ 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, true);
case "favicon" -> getOption(entry.favicon(), pl, player, finalServer);
case "motd" -> getOption(entry.motd(), pl, player, finalServer, true);
case "playercount_extraplayers" -> extraPlayers == null ? "" : String.valueOf(extraPlayers);
case "playercount_hideplayers" -> String.valueOf(entry.hidePlayersEnabled().getOrDefault(false));
case "playercount_hideplayershover" -> String.valueOf(entry.hidePlayersHoverEnabled().getOrDefault(false));
case "playercount_hover" -> getOption(entry.players(), pl, player, finalServer, false);
case "playercount_maxplayers" -> maxPlayers == null ? "" : String.valueOf(maxPlayers);
case "playercount_onlineplayers" -> onlinePlayers == null ? "" : String.valueOf(onlinePlayers);
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);
case "playercount_onlineplayers" -> onlinePlayers == null ? "null" : String.valueOf(onlinePlayers);
case "server_playersmax" -> String.valueOf(max);
default -> null;
};
@@ -137,10 +139,16 @@ public class PAPIPlaceholders extends PlaceholderExpansion{
}
private String getOption(String str, Player pl, BukkitPlayer player, BukkitServer server){
if(str == null)
return "";
return getOption(Collections.singletonList(str), pl, player, server, false);
}
private String getOption(List<String> list, Player pl, BukkitPlayer player, BukkitServer server, boolean isMotd){
if(list.isEmpty())
return "";
return list.stream()
.map(line -> ComponentParser.text(line)
.modifyText(text -> StringReplacer.replace(text, player, server))
+44 -4
View File
@@ -35,23 +35,46 @@
<version>parent</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.version>5.4.1</plugin.version>
<project.build.build_id/>
<plugin.version>5.5.1</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<api.version>4.1.0</api.version>
<!-- Adventure versions -->
<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>
<!-- Configurate version -->
<dependency.configurate-yaml>4.1.2</dependency.configurate-yaml>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<!-- Cloud versions -->
<dependency.cloud-annotations>2.0.0</dependency.cloud-annotations>
<dependency.cloud-bungee>2.0.0-beta.10</dependency.cloud-bungee>
<dependency.cloud-paper>2.0.0-beta.10</dependency.cloud-paper>
<dependency.cloud-velocity>2.0.0-beta.10</dependency.cloud-velocity>
<dependency.cloud-minecraft-extras>2.0.0-beta.10</dependency.cloud-minecraft-extras>
</properties>
<profiles>
<profile>
<id>jenkins</id>
<activation>
<property>
<name>env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<project.build.build_id>_${env.BUILD_NUMBER}</project.build.build_id>
</properties>
</profile>
</profiles>
<repositories>
<repository>
<id>jitpack</id>
@@ -67,6 +90,23 @@
</repository>
</repositories>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<modules>
<module>core</module>
<module>bungeecord</module>
+3 -2
View File
@@ -1,4 +1,5 @@
mkdocs-material==9.5.49
mkdocs-material==9.6.2
mkdocs-glightbox==0.4.0
mkdocs-redirects==1.2.2
git+https://github.com/Andre601/mkdocs-pagenav-generator
git+https://github.com/Andre601/mkdocs-pagenav-generator
mkdocs-macros-plugin==1.3.7
+48 -34
View File
@@ -39,8 +39,9 @@
<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>
<repositories>
@@ -50,7 +51,7 @@
</repository>
<repository>
<id>repo-sayandevelopment</id>
<url>https://repo.sayandev.org/snapshots</url>
<url>https://repo.sayandev.org/releases/</url>
</repository>
</repositories>
@@ -102,13 +103,13 @@
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-api</artifactId>
<version>1.6.1</version>
<version>1.6.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sayandev</groupId>
<artifactId>sayanvanish-proxy-velocity</artifactId>
<version>1.6.1</version>
<version>1.6.4</version>
<scope>provided</scope>
</dependency>
@@ -119,10 +120,16 @@
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.incendo</groupId>
<artifactId>cloud-velocity</artifactId>
<version>${dependency.cloud-velocity}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>AdvancedServerList-Velocity-${plugin.version}</finalName>
<finalName>AdvancedServerList-Velocity-${plugin.version}${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>
@@ -130,44 +137,51 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.libby</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>com.alessiodp.libby</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.libby</shadedPattern>
</relocation>
<relocation>
<pattern>ch.andre601.expressionparser</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.expressionparser</shadedPattern>
</relocation>
<relocation>
<pattern>com.unascribed.flexver</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.flexver</shadedPattern>
</relocation>
<relocation>
<pattern>org.incendo.cloud</pattern>
<shadedPattern>ch.andre601.advancedserverlist.velocity.depends.cloud</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
@@ -27,11 +27,12 @@ package ch.andre601.advancedserverlist.velocity;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.handlers.FaviconHandler;
import ch.andre601.advancedserverlist.velocity.commands.CmdAdvancedServerList;
import ch.andre601.advancedserverlist.velocity.listeners.JoinEvent;
import ch.andre601.advancedserverlist.velocity.listeners.PingEvent;
import ch.andre601.advancedserverlist.velocity.commands.VelocityCommandManagerInterface;
import ch.andre601.advancedserverlist.velocity.listeners.PlayerJoinEventListener;
import ch.andre601.advancedserverlist.velocity.listeners.ProxyPingEventListener;
import ch.andre601.advancedserverlist.velocity.logging.VelocityLogger;
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityPlayerPlaceholders;
import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityProxyPlaceholders;
@@ -39,10 +40,10 @@ import ch.andre601.advancedserverlist.velocity.objects.placeholders.VelocityServ
import com.alessiodp.libby.Library;
import com.alessiodp.libby.VelocityLibraryManager;
import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
@@ -54,6 +55,7 @@ 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.incendo.cloud.CommandManager;
import org.sayandev.sayanvanish.velocity.api.SayanVanishVelocityAPI;
import java.awt.image.BufferedImage;
@@ -75,6 +77,7 @@ public class VelocityCore implements PluginCore<Favicon>{
private final ProxyServer proxy;
private final Path path;
private final Metrics.Factory metrics;
private final VelocityCommandManagerInterface commandHandler;
private AdvancedServerList<Favicon> core;
private FaviconHandler<Favicon> faviconHandler = null;
@@ -84,7 +87,7 @@ public class VelocityCore implements PluginCore<Favicon>{
private ScheduledTask scheduledTask = null;
@Inject
public VelocityCore(ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
public VelocityCore(PluginContainer pluginContainer, ProxyServer proxy, @DataDirectory Path path, Metrics.Factory metrics){
ComponentLogger logger = ComponentLogger.logger("AdvancedServerList");
this.pluginLogger = new VelocityLogger(this, logger);
this.logger = logger;
@@ -92,6 +95,7 @@ public class VelocityCore implements PluginCore<Favicon>{
this.proxy = proxy;
this.path = path;
this.metrics = metrics;
this.commandHandler = new VelocityCommandManagerInterface(pluginContainer, proxy);
}
@Subscribe
@@ -107,21 +111,10 @@ public class VelocityCore implements PluginCore<Favicon>{
scheduledTask.cancel();
}
@Override
public void loadCommands(){
CommandMeta command = getProxy().getCommandManager()
.metaBuilder("advancedserverlist")
.aliases("asl")
.build();
getProxy().getCommandManager().register(command, new CmdAdvancedServerList(this));
getPluginLogger().success("Registered <white>/advancedserverlist</white>!");
}
@Override
public void loadEvents(){
new JoinEvent(this);
new PingEvent(this);
new PlayerJoinEventListener(this);
new ProxyPingEventListener(this);
}
@Override
@@ -191,6 +184,11 @@ public class VelocityCore implements PluginCore<Favicon>{
return faviconHandler;
}
@Override
public CommandManager<CmdSender> getCommandManager(){
return commandHandler.commandHandler();
}
@Override
public String getPlatformInfo(){
return getProxy().getVersion().getName() + " " + getProxy().getVersion().getVersion();
@@ -28,22 +28,22 @@ package ch.andre601.advancedserverlist.velocity.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.parsing.ComponentParser;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.audience.Audience;
public class VelocityCmdSender implements CmdSender{
private final CommandSource sender;
public VelocityCmdSender(CommandSource sender){
this.sender = sender;
}
@Override
public boolean hasPermission(String permission){
return sender.hasPermission(permission) || sender.hasPermission("advancedserverlist.admin");
}
public record VelocityCmdSender(CommandSource sender) implements CmdSender{
@Override
public void sendMsg(String msg, Object... args){
sender.sendMessage(ComponentParser.text(String.format(msg, args)).toComponent());
}
@Override
public Audience audience(){
return sender;
}
@Override
public boolean isPlayer(){
return sender instanceof Player;
}
}
@@ -0,0 +1,64 @@
/*
* 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.velocity.commands;
import ch.andre601.advancedserverlist.core.interfaces.commands.CmdSender;
import ch.andre601.advancedserverlist.core.interfaces.commands.CommandManagerInterface;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.proxy.ProxyServer;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.velocity.VelocityCommandManager;
public class VelocityCommandManagerInterface implements CommandManagerInterface<CommandSource>{
private final PluginContainer pluginContainer;
private final ProxyServer proxy;
public VelocityCommandManagerInterface(PluginContainer pluginContainer, ProxyServer proxy){
this.pluginContainer = pluginContainer;
this.proxy = proxy;
}
@Override
public CommandManager<CmdSender> commandHandler(){
return new VelocityCommandManager<>(
pluginContainer,
proxy,
ExecutionCoordinator.asyncCoordinator(),
senderMapper()
);
}
@Override
public SenderMapper<CommandSource, CmdSender> senderMapper(){
return SenderMapper.create(
VelocityCmdSender::new,
sender -> ((VelocityCmdSender)sender).sender()
);
}
}
@@ -33,11 +33,11 @@ import com.velocitypowered.api.proxy.Player;
import java.net.InetSocketAddress;
public class JoinEvent{
public class PlayerJoinEventListener{
private final VelocityCore plugin;
public JoinEvent(VelocityCore plugin){
public PlayerJoinEventListener(VelocityCore plugin){
this.plugin = plugin;
plugin.getProxy().getEventManager().register(plugin, this);
}
@@ -29,20 +29,19 @@ import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.api.velocity.events.PostServerListSetEvent;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
public class PingEvent{
public class ProxyPingEventListener{
private final VelocityCore plugin;
public PingEvent(VelocityCore plugin){
public ProxyPingEventListener(VelocityCore plugin){
this.plugin = plugin;
plugin.getProxy().getEventManager().register(plugin, this);
}
@Subscribe(order = PostOrder.LAST) // Maintenance has LAST priority, so ASL needs it too.
@Subscribe(priority = Short.MIN_VALUE + 1) // Equivalent to PostOrder.LAST which maintenance uses.
public void onProxyPing(ProxyPingEvent event){
ProfileEntry entry = PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
@@ -31,24 +31,11 @@ import com.velocitypowered.api.network.ProtocolVersion;
import java.util.UUID;
public class VelocityPlayerImpl implements VelocityPlayer{
private final String name;
private final int protocol;
private final UUID uuid;
private final String version;
public VelocityPlayerImpl(CachedPlayer player, int protocol){
this.name = player.name();
this.protocol = protocol;
this.uuid = player.uuid();
this.version = ProtocolVersion.getProtocolVersion(protocol).getVersionIntroducedIn();
}
public record VelocityPlayerImpl(CachedPlayer player, int protocol) implements VelocityPlayer{
@Override
public String getName(){
return name;
return player.name();
}
@Override
@@ -58,11 +45,11 @@ public class VelocityPlayerImpl implements VelocityPlayer{
@Override
public UUID getUUID(){
return uuid;
return player.uuid();
}
@Override
public String getVersion(){
return version;
return ProtocolVersion.getProtocolVersion(protocol).getVersionIntroducedIn();
}
}
+5 -5
View File
@@ -37,8 +37,8 @@
<artifactId>version-uploader</artifactId>
<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>
@@ -46,7 +46,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.12.1</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -58,7 +58,7 @@
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.1</version>
<version>5.4.2</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -82,7 +82,7 @@
</dependencies>
<build>
<finalName>VersionUploader</finalName>
<finalName>VersionUploader${project.build.build_id}</finalName>
<resources>
<resource>
<filtering>true</filtering>