Compare commits

...
28 Commits
Author SHA1 Message Date
Andre601 a91e839f8c Update API reference 2024-03-14 14:53:36 +01:00
Andre601 d4668e0e76 Add PostServerListSetEvent 2024-03-14 14:08:17 +01:00
Andre601 305f3452c4 Merge pull request 'Update dependency com.google.guava:guava to v33.1.0-jre' (#245) from renovate/com.google.guava-guava-33.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/245
2024-03-14 12:02:24 +00:00
Andre601's Renovate Bot fec3361fd7 Update dependency com.google.guava:guava to v33.1.0-jre 2024-03-14 12:01:22 +00:00
Andre601 f0861ffa6a Merge pull request 'Allow handling of options while Maintenance is active' (#244) from feature/configure-maintenance-support into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/244
2024-03-13 23:15:49 +00:00
Andre601 cfca3f72dc Fix ambigous method call getBoolean 2024-03-13 22:04:17 +01:00
Andre601 aca83e8350 Update priorities and bump version 2024-03-13 20:44:08 +01:00
Andre601 8383c8b97f Allow handling of options while Maintenance is active 2024-03-13 20:33:41 +01:00
Andre601 3d1ddaa782 Update Nav 2024-03-13 16:06:07 +01:00
Andre601 1d615e252f Update requirements.txt 2024-03-13 02:51:02 +01:00
Andre601 310e72d048 Don't use awesome-pages 2024-03-13 02:50:31 +01:00
Andre601 2754bf13aa Allow support for vanished players 2024-03-10 14:01:10 +01:00
Andre601 9ff5fcdaa7 Unify Placeholder parsing system. 2024-03-07 22:01:18 +01:00
Andre601 0ba7ed6ece Merge pull request 'Update dependency com.viaversion:viaversion-api to v4.9.3' (#241) from renovate/com.viaversion-viaversion-api-4.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/241
2024-03-06 12:46:39 +00:00
Andre601 2d8c774401 Merge pull request 'Update dependency mkdocs-material to v9.5.13' (#242) from renovate/mkdocs-material-9.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/242
2024-03-06 12:46:23 +00:00
Andre601's Renovate Bot f68be63f64 Update dependency mkdocs-material to v9.5.13 2024-03-06 12:14:43 +00:00
Andre601's Renovate Bot 2695b393d8 Update dependency com.viaversion:viaversion-api to v4.9.3 2024-03-06 12:14:35 +00:00
Andre601 55821d2edf Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.3' (#240) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/240
2024-03-05 12:02:36 +00:00
Andre601's Renovate Bot b64e32503e Update dependency ch.qos.logback:logback-classic to v1.5.3 2024-03-05 12:01:13 +00:00
Andre601 c5ab9b118f Use code highlighting for expression examples 2024-03-05 02:11:01 +01:00
Andre601 6cc54349b5 Fix typo with fontawesome 2024-03-05 01:02:47 +00:00
Andre601 98d2de975e Add divider lines to optional dependencies 2024-03-05 00:59:59 +00:00
Andre601 6d1c118660 Remove unusued project.build.commit tag 2024-03-03 22:14:34 +01:00
Andre601 49e5b195ec Update way of reporting condition errors 2024-03-03 22:14:11 +01:00
Andre601 c92611e7f8 Merge pull request 'Update dependency ch.qos.logback:logback-classic to v1.5.2' (#238) from renovate/ch.qos.logback-logback-classic-1.x into master
Reviewed-on: https://codeberg.org/Andre601/AdvancedServerList/pulls/238
2024-03-03 13:46:52 +00:00
Andre601's Renovate Bot 233414c45c Update dependency ch.qos.logback:logback-classic to v1.5.2 2024-03-03 12:01:19 +00:00
Andre601 c0629e10bc Add BanPlugins Addon to optional dependencies 2024-03-03 02:00:17 +00:00
Andre601 621eb7c489 Update API reference for ProfileEntry.Builder + changelog 2024-03-03 00:50:16 +01:00
59 changed files with 1117 additions and 523 deletions

No files matched your search

+16
View File
@@ -64,6 +64,8 @@
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<!-- BungeeCord API -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
@@ -78,6 +80,8 @@
<type>javadoc</type>
<scope>provided</scope>
</dependency>
<!-- Adventure Library. Needs to be shaded in -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
@@ -96,18 +100,30 @@
<version>4.3.2</version>
<scope>compile</scope>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bungeecord</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<!-- Configurate -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>com.github.LeonMangler</groupId>
<artifactId>PremiumVanishAPI</artifactId>
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
@@ -35,13 +35,18 @@ import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.interfaces.PluginLogger;
import ch.andre601.advancedserverlist.core.interfaces.core.PluginCore;
import ch.andre601.advancedserverlist.core.profiles.favicon.FaviconHandler;
import de.myzelyam.api.vanish.BungeeVanishAPI;
import net.md_5.bungee.api.Favicon;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SimplePie;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
@@ -51,7 +56,7 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
@Override
public void onEnable(){
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init());
this.core = AdvancedServerList.init(this, BungeePlayerPlaceholders.init(), BungeeServerPlaceholders.init(this));
}
@Override
@@ -133,4 +138,15 @@ public class BungeeCordCore extends Plugin implements PluginCore<Favicon>{
public Favicon createFavicon(BufferedImage image) throws IllegalArgumentException{
return Favicon.create(image);
}
public int getOnlinePlayers(ServerInfo server){
List<ProxiedPlayer> players = new ArrayList<>(server == null ? getProxy().getPlayers() : server.getPlayers());
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().getPlugin("PremiumVanish") != null){
players.removeIf(BungeeVanishAPI::isInvisible);
}
return players.size();
}
}
@@ -147,7 +147,7 @@ public class BungeeEventWrapper implements GenericEventWrapper<Favicon, BungeePl
@Override
public int getOnlinePlayers(){
return ping.getPlayers().getOnline();
return plugin.getOnlinePlayers(null);
}
@Override
@@ -25,12 +25,13 @@
package ch.andre601.advancedserverlist.bungeecord.listeners;
import ch.andre601.advancedserverlist.api.bungeecord.events.PostServerListSetEvent;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
public class PingEvent implements Listener{
@@ -41,8 +42,10 @@ public class PingEvent implements Listener{
plugin.getProxy().getPluginManager().registerListener(plugin, this);
}
@EventHandler(priority = EventPriority.LOW)
@EventHandler(priority = 90) // Maintenance has Event Priority 80, so we need to be AFTER it.
public void onProxyPing(ProxyPingEvent event){
PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
ProfileEntry entry = PingEventHandler.handleEvent(new BungeeEventWrapper(plugin, event));
plugin.getProxy().getPluginManager().callEvent(new PostServerListSetEvent(entry));
}
}
@@ -29,18 +29,22 @@ import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.bungeecord.objects.BungeeProxy;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.bungeecord.BungeeCordCore;
import net.md_5.bungee.api.config.ServerInfo;
import java.net.InetSocketAddress;
public class BungeeServerPlaceholders extends PlaceholderProvider{
private BungeeServerPlaceholders(){
private final BungeeCordCore plugin;
private BungeeServerPlaceholders(BungeeCordCore plugin){
super("server");
this.plugin = plugin;
}
public static BungeeServerPlaceholders init(){
return new BungeeServerPlaceholders();
public static BungeeServerPlaceholders init(BungeeCordCore plugin){
return new BungeeServerPlaceholders(plugin);
}
@Override
@@ -64,7 +68,7 @@ public class BungeeServerPlaceholders extends PlaceholderProvider{
if(info == null)
continue;
players += info.getPlayers().size();
players += plugin.getOnlinePlayers(info);
}
yield String.valueOf(players);
+5 -3
View File
@@ -41,7 +41,7 @@
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<plugin.config.version>4</plugin.config.version>
<plugin.config.version>5</plugin.config.version>
</properties>
<repositories>
@@ -73,7 +73,7 @@
<dependency>
<groupId>ch.andre601</groupId>
<artifactId>expressionparser</artifactId>
<version>v1.2.0</version>
<version>1.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -102,6 +102,8 @@
<version>4.16.0</version>
<scope>provided</scope>
</dependency>
<!-- Misc -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
@@ -117,7 +119,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.0.0-jre</version>
<version>33.1.0-jre</version>
<scope>provided</scope>
</dependency>
@@ -46,7 +46,7 @@ public class AdvancedServerList<F>{
private final FileHandler fileHandler;
private final CommandHandler commandHandler;
private final PlayerHandler playerHandler;
private final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private static final AdvancedServerListAPI api = AdvancedServerListAPI.get();
private final ProfileConditionParser parser = ProfileConditionParser.create();
private UpdateChecker updateChecker;
@@ -59,7 +59,7 @@ public class AdvancedServerList<F>{
this.commandHandler = new CommandHandler(this);
this.playerHandler = new PlayerHandler(this);
placeholders.forEach(this.api::addPlaceholderProvider);
placeholders.forEach(AdvancedServerList.getApi()::addPlaceholderProvider);
load();
}
@@ -88,7 +88,7 @@ public class AdvancedServerList<F>{
return version;
}
public AdvancedServerListAPI getApi(){
public static AdvancedServerListAPI getApi(){
return api;
}
@@ -44,11 +44,11 @@ public class PingEventHandler{
private static PAPIUtil papiUtil = null;
private static MaintenanceUtil maintenanceUtil = null;
public static <F, P extends GenericPlayer> void handleEvent(GenericEventWrapper<F, P> event){
public static <F, P extends GenericPlayer> ProfileEntry handleEvent(GenericEventWrapper<F, P> event){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Received ping event. Handling it...");
if(event.isInvalidProtocol() || event.isMaintenanceModeActive()){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Not handling event. Either protocol was invalid of Maintenance is enabled.");
return;
if(event.isInvalidProtocol()){
event.getPlugin().getPluginLogger().debug(PingEventHandler.class, "Not handling event. Protocol was invalid.");
return null;
}
PluginCore<F> plugin = event.getPlugin();
@@ -70,7 +70,7 @@ public class PingEventHandler{
if(profile == null){
logger.debugWarn(PingEventHandler.class, "Server List Profile couldn't be resolved properly. Cancelling event handling...");
return;
return null;
}
logger.debug(PingEventHandler.class, "Received valid Server List Profile. Calling PreServerListSetEvent...");
@@ -78,7 +78,7 @@ public class PingEventHandler{
GenericServerListEvent e = event.callEvent(ProfileManager.merge(profile));
if(e == null || e.isCancelled()){
logger.debug(PingEventHandler.class, "PreServerListSetEvent was cancelled. Stopping ping handling...");
return;
return null;
}
logger.debug(PingEventHandler.class, "PreServerListSetEvent completed. Proceeding with ping handling...");
@@ -86,12 +86,12 @@ public class PingEventHandler{
ProfileEntry entry = e.getEntry();
if(entry.isInvalid()){
logger.debugWarn(PingEventHandler.class, "No valid ProfileEntry retrieved. Cancelling ping handling...");
return;
return null;
}
boolean extraPlayers = ProfileManager.checkOption(entry.extraPlayersEnabled());
if(extraPlayers){
if(extraPlayers && ignoreMaintenance(event, "extraPlayers")){
max = online + (entry.extraPlayersCount() == null ? 0 : entry.extraPlayersCount());
logger.debug(PingEventHandler.class, "Extra Players enabled. Applying '%d' as max player count...", max);
@@ -99,7 +99,7 @@ public class PingEventHandler{
event.setMaxPlayers(max);
}
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers){
if(ProfileManager.checkOption(entry.maxPlayersEnabled()) && !extraPlayers && ignoreMaintenance(event, "maxPlayers")){
max = (entry.maxPlayersCount() == null) ? 0 : entry.maxPlayersCount();
logger.debug(PingEventHandler.class, "Max Players enabled. Applying '%d' as max player count...", max);
@@ -109,7 +109,7 @@ public class PingEventHandler{
GenericServer finalServer = event.createGenericServer(online, max, host);
if(ProfileManager.checkOption(entry.motd())){
if(ProfileManager.checkOption(entry.motd()) && ignoreMaintenance(event, "motd")){
logger.debug(PingEventHandler.class, "MOTD set. Applying '%s'...", String.join("\\n", entry.motd()));
event.setMotd(
@@ -122,13 +122,13 @@ public class PingEventHandler{
boolean hidePlayers = ProfileManager.checkOption(entry.hidePlayersEnabled());
if(hidePlayers){
if(hidePlayers && ignoreMaintenance(event, "hidePlayers")){
logger.debug(PingEventHandler.class, "Hide Players enabled. Hiding player count...");
event.hidePlayers();
}
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers){
if(ProfileManager.checkOption(entry.playerCountText()) && !hidePlayers && ignoreMaintenance(event, "playerCountText")){
logger.debug(PingEventHandler.class, "Player Count Text set. Applying '%s'...", entry.playerCountText());
event.setPlayerCount(
@@ -139,13 +139,13 @@ public class PingEventHandler{
);
}
if(ProfileManager.checkOption(entry.players()) && !hidePlayers){
if(ProfileManager.checkOption(entry.players()) && !hidePlayers && ignoreMaintenance(event, "playerCountHover")){
logger.debug(PingEventHandler.class, "Player Count Hover set. Applying '%s'...", String.join("\\n", entry.players()));
event.setPlayers(entry.players(), player, server);
}
if(ProfileManager.checkOption(entry.favicon())){
if(ProfileManager.checkOption(entry.favicon()) && ignoreMaintenance(event, "favicon")){
logger.debug(PingEventHandler.class, "Favicon set. Resolving '%s'...", entry.favicon());
String faviconString = StringReplacer.replace(entry.favicon(), player, server);
@@ -165,6 +165,8 @@ public class PingEventHandler{
logger.debug(PingEventHandler.class, "Event handling completed. Updating Ping data...");
event.updateEvent();
return entry;
}
public static PAPIUtil getPAPIUtil(){
@@ -180,4 +182,11 @@ public class PingEventHandler{
return (maintenanceUtil = new MaintenanceUtil());
}
private static <F, P extends GenericPlayer> boolean ignoreMaintenance(GenericEventWrapper<F, P> event, String option){
if(!event.isMaintenanceModeActive())
return true;
return !event.getPlugin().getCore().getFileHandler().getBool(true, "disableDuringMaintenance", option);
}
}
@@ -46,12 +46,29 @@ public class ConfigMigrator{
public static ConfigurationTransformation.Versioned create(){
return ConfigurationTransformation.versionedBuilder()
.versionKey("configVersion")
.addVersion(LATEST, threeToFour())
.addVersion(LATEST, fourToFive())
.addVersion(4, threeToFour())
.addVersion(3, twoToThree())
.addVersion(2, oneToTwo())
.build();
}
public static ConfigurationTransformation fourToFive(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
value.node("disableDuringMaintenance", "motd").set(true);
value.node("disableDuringMaintenance", "favicon").set(true);
value.node("disableDuringMaintenance", "hidePlayers").set(true);
value.node("disableDuringMaintenance", "playerCountText").set(true);
value.node("disableDuringMaintenance", "playerCountHover").set(true);
value.node("disableDuringMaintenance", "extraPlayers").set(true);
value.node("disableDuringMaintenance", "maxPlayers").set(true);
return null;
})
.build();
}
public static ConfigurationTransformation threeToFour(){
return ConfigurationTransformation.builder()
.addAction(NodePath.path(), (path, value) -> {
@@ -187,8 +187,12 @@ public class FileHandler{
return node.node(path).getString(def);
}
public boolean getBool(boolean def, Object... path){
return node.node(path).getBoolean(def);
}
public boolean getBoolean(Object... path){
return node.node(path).getBoolean();
return getBool(false, path);
}
public long getLong(long def, long limit, Object... path){
@@ -39,7 +39,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public record ServerListProfile(int priority, String condition, ProfileEntry defaultProfile, List<ProfileEntry> profiles){
public record ServerListProfile(int priority, String condition, ProfileEntry defaultProfile, List<ProfileEntry> profiles, String file){
private static final Random random = new Random();
public boolean evalConditions(ProfileConditionParser parser, PluginLogger logger, GenericPlayer player, GenericServer server){
@@ -50,13 +50,17 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
ExpressionTemplate template = parser.compile(condition, player, server, collector);
if(collector.hasWarnings()){
logger.warn("Encountered %d Error(s) while parsing condition '%s':", collector.getWarnings().size(), condition);
logger.warn("Encountered %d Error(s) while parsing condition for file '%s':", collector.getWarnings().size(), file);
for(ParseWarnCollector.Context context : collector.getWarnings()){
if(context.position() <= -1){
logger.warn(" - %s", context.message());
logger.warn(" - %s", condition);
logger.warn(" -> %s", context.message());
}else{
logger.warn(" - At Position %d: %s", context.position(), context.message());
logger.warn(" - At position %d:", context.position());
logger.warn(" %s", condition);
logger.warn(" ".repeat(context.position() + 5) + "^");
logger.warn(" -> %s", context.message());
}
}
}
@@ -159,7 +163,7 @@ public record ServerListProfile(int priority, String condition, ProfileEntry def
}
public ServerListProfile build(){
return new ServerListProfile(this.priority, this.condition, this.defaultProfile, this.profiles);
return new ServerListProfile(this.priority, this.condition, this.defaultProfile, this.profiles, this.fileName);
}
}
}
@@ -54,7 +54,7 @@ public class ProfileConditionParser implements ExpressionParserEngine{
}
public static ProfileConditionParser create(){
return new ProfileConditionParserBuilder().createDefault()
return new ProfileConditionParserBuilder().addDefaults()
.addTokenReader(new PlaceholderTokenReader(-20))
.addValueReader(new PlaceholderValueReader())
.build();
@@ -1,120 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2022-2024 Andre_601
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package ch.andre601.advancedserverlist.core.profiles.conditions.placeholders;
import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import java.text.ParsePosition;
public class PlaceholderParser{
public static PlaceholderToken.Placeholder parse(String text, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
AdvancedServerListAPI api = AdvancedServerListAPI.get();
// We want to point to the start of a placeholder in the ParseWarnCollector.
// Since the PlaceholderTokenReader updates the index by 2 are we reverting this here.
int placeholderStart = position.getIndex() - 2;
int index = position.getIndex();
StringBuilder identifier = new StringBuilder();
StringBuilder values = new StringBuilder();
boolean identified = false;
boolean invalid = true;
char[] chars = text.substring(index).toCharArray();
for(final char c : chars){
index++;
if(c == '}'){
invalid = false;
break;
}
if(c == ' ' && !identified){
identified = true;
continue;
}
if(identified){
values.append(c);
}else{
identifier.append(c);
}
}
String identifierStr = identifier.toString();
String valuesStr = values.toString();
StringBuilder raw = new StringBuilder();
// Skipping whatever character we currently were on (i.e. })
position.setIndex(index + 1);
if(invalid){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have a closing bracket (}).", raw.toString());
return new PlaceholderToken.Placeholder(raw.toString());
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierStr);
if(provider == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
return new PlaceholderToken.Placeholder(raw.toString());
}
String replacement = provider.parsePlaceholder(valuesStr, player, server);
if(replacement == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' has an invalid value String '%s'.", raw.toString(), valuesStr);
return new PlaceholderToken.Placeholder(raw.toString());
}
return new PlaceholderToken.Placeholder(replacement);
}
}
@@ -27,8 +27,8 @@ package ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.rea
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.PlaceholderParser;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.advancedserverlist.core.profiles.replacer.StringReplacer;
import ch.andre601.expressionparser.ParseWarnCollector;
import ch.andre601.expressionparser.tokens.Token;
@@ -44,7 +44,7 @@ public class PlaceholderTokenReader extends CustomTokenReader{
public Token read(String text, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
if(position.getIndex() + 1 < text.length() && text.charAt(position.getIndex()) == '$' && text.charAt(position.getIndex() + 1) == '{'){
position.setIndex(position.getIndex() + 2);
return new PlaceholderToken(PlaceholderParser.parse(text, position, player, server, collector));
return new PlaceholderToken(StringReplacer.parsePlaceholder(text, position, player, server, collector));
}
return null;
}
@@ -86,15 +86,15 @@ public class ProfileManager{
Integer maxPlayers = resolveNullableInt(node, "playerCount", "maxPlayers", "amount");
return new ProfileEntry.Builder()
.setMotd(motd)
.setPlayers(players)
.setPlayerCountText(playerCountText)
.setFavicon(favicon)
.setHidePlayersEnabled(hidePlayers)
.setExtraPlayersEnabled(extraPlayersEnabled)
.setMaxPlayersEnabled(maxPlayersEnabled)
.setExtraPlayersCount(extraPlayers)
.setMaxPlayersCount(maxPlayers)
.motd(motd)
.players(players)
.playerCountText(playerCountText)
.favicon(favicon)
.hidePlayersEnabled(hidePlayers)
.extraPlayersEnabled(extraPlayersEnabled)
.maxPlayersEnabled(maxPlayersEnabled)
.extraPlayersCount(extraPlayers)
.maxPlayersCount(maxPlayers)
.build();
}
@@ -29,6 +29,11 @@ import ch.andre601.advancedserverlist.api.AdvancedServerListAPI;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.core.AdvancedServerList;
import ch.andre601.advancedserverlist.core.profiles.conditions.placeholders.tokens.PlaceholderToken;
import ch.andre601.expressionparser.ParseWarnCollector;
import java.text.ParsePosition;
public class StringReplacer{
@@ -36,99 +41,113 @@ public class StringReplacer{
if(input == null)
return null;
char[] chars = input.toCharArray();
ParsePosition position = new ParsePosition(0);
StringBuilder builder = new StringBuilder(input.length());
StringBuilder identifier = new StringBuilder();
StringBuilder placeholder = new StringBuilder();
AdvancedServerListAPI api = AdvancedServerListAPI.get();
for(int i = 0; i < chars.length; i++){
char c = chars[i];
char next = (i == (chars.length - 1)) ? '\0' : chars[i + 1];
if(c != '$' || i + 2 >= chars.length){
builder.append(c);
while(position.getIndex() < input.length()){
if(position.getIndex() + 1 < input.length() && input.charAt(position.getIndex()) == '$' && input.charAt(position.getIndex() + 1) == '{'){
position.setIndex(position.getIndex() + 2);
builder.append(parsePlaceholder0(input, position, player, server, null));
continue;
}
if(next != '{'){
if(next == '\0')
continue;
builder.append(next);
i++;
continue;
}
i++;
boolean identified = false;
boolean invalid = true;
while(++i < chars.length){
final char id = chars[i];
if(id == '}'){
invalid = false;
break;
}
if(id == ' ' && !identified){
identified = true;
continue;
}
if(identified){
placeholder.append(id);
}else{
identifier.append(id);
}
}
String identifierString = identifier.toString();
String placeholderString = placeholder.toString();
identifier.setLength(0);
placeholder.setLength(0);
if(invalid){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
continue;
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierString);
if(provider == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
String replacement = provider.parsePlaceholder(placeholderString, player, server);
if(replacement == null){
builder.append("${").append(identifierString);
if(identified){
builder.append(' ').append(placeholderString);
}
builder.append('}');
continue;
}
builder.append(replacement);
builder.append(input.charAt(position.getIndex()));
position.setIndex(position.getIndex() + 1);
}
return builder.toString();
}
public static PlaceholderToken.Placeholder parsePlaceholder(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
return new PlaceholderToken.Placeholder(parsePlaceholder0(input, position, player, server, collector));
}
private static String parsePlaceholder0(String input, ParsePosition position, GenericPlayer player, GenericServer server, ParseWarnCollector collector){
AdvancedServerListAPI api = AdvancedServerList.getApi();
int placeholderStart = position.getIndex() - 2;
int index = position.getIndex();
StringBuilder identifier = new StringBuilder();
StringBuilder values = new StringBuilder();
boolean identified = false;
boolean invalid = true;
char[] chars = input.substring(index).toCharArray();
for(final char c : chars){
index++;
if(c == '}'){
invalid = false;
break;
}
if(c == ' ' && !identified){
identified = true;
continue;
}
if(identified){
values.append(c);
}else{
identifier.append(c);
}
}
String identifierStr = identifier.toString();
String valuesStr = values.toString();
StringBuilder raw = new StringBuilder();
// Condition parsing needs one extra increase of index... for some reason
if(collector != null)
index++;
position.setIndex(index);
if(invalid){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have a closing bracket (})", raw.toString());
return raw.toString();
}
PlaceholderProvider provider = api.retrievePlaceholderProvider(identifierStr);
if(provider == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' does not have any available PlaceholderProvider", raw.toString());
return raw.toString();
}
String replacement = provider.parsePlaceholder(valuesStr, player, server);
if(replacement == null){
raw.append("${").append(identifierStr);
if(identified)
raw.append(' ').append(valuesStr);
raw.append('}');
if(collector != null)
collector.appendWarningFormatted(placeholderStart, "Placeholder '%s' has an invalid value String '%s'", raw.toString(), valuesStr);
return raw.toString();
}
return replacement;
}
}
+36
View File
@@ -50,6 +50,42 @@ debug: false
#
faviconCacheTime: 1
#
# List of options that should be disabled while the Maintenance Mode of the plugin Maintenance is active.
# Any option not listed here will NOT be disabled, meaning AdvancedServerList will continue to handle it.
#
# Each option defaults to true when not present, disabling said option while Maintenance is active.
#
disableDuringMaintenance:
#
# When true (Default), disables handling of MOTD while Maintenance is enabled.
#
motd: true
#
# When true (Default), disables handling of Favicon while Maintenance is enabled.
#
favicon: true
#
# When true (Default), disables hiding of player count while Maintenance is enabled.
#
hidePlayers: true
#
# When true (Default), disables handling of player count text while Maintenance is enabled.
#
playerCountText: true
#
# When true (Default), disables handling of player count hover while Maintenance is enabled.
#
playerCountHover: true
#
# When true (Default), disables use of extra players feature while Maintenance is enabled.
#
extraPlayers: true
#
# When true (Default), disables use of max players feature while Maintenance is enabled.
#
maxPlayers: true
#
# DO NOT EDIT!
#
+7 -7
View File
@@ -8,28 +8,28 @@
Object summaries
-->
{% if page.meta.constructors %}
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor') }}
{{ info.summary('Constructor Summary', page.meta.constructors, details_type='constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.classes %}
{{ info.summary('Class Summary', page.meta.classes, details_type='class') }}
{{ info.summary('Class Summary', page.meta.classes, details_type='class', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.summary('Enum Constant Summary', page.meta.enums, details_type='enum') }}
{{ info.summary('Enum Constant Summary', page.meta.enums, details_type='enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods or page.meta.inherits %}
{{ info.summary('Method Summary', page.meta.methods, page.meta.inherits, details_type='method') }}
{{ info.summary('Method Summary', page.meta.methods, page.meta.inherits, details_type='method', defaults=page.meta.defaults) }}
{% endif %}
<!--
Detailed object info
-->
{% if page.meta.constructors %}
{{ info.info('Constructor Detail', page.meta.constructors) }}
{{ info.info('Constructor Detail', page.meta.constructors, 'constructor', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.enums %}
{{ info.info('Enum Constant Detail', page.meta.enums, true) }}
{{ info.info('Enum Constant Detail', page.meta.enums, 'enum', defaults=page.meta.defaults) }}
{% endif %}
{% if page.meta.methods %}
{{ info.info('Method Detail', page.meta.methods)}}
{{ info.info('Method Detail', page.meta.methods, 'method', defaults=page.meta.defaults)}}
{% endif %}
{% endif %}
{% endblock %}
+15 -5
View File
@@ -1,4 +1,4 @@
{% macro summary(title, summaries, inherits, details_type = 'unknown') -%}
{% macro summary(title, summaries, inherits, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
@@ -28,6 +28,8 @@
{% if summary.type and summary.type.name %}
{% set modifiers.name = modifiers.name ~ summary.type.name %}
{% elif defaults and defaults.type and defaults.type.name %}
{% set modifiers.name = modifiers.name ~ defaults.type.name %}
{% else %}
{% set modifiers.name = modifiers.name ~ "void" %}
{% endif %}
@@ -103,14 +105,14 @@
</div>
{%- endmacro %}
{% macro info(title, details, enum = false) -%}
{% macro info(title, details, details_type = 'unknown', defaults = []) -%}
<h2 id="{{ title | lower() | replace(' ', '-') | e}}">
{{ title }}
</h2>
{% for detail in details %}
<div class="api-detail">
{% set final_name = namespace(name = "") %}
{% if enum %}
{% if details_type == "enum" %}
{% set final_name.name = detail.name | upper() %}
{% else %}
{% set final_name.name = detail.name ~ "(" %}
@@ -121,7 +123,7 @@
{% if loop.revindex > 1 %}{% set final_name.name = final_name.name ~ ", " %}{% endif %}
{% endfor %}
{% if not enum %}
{% if details_type != "enum" %}
{% set final_name.name = final_name.name ~ ")" %}
{% endif %}
@@ -138,12 +140,20 @@
<api__static></api__static> <api__final></api__final>
{% endif %}
{% if detail.type %}
{% if detail.type and details_type == "method" %}
{% if detail.type.link %}
<a href="{{ detail.type.link }}" class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- detail.type.type | default('primitive') -}}">{{ detail.type.name | default('void') | e }}</span>
{% endif %}
{% elif defaults and defaults.type and details_type == "method" %}
{% if defaults.type.link %}
<a href="{{ defaults.type.link }}" class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') | e }}</a>
{% else %}
<span class="api-type__{{- defaults.type.type | default('primitive') -}}">{{ defaults.type.name | default('void') }}</span>
{% endif %}
{% elif details_type == "method" %}
<span class="api-type__primitive">void</span>
{% endif %}
<code>{{ final_name.name | e }}</code><a href="#{{ final_name.name | lower() | replace(' ', '-') | e }}" class="headerlink" title="Permanent link"></a>
</h3>
-10
View File
@@ -1,10 +0,0 @@
nav:
- Home: index.md
- getting-started
- commands
- profiles
- examples
- migration
- api
- addons
- PlaceholderAPI: placeholderapi
-2
View File
@@ -1,2 +0,0 @@
nav:
- ...
+80 -1
View File
@@ -7,6 +7,85 @@ icon: octicons/log-24
This page lists the recent changes made towards the AdvancedServerListAPI.
They are ordered newest to oldest.
## v3.2.1 { #v3.2.1 }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.1-changed }
- Removed usage of `${api.version}` in the different pom.xml for version resolving.
## v3.2.0 { #v3.2.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.2.0-added }
- New setter methods added to [`ProfileEntry.Builder`][profileentry.builder] class, replacing old ones (See deprecations below):
- [`extraPlayersCount(Integer)`][extraplayerscount]
- [`extraPlayersEnabled(NullBool)`][extraplayersenabled]
- [`favicon(String)`][favicon]
- [`hidePlayersEnabled(NullBool)`][hideplayersenabled]
- [`maxPlayersCount(Integer)`][maxplayerscount]
- [`maxPlayersEnabled(NullBool)`][maxplayersenabled]
- [`motd(List<String>)`][motd]
- [`playerCountText(String)`][playercounttext]
- [`players(List<String>)`][players]
[extraplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayerscount(integer)
[extraplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#extraplayersenabled(nullbool)
[favicon]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#favicon(string)
[hideplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#hideplayersenabled(nullbool)
[maxplayerscount]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayerscount(integer)
[maxplayersenabled]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#maxplayersenabled(nullbool)
[motd]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#motd(list<string>)
[playercounttext]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#playercounttext(string)
[players]: reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md#players(list<string>)
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v3.2.0-changed }
- The API has been moved to Codeberg and is now available under a new repository URL to download. The group and artifact ID remained the same, but version no longer has a `v` prefix:
/// tab | ":simple-apachemaven: Maven (pom.xml)"
```xml
<repositories>
<repository>
<id>codeberg</id>
<url>https://codeberg.org/api/packages/Andre601/maven/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>ch.andre601.asl-api</groupId>
<artifactId>api</artifactId>
<version>{apiVersion}</version>
<scope>provided</scope>
</dependency>
</dependencies>
```
///
/// tab | ":simple-gradle: Gradle (build.gradle)"
```groovy
repositories {
maven = { url ="https://codeberg.org/api/packages/Andre601/maven/" }
}
dependencies {
compileOnly "ch.andre601.asl-api:api:{apiVersion}"
}
```
///
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v3.2.0-deprecated }
- Setters in [`ProfileEntry.Builder`][profileentry.builder] deprecated in favour of more consistent method naming.
- `setExtraPlayersCount(Integer)`
- `setExtraPlayersEnabled(NullBool)`
- `setFavicon(String)`
- `setHidePlayersEnabled(NullBool)`
- `setMaxPlayersCount(Integer)`
- `setMaxPlayersEnabled(NullBool)`
- `setMotd(List<String>)`
- `setPlayerCountText(String)`
- `setPlayers(List<String>)`
## v3.1.0 { #v3.1.0 }
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v3.1.0-added }
@@ -111,6 +190,6 @@ Templates for changelog
### :octicons-plus-circle-24:{ .changelog-added title="Added" } Added { #v-added }
### :octicons-pencil-24:{ .changelog-changed title="Changed" } Changed { #v-changed }
### :octicons-trash-24:{ .changelog-removed title="Removed" } Removed { #v-removed }
### :octicons-zap-24:{ .changelog-deprecated title="Deprecated" } Deprecated { #v-deprecated }
### :octicons-zap-24:{ .changelog-breaking title="Deprecated" } Deprecated { #v-deprecated }
-->
-6
View File
@@ -1,6 +0,0 @@
nav:
- index.md
- api: api
- platform-bukkit: platform-bukkit
- platform-bungeecord: platform-bungeecord
- platform-velocity: platform-velocity
-3
View File
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api: ch.andre601.advancedserverlist.api
@@ -8,7 +8,7 @@ constructors:
- name: 'identifier'
description: 'The identifier to use for the placeholder. Cannot be empty.'
type: String
attributes:
attribute:
- notnull
methods:
@@ -28,7 +28,7 @@ methods:
type: GenericServer
description: 'The <a href="./../objects/genericserver/"><code>GenericServer</code> instance</a> used.'
returns: 'Possibly-parsed or possibly-null String to replace the placeholder with.'
attributes:
attribute:
- nullable
- abstract
type:
@@ -1,59 +1,213 @@
---
template: api-doc.html
defaults:
type:
name: 'Builder'
type: 'object'
constructors:
- name: 'Builder'
description: 'Empty Builder Constructor used to create a new instance of this class.'
methods:
- name: 'setMotd'
- name: 'extraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: 'Integer'
attribute:
- 'nullable'
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
- name: 'extraPlayersEnabled'
description: |
Sets whether the extra players feature should be enabled or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.
- name: 'favicon'
description: |
Sets the value to use for the favicon.<br>
The following values are supported:
<ul>
<li>URL to a valid PNG file.</li>
<li>File name (with <code>.png</code> extension) matching a file saved in the favicons folder of AdvancedServerList.</li>
<li><code>${player uuid}</code> to display the avatar of the player.
</ul>
Set to an empty String or <code>null</code> to not alter the Favicon.
parameters:
- name: 'favicon'
description: 'The favicon to set.'
type: 'String'
attribute:
- 'nullable'
returns: 'This Builder after the Favicon has been set. Useful for chaining.'
- name: 'hidePlayersEnabled'
description: |
Sets whether the player count should be hidden or not.<br>
<br>
Set to <a href="../../../objects/nullbool#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
parameters:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: 'NullBool'
attribute:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
- name: 'maxPlayersCount'
description: |
Sets the number of max players allowed to join this server.<br>
This option has no effect when <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled</a> is set to <a href="../../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively <a href="#maxplayersenabled(nullbool)">disable max Players</a>.
parameters:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: 'Integer'
attribute:
- 'nullable'
returns: 'This Builder after the max player count has been set. Useful for chaining.'
- name: 'maxPlayersEnabled'
description: |
Sets whether the max players feature should be enabled.<br>
<br>
Set to <a href="../../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should maxPlayersEnabled be null.
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: 'NullBool'
attribute:
- 'notnull'
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
- name: 'motd'
description: |
Sets a new MOTD to use.<br>
<br>
Set to an empty list to not change the MOTD.<br>
Only the first two entries of the list will be considered and any additional ones discarded.
returns: 'This Builder after the motd has been set. Useful for chaining.'
Only the first two entries of the list will be considered and any additional ones discarded.<br>
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided motd list be null.
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attributes:
- notnull
attribute:
- 'notnull'
returns: 'This Builder after the motd has been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayers'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Set to an empty list to not change the hover text.
returns: 'This Builder after the players have been set. Useful for chaining.'
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayerCountText'
- name: 'playerCountText'
description: |
Sets the text to override the player count with.<br>
<br>
Set to an empty String or <code>null</code> to not alter the player count text.
returns: 'This Builder after the player count text has been set. Useful for chaining.'
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: String
attributes:
type: 'String'
attribute:
- 'nullable'
returns: 'This Builder after the player count text has been set. Useful for chaining.'
- name: 'players'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Set to an empty list to not change the hover text.
<br>
An <code>IllegalArgumentException</code> may be thrown by the <code>CheckUtil</code> should the provided okayersmotd list be null.
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
- 'notnull'
returns: 'This Builder after the players have been set. Useful for chaining.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
- name: 'build'
description: 'Creates a new <a href="./.."><code>ProfileEntry</code> instance</a> with the values set in this Builder.'
returns: 'New <a href="./.."><code>ProfileEntry</code> instance</a>.'
type:
name: 'ProfileEntry'
type: 'object'
link: './..'
#
# Deprecated stuff
#
- name: 'setExtraPlayerCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attribute:
- nullable
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayerscount(integer)">extraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersEnabled'
description: |
Sets whether the extra players feature should be enabled or not.<br>
<br>
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#extraplayersenabled(nullbool)">extraPlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
@@ -71,8 +225,9 @@ methods:
- name: 'favicon'
description: 'The favicon to set'
type: String
attributes:
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#favicon(string)">favicon(String)</a> instead.'
type:
name: 'Builder'
type: 'object'
@@ -86,83 +241,15 @@ methods:
- name: 'hidePlayersEnabled'
description: 'Whether the player count should be hidden or not.'
type: NullBool
attributes:
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#hideplayersenabled(nullbool)">hidePlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersEnabled'
description: |
Sets whether the extra players feature should be enabled or not.<br>
<br>
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setMaxPlayersEnabled'
description: |
Sets whether the max players feature should be enabled.<br>
<br>
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attributes:
- notnull
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayerCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attributes:
- nullable
deprecated: 'Typo in the name. Use <a href="#setextraplayerscount(integer)">setExtraPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setExtraPlayersCount'
description: |
Sets the number of players to add to the online players to use as the new max players value.<br>
This option has no effect when <a href="../#extraplayersenabled()"><code>extraPlayersEnabled</code></a> is set to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a> or <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a>.<br>
<br>
Set this to <code>null</code> to not alter the max player count. Alternatively, set <a href="#setextraplayersenabled(nullbool)"><code>setExtraPlayersEnabled(NullBool)</code></a> to <a href="../../objects/nullbool/#false"><code>NullBool.FALSE</code></a>.
returns: 'This Builder after the extra player count has been set. Useful for chaining.'
parameters:
- name: 'extraPlayersCount'
description: 'The number of extra players to add.'
type: Integer
attributes:
- nullable
type:
name: 'Builder'
type: 'object'
- name: 'setMaxPlayersCount'
description: |
Sets the number of max players allowed to join this server.<br>
@@ -174,18 +261,86 @@ methods:
- name: 'maxPlayersCount'
description: 'The number of max players to set.'
type: Integer
attributes:
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayerscount(integer)">maxPlayersCount(Integer)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'build'
description: 'Creates a new <a href="./.."><code>ProfileEntry</code> instance</a> with the values set in this Builder.'
returns: 'New <a href="./.."><code>ProfileEntry</code> instance</a>.'
- name: 'setMaxPlayersEnabled'
description: |
Sets whether the max players feature should be enabled.<br>
<br>
Set to <a href="../../objects/nullbool/#not_set"><code>NullBool.NOT_SET</code></a> to not set this.
returns: 'This Builder after the NullBool has been set. Useful for chaining.'
parameters:
- name: 'maxPlayersEnabled'
description: 'Whether the extra players feature should be enabled or not.'
type: NullBool
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#maxplayersenabled(nullbool)">maxPlayersEnabled(NullBool)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'ProfileEntry'
name: 'Builder'
type: 'object'
- name: 'setMotd'
description: |
Sets a new MOTD to use.<br>
<br>
Set to an empty list to not change the MOTD.<br>
Only the first two entries of the list will be considered and any additional ones discarded.
returns: 'This Builder after the motd has been set. Useful for chaining.'
parameters:
- name: 'motd'
description: 'The MOTD to use.'
type: 'List<String>'
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#motd(string)">motd(String)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayerCountText'
description: |
Sets the text to override the player count with.<br>
<br>
Set to an empty String or <code>null</code> to not alter the player count text.
returns: 'This Builder after the player count text has been set. Useful for chaining.'
parameters:
- name: 'playerCountText'
description: 'The text to show in the player count.'
type: String
attribute:
- nullable
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#playercounttext(string)">playerCountText(String)</a> instead.'
type:
name: 'Builder'
type: 'object'
- name: 'setPlayers'
description: |
Sets the players (lines) to use for the hover.<br>
<br>
Set to an empty list to not change the hover text.
returns: 'This Builder after the players have been set. Useful for chaining.'
parameters:
- name: 'players'
description: 'The lines to set for the hover.'
type: 'List<String>'
attribute:
- notnull
deprecated: 'Method renamed to fit <a href="..">ProfileEntry</a> record more closely. Use <a href="#players(list<string>)">players(List&lt;String&gt;)</a> instead.'
throws:
- name: 'IllegalArgumentException'
description: 'Thrown by the <code>CheckUtil</code> in case <code>null</code> has been provided as parameter.'
type:
name: 'Builder'
type: 'object'
link: './..'
---
# <api__class></api__class> Builder
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.bukkit: ch.andre601.advancedserverlist.api.bukkit
@@ -0,0 +1,49 @@
---
template: api-doc.html
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
methods:
- name: 'getHandlerList'
description: 'Static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList</code></a> getter. Required by Paper.'
returns: 'The static <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/HandlerList.html" target="_blank" rel="nofollow"><code>HandlerList instance</code></a> of this event.'
attributes:
- static
type:
name: 'HandlerList'
type: 'object'
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
inherits:
'org.bukkit.event.Event':
link: 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/Event.html'
list:
- 'getHandlers()'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.bungeecord: ch.andre601.advancedserverlist.api.bungeecord
@@ -0,0 +1,35 @@
---
template: api-doc.html
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
@@ -1,3 +0,0 @@
nav:
- index.md
- ch.andre601.advancedserverlist.api.velocity: ch.andre601.advancedserverlist.api.velocity
@@ -0,0 +1,35 @@
---
template: api-doc.html
constructors:
- name: 'PostServerListSetEvent'
description: 'Constructor for creating a new PostServerListSetEvent instance.'
parameters:
- name: 'entry'
description: 'The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> used during the PingEvent.'
type: ProfileEntry
attribute:
- nullable
methods:
- name: 'getEntry'
description: |
The <a href="../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/"><code>ProfileEntry</code></a> that was used during the PingEvent handling.<br>
<br>
The returned value may be <code>null</code> should the PingEvent handling be cancelled at any point (i.e. due to an invalid protocol or because the <a href="../preserverlistsetevent/"><code>PreServerListSetEvent</code></a> has been cancelled).<br>
The values within the ProfileEntry also do not represent what is actually used within the Server list itself, but only the values provided for the PingEvent handling.
returns: 'Possibly-null ProfileEntry used for the PingEvent.'
attributes:
- nullable
type:
name: 'ProfileEntry'
type: 'object'
link: '../../../../api/ch.andre601.advancedserverlist.api/profiles/profileentry/'
---
# <api__class></api__class> PostServerListSetEvent
Called **after** the plugin has updated the Server List.
The provided [`ProfileEntry`](#getentry()) may be null due to the PingEvent handling being cancelled (i.e. due to a invalid protocol or due to the [`PreServerListSetEvent`](preserverlistsetevent.md) being cancelled).
The entry also only represents the values used during the PingEvent, not the actual content that is being displayed.
+33 -12
View File
@@ -53,46 +53,67 @@ The plugin also supports these additional plugins. They are all optional.
<div class="grid cards" markdown>
- [**PlaceholderAPI**][placeholderapi]
----
Supported on:
AdvancedServerList supports the use of placeholder from PlaceholderAPI in all its text options, excluding the `condition` option.
- :fontawesome-solid-paper-plane: Paper
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
- [**ViaVersion**][viaversion]
----
Supported on:
When installed will AdvancedServerList use ViaVersion to resolve the protocol version of a player for its PlaceholderAPI placeholders.
- :fontawesome-solid-paper-plane: Paper
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper
- [**PAPIProxyBridge**][papiproxybridge]
----
Supported on:
Allows AdvancedServerList to parse placeholders from PlaceholderAPI while being used on a proxy.
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
----
**Supported on:**
:simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
- [**Maintenance**][maintenance]
----
Supported on:
AdvancedServerList will disable any modification of the server list entry should Maintenance mode be enabled.
- :fontawesome-solid-paper-plane: Paper
- :simple-spigotmc: BungeeCord
- :fontawesome-solid-paper-plane: Velocity
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
- [**BanPlugins Addon**][addon]
----
Official Add-on for AdvancedServerList that adds placeholders for different Ban/Punishment plugins such as AdvancedBan and LibertyBans.
----
**Supported on:**
:fontawesome-solid-paper-plane: Paper, :simple-spigotmc: BungeeCord, :fontawesome-solid-paper-plane: Velocity
</div>
[placeholderapi]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
[viaversion]: https://hangar.papermc.io/ViaVersion/ViaVersion
[papiproxybridge]: https://hangar.papermc.io/William278/PAPIProxyBridge
[maintenance]: https://hangar.papermc.io/kennytv/Maintenance
[addon]: ../addons/banplugins.md
## 2. Installation { #installation }
+51 -15
View File
@@ -58,18 +58,54 @@ All listed dependencies are optional.
## Pages
- [Getting started](getting-started/index.md)
- [Commands](commands/index.md)
- [Profiles](profiles/index.md)
- [Formatting](profiles/formatting.md)
- [Placeholders](profiles/placeholders.md)
- [Examples](examples/index.md)
- [Migration](migration/index.md)
- [v1.5.3 to v1.6.0](migration/v1_5_3-to-v1_6_0.md)
- [v1.9.0 to v1.10.0](migration/v1_9_0-to-v1_10_0.md)
- [API](api/index.md)
- [Changelog](api/changelog.md)
- [Javadocs](api/javadocs.md) (External site)
- [Source Code](api/source.md) (External site)
- [Reference](api/reference/index.md)
- [PlaceholderAPI](placeholderapi/index.md)
<div class="grid cards" markdown>
- [:octicons-milestone-24: **Getting Started**](getting-started/index.md)
----
A simple guide on how to get started with AdvancedServerList.
- [:octicons-rel-file-path-24: **Commands**](commands/index.md)
----
A list of all available commands in AdvancedServerList.
- [:octicons-note-24: **Profiles**](profiles/index.md)
----
Pages containing information about the Server List Profile System and all its available options.
- [:octicons-list-unordered-24: **Examples**](examples/index.md)
----
Collection of various profile examples to use for different situations.
- [:octicons-file-directory-symlink-24: **Migration**](migration/index.md)
----
Pages explaining how to migrate from one version of the plugin to another.
- [:octicons-command-palette-24: **API**](api/index.md)
----
Pages all about the API of AdvancedServerList.
- [:octicons-plus-circle-24: **Addons**](addons/index.md)
----
Pages listing 1st-party and 3rd-party add-ons for AdvancedServerList.
- [:material-percent: **PlaceholderAPI**](placeholderapi/index.md)
----
Information about available placeholders to use in PlaceholderAPI and how to use placeholders from other plugins in AdvancedServerList using PlaceholderAPI.
</div>
-7
View File
@@ -1,7 +0,0 @@
nav:
- index.md
- v3_8_0-to-v3_9_0.md
- v3_7_0-to-v3_8_0.md
- pre-v3_7_0-to-v3_7_0.md
- v1_9_0-to-v1_10_0.md
- v1_5_3-to-v1_6_0.md
+6
View File
@@ -12,6 +12,12 @@ Note that these pages only cover server list profile files. The config.yml is au
<div class="grid cards" markdown>
- [**v3.8.0 to v3.9.0**](v3_8_0-to-v3_9_0.md)
----
Migrate from version 3.8.0 to 3.9.0.
- [**v3.7.0 to v3.8.0**](v3_7_0-to-v3_8_0.md)
----
+4
View File
@@ -49,8 +49,12 @@ priority: 0
-conditions:
- - '${player protocol} >= 763'
- - '${player isWhitelisted} == true'
+# The text can all be in one line. This is only for better readability.
+condition: |
+ ${player protocol} >= 763 and
+ ${player isWhitelisted}
motd:
- 'Welcome ${player name}!'
```
///
+1 -1
View File
@@ -18,7 +18,7 @@ Here is a before and after example to help visualize the change:
```yaml
priority: 0
conditions: '${server host} <- "survival"'
condition: '${server host} <- "survival"'
motd:
- 'Welcome ${player name}!'
+1 -1
View File
@@ -18,7 +18,7 @@ Here is a before and after example to help visualize the change:
```yaml
priority: 0
conditions: '${player name} ~= "Someone"'
condition: '${player name} ~= "Someone"'
motd:
- 'Welcome ${player name}!'
+5 -5
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
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
"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
${player protocol}
${player name}
@@ -110,7 +110,7 @@ These additional binary operators can also be used to perform certain actions:
| `/` | Divides one number by another. Strings use their text length as number. |
/// example | Examples
```
```shell
${player name} != "Anonymous"
763 > ${player protocol} > 758
${player hasPlayedBefore} and ${player isBanned} == "false"
@@ -126,7 +126,7 @@ Parenthesis can be used to prevent ambiguities.
`!` can be used to negate boolean expressions.
```
```shell
!${player isWhitelisted}
```
+74 -3
View File
@@ -69,8 +69,6 @@ extra:
plugins:
- search
- glightbox
- awesome-pages:
filename: .pages.yml
- pagenav-generator
markdown_extensions:
@@ -107,4 +105,77 @@ markdown_extensions:
hooks:
- docs/.hooks/badges.py
- docs/.hooks/replacer.py
- docs/.hooks/replacer.py
nav:
- Home: index.md
- Getting Started: getting-started/index.md
- Commands: commands/index.md
- Profiles:
- profiles/index.md
- Expressions: profiles/expressions.md
- Formatting: profiles/formatting.md
- Placeholders: profiles/placeholders.md
- Examples: examples/index.md
- Migration:
- migration/index.md
- v3.8.0 to v3.9.0: migration/v3_8_0-to-v3_9_0.md
- v3.7.0 to v3.8.0: migration/v3_7_0-to-v3_8_0.md
- '< v3.7.0 to v3.7.0': migration/pre-v3_7_0-to-v3_7_0.md
- v1.9.0 to v1.10.0: migration/v1_9_0-to-v1_10_0.md
- v1.5.3 to v1.6.0: migration/v1_5_3-to-v1_6_0.md
- API:
- api/index.md
- Changelog: api/changelog.md
- Javadocs: api/javadocs.md
- Source Code: api/source.md
- Reference:
- api/reference/index.md
- api:
- api/reference/api/index.md
- ch.andre601.advancedserverlist.api:
- api/reference/api/ch.andre601.advancedserverlist.api/advancedserverlistapi.md
- api/reference/api/ch.andre601.advancedserverlist.api/placeholderprovider.md
- events:
- api/reference/api/ch.andre601.advancedserverlist.api/events/genericserverlistevent.md
- exceptions:
- api/reference/api/ch.andre601.advancedserverlist.api/exceptions/invalidplaceholderproviderexception.md
- objects:
- api/reference/api/ch.andre601.advancedserverlist.api/objects/genericplayer.md
- api/reference/api/ch.andre601.advancedserverlist.api/objects/genericserver.md
- api/reference/api/ch.andre601.advancedserverlist.api/objects/nullbool.md
- profiles:
- '<api__record></api__record> ProfileEntry':
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/index.md
- api/reference/api/ch.andre601.advancedserverlist.api/profiles/profileentry/builder.md
- platform-bukkit:
- api/reference/platform-bukkit/index.md
- ch.andre601.advancedserverlist.api.bukkit:
- events:
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/events/postserverlistsetevent.md
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/events/preserverlistsetevent.md
- objects:
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/objects/bukkitplayer.md
- api/reference/platform-bukkit/ch.andre601.advancedserverlist.api.bukkit/objects/bukkitserver.md
- platform-bungeecord:
- api/reference/platform-bungeecord/index.md
- ch.andre601.advancedserverlist.api.bungeecord:
- events:
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/events/postserverlistsetevent.md
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/events/preserverlistsetevent.md
- objects:
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/objects/bungeeplayer.md
- api/reference/platform-bungeecord/ch.andre601.advancedserverlist.api.bungeecord/objects/bungeeproxy.md
- platform-velocity:
- api/reference/platform-velocity/index.md
- ch.andre601.advancedserverlist.api.velocity:
- events:
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/events/postserverlistsetevent.md
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/events/preserverlistsetevent.md
- objects:
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/objects/velocityplayer.md
- api/reference/platform-velocity/ch.andre601.advancedserverlist.api.velocity/objects/velocityproxy.md
- Addons:
- addons/index.md
- BanPlugins: addons/banplugins.md
- PlaceholderAPI: placeholderapi/index.md
+1 -1
View File
@@ -92,7 +92,7 @@
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.9.2</version>
<version>4.9.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -39,11 +39,16 @@ import ch.andre601.advancedserverlist.paper.objects.placeholders.PaperServerPlac
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.CachedServerIcon;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon>{
@@ -68,7 +73,7 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
}
}
this.core = AdvancedServerList.init(this, new PaperPlayerPlaceholders(), new PaperServerPlaceholders());
this.core = AdvancedServerList.init(this, new PaperPlayerPlaceholders(), new PaperServerPlaceholders(this));
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI"))
papiPlaceholders = new PAPIPlaceholders(this);
@@ -171,6 +176,21 @@ public class PaperCore extends JavaPlugin implements PluginCore<CachedServerIcon
return (worldCache = new WorldCache());
}
public int getPlayersOnline(World world){
List<? extends Player> players = new ArrayList<>(world == null ? getServer().getOnlinePlayers() : world.getPlayers());
players.removeIf(player -> {
for(MetadataValue metadata : player.getMetadata("vanished")){
if(metadata.asBoolean())
return true;
}
return false;
});
return players.size();
}
private void printNoPaperWarning(){
getPluginLogger().warn("======================================================================================");
getPluginLogger().warn("THIS SERVER DOES NOT USE PAPER OR A COMPATIBLE FORK!");
@@ -145,7 +145,7 @@ public class PaperEventWrapper implements GenericEventWrapper<CachedServerIcon,
@Override
public int getOnlinePlayers(){
return event.getNumPlayers();
return plugin.getPlayersOnline(null);
}
@Override
@@ -25,10 +25,13 @@
package ch.andre601.advancedserverlist.paper.listeners;
import ch.andre601.advancedserverlist.api.bukkit.events.PostServerListSetEvent;
import ch.andre601.advancedserverlist.api.profiles.ProfileEntry;
import ch.andre601.advancedserverlist.core.events.PingEventHandler;
import ch.andre601.advancedserverlist.paper.PaperCore;
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
public class PingEvent implements Listener{
@@ -40,8 +43,10 @@ public class PingEvent implements Listener{
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
@EventHandler(priority = EventPriority.HIGHEST) // Maintenance plugin has HIGHEST priority, so ASL needs too.
public void onPaperServerListPing(PaperServerListPingEvent event){
PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
ProfileEntry entry = PingEventHandler.handleEvent(new PaperEventWrapper(plugin, event));
plugin.getServer().getPluginManager().callEvent(new PostServerListSetEvent(entry));
}
}
@@ -28,15 +28,20 @@ package ch.andre601.advancedserverlist.paper.objects.placeholders;
import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.paper.PaperCore;
import ch.andre601.advancedserverlist.paper.objects.impl.PaperServerImpl;
import org.bukkit.Bukkit;
import org.bukkit.World;
public class PaperServerPlaceholders extends PlaceholderProvider{
public PaperServerPlaceholders(){
private final PaperCore plugin;
public PaperServerPlaceholders(PaperCore plugin){
super("server");
this.plugin = plugin;
}
@Override
public String parsePlaceholder(String placeholder, GenericPlayer player, GenericServer server){
if(!(server instanceof PaperServerImpl paperServer))
@@ -58,7 +63,7 @@ public class PaperServerPlaceholders extends PlaceholderProvider{
if(world == null)
continue;
players += world.getPlayers().size();
players += plugin.getPlayersOnline(world);
}
yield String.valueOf(players);
+2 -3
View File
@@ -36,12 +36,11 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.commit/>
<plugin.version>4.3.0</plugin.version>
<plugin.version>4.6.0</plugin.version>
<plugin.description>Create multiple Server lists based on conditions.</plugin.description>
<api.version>3.2.1</api.version>
<api.version>3.3.0</api.version>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
+1 -2
View File
@@ -1,4 +1,3 @@
mkdocs-material==9.5.12
mkdocs-material==9.5.13
mkdocs-glightbox==0.3.7
mkdocs-awesome-pages-plugin==2.9.2
git+https://github.com/Andre601/mkdocs-pagenav-generator
+14
View File
@@ -63,24 +63,38 @@
<version>${api.version}</version>
<scope>compile</scope>
</dependency>
<!-- Velocity API -->
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.1.2-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-velocity</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<!-- Configurate -->
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>configurate-yaml</artifactId>
<version>4.1.2</version>
<scope>provided</scope>
</dependency>
<!-- Plugins -->
<dependency>
<groupId>com.github.LeonMangler</groupId>
<artifactId>PremiumVanishAPI</artifactId>
<version>2.9.0-4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
@@ -41,14 +41,19 @@ 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.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.Favicon;
import de.myzelyam.api.vanish.VelocityVanishAPI;
import org.bstats.charts.SimplePie;
import org.bstats.velocity.Metrics;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class VelocityCore implements PluginCore<Favicon>{
@@ -71,7 +76,7 @@ public class VelocityCore implements PluginCore<Favicon>{
@Subscribe
public void init(ProxyInitializeEvent event){
this.core = AdvancedServerList.init(this, VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init());
this.core = AdvancedServerList.init(this, VelocityPlayerPlaceholders.init(), VelocityServerPlaceholders.init(this));
}
@Subscribe
@@ -154,11 +159,25 @@ public class VelocityCore implements PluginCore<Favicon>{
}
@Override
public Favicon createFavicon(BufferedImage image) throws Exception{
public Favicon createFavicon(BufferedImage image){
return Favicon.create(image);
}
public ProxyServer getProxy(){
return proxy;
}
public int getOnlinePlayers(RegisteredServer server){
if(getProxy() == null)
return -1;
List<Player> players = new ArrayList<>(server == null ? getProxy().getAllPlayers() : server.getPlayersConnected());
// Exclude players when PremiumVanish is enabled and player is hidden.
if(getProxy().getPluginManager().isLoaded("premiumvanish")){
players.removeIf(VelocityVanishAPI::isInvisible);
}
return players.size();
}
}
@@ -25,6 +25,8 @@
package ch.andre601.advancedserverlist.velocity.listeners;
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;
@@ -40,8 +42,10 @@ public class PingEvent{
plugin.getProxy().getEventManager().register(plugin, this);
}
@Subscribe(order = PostOrder.EARLY)
@Subscribe(order = PostOrder.LAST) // Maintenance has LAST priority, so ASL needs it too.
public void onProxyPing(ProxyPingEvent event){
PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
ProfileEntry entry = PingEventHandler.handleEvent(new VelocityEventWrapper(plugin, event));
plugin.getProxy().getEventManager().fire(new PostServerListSetEvent(entry));
}
}
@@ -44,10 +44,7 @@ import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import net.kyori.adventure.text.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ExecutionException;
public class VelocityEventWrapper implements GenericEventWrapper<Favicon, VelocityPlayerImpl>{
@@ -146,7 +143,11 @@ public class VelocityEventWrapper implements GenericEventWrapper<Favicon, Veloci
@Override
public int getOnlinePlayers(){
return builder.getOnlinePlayers();
int players = plugin.getOnlinePlayers(null);
if(players == -1)
return builder.getOnlinePlayers();
return players;
}
@Override
@@ -29,16 +29,20 @@ import ch.andre601.advancedserverlist.api.PlaceholderProvider;
import ch.andre601.advancedserverlist.api.objects.GenericPlayer;
import ch.andre601.advancedserverlist.api.objects.GenericServer;
import ch.andre601.advancedserverlist.api.velocity.objects.VelocityProxy;
import ch.andre601.advancedserverlist.velocity.VelocityCore;
import com.velocitypowered.api.proxy.server.RegisteredServer;
public class VelocityServerPlaceholders extends PlaceholderProvider{
private VelocityServerPlaceholders(){
private final VelocityCore plugin;
private VelocityServerPlaceholders(VelocityCore plugin){
super("server");
this.plugin = plugin;
}
public static VelocityServerPlaceholders init(){
return new VelocityServerPlaceholders();
public static VelocityServerPlaceholders init(VelocityCore core){
return new VelocityServerPlaceholders(core);
}
@Override
@@ -62,7 +66,11 @@ public class VelocityServerPlaceholders extends PlaceholderProvider{
if(registeredServer == null)
continue;
players += registeredServer.getPlayersConnected().size();
int connected = plugin.getOnlinePlayers(registeredServer);
if(connected == -1)
continue;
players += connected;
}
yield String.valueOf(players);
+1 -1
View File
@@ -52,7 +52,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.1</version>
<version>1.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -35,7 +35,7 @@ public enum PlatformInfo{
"paper/target/AdvancedServerList-Paper-{{version}}.jar",
"addons/banplugins/target/AdvancedServerList-BanPlugins-Addon-{{version}}.jar"
),
"paper", "folia"
List.of("Paper", "Folia")
),
BUNGEECORD(
"bungeecord",
@@ -43,7 +43,7 @@ public enum PlatformInfo{
"bungeecord/target/AdvancedServerList-BungeeCord-{{version}}.jar",
"addons/banplugins/target/AdvancedServerList-BanPlugins-Addon-{{version}}.jar"
),
"bungeecord", "waterfall"
List.of("BungeeCord", "Waterfall")
),
VELOCITY(
"velocity",
@@ -51,17 +51,19 @@ public enum PlatformInfo{
"velocity/target/AdvancedServerList-Velocity-{{version}}.jar",
"addons/banplugins/target/AdvancedServerList-BanPlugins-Addon-{{version}}.jar"
),
"velocity"
List.of("Velocity")
);
private final String platform;
private final List<String> filePaths;
private final List<String> loaders;
private final List<String> platformNames;
PlatformInfo(String platform, List<String> filePaths, String... loaders){
PlatformInfo(String platform, List<String> filePaths, List<String> loaders){
this.platform = platform;
this.filePaths = filePaths;
this.loaders = List.of(loaders);
this.loaders = loaders.stream().map(String::toLowerCase).toList();
this.platformNames = loaders;
}
public String getPlatform(){
@@ -75,4 +77,8 @@ public enum PlatformInfo{
public List<String> getLoaders(){
return loaders;
}
public List<String> getPlatformNames(){
return platformNames;
}
}
@@ -25,18 +25,22 @@
package ch.andre601.advancedserverlist.versionuploader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ModrinthRelease{
public class ReleaseHolder{
Map<String, String> releases = new HashMap<>();
private final List<ReleaseInfo> releases = new ArrayList<>();
public void addRelease(String platform, String id){
releases.put(platform, id);
public void addRelease(String type, String platform, String url){
releases.add(new ReleaseInfo(type, platform, url));
}
public Map<String, String> getReleases(){
public List<ReleaseInfo> getReleases(){
return releases;
}
record ReleaseInfo(String type, String platform, String url){}
}
@@ -40,8 +40,8 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.StringJoiner;
import java.util.concurrent.CompletableFuture;
public class VersionUploader{
@@ -53,7 +53,7 @@ public class VersionUploader{
if(args.length == 0){
LOGGER.warn("MISSING ARGUMENT!");
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar <--all|--modrinth|--hangar> [--dryrun]");
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar [--dryrun] --all | --modrinth | --hangar");
System.exit(1);
return;
}
@@ -72,22 +72,19 @@ public class VersionUploader{
}
CompletableFuture<?> future;
ModrinthRelease modrinthRelease = null;
ReleaseHolder releaseHolder = new ReleaseHolder();
switch(args[0].toLowerCase(Locale.ROOT)){
case "--modrinth" -> {
modrinthRelease = new ModrinthRelease();
future = new ModrinthVersionUploader().performUpload(release, modrinthRelease, dryrun);
}
case "--hangar" -> future = new HangarVersionUploader().performUpload(release, dryrun);
case "--modrinth" -> future = new ModrinthVersionUploader().performUpload(release, releaseHolder, dryrun);
case "--hangar" -> future = new HangarVersionUploader().performUpload(release, releaseHolder, dryrun);
case "--all" -> {
modrinthRelease = new ModrinthRelease();
future = CompletableFuture.allOf(
new ModrinthVersionUploader().performUpload(release, modrinthRelease, dryrun),
new HangarVersionUploader().performUpload(release, dryrun)
new ModrinthVersionUploader().performUpload(release, releaseHolder, dryrun),
new HangarVersionUploader().performUpload(release, releaseHolder, dryrun)
);
}
default -> {
LOGGER.warn("Unknown argument '{}' provided. Supported are '--all', '--modrinth' or '--hangar'", args[0]);
LOGGER.warn("Unknown argument '{}' provided.", args[0]);
LOGGER.warn("COMMAND USAGE: java -jar VersionUploader.jar [--dryrun] --all | --modrinth | --hangar");
System.exit(1);
return;
}
@@ -111,8 +108,8 @@ public class VersionUploader{
System.exit(1);
}
if(modrinthRelease == null || modrinthRelease.getReleases().isEmpty()){
LOGGER.warn("No Modrinth release info on Discord to share... Skipping.");
if(releaseHolder.getReleases().isEmpty()){
LOGGER.warn("No releases to share on Discord... Skipping.");
return;
}
@@ -124,17 +121,31 @@ public class VersionUploader{
WebhookEmbedBuilder builder = new WebhookEmbedBuilder()
.setTitle(new WebhookEmbed.EmbedTitle("New Release", null))
.setDescription("A new release of AdvancedServerList is available on Modrinth for you to download!")
.setDescription("A new release of AdvancedServerList is available on Modrinth and Hangar for you to download!")
.setColor(0x1BD96A);
for(Map.Entry<String, String> entry : modrinthRelease.getReleases().entrySet()){
builder.addField(new WebhookEmbed.EmbedField(
false,
entry.getKey(),
"https://modrinth.com/plugin/advancedserverlist/version/" + entry.getValue()
));
StringJoiner modrinthText = new StringJoiner("\n");
String hangarText = null;
for(ReleaseHolder.ReleaseInfo info : releaseHolder.getReleases()){
String text = String.format("[%s](%s)", info.platform(), info.url());
if(info.type().equalsIgnoreCase("modrinth")){
modrinthText.add(text);
}else{
hangarText = text;
}
}
builder.addField(new WebhookEmbed.EmbedField(
true,
"Modrinth:",
modrinthText.toString()
)).addField(new WebhookEmbed.EmbedField(
true,
"Hangar:",
hangarText == null ? "No download available" : hangarText
));
try(WebhookClient client = new WebhookClientBuilder(webhookUrl).build()){
CompletableFuture<ReadonlyMessage> webhookFuture = client.send(builder.build()).whenComplete((readonlyMessage, throwable) -> {
if(throwable != null){
@@ -26,6 +26,7 @@
package ch.andre601.advancedserverlist.versionuploader.hangar;
import ch.andre601.advancedserverlist.versionuploader.PlatformInfo;
import ch.andre601.advancedserverlist.versionuploader.ReleaseHolder;
import ch.andre601.advancedserverlist.versionuploader.VersionUploader;
import ch.andre601.advancedserverlist.versionuploader.data.CodebergRelease;
import ch.andre601.advancedserverlist.versionuploader.hangar.version.Dependency;
@@ -35,6 +36,7 @@ import ch.andre601.advancedserverlist.versionuploader.hangar.version.Version;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.FileBody;
@@ -72,7 +74,7 @@ public class HangarVersionUploader{
this.apiKey = System.getenv("HANGAR_API_TOKEN");
}
public CompletableFuture<?> performUpload(CodebergRelease release, boolean dryrun){
public CompletableFuture<?> performUpload(CodebergRelease release, ReleaseHolder releaseInfo, boolean dryrun){
LOGGER.info("Starting HangarVersionUploader...");
if((apiKey == null || apiKey.isEmpty()) && !dryrun){
@@ -145,14 +147,14 @@ public class HangarVersionUploader{
try{
HttpClient client = HttpClients.createDefault();
return uploadVersion(client, versionUpload, filePaths);
return uploadVersion(client, versionUpload, filePaths, releaseInfo);
}catch(ParseException | IOException ex){
LOGGER.warn("Encountered an exception while uploading to Hangar!", ex);
return CompletableFuture.completedFuture(ex);
}
}
private CompletableFuture<?> uploadVersion(HttpClient client, Version versionUpload, List<Path> filePaths) throws IOException, ParseException{
private CompletableFuture<?> uploadVersion(HttpClient client, Version versionUpload, List<Path> filePaths, ReleaseHolder releaseInfo) throws IOException, ParseException{
return CompletableFuture.supplyAsync(() -> {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("versionUpload", new StringBody(GSON.toJson(versionUpload), ContentType.APPLICATION_JSON));
@@ -174,7 +176,22 @@ public class HangarVersionUploader{
));
}
LOGGER.info("Successfully uploaded new release on Hangar!");
return true;
String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
try{
JsonObject json = GSON.fromJson(body, JsonObject.class);
if(json == null)
return true;
releaseInfo.addRelease(
"hangar",
"Paper, Waterfall, Velocity",
json.getAsJsonPrimitive("url").getAsString()
);
return true;
}catch(JsonSyntaxException ex){
return true;
}
});
}catch(IOException ex){
LOGGER.warn("Encountered IOException while perfoming upload.", ex);
@@ -25,7 +25,7 @@
package ch.andre601.advancedserverlist.versionuploader.modrinth;
import ch.andre601.advancedserverlist.versionuploader.ModrinthRelease;
import ch.andre601.advancedserverlist.versionuploader.ReleaseHolder;
import ch.andre601.advancedserverlist.versionuploader.PlatformInfo;
import ch.andre601.advancedserverlist.versionuploader.VersionUploader;
import ch.andre601.advancedserverlist.versionuploader.data.CodebergRelease;
@@ -45,7 +45,9 @@ import java.util.concurrent.CompletableFuture;
public class ModrinthVersionUploader{
private static final Logger LOGGER = LoggerFactory.getLogger(ModrinthVersionUploader.class);
private final Logger logger = LoggerFactory.getLogger(ModrinthVersionUploader.class);
private final String versionUrl = "https://modrinth.com/plugin/advancedserverlist/version/";
private final List<PlatformInfo> platforms = List.of(
PlatformInfo.PAPER,
@@ -62,11 +64,11 @@ public class ModrinthVersionUploader{
this.api = createClient();
}
public CompletableFuture<?> performUpload(CodebergRelease release, ModrinthRelease modrinthRelease, boolean dryrun){
LOGGER.info("Starting ModrinthVersionUploader...");
public CompletableFuture<?> performUpload(CodebergRelease release, ReleaseHolder releaseHolder, boolean dryrun){
logger.info("Starting ModrinthVersionUploader...");
if(api == null){
LOGGER.warn("Cannot create updates on Modrinth. API instance is null.");
logger.warn("Cannot create updates on Modrinth. API instance is null.");
return CompletableFuture.completedFuture(false);
}
@@ -74,7 +76,7 @@ public class ModrinthVersionUploader{
final String pluginVersion = VersionUploader.retrieveVersion();
if(pluginVersion == null || pluginVersion.isEmpty()){
LOGGER.warn("Retrieved null/empty plugin version.");
logger.warn("Retrieved null/empty plugin version.");
return CompletableFuture.completedFuture(false);
}
@@ -97,7 +99,7 @@ public class ModrinthVersionUploader{
);
for(int i = 0; i < platforms.size(); i++){
LOGGER.info("Creating release for platform {}...", platforms.get(i).getPlatform());
logger.info("Creating release for platform {}...", platforms.get(i).getPlatform());
List<File> files = platforms.get(i).getFilePaths().stream()
.map(path -> new File(path.replace("{{version}}", pluginVersion)))
@@ -125,7 +127,7 @@ public class ModrinthVersionUploader{
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(builder.build());
LOGGER.info("JSON Data to send: {}", json);
logger.info("JSON Data to send: {}", json);
futures[i] = CompletableFuture.completedFuture(json);
continue;
@@ -134,14 +136,20 @@ public class ModrinthVersionUploader{
final int index = i;
futures[i] = api.versions().createProjectVersion(builder.build()).whenComplete(((projectVersion, throwable) -> {
if(throwable != null){
LOGGER.warn("Encountered an exception while uploading a new release to Modrinth!", throwable);
logger.warn("Encountered an exception while uploading a new release to Modrinth!", throwable);
return;
}
LOGGER.info("Created new release!");
LOGGER.info("Link: https://modrinth.com/plugin/advancedserverlist/version/{}", projectVersion.getId());
String url = versionUrl + projectVersion.getId();
modrinthRelease.addRelease(String.join(", ", platforms.get(index).getLoaders()), projectVersion.getId());
logger.info("Created new release!");
logger.info("Link: {}", url);
releaseHolder.addRelease(
"modrinth",
String.join(", ", platforms.get(index).getPlatformNames()),
url
);
}));
}