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

@ -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);
}
}
}