New config used in core

This commit is contained in:
Camotoy 2024-07-06 19:16:08 -04:00
parent db9b951352
commit 29f8e294ad
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
66 changed files with 758 additions and 1045 deletions

View file

@ -108,7 +108,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
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
@ -142,7 +142,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
}
initChannel.invoke(channelInitializer, ch);
if (bootstrap.getGeyserConfig().isDisableCompression()) {
if (bootstrap.config().asPluginConfig().orElseThrow().useDirectConnection()) {
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
new GeyserBungeeCompressionDisabler());
}

View file

@ -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(Constants.UPDATE_PERMISSION)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player));

View file

@ -96,7 +96,7 @@ public class GeyserModInjector extends GeyserInjector {
int index = ch.pipeline().names().indexOf("encoder");
String baseName = index != -1 ? "encoder" : "outbound_config";
if (bootstrap.getGeyserConfig().isDisableCompression()) {
if (bootstrap.config().asPluginConfig().orElseThrow().disableCompression()) {
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserModCompressionDisabler());
}
}
@ -125,7 +125,7 @@ public class GeyserModInjector extends GeyserInjector {
childHandler = (ChannelInitializer<Channel>) childHandlerField.get(handler);
break;
} catch (Exception e) {
if (bootstrap.getGeyserConfig().isDebugMode()) {
if (bootstrap.config().debugMode()) {
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
e.printStackTrace();
}

View file

@ -56,7 +56,6 @@ public class IntegratedServerMixin implements GeyserServerPortGetter {
// If the LAN is opened, starts Geyser.
GeyserModBootstrap instance = GeyserModBootstrap.getInstance();
instance.setServer((MinecraftServer) (Object) this);
instance.getGeyserConfig().getRemote().setPort(port);
instance.onGeyserEnable();
// Ensure player locale has been loaded, in case it's different from Java system language
GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode);

View file

@ -122,7 +122,7 @@ public class GeyserSpigotInjector extends GeyserInjector {
int index = ch.pipeline().names().indexOf("encoder");
String baseName = index != -1 ? "encoder" : "outbound_config";
if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
if (bootstrap.config().asPluginConfig().orElseThrow().disableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserSpigotCompressionDisabler());
}
}
@ -157,7 +157,7 @@ public class GeyserSpigotInjector extends GeyserInjector {
}
break;
} catch (Exception e) {
if (bootstrap.getGeyserConfig().isDebugMode()) {
if (bootstrap.config().debugMode()) {
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
e.printStackTrace();
}
@ -176,8 +176,8 @@ public class GeyserSpigotInjector extends GeyserInjector {
*/
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
MinecraftProtocol protocol = new MinecraftProtocol();
LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(),
bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress,
LocalSession session = new LocalSession(bootstrap.config().java().address(),
bootstrap.config().java().port(), this.serverSocketAddress,
InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper());
session.connect();
session.disconnect("");

View file

@ -487,7 +487,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml",
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
ConfigLoaderTemp.load(GeyserPluginConfig.class);
ConfigLoaderTemp.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
} catch (IOException ex) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();

View file

@ -38,7 +38,7 @@ public final class GeyserSpigotUpdateListener implements Listener {
@EventHandler
public void onPlayerJoin(final PlayerJoinEvent event) {
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
final Player player = event.getPlayer();
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new SpigotCommandSource(player));

View file

@ -76,7 +76,7 @@ public final class GeyserPaperCommandListener implements Listener {
return false;
}
if (GeyserImpl.getInstance().getConfig().isUseDirectConnection()) {
if (GeyserImpl.getInstance().config().asPluginConfig().orElseThrow().useDirectConnection()) {
InetSocketAddress address = player.getAddress();
if (address != null) {
return address.getPort() != 0;

View file

@ -25,11 +25,6 @@
package org.geysermc.geyser.platform.standalone;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import io.netty.util.ResourceLeakDetector;
import lombok.Getter;
import net.minecrell.terminalconsole.TerminalConsoleAppender;
@ -44,16 +39,17 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import org.geysermc.geyser.configuration.GeyserConfig;
import org.geysermc.geyser.configuration.GeyserRemoteConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.FileUtils;
import org.geysermc.geyser.util.LoopbackUtil;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.NodePath;
import org.spongepowered.configurate.serialize.SerializationException;
import java.io.File;
import java.io.IOException;
@ -61,13 +57,13 @@ import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.HashMap;
import java.util.Map;
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserStandaloneConfiguration geyserConfig;
private GeyserConfig geyserConfig;
private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
private GeyserStandaloneGUI gui;
@ -78,15 +74,15 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserImpl geyser;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final Map<String, String> argsConfigKeys = new HashMap<>();
private static final Map<NodePath, String> argsConfigKeys = new HashMap<>();
public static void main(String[] args) {
if (System.getProperty("io.netty.leakDetection.level") == null) {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
}
System.setProperty("bstats.relocatecheck", "false");
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
// Set defaults
boolean useGuiOpts = bootstrap.useGui;
@ -94,8 +90,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
GeyserLocale.init(bootstrap);
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
for (int i = 0; i < args.length; i++) {
// By default, standalone Geyser will check if it should open the GUI based on if the GUI is null
// Optionally, you can force the use of a GUI or no GUI by specifying args
@ -127,34 +121,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
// Split the argument by an =
String[] argParts = arg.substring(2).split("=");
if (argParts.length == 2) {
// Split the config key by . to allow for nested options
String[] configKeyParts = argParts[0].split("\\.");
// Loop the possible config options to check the passed key is valid
boolean found = false;
for (BeanPropertyDefinition property : availableProperties) {
if (configKeyParts[0].equals(property.getName())) {
if (configKeyParts.length > 1) {
// Loop sub-section options to check the passed key is valid
for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
if (configKeyParts[1].equals(subProperty.getName())) {
found = true;
break;
}
}
} else {
found = true;
}
break;
}
}
// Add the found key to the stored list for later usage
if (found) {
argsConfigKeys.put(argParts[0], argParts[1]);
break;
}
argsConfigKeys.put(NodePath.of(argParts[0].split("\\.")), argParts[1]);
break;
}
}
System.err.println(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
@ -192,18 +160,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
@Override
public void onGeyserEnable() {
try {
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
ConfigLoaderTemp.load(GeyserRemoteConfig.class);
handleArgsConfigOptions();
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
geyserConfig.setAutoconfiguredRemote(true); // Doesn't really need to be set but /shrug
geyserConfig.getRemote().setAddress("127.0.0.1");
}
geyserConfig = ConfigLoaderTemp.load(new File(configFilename), GeyserRemoteConfig.class, this::handleArgsConfigOptions);
} catch (IOException ex) {
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
if (gui == null) {
@ -213,11 +170,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
return;
}
}
geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
geyserLogger.setDebug(geyserConfig.debugMode());
// Allow libraries like Protocol to have their debug information passthrough
log4jLogger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO);
log4jLogger.get().setLevel(geyserConfig.debugMode() ? Level.DEBUG : Level.INFO);
geyser = GeyserImpl.load(PlatformType.STANDALONE, this);
@ -266,8 +222,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
}
@Override
public GeyserConfiguration getGeyserConfig() {
return geyserConfig;
public GeyserConfig config() {
return this.geyserConfig;
}
@Override
@ -318,100 +274,47 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
return false;
}
/**
* Get the {@link BeanPropertyDefinition}s for the given class
*
* @param clazz The class to get the definitions for
* @return A list of {@link BeanPropertyDefinition} for the given class
*/
public static List<BeanPropertyDefinition> getPOJOForClass(Class<?> clazz) {
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructType(clazz);
// Introspect the given type
BeanDescription beanDescription = OBJECT_MAPPER.getSerializationConfig().introspect(javaType);
// Find properties
List<BeanPropertyDefinition> properties = beanDescription.findProperties();
// Get the ignored properties
Set<String> ignoredProperties = OBJECT_MAPPER.getSerializationConfig().getAnnotationIntrospector()
.findPropertyIgnoralByName(OBJECT_MAPPER.getSerializationConfig() ,beanDescription.getClassInfo()).getIgnored();
// Filter properties removing the ignored ones
return properties.stream()
.filter(property -> !ignoredProperties.contains(property.getName()))
.collect(Collectors.toList());
@Override
public Path getFloodgateKeyPath() {
return Path.of(geyserConfig.floodgateKeyFile());
}
/**
* Set a POJO property value on an object
*
* @param property The {@link BeanPropertyDefinition} to set
* @param parentObject The object to alter
* @param value The new value of the property
*/
@SuppressWarnings({"unchecked", "rawtypes"}) // Required for enum usage
private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) {
private static void setConfigOption(CommentedConfigurationNode node, Object value) throws SerializationException {
Object parsedValue = value;
// Change the values type if needed
if (int.class.equals(property.getRawPrimaryType())) {
Class<?> clazz = node.raw().getClass();
if (Integer.class == clazz) {
parsedValue = Integer.valueOf((String) parsedValue);
} else if (boolean.class.equals(property.getRawPrimaryType())) {
} else if (Boolean.class == clazz) {
parsedValue = Boolean.valueOf((String) parsedValue);
} else if (Enum.class.isAssignableFrom(property.getRawPrimaryType())) {
parsedValue = Enum.valueOf((Class<? extends Enum>) property.getRawPrimaryType(), ((String) parsedValue).toUpperCase(Locale.ROOT));
}
// Force the value to be set
AnnotatedField field = property.getField();
field.fixAccess(true);
field.setValue(parentObject, parsedValue);
node.set(parsedValue);
}
/**
* Update the loaded {@link GeyserStandaloneConfiguration} with any values passed in the command line arguments
* Update the loaded config with any values passed in the command line arguments
*/
private void handleArgsConfigOptions() {
// Get the available properties from the class
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
private void handleArgsConfigOptions(CommentedConfigurationNode node) {
for (Map.Entry<NodePath, String> configKey : argsConfigKeys.entrySet()) {
NodePath path = configKey.getKey();
CommentedConfigurationNode subNode = node.node(path);
if (subNode.virtual()) {
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", path));
continue;
}
for (Map.Entry<String, String> configKey : argsConfigKeys.entrySet()) {
String[] configKeyParts = configKey.getKey().split("\\.");
// Loop over the properties looking for any matches against the stored one from the argument
for (BeanPropertyDefinition property : availableProperties) {
if (configKeyParts[0].equals(property.getName())) {
if (configKeyParts.length > 1) {
// Loop through the sub property if the first part matches
for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
if (configKeyParts[1].equals(subProperty.getName())) {
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
// Set the sub property value on the config
try {
Object subConfig = property.getGetter().callOn(geyserConfig);
setConfigOption(subProperty, subConfig, configKey.getValue());
} catch (Exception e) {
geyserLogger.error("Failed to set config option: " + property.getFullName());
}
break;
}
}
} else {
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
// Set the property value on the config
try {
setConfigOption(property, geyserConfig, configKey.getValue());
} catch (Exception e) {
geyserLogger.error("Failed to set config option: " + property.getFullName());
}
}
break;
}
try {
setConfigOption(subNode, configKey.getValue());
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
} catch (SerializationException e) {
geyserLogger.error("Failed to set config option: " + path);
}
}
}

View file

@ -27,10 +27,15 @@ package org.geysermc.geyser.platform.velocity;
import com.velocitypowered.api.proxy.ProxyServer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.local.LocalAddress;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserPluginBootstrap;
import org.geysermc.geyser.network.netty.GeyserInjector;
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
@ -47,7 +52,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
@Override
@SuppressWarnings("unchecked")
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
protected void initializeLocalChannel0(GeyserPluginBootstrap bootstrap) throws Exception {
Field cm = proxy.getClass().getDeclaredField("cm");
cm.setAccessible(true);
Object connectionManager = cm.get(proxy);
@ -80,7 +85,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
protected void initChannel(@NonNull Channel ch) throws Exception {
initChannel.invoke(channelInitializer, ch);
if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
if (bootstrap.config().disableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
ch.pipeline().addAfter("minecraft-encoder", "geyser-compression-disabler",
new GeyserVelocityCompressionDisabler());
}

View file

@ -37,7 +37,7 @@ public final class GeyserVelocityUpdateListener {
@Subscribe
public void onPlayerJoin(PostLoginEvent event) {
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
final Player player = event.getPlayer();
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player));