Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import net.kyori.adventure.text.Component;

/**
* Exposes certain proxy configuration information that plugins may use.
Expand Down Expand Up @@ -47,11 +48,11 @@ public interface ProxyConfig {
boolean shouldQueryShowPlugins();

/**
* Get the MOTD component shown in the tab list.
* Get the MOTD component shown in the tab list and the server list ping response.
*
* @return the motd component
*/
net.kyori.adventure.text.Component getMotd();
Component getMotd();

/**
* Get the maximum players shown in the tab list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.velocitypowered.proxy.config.migration.KeyAuthenticationMigration;
import com.velocitypowered.proxy.config.migration.MiniMessageTranslationsMigration;
import com.velocitypowered.proxy.config.migration.MotdMigration;
import com.velocitypowered.proxy.config.migration.MotdMultilineMigration;
import com.velocitypowered.proxy.config.migration.PacketLimiterMigration;
import com.velocitypowered.proxy.config.migration.TransferIntegrationMigration;
import com.velocitypowered.proxy.util.AddressUtil;
Expand All @@ -48,6 +49,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -64,7 +66,7 @@ public class VelocityConfiguration implements ProxyConfig {
@Expose
private String bind = "0.0.0.0:25565";
@Expose
private String motd = "<aqua>A Velocity Server";
private List<String> motd = ImmutableList.of("<aqua>A Velocity Server");
@Expose
private int showMaxPlayers = 500;
@Expose
Expand All @@ -91,7 +93,7 @@ public class VelocityConfiguration implements ProxyConfig {
private final Metrics metrics;
@Expose
private boolean enablePlayerAddressLogging = true;
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
private @MonotonicNonNull Component motdAsComponent;
private @Nullable Favicon favicon;
@Expose
private boolean forceKeyAuthentication = true; // Added in 1.19
Expand All @@ -107,7 +109,7 @@ private VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced
this.metrics = metrics;
}

private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
private VelocityConfiguration(String bind, List<String> motd, int showMaxPlayers, boolean onlineMode,
boolean preventClientProxyConnections, boolean announceForge,
PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret,
boolean onlineModeKickExistingPlayers, PingPassthroughMode pingPassthrough,
Expand Down Expand Up @@ -282,9 +284,12 @@ public boolean shouldQueryShowPlugins() {
}

@Override
public net.kyori.adventure.text.Component getMotd() {
public Component getMotd() {
if (motdAsComponent == null) {
motdAsComponent = MiniMessage.miniMessage().deserialize(motd);
motdAsComponent = motd.stream()
.map(MiniMessage.miniMessage()::deserialize)
.reduce((a, b) -> a.appendNewline().append(b))
.orElseGet(Component::empty);
}
return motdAsComponent;
}
Expand Down Expand Up @@ -513,7 +518,8 @@ public static VelocityConfiguration read(Path path) throws IOException {
new MotdMigration(),
new MiniMessageTranslationsMigration(),
new TransferIntegrationMigration(),
new PacketLimiterMigration()
new PacketLimiterMigration(),
new MotdMultilineMigration()
};

for (final ConfigurationMigration migration : migrations) {
Expand Down Expand Up @@ -545,7 +551,7 @@ public static VelocityConfiguration read(Path path) throws IOException {
}
}
final byte[] forwardingSecret = forwardingSecretString.getBytes(StandardCharsets.UTF_8);
final String motd = config.getOrElse("motd", "<#09add3>A Velocity Server");
final List<String> motd = config.getOrElse("motd", ImmutableList.of("<#09add3>A Velocity Server"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to add a validation check in case someone tries to add more than 2 lines


// Read the rest of the config
final CommentedConfig serversConfig = config.get("servers");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public sealed interface ConfigurationMigration
MotdMigration,
MiniMessageTranslationsMigration,
TransferIntegrationMigration,
PacketLimiterMigration {
PacketLimiterMigration,
MotdMultilineMigration {
boolean shouldMigrate(CommentedFileConfig config);

void migrate(CommentedFileConfig config, Logger logger) throws IOException;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2026 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.velocitypowered.proxy.config.migration;

import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import java.util.List;
import org.apache.logging.log4j.Logger;

/**
* Migrates a single string motd to a multiline (string list) motd.
*/
public final class MotdMultilineMigration implements ConfigurationMigration {

@Override
public boolean shouldMigrate(CommentedFileConfig config) {
return configVersion(config) < 2.9;
}

@Override
public void migrate(CommentedFileConfig config, Logger logger) {
String motd = config.get("motd");
config.set("motd", List.of(motd));

config.set("config-version", "2.9");
Comment on lines +36 to +39

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the migration will only happen once, it might be a good idea to migrate the use of \n or <newline>/<br> to a new line in the configuration

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, though it'll be best-effort and we probably dont want to match every case. Splitting on those 3 delimiters seems reasonable (case insensitive) but afaik minimessage also supports self-closing tags (?), possibly spaces between the tag name and the self-closing /. Emulating the minimessage parsing engine seems out of scope, and deserializing+serializing would be too intrusive imo.

}
}
6 changes: 4 additions & 2 deletions proxy/src/main/resources/default-velocity.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Config version. Do not change this
config-version = "2.8"
config-version = "2.9"

# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25565.
bind = "0.0.0.0:25565"

# What should be the MOTD? This gets displayed when the player adds your server to
# their server list. Only MiniMessage format is accepted.
motd = "<#09add3>A Velocity Server"
motd = [
"<#09add3>A Velocity Server"
]

# What should we display for the maximum number of players? (Velocity does not support a cap
# on the number of players online.)
Expand Down