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

Switch config system to Configurate #5010

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
25e7deb
Start implementing Configurate config system
Camotoy May 23, 2024
dedb592
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy May 26, 2024
a135d3c
More development
Camotoy May 27, 2024
25a755f
Start migrating to Gson only
Camotoy May 27, 2024
10bf4ee
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Jun 15, 2024
cb4c5ad
Progress
Camotoy Jun 15, 2024
528de86
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Jun 24, 2024
8d24891
Update usage of WebUtils
Camotoy Jun 24, 2024
2d33cfd
Most things now use Gson for JSON
Camotoy Jun 26, 2024
0dadbc2
Allow tests to succeed by using new Gson version
Camotoy Jun 26, 2024
7eb5b53
Use slightly cleaner version for Version deserializer
Camotoy Jun 26, 2024
360350d
Work around older Gson versions without record support
Camotoy Jun 26, 2024
add02ca
GeyserCustomSkullConfiguration uses Configurate
Camotoy Jun 27, 2024
db9b951
Fix regression in properties get
Camotoy Jun 27, 2024
29f8e29
New config used in core
Camotoy Jul 6, 2024
c095c27
The configuration is gone. Long live the config.
Camotoy Jul 7, 2024
ab4cc97
More changes and migrations away from Jackson
Camotoy Jul 9, 2024
76ca326
Improve node ordering when updating configs
Konicai Aug 9, 2024
0952f79
typo
Konicai Aug 9, 2024
e506c14
Better check for ignoring non-configurate configs for considering com…
Konicai Aug 9, 2024
f7a677e
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Aug 21, 2024
85d63de
Merge pull request #4954 from Konicai/feature/configurate
Camotoy Aug 21, 2024
d9d78cd
Ensure metrics UUID is valid
Camotoy Aug 22, 2024
f113c89
Initial advanced config
Camotoy Aug 24, 2024
5870856
Remove Jackson; finish config value placements
Camotoy Aug 29, 2024
c4c8808
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Sep 1, 2024
f40cbca
Remove duplicate relocate declarations
Camotoy Sep 1, 2024
a2e9e70
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Sep 9, 2024
a6c21b1
Let annotations work
Camotoy Sep 10, 2024
b719278
Renaming to PluginSpecific
Camotoy Sep 10, 2024
1271505
Use global bStats config where possible
Camotoy Sep 12, 2024
e99759d
Fix test
Camotoy Sep 12, 2024
5551169
Re-introduce asterisk behavior in configs
Camotoy Sep 13, 2024
45f8baf
Remove GeyserPluginBootstrap as it's no longer necessary
Camotoy Sep 22, 2024
adee6a7
Remove old config.yml file
Camotoy Sep 22, 2024
869f7a8
Update Xbox achievement comment
Camotoy Sep 22, 2024
2034ffa
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Sep 23, 2024
3448c2f
Apply suggestions from code review
Camotoy Sep 23, 2024
d03e661
Merge branch 'feature/configurate' of https://github.com/GeyserMC/Gey…
Camotoy Sep 23, 2024
2ee488d
No need to remove values anymore
Camotoy Sep 23, 2024
a44edb3
Fix: disable bstats relocation on platforms where it is not needed
onebeastchris Sep 24, 2024
02a361e
ensure it builds
onebeastchris Sep 24, 2024
0d9b20a
Update custom unavailable slot comment
Camotoy Sep 24, 2024
bfd032d
Update cooldown image
Camotoy Sep 25, 2024
fc10ec2
Logger message for direct-compression still being enabled
Camotoy Sep 25, 2024
f42ee7d
Merge branch 'master' into feature/configurate
Camotoy Sep 25, 2024
8b43498
oops
Camotoy Sep 25, 2024
0a62562
More explicit RuntimeException message
Camotoy Sep 26, 2024
c4bed65
Constant for 'system' locale
Camotoy Sep 26, 2024
b2ea579
Better config JSON encoding (something is broken with Cloudflare; we'…
Camotoy Sep 26, 2024
c427630
Fix broadcast port default
Camotoy Oct 8, 2024
6c5c451
Merge branch 'master' of https://github.com/GeyserMC/Geyser into feat…
Camotoy Nov 19, 2024
8b51883
Add this file too
Camotoy Nov 19, 2024
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
5 changes: 3 additions & 2 deletions bootstrap/bungeecord/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ dependencies {
}

platformRelocate("net.md_5.bungee.jni")
platformRelocate("com.fasterxml.jackson")
platformRelocate("io.netty.channel.kqueue") // This is not used because relocating breaks natives, but we must include it or else we get ClassDefNotFound
platformRelocate("net.kyori")
platformRelocate("org.incendo")
platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated
platformRelocate("io.leangen.geantyref") // provided by cloud and Configurate, should also be relocated
platformRelocate("org.yaml") // Broken as of 1.20
platformRelocate("org.spongepowered")
platformRelocate("org.bstats")

// These dependencies are already present on the platform
provided(libs.bungeecord.proxy)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* 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.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.platform.bungeecord;

import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import org.geysermc.geyser.util.metrics.MetricsPlatform;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.UUID;

public final class BungeeMetrics implements MetricsPlatform {
private final Configuration configuration;

public BungeeMetrics(Plugin plugin) throws IOException {
// https://github.com/Bastian/bstats-metrics/blob/master/bungeecord/src/main/java/org/bstats/bungeecord/Metrics.java
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
//noinspection ResultOfMethodCallIgnored
bStatsFolder.mkdirs();
File configFile = new File(bStatsFolder, "config.yml");
if (!configFile.exists()) {
writeFile(configFile,
"# bStats (https://bStats.org) collects some basic information for plugin authors, like how",
"# many people use their plugin and their total player count. It's recommended to keep bStats",
"# enabled, but if you're not comfortable with this, you can turn this setting off. There is no",
"# performance penalty associated with having metrics enabled, and data sent to bStats is fully",
"# anonymous.",
"enabled: true",
"serverUuid: \"" + UUID.randomUUID() + "\"",
"logFailedRequests: false",
"logSentData: false",
"logResponseStatusText: false");
}

this.configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
}

@Override
public boolean enabled() {
return configuration.getBoolean("enabled", true);
}

@Override
public String serverUuid() {
return configuration.getString("serverUuid");
}

@Override
public boolean logFailedRequests() {
return configuration.getBoolean("logFailedRequests", false);
}

@Override
public boolean logSentData() {
return configuration.getBoolean("logSentData", false);
}

@Override
public boolean logResponseStatusText() {
return configuration.getBoolean("logResponseStatusText", false);
}

private void writeFile(File file, String... lines) throws IOException {
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
for (String line : lines) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Excepti
listenerInfo.isPingPassthrough(),
listenerInfo.getQueryPort(),
listenerInfo.isQueryEnabled(),
bootstrap.getGeyserConfig().getRemote().isUseProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
bootstrap.config().java().useProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
);

// The field that stores all listeners in BungeeCord
Expand Down Expand Up @@ -142,7 +142,7 @@ protected void initChannel(@NonNull Channel ch) throws Exception {
}
initChannel.invoke(channelInitializer, ch);

if (bootstrap.getGeyserConfig().isDisableCompression()) {
if (bootstrap.config().advanced().disableCompression()) {
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
new GeyserBungeeCompressionDisabler());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
try {
event = future.get(100, TimeUnit.MILLISECONDS);
} catch (Throwable cause) {
String address = GeyserImpl.getInstance().getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
String address = GeyserImpl.getInstance().config().logPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
GeyserImpl.getInstance().getLogger().error("Failed to get ping information for " + address, cause);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,25 @@
import net.md_5.bungee.protocol.ProtocolConstants;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.FloodgateKeyLoader;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.command.CommandSourceConverter;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.FileUtils;
import org.geysermc.geyser.util.metrics.MetricsPlatform;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bungee.BungeeCommandManager;
import org.incendo.cloud.execution.ExecutionCoordinator;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
Expand All @@ -59,13 +60,12 @@
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {

private CommandRegistry commandRegistry;
private GeyserBungeeConfiguration geyserConfig;
private GeyserPluginConfig geyserConfig;
private GeyserBungeeInjector geyserInjector;
private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger());
private IGeyserPingPassthrough geyserBungeePingPassthrough;
Expand Down Expand Up @@ -97,9 +97,7 @@ public void onGeyserInitialize() {
if (!this.loadConfig()) {
return;
}
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this);
this.geyser = GeyserImpl.load(this);
this.geyserInjector = new GeyserBungeeInjector(this);

// Registration of listeners occurs only once
Expand Down Expand Up @@ -163,13 +161,11 @@ public void onGeyserEnable() {
if (!loadConfig()) {
return;
}
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
}

// Force-disable query if enabled, or else Geyser won't enable
for (ListenerInfo info : getProxy().getConfig().getListeners()) {
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.getBedrock().port()) {
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.bedrock().port()) {
try {
Field queryField = ListenerInfo.class.getDeclaredField("queryEnabled");
queryField.setAccessible(true);
Expand All @@ -187,7 +183,7 @@ public void onGeyserEnable() {

GeyserImpl.start();

if (geyserConfig.isLegacyPingPassthrough()) {
if (!geyserConfig.integratedPingPassthrough()) {
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
} else {
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
Expand Down Expand Up @@ -224,8 +220,13 @@ public void onDisable() {
}

@Override
public GeyserBungeeConfiguration getGeyserConfig() {
return geyserConfig;
public PlatformType platformType() {
return PlatformType.BUNGEECORD;
}

@Override
public GeyserPluginConfig config() {
return this.geyserConfig;
}

@Override
Expand Down Expand Up @@ -277,11 +278,29 @@ public int getServerPort() {

@Override
public boolean testFloodgatePluginPresent() {
if (getProxy().getPluginManager().getPlugin("floodgate") != null) {
geyserConfig.loadFloodgate(this);
return true;
return getProxy().getPluginManager().getPlugin("floodgate") != null;
}

@Override
public Path getFloodgateKeyPath() {
Plugin floodgate = getProxy().getPluginManager().getPlugin("floodgate");
Path geyserDataFolder = getDataFolder().toPath();
Path floodgateDataFolder = floodgate != null ? floodgate.getDataFolder().toPath() : null;

return FloodgateKeyLoader.getKeyPath(geyserConfig, floodgateDataFolder, geyserDataFolder, geyserLogger);
}

@Override
public MetricsPlatform createMetricsPlatform() {
try {
return new BungeeMetrics(this);
} catch (IOException e) {
this.geyserLogger.debug("Integrated bStats support failed to load.");
if (this.config().debugMode()) {
e.printStackTrace();
}
return null;
}
return false;
}

private Optional<InetSocketAddress> findCompatibleListener() {
Expand All @@ -293,17 +312,7 @@ private Optional<InetSocketAddress> findCompatibleListener() {

@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean loadConfig() {
try {
if (!getDataFolder().exists()) //noinspection ResultOfMethodCallIgnored
getDataFolder().mkdir();
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
return true;
this.geyserConfig = new ConfigLoader(this).createFolder().load(GeyserPluginConfig.class);
return this.geyserConfig != null;
}
}
Comment on lines 313 to 318
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it's worth it to make this a default method in GeyserBootstrap - it's currently duplicated in every bootstrap impl

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public final class GeyserBungeeUpdateListener implements Listener {

@EventHandler
public void onPlayerJoin(final PostLoginEvent event) {
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
final ProxiedPlayer player = event.getPlayer();
if (player.hasPermission(Permissions.CHECK_UPDATE)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player));
Expand Down
3 changes: 1 addition & 2 deletions bootstrap/mod/fabric/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
shadow(projects.core) { isTransitive = false }
includeTransitive(projects.core)

// These are NOT transitively included, and instead shadowed + relocated.
// These are NOT transitively included, and instead shadowed (+ relocated, if not under the org.geyser namespace).
// Avoids fabric complaining about non-SemVer versioning
shadow(libs.protocol.connection) { isTransitive = false }
shadow(libs.protocol.common) { isTransitive = false }
Expand All @@ -46,7 +46,6 @@ tasks.withType<Jar> {

relocate("org.cloudburstmc.netty")
relocate("org.cloudburstmc.protocol")
relocate("com.github.steveice10.mc.auth")

tasks {
remapJar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package org.geysermc.geyser.platform.fabric;

import com.google.gson.annotations.JsonAdapter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.fabricmc.api.EnvType;
Expand All @@ -48,7 +49,7 @@ public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
private final String minecraftVersion;
private final EnvType environmentType;

@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final boolean onlineMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap)
Optional<ModContainer> floodgate = FabricLoader.getInstance().getModContainer("floodgate");
if (floodgate.isPresent()) {
Path floodgateDataFolder = FabricLoader.getInstance().getConfigDir().resolve("floodgate");
bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder);
bootstrap.loadFloodgate(floodgateDataFolder);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package org.geysermc.geyser.platform.neoforge;

import com.google.gson.annotations.JsonAdapter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.minecraft.server.MinecraftServer;
Expand All @@ -47,7 +48,7 @@ public class GeyserNeoForgeDumpInfo extends BootstrapDumpInfo {
private final String minecraftVersion;
private final Dist dist;

@AsteriskSerializer.Asterisk(isIp = true)
@JsonAdapter(value = AsteriskSerializer.class)
private final String serverIP;
private final int serverPort;
private final boolean onlineMode;
Expand Down Expand Up @@ -81,4 +82,4 @@ public static class ModInfo {
public String version;
public String url;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public GeyserNeoForgePlatform(ModContainer container) {
public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) {
if (ModList.get().isLoaded("floodgate")) {
Path floodgateDataFolder = FMLPaths.CONFIGDIR.get().resolve("floodgate");
bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder);
bootstrap.loadFloodgate(floodgateDataFolder);
return true;
}
return false;
Expand Down
Loading