fix(config): keep server/forced-host defaults empty in code

Move the example servers, try order, and forced hosts out of the model's
field defaults and into default-velocity.yml only. Previously, removing a
section caused the loader to substitute the bundled examples, which reference
servers the user may not have and then fail validation. With empty code
defaults, a removed or emptied section now yields an empty collection and the
examples are seeded solely on first-start from the documented default file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Shane Freeder
2026-06-17 21:46:38 +01:00
parent cf4580f159
commit 0a090c8bb3
3 changed files with 30 additions and 12 deletions

View File

@@ -259,7 +259,7 @@ public final class ConfigurationLoader {
public VelocityConfiguration.Servers deserialize(final Type type, final ConfigurationNode node) public VelocityConfiguration.Servers deserialize(final Type type, final ConfigurationNode node)
throws SerializationException { throws SerializationException {
final Map<String, String> servers = new LinkedHashMap<>(); final Map<String, String> servers = new LinkedHashMap<>();
List<String> attemptConnectionOrder = ImmutableList.of("lobby"); List<String> attemptConnectionOrder = ImmutableList.of();
for (final Map.Entry<Object, ? extends ConfigurationNode> entry for (final Map.Entry<Object, ? extends ConfigurationNode> entry
: node.childrenMap().entrySet()) { : node.childrenMap().entrySet()) {
final String key = entry.getKey().toString(); final String key = entry.getKey().toString();

View File

@@ -472,12 +472,11 @@ public class VelocityConfiguration implements ProxyConfig {
static class Servers { static class Servers {
private Map<String, String> servers = ImmutableMap.of( // Example entries live in default-velocity.yml, not here: the code default must stay empty so
"lobby", "127.0.0.1:30066", // that a user who removes the section gets an empty map rather than resurrected examples that
"factions", "127.0.0.1:30067", // reference servers they no longer have.
"minigames", "127.0.0.1:30068" private Map<String, String> servers = ImmutableMap.of();
); private List<String> attemptConnectionOrder = ImmutableList.of();
private List<String> attemptConnectionOrder = ImmutableList.of("lobby");
Servers() { Servers() {
} }
@@ -526,11 +525,10 @@ public class VelocityConfiguration implements ProxyConfig {
static class ForcedHosts { static class ForcedHosts {
private Map<String, List<String>> forcedHosts = ImmutableMap.of( // Example entries live in default-velocity.yml, not here: the code default must stay empty so
"lobby.example.com", ImmutableList.of("lobby"), // that removing the section yields no forced hosts rather than examples pointing at servers the
"factions.example.com", ImmutableList.of("factions"), // user does not have (which would fail validation).
"minigames.example.com", ImmutableList.of("minigames") private Map<String, List<String>> forcedHosts = ImmutableMap.of();
);
ForcedHosts() { ForcedHosts() {
} }

View File

@@ -179,6 +179,26 @@ class ConfigurationLoaderTest {
assertEquals(secret.toString(), node.node("forwarding-secret-file").getString()); assertEquals(secret.toString(), node.node("forwarding-secret-file").getString());
} }
/**
* Removing the {@code forced-hosts}/{@code try} sections must leave them empty rather than
* resurrecting the bundled example entries, which would reference servers the user does not have
* and fail validation.
*/
@Test
void removedSectionsDoNotResurrectDefaults(@TempDir final Path dir) throws IOException {
final Path path = dir.resolve("velocity.yml");
Files.writeString(path, """
servers:
only: "1.2.3.4:25565"
""", StandardCharsets.UTF_8);
final VelocityConfiguration config = ConfigurationLoader.load(path);
assertEquals(ImmutableMap.of("only", "1.2.3.4:25565"), config.getServers());
assertTrue(config.getForcedHosts().isEmpty());
assertTrue(config.getAttemptConnectionOrder().isEmpty());
}
private static void assertConfig(final VelocityConfiguration config) { private static void assertConfig(final VelocityConfiguration config) {
assertEquals(123, config.getShowMaxPlayers()); assertEquals(123, config.getShowMaxPlayers());
assertFalse(config.isOnlineMode()); assertFalse(config.isOnlineMode());