Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding more options for configuring ping passthrough. #1290

Open
wants to merge 14 commits into
base: dev/3.0.0
Choose a base branch
from
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 @@ -18,11 +18,36 @@
package com.velocitypowered.proxy.config;

/**
* Supported passthrough modes for ping passthrough.
* Object to contain all of the things that can be toggled for ping passthrough.
*/
public enum PingPassthroughMode {
DISABLED,
MODS,
DESCRIPTION,
ALL
public class PingPassthroughMode {
public boolean version;
public boolean players;
public boolean description;
public boolean favicon;
public boolean modinfo;

/**
* Passthrough mode constructor.
* Looking at other code, I'm not sure the constructor is supposed to need a javadoc style comment,
* but checkstyle was yelling at me because I didn't include one.
* Probably for the best.
*
* @param version whether the version should be passed through.
* @param players whether the player count should be passed through.
* @param description whether the description should be passed through.
* @param favicon whether the favicon should be passed through.
* @param modinfo whether the modinfo should be passed through.
*/
public PingPassthroughMode(boolean version, boolean players, boolean description, boolean favicon, boolean modinfo) {
this.version = version;
this.players = players;
this.description = description;
this.favicon = favicon;
this.modinfo = modinfo;
}

public boolean enabled() {
return this.version || this.players || this.description || this.favicon || this.modinfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class VelocityConfiguration implements ProxyConfig {
@Expose
private boolean onlineModeKickExistingPlayers = false;
@Expose
private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
private PingPassthroughMode pingPassthrough = new PingPassthroughMode(false, false, false, false, false);
private final Servers servers;
private final ForcedHosts forcedHosts;
@Expose
Expand Down Expand Up @@ -500,9 +500,14 @@ public static VelocityConfiguration read(Path path) throws IOException {
final CommentedConfig metricsConfig = config.get("metrics");
final PlayerInfoForwarding forwardingMode = config.getEnumOrElse(
"player-info-forwarding-mode", PlayerInfoForwarding.NONE);
final PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
PingPassthroughMode.DISABLED);

// final PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
// PingPassthroughMode.DISABLED);
final PingPassthroughMode pingPassthrough = new PingPassthroughMode(
config.getOrElse("ping-passthrough-version", false),
config.getOrElse("ping-passthrough-players", false),
config.getOrElse("ping-passthrough-description", false),
config.getOrElse("ping-passthrough-favicon", false),
config.getOrElse("ping-passthrough-modinfo", false));
final String bind = config.getOrElse("bind", "0.0.0.0:25577");
final int maxPlayers = config.getIntOrElse("show-max-players", 500);
final boolean onlineMode = config.getOrElse("online-mode", true);
Expand Down Expand Up @@ -532,7 +537,7 @@ public static VelocityConfiguration read(Path path) throws IOException {
forwardingMode,
forwardingSecret,
kickExisting,
pingPassthroughMode,
pingPassthrough,
enablePlayerAddressLogging,
new Servers(serversConfig),
new ForcedHosts(forcedHostsConfig),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.velocitypowered.api.proxy.server.PingOptions;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.api.util.ModInfo;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.config.PingPassthroughMode;
Expand Down Expand Up @@ -81,58 +82,62 @@ private CompletableFuture<ServerPing> attemptPingPassthrough(VelocityInboundConn

CompletableFuture<List<ServerPing>> pingResponses = CompletableFutures.successfulAsList(pings,
(ex) -> fallback);
switch (mode) {
case ALL:
return pingResponses.thenApply(responses -> {
// Find the first non-fallback
for (ServerPing response : responses) {
if (response == fallback) {
continue;
}
return response;
}
return fallback;
});
case MODS:
return pingResponses.thenApply(responses -> {
// Find the first non-fallback that contains a mod list
for (ServerPing response : responses) {
if (response == fallback) {
continue;
}
Optional<ModInfo> modInfo = response.getModinfo();
if (modInfo.isPresent()) {
return fallback.asBuilder().mods(modInfo.get()).build();
}
}
return fallback;
});
case DESCRIPTION:
return pingResponses.thenApply(responses -> {
// Find the first non-fallback. If it includes a modlist, add it too.
for (ServerPing response : responses) {
if (response == fallback) {
continue;
}

if (response.getDescriptionComponent() == null) {
continue;
}

return new ServerPing(
fallback.getVersion(),
fallback.getPlayers().orElse(null),
response.getDescriptionComponent(),
fallback.getFavicon().orElse(null),
response.getModinfo().orElse(null)
);
}
return fallback;
});
// Not possible, but covered for completeness.
default:
return CompletableFuture.completedFuture(fallback);
}
return pingResponses.thenApply(responses -> {
// Find the first non-fallback. If it includes a modlist, add it too.
for (ServerPing response : responses) {
if (response == fallback) {
continue;
}

if (response.getDescriptionComponent() == null) {
continue;
}

ServerPing.Version version;
if (mode.version) {
version = response.getVersion();
} else {
version = fallback.getVersion();
}

ServerPing.Players players;
if (mode.players) {
players = response.getPlayers().orElse(null);
} else {
players = fallback.getPlayers().orElse(null);
}

net.kyori.adventure.text.Component description;
if (mode.description) {
description = response.getDescriptionComponent();
} else {
description = fallback.getDescriptionComponent();
}

Favicon favicon;
if (mode.favicon) {
favicon = response.getFavicon().orElse(null);
} else {
favicon = fallback.getFavicon().orElse(null);
}

ModInfo modinfo;
if (mode.modinfo) {
modinfo = response.getModinfo().orElse(null);
} else {
modinfo = fallback.getModinfo().orElse(null);
}

return new ServerPing(
version,
players,
description,
favicon,
modinfo
);
}
return fallback;
});
}

/**
Expand All @@ -147,7 +152,7 @@ public CompletableFuture<ServerPing> getInitialPing(VelocityInboundConnection co
? connection.getProtocolVersion() : ProtocolVersion.MAXIMUM_VERSION;
PingPassthroughMode passthroughMode = configuration.getPingPassthrough();

if (passthroughMode == PingPassthroughMode.DISABLED) {
if (!passthroughMode.enabled()) {
return CompletableFuture.completedFuture(constructLocalPing(shownVersion));
} else {
String virtualHostStr = connection.getVirtualHost().map(InetSocketAddress::getHostString)
Expand Down
31 changes: 17 additions & 14 deletions proxy/src/main/resources/default-velocity.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,23 @@ announce-forge = false
# any existing player who is online if a duplicate connection attempt is made.
kick-existing-players = false

# Should Velocity pass server list ping requests to a backend server?
# Available options:
# - "disabled": No pass-through will be done. The velocity.toml and server-icon.png
# will determine the initial server list ping response.
# - "mods": Passes only the mod list from your backend server into the response.
# The first server in your try list (or forced host) with a mod list will be
# used. If no backend servers can be contacted, Velocity won't display any
# mod information.
# - "description": Uses the description and mod list from the backend server. The first
# server in the try (or forced host) list that responds is used for the
# description and mod list.
# - "all": Uses the backend server's response as the proxy response. The Velocity
# configuration is used if no servers could be contacted.
ping-passthrough = "DISABLED"
# For the below options, the backend server Velocity contacts will be the first server that responds in the try list (or the forced host).
# If no servers can be contacted, the Velocity configuration will be used instead.

# Should Velocity send the version number from the backend server when responding to server list ping requests?
ping-passthrough-version = false

# Should Velocity send the player count from the backend server when responding to server list ping requests?
ping-passthrough-players = false

# Should Velocity send the description from the backend server when responding to server list ping requests?
ping-passthrough-description = false

# Should Velocity send the favicon (also known as the server icon) from the backend server when responding to server list ping requests?
ping-passthrough-favicon = false

# Should Velocity send the mod list from the backend server when responding to server list ping requests?
ping-passthrough-modinfo = false

# If not enabled (default is true) player IP addresses will be replaced by <ip address withheld> in logs
enable-player-address-logging = true
Expand Down