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
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2018-2025 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/

package com.velocitypowered.api.proxy.config;

import static java.util.Objects.requireNonNull;

import com.velocitypowered.api.proxy.server.ServerInfoForwardingMode;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* Exposes server configuration information that plugins may use.<br>
*
* <b>What's the forwarding mode?</b><br>
* The server can use a different mode to obtain and forward player info.<br>
* For instance, if you are running a 1.12 (or lower version) server on a velocity proxy with MODERN player info forwarding
* the server doesn't support MODERN forwarding. So you need to set LEGACY forwarding mode for that server
* and velocity will use ONLY FOR THAT SERVER the legacy forwarding mode.<br><br>
* If the forwarding mode is null it means that the server is using the "player-info-forwarding-mode", set in the config.
*
* @param address The address of the backend server.
* @param forwardingMode The forwarding mode of the backend server.
* @since 3.4.0
* @see ServerInfoForwardingMode
* @see com.velocitypowered.api.proxy.server.ServerInfo#ServerInfo(String, java.net.InetSocketAddress, ServerInfoForwardingMode)
* @apiNote <i><b>TIP:</b> If you need to set this value when creating dynamic servers in your plugins
* you can do that by adding the {@link ServerInfoForwardingMode} value as the last parameter
* while creating a new {@link com.velocitypowered.api.proxy.server.ServerInfo}.</i>
*/
@NullMarked
public record BackendServerConfig(
String address,
@Nullable ServerInfoForwardingMode forwardingMode
) {
public BackendServerConfig {
requireNonNull(address);
}

public BackendServerConfig(final String address) {
this(address, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,23 @@ public interface ProxyConfig {
* does. For a view of all registered servers, see {@link ProxyServer#getAllServers()}.
*
* @return registered servers map
* @deprecated use {@link #getBackendServers()} instead.
*/
@Deprecated(forRemoval = true, since = "3.4.0")
Map<String, String> getServers();

/**
* Get a Map of all servers registered in <code>velocity.toml</code>. This method does
* <strong>not</strong> return all the servers currently in memory, although in most cases it
* does. For a view of all registered servers, see {@link ProxyServer#getAllServers()}.
*
* @return registered servers map with, instead of the only address, the Backend Server Object for each
* of them which contains the address of the server and its info forwarding mode.
* @since 3.4.0
* @see com.velocitypowered.api.proxy.server.ServerInfoForwardingMode
*/
Map<String, BackendServerConfig> getBackendServers();

/**
* Get the order of servers that players will be connected to.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ public final class ServerInfo implements Comparable<ServerInfo> {
private final String name;
private final InetSocketAddress address;

@Nullable
private final ServerInfoForwardingMode forwardingMode;

/**
* Creates a new ServerInfo object.
*
* @param name the name for the server
* @param address the address of the server to connect to
* @param forwardingMode the server info forwarding mode, or {@code null} if the mode from the config should be used
* @since 3.4.0
*/
public ServerInfo(String name, InetSocketAddress address, @Nullable ServerInfoForwardingMode forwardingMode) {
this.name = Preconditions.checkNotNull(name, "name");
this.address = Preconditions.checkNotNull(address, "address");
this.forwardingMode = forwardingMode;
}

/**
* Creates a new ServerInfo object.
*
Expand All @@ -30,6 +47,7 @@ public final class ServerInfo implements Comparable<ServerInfo> {
public ServerInfo(String name, InetSocketAddress address) {
this.name = Preconditions.checkNotNull(name, "name");
this.address = Preconditions.checkNotNull(address, "address");
this.forwardingMode = null;
}

public final String getName() {
Expand All @@ -40,11 +58,23 @@ public final InetSocketAddress getAddress() {
return address;
}

/**
* Returns the forwarding mode used by the backend server to communicate with Velocity.
*
* @return the configured forwarding mode for the server, or {@code null}
* if the mode is inherited from the "player-info-forwarding-mode" set in the config
*/
@Nullable
public final ServerInfoForwardingMode getServerInfoForwardingMode() {
return forwardingMode;
}

@Override
public String toString() {
return "ServerInfo{"
+ "name='" + name + '\''
+ ", address=" + address
+ ", forwarding=" + forwardingMode
+ '}';
}

Expand All @@ -53,17 +83,17 @@ public final boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
if (!(o instanceof final ServerInfo that)) {
return false;
}
ServerInfo that = (ServerInfo) o;
return Objects.equals(name, that.name)
&& Objects.equals(address, that.address);
&& Objects.equals(address, that.address)
&& Objects.equals(forwardingMode, that.forwardingMode);
}

@Override
public final int hashCode() {
return Objects.hash(name, address);
return Objects.hash(name, address, forwardingMode);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2018-2025 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/

package com.velocitypowered.api.proxy.server;

/**
* Supported per-server player info forwarding methods.
*
* @since 3.4.0
*/
public enum ServerInfoForwardingMode {
MODERN,
BUNGEEGUARD,
LEGACY,
NONE
}

23 changes: 18 additions & 5 deletions proxy/src/main/java/com/velocitypowered/proxy/ProxyOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.velocitypowered.proxy;

import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.api.proxy.server.ServerInfoForwardingMode;
import com.velocitypowered.proxy.util.AddressUtil;
import java.io.IOException;
import java.net.InetSocketAddress;
Expand Down Expand Up @@ -105,17 +106,29 @@ private static class ServerInfoConverter implements ValueConverter<ServerInfo> {

@Override
public ServerInfo convert(String s) {
String[] split = s.split(":", 2);
String[] split = s.split(":", 4);
if (split.length < 2) {
throw new ValueConversionException("Invalid server format. Use <name>:<address>");
throw new ValueConversionException("Invalid server format. Use <name>:<host>:[port]:[forwardingmode]");
}
InetSocketAddress address;
ServerInfoForwardingMode mode = null;
try {
address = AddressUtil.parseAddress(split[1]);
if (split.length >= 3) {
address = AddressUtil.parseAddress(split[1] + ":" + split[2]);
} else {
address = AddressUtil.parseAddress(split[1]);
}
} catch (IllegalStateException e) {
throw new ValueConversionException("Invalid hostname for server flag with name: " + split[0]);
}
return new ServerInfo(split[0], address);
if (split.length == 4) {
try {
mode = ServerInfoForwardingMode.valueOf(split[3].toUpperCase());
} catch (IllegalArgumentException e) {
throw new ValueConversionException("Invalid forwarding mode for server flag with name: " + split[0]);
}
}
return new ServerInfo(split[0], address, mode);
}

@Override
Expand All @@ -125,7 +138,7 @@ public Class<? extends ServerInfo> valueType() {

@Override
public String valuePattern() {
return "name>:<address";
return "name>:<host>:[port]:[forwardingmode]";
}
}
}
17 changes: 13 additions & 4 deletions proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.velocitypowered.api.plugin.PluginManager;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.config.BackendServerConfig;
import com.velocitypowered.api.proxy.player.ResourcePackInfo;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
Expand Down Expand Up @@ -297,8 +298,12 @@ void start() {
}

if (!options.isIgnoreConfigServers()) {
for (Map.Entry<String, String> entry : configuration.getServers().entrySet()) {
servers.register(new ServerInfo(entry.getKey(), AddressUtil.parseAddress(entry.getValue())));
for (Map.Entry<String, BackendServerConfig> entry : configuration.getBackendServers().entrySet()) {
servers.register(new ServerInfo(
entry.getKey(),
AddressUtil.parseAddress(entry.getValue().address()),
entry.getValue().forwardingMode())
);
}
}

Expand Down Expand Up @@ -489,8 +494,12 @@ public boolean reloadConfiguration() throws IOException {
// Re-register servers. If a server is being replaced, make sure to note what players need to
// move back to a fallback server.
Collection<ConnectedPlayer> evacuate = new ArrayList<>();
for (Map.Entry<String, String> entry : newConfiguration.getServers().entrySet()) {
ServerInfo newInfo = new ServerInfo(entry.getKey(), AddressUtil.parseAddress(entry.getValue()));
for (Map.Entry<String, BackendServerConfig> entry : newConfiguration.getBackendServers().entrySet()) {
ServerInfo newInfo = new ServerInfo(
entry.getKey(),
AddressUtil.parseAddress(entry.getValue().address()),
entry.getValue().forwardingMode()
);
Optional<RegisteredServer> rs = servers.getServer(entry.getKey());
if (rs.isEmpty()) {
servers.register(newInfo);
Expand Down
Loading