2019-12-01 21:16:52 +00:00
|
|
|
/*
|
2021-01-01 15:10:36 +00:00
|
|
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
2019-12-01 21:16:52 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2021-11-20 21:34:30 +00:00
|
|
|
package org.geysermc.geyser.platform.standalone;
|
2019-12-01 21:16:52 +00:00
|
|
|
|
2020-11-07 19:17:17 +00:00
|
|
|
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;
|
2021-07-18 22:44:08 +00:00
|
|
|
import io.netty.util.ResourceLeakDetector;
|
2020-07-03 00:10:43 +00:00
|
|
|
import lombok.Getter;
|
|
|
|
import net.minecrell.terminalconsole.TerminalConsoleAppender;
|
2021-02-08 18:30:37 +00:00
|
|
|
import org.apache.logging.log4j.Level;
|
2020-07-03 00:10:43 +00:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.core.Appender;
|
|
|
|
import org.apache.logging.log4j.core.Logger;
|
|
|
|
import org.apache.logging.log4j.core.appender.ConsoleAppender;
|
2020-11-14 23:49:56 +00:00
|
|
|
import org.geysermc.common.PlatformType;
|
2021-11-20 21:34:30 +00:00
|
|
|
import org.geysermc.geyser.GeyserImpl;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.GeyserBootstrap;
|
2021-11-20 21:34:30 +00:00
|
|
|
import org.geysermc.geyser.command.CommandManager;
|
|
|
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
|
|
|
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
|
|
|
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
|
|
|
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
|
|
|
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.util.FileUtils;
|
|
|
|
import org.geysermc.geyser.text.GeyserLocale;
|
2021-11-20 21:34:30 +00:00
|
|
|
import org.geysermc.geyser.platform.standalone.command.GeyserCommandManager;
|
|
|
|
import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI;
|
2019-12-01 21:16:52 +00:00
|
|
|
|
2020-04-20 01:56:03 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
2020-07-13 23:20:56 +00:00
|
|
|
import java.lang.reflect.Method;
|
2020-06-20 17:54:40 +00:00
|
|
|
import java.nio.file.Path;
|
|
|
|
import java.nio.file.Paths;
|
2020-08-25 21:39:51 +00:00
|
|
|
import java.text.MessageFormat;
|
2020-11-07 19:17:17 +00:00
|
|
|
import java.util.*;
|
|
|
|
import java.util.stream.Collectors;
|
2020-04-20 01:56:03 +00:00
|
|
|
|
2020-04-29 20:01:53 +00:00
|
|
|
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
2020-04-19 23:08:14 +00:00
|
|
|
|
|
|
|
private GeyserCommandManager geyserCommandManager;
|
2020-05-23 21:50:04 +00:00
|
|
|
private GeyserStandaloneConfiguration geyserConfig;
|
2020-04-29 20:01:53 +00:00
|
|
|
private GeyserStandaloneLogger geyserLogger;
|
2020-05-23 21:50:04 +00:00
|
|
|
private IGeyserPingPassthrough geyserPingPassthrough;
|
2019-12-01 21:16:52 +00:00
|
|
|
|
2020-07-03 00:10:43 +00:00
|
|
|
private GeyserStandaloneGUI gui;
|
|
|
|
|
|
|
|
@Getter
|
2020-07-13 23:20:56 +00:00
|
|
|
private boolean useGui = System.console() == null && !isHeadless();
|
2020-08-25 21:39:51 +00:00
|
|
|
private String configFilename = "config.yml";
|
2020-07-03 00:10:43 +00:00
|
|
|
|
2021-11-20 21:34:30 +00:00
|
|
|
private GeyserImpl geyser;
|
2020-03-17 16:43:09 +00:00
|
|
|
|
2020-11-07 19:17:17 +00:00
|
|
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
|
|
|
|
|
|
|
private static final Map<String, String> argsConfigKeys = new HashMap<>();
|
2020-08-25 21:39:51 +00:00
|
|
|
|
2019-12-01 21:16:52 +00:00
|
|
|
public static void main(String[] args) {
|
2021-07-18 22:44:08 +00:00
|
|
|
if (System.getProperty("io.netty.leakDetection.level") == null) {
|
|
|
|
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
|
|
|
|
}
|
|
|
|
|
2020-08-25 21:39:51 +00:00
|
|
|
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
|
|
|
|
// Set defaults
|
|
|
|
boolean useGuiOpts = bootstrap.useGui;
|
|
|
|
String configFilenameOpt = bootstrap.configFilename;
|
|
|
|
|
2021-12-03 16:01:06 +00:00
|
|
|
GeyserLocale.init(bootstrap);
|
|
|
|
|
2020-11-07 19:17:17 +00:00
|
|
|
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
|
|
|
|
|
2020-08-25 21:39:51 +00:00
|
|
|
for (int i = 0; i < args.length; i++) {
|
2020-07-03 00:10:43 +00:00
|
|
|
// 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
|
2020-08-25 21:39:51 +00:00
|
|
|
// Allows gui and nogui without options, for backwards compatibility
|
|
|
|
String arg = args[i];
|
|
|
|
switch (arg) {
|
2021-09-10 18:10:56 +00:00
|
|
|
case "--gui", "gui" -> useGuiOpts = true;
|
|
|
|
case "--nogui", "nogui" -> useGuiOpts = false;
|
|
|
|
case "--config", "-c" -> {
|
2020-08-25 21:39:51 +00:00
|
|
|
if (i >= args.length - 1) {
|
2021-11-20 23:29:46 +00:00
|
|
|
System.err.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config_not_specified"), "-c"));
|
2020-08-25 21:39:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-09-10 18:10:56 +00:00
|
|
|
configFilenameOpt = args[i + 1];
|
|
|
|
i++;
|
2021-11-20 23:29:46 +00:00
|
|
|
System.out.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config_specified"), configFilenameOpt));
|
2021-09-10 18:10:56 +00:00
|
|
|
}
|
|
|
|
case "--help", "-h" -> {
|
2021-11-20 23:29:46 +00:00
|
|
|
System.out.println(MessageFormat.format(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.usage"), "[java -jar] Geyser.jar [opts]"));
|
|
|
|
System.out.println(" " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.options"));
|
|
|
|
System.out.println(" -c, --config [file] " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.config"));
|
|
|
|
System.out.println(" -h, --help " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.help"));
|
|
|
|
System.out.println(" --gui, --nogui " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.gui"));
|
2020-08-25 21:39:51 +00:00
|
|
|
return;
|
2021-09-10 18:10:56 +00:00
|
|
|
}
|
|
|
|
default -> {
|
2020-11-07 19:17:17 +00:00
|
|
|
// We have likely added a config option argument
|
|
|
|
if (arg.startsWith("--")) {
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-11-20 23:29:46 +00:00
|
|
|
System.err.println(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
|
2020-08-25 21:39:51 +00:00
|
|
|
return;
|
2021-09-10 18:10:56 +00:00
|
|
|
}
|
2020-07-03 00:10:43 +00:00
|
|
|
}
|
|
|
|
}
|
2020-08-25 21:39:51 +00:00
|
|
|
bootstrap.onEnable(useGuiOpts, configFilenameOpt);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onEnable(boolean useGui, String configFilename) {
|
|
|
|
this.configFilename = configFilename;
|
|
|
|
this.useGui = useGui;
|
|
|
|
this.onEnable();
|
2019-12-01 21:16:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnable() {
|
2020-07-03 00:10:43 +00:00
|
|
|
Logger logger = (Logger) LogManager.getRootLogger();
|
|
|
|
for (Appender appender : logger.getAppenders().values()) {
|
|
|
|
// Remove the appender that is not in use
|
|
|
|
// Prevents multiple appenders/double logging and removes harmless errors
|
|
|
|
if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) {
|
|
|
|
logger.removeAppender(appender);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (useGui && gui == null) {
|
|
|
|
gui = new GeyserStandaloneGUI();
|
|
|
|
gui.redirectSystemStreams();
|
|
|
|
gui.startUpdateThread();
|
|
|
|
}
|
|
|
|
|
2020-04-29 20:01:53 +00:00
|
|
|
geyserLogger = new GeyserStandaloneLogger();
|
2020-04-19 23:08:14 +00:00
|
|
|
|
2020-03-25 05:55:09 +00:00
|
|
|
LoopbackUtil.checkLoopback(geyserLogger);
|
2020-03-24 07:56:04 +00:00
|
|
|
|
2019-12-01 21:16:52 +00:00
|
|
|
try {
|
2021-12-03 16:01:06 +00:00
|
|
|
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
|
|
|
|
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
2020-04-29 20:01:53 +00:00
|
|
|
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
|
2020-11-07 19:17:17 +00:00
|
|
|
|
|
|
|
handleArgsConfigOptions();
|
|
|
|
|
2020-08-16 17:45:52 +00:00
|
|
|
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
|
2020-08-19 17:14:17 +00:00
|
|
|
geyserConfig.setAutoconfiguredRemote(true); // Doesn't really need to be set but /shrug
|
2020-08-16 17:45:52 +00:00
|
|
|
geyserConfig.getRemote().setAddress("127.0.0.1");
|
|
|
|
}
|
2019-12-01 21:16:52 +00:00
|
|
|
} catch (IOException ex) {
|
2021-11-20 23:29:46 +00:00
|
|
|
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
2020-11-27 23:55:33 +00:00
|
|
|
if (gui == null) {
|
|
|
|
System.exit(1);
|
|
|
|
} else {
|
|
|
|
// Leave the process running so the GUI is still visible
|
|
|
|
return;
|
|
|
|
}
|
2019-12-01 21:16:52 +00:00
|
|
|
}
|
2020-05-21 03:43:22 +00:00
|
|
|
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
2019-12-01 21:16:52 +00:00
|
|
|
|
2021-02-08 18:30:37 +00:00
|
|
|
// Allow libraries like Protocol to have their debug information passthrough
|
|
|
|
logger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO);
|
|
|
|
|
2021-11-20 21:34:30 +00:00
|
|
|
geyser = GeyserImpl.start(PlatformType.STANDALONE, this);
|
|
|
|
geyserCommandManager = new GeyserCommandManager(geyser);
|
2020-05-23 21:50:04 +00:00
|
|
|
|
2020-07-03 00:10:43 +00:00
|
|
|
if (gui != null) {
|
|
|
|
gui.setupInterface(geyserLogger, geyserCommandManager);
|
|
|
|
}
|
|
|
|
|
2021-11-20 21:34:30 +00:00
|
|
|
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
2020-05-23 21:50:04 +00:00
|
|
|
|
2020-07-03 00:10:43 +00:00
|
|
|
if (!useGui) {
|
|
|
|
geyserLogger.start(); // Throws an error otherwise
|
|
|
|
}
|
2019-12-01 21:16:52 +00:00
|
|
|
}
|
|
|
|
|
2020-07-13 23:20:56 +00:00
|
|
|
/**
|
|
|
|
* Check using {@link java.awt.GraphicsEnvironment} that we are a headless client
|
|
|
|
*
|
|
|
|
* @return If the current environment is headless
|
|
|
|
*/
|
|
|
|
private boolean isHeadless() {
|
|
|
|
try {
|
|
|
|
Class<?> graphicsEnv = Class.forName("java.awt.GraphicsEnvironment");
|
|
|
|
Method isHeadless = graphicsEnv.getDeclaredMethod("isHeadless");
|
|
|
|
return (boolean) isHeadless.invoke(null);
|
|
|
|
} catch (Exception ignore) { }
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-01 21:16:52 +00:00
|
|
|
@Override
|
|
|
|
public void onDisable() {
|
2021-11-20 21:34:30 +00:00
|
|
|
geyser.shutdown();
|
2019-12-01 21:16:52 +00:00
|
|
|
System.exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public GeyserConfiguration getGeyserConfig() {
|
|
|
|
return geyserConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-04-29 20:01:53 +00:00
|
|
|
public GeyserStandaloneLogger getGeyserLogger() {
|
2019-12-01 21:16:52 +00:00
|
|
|
return geyserLogger;
|
|
|
|
}
|
2020-04-19 23:08:14 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public CommandManager getGeyserCommandManager() {
|
|
|
|
return geyserCommandManager;
|
|
|
|
}
|
2020-05-23 21:50:04 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
|
|
|
return geyserPingPassthrough;
|
|
|
|
}
|
2020-06-20 17:54:40 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path getConfigFolder() {
|
|
|
|
// Return the current working directory
|
|
|
|
return Paths.get(System.getProperty("user.dir"));
|
|
|
|
}
|
2020-06-27 15:36:48 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public BootstrapDumpInfo getDumpInfo() {
|
2020-07-30 15:59:42 +00:00
|
|
|
return new GeyserStandaloneDumpInfo(this);
|
2020-06-27 15:36:48 +00:00
|
|
|
}
|
2020-11-07 19:17:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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()
|
|
|
|
.findPropertyIgnorals(beanDescription.getClassInfo()).getIgnored();
|
|
|
|
|
|
|
|
// Filter properties removing the ignored ones
|
|
|
|
return properties.stream()
|
|
|
|
.filter(property -> !ignoredProperties.contains(property.getName()))
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2021-08-12 18:16:19 +00:00
|
|
|
@SuppressWarnings("unchecked") // Required for enum usage
|
2020-11-07 19:17:17 +00:00
|
|
|
private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) {
|
|
|
|
Object parsedValue = value;
|
|
|
|
|
|
|
|
// Change the values type if needed
|
|
|
|
if (int.class.equals(property.getRawPrimaryType())) {
|
|
|
|
parsedValue = Integer.valueOf((String) parsedValue);
|
|
|
|
} else if (boolean.class.equals(property.getRawPrimaryType())) {
|
|
|
|
parsedValue = Boolean.valueOf((String) parsedValue);
|
2021-08-12 18:16:19 +00:00
|
|
|
} else if (Enum.class.isAssignableFrom(property.getRawPrimaryType())) {
|
|
|
|
parsedValue = Enum.valueOf((Class<? extends Enum>) property.getRawPrimaryType(), ((String) parsedValue).toUpperCase(Locale.ROOT));
|
2020-11-07 19:17:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Force the value to be set
|
|
|
|
AnnotatedField field = property.getField();
|
|
|
|
field.fixAccess(true);
|
|
|
|
field.setValue(parentObject, parsedValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the loaded {@link GeyserStandaloneConfiguration} 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);
|
|
|
|
|
|
|
|
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())) {
|
2021-11-20 23:29:46 +00:00
|
|
|
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
2020-11-07 19:17:17 +00:00
|
|
|
|
|
|
|
// 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 {
|
2021-11-20 23:29:46 +00:00
|
|
|
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
2020-11-07 19:17:17 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-01 21:16:52 +00:00
|
|
|
}
|