Initial advanced config

This commit is contained in:
Camotoy 2024-08-24 18:56:15 -04:00
parent d9d78cd9ca
commit f113c8967e
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
21 changed files with 245 additions and 103 deletions

View file

@ -142,7 +142,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
}
initChannel.invoke(channelInitializer, ch);
if (bootstrap.config().useDirectConnection()) {
if (bootstrap.config().advanced().disableCompression()) {
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
new GeyserBungeeCompressionDisabler());
}

View file

@ -97,7 +97,7 @@ public class GeyserModInjector extends GeyserInjector {
int index = ch.pipeline().names().indexOf("encoder");
String baseName = index != -1 ? "encoder" : "outbound_config";
if (bootstrap.config().disableCompression()) {
if (bootstrap.config().advanced().disableCompression()) {
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserModCompressionDisabler());
}
}

View file

@ -123,7 +123,7 @@ public class GeyserSpigotInjector extends GeyserInjector {
int index = ch.pipeline().names().indexOf("encoder");
String baseName = index != -1 ? "encoder" : "outbound_config";
if (bootstrap.config().disableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
if (bootstrap.config().advanced().disableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserSpigotCompressionDisabler());
}
}

View file

@ -287,7 +287,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
@Override
public Path getFloodgateKeyPath() {
return Path.of(geyserConfig.floodgateKeyFile());
return Path.of(geyserConfig.advanced().floodgateKeyFile());
}
/**

View file

@ -85,7 +85,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
protected void initChannel(@NonNull Channel ch) throws Exception {
initChannel.invoke(channelInitializer, ch);
if (bootstrap.config().disableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
if (bootstrap.config().advanced().disableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
ch.pipeline().addAfter("minecraft-encoder", "geyser-compression-disabler",
new GeyserVelocityCompressionDisabler());
}

View file

@ -232,7 +232,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserPlugin
@Override
public Path getFloodgateKeyPath() {
return new File(ROOT_FOLDER, config.floodgateKeyFile()).toPath();
return new File(ROOT_FOLDER, config.advanced().floodgateKeyFile()).toPath();
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")

View file

@ -46,6 +46,7 @@ public final class Constants {
public static final String MINECRAFT_SKIN_SERVER_URL = "https://textures.minecraft.net/texture/";
public static final int CONFIG_VERSION = 5;
public static final int ADVANCED_CONFIG_VERSION = 1;
public static final int BSTATS_ID = 5273;

View file

@ -45,7 +45,7 @@ public class FloodgateKeyLoader {
}
}
Path floodgateKey = geyserDataFolder.resolve(config.floodgateKeyFile());
Path floodgateKey = geyserDataFolder.resolve(config.advanced().floodgateKeyFile());
if (!Files.exists(floodgateKey)) {
logger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed"));

View file

@ -461,10 +461,10 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
}
}
if (config.metrics().enabled()) {
if (config.enableMetrics()) {
metrics = new MetricsBase(
"server-implementation",
config.metrics().uuid().toString(),
config.advanced().metricsUuid().toString(),
Constants.BSTATS_ID,
true, // Already checked above.
builder -> {

View file

@ -0,0 +1,111 @@
/*
* 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.configuration;
import org.geysermc.geyser.Constants;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultString;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.UUID;
@ConfigSerializable
public interface AdvancedConfig {
// Cannot be type File yet because we may want to hide it in plugin instances.
@Comment("""
Floodgate uses encryption to ensure use from authorized sources.
This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
You can ignore this when not using Floodgate.
If you're using a plugin version of Floodgate on the same server, the key will automatically be picked up from Floodgate.""")
@DefaultString("key.pem")
String floodgateKeyFile();
@Comment("""
The maximum number of custom skulls to be displayed per player. Increasing this may decrease performance on weaker devices.
Setting this to -1 will cause all custom skulls to be displayed regardless of distance or number.""")
@DefaultNumeric(128)
int maxVisibleCustomSkulls();
@Comment("The radius in blocks around the player in which custom skulls are displayed.")
@DefaultNumeric(32)
int customSkullRenderDistance();
@Comment("""
Specify how many days images will be cached to disk to save downloading them from the internet.
A value of 0 is disabled. (Default: 0)""")
int cacheImages();
@Comment("""
Which item to use to mark unavailable slots in a Bedrock player inventory. Examples of this are the 2x2 crafting grid while in creative,
or custom inventory menus with sizes different from the usual 3x9. A barrier block is the default item.""")
@DefaultString("minecraft:barrier")
String unusableSpaceBlock();
@Comment("""
Geyser updates the Scoreboard after every Scoreboard packet, but when Geyser tries to handle
a lot of scoreboard packets per second can cause serious lag.
This option allows you to specify after how many Scoreboard packets per seconds
the Scoreboard updates will be limited to four updates per second.""")
@DefaultNumeric(20)
int scoreboardPacketThreshold();
@Comment("""
The internet supports a maximum MTU of 1492 but could cause issues with packet fragmentation.
1400 is the default.""")
@DefaultNumeric(1400)
int mtu();
@Comment("""
Only for plugin versions of Geyser.
Whether to connect directly into the Java server without creating a TCP connection.
This should only be disabled if a plugin that interfaces with packets or the network does not work correctly with Geyser.
If enabled on plugin versions, the remote address and port sections are ignored
If disabled on plugin versions, expect performance decrease and latency increase
""")
@DefaultBoolean(true)
boolean useDirectConnection();
@Comment("""
Only for plugin versions of Geyser.
Whether Geyser should attempt to disable compression for Bedrock players. This should be a benefit as there is no need to compress data
when Java packets aren't being handled over the network.
This requires use-direct-connection to be true.
""")
@DefaultBoolean(true)
boolean disableCompression();
@Comment("Do not touch!")
default UUID metricsUuid() {
return UUID.randomUUID();
}
@Comment("Do not touch!")
default int version() {
return Constants.ADVANCED_CONFIG_VERSION;
}
}

View file

@ -26,7 +26,10 @@
package org.geysermc.geyser.configuration;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.Constants;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.NodePath;
import org.spongepowered.configurate.interfaces.InterfaceDefaultOptions;
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
import org.spongepowered.configurate.yaml.NodeStyle;
@ -34,8 +37,10 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Stream;
import static org.spongepowered.configurate.NodePath.path;
import static org.spongepowered.configurate.transformation.TransformAction.remove;
@ -56,20 +61,21 @@ public final class ConfigLoader {
In most cases, especially with server hosting providers, further hosting-specific configuration is required.
--------------------------------""";
private static final String ADVANCED_HEADER = """
--------------------------------
Geyser ADVANCED Configuration File
In most cases, you do *not* need to mess with this file to get Geyser running.
Tread with caution.
--------------------------------
""";
public static <T extends GeyserConfig> T load(File file, Class<T> configClass) throws IOException {
return load(file, configClass, null);
}
public static <T extends GeyserConfig> T load(File file, Class<T> configClass, @Nullable Consumer<CommentedConfigurationNode> transformer) throws IOException {
var loader = YamlConfigurationLoader.builder()
.file(file)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(options -> InterfaceDefaultOptions.addTo(options)
.shouldCopyDefaults(false) // If we use ConfigurationNode#get(type, default), do not write the default back to the node.
.header(HEADER)
.serializers(builder -> builder.register(new LowercaseEnumSerializer())))
.build();
var loader = createLoader(file, HEADER);
CommentedConfigurationNode node = loader.load();
boolean originallyEmpty = !file.exists() || node.isNull();
@ -111,10 +117,21 @@ public final class ConfigLoader {
.addAction(path("metrics", "uuid"), (path, value) -> {
if ("generateduuid".equals(value.getString())) {
// Manually copied config without Metrics UUID creation?
return new Object[]{UUID.randomUUID()};
value.set(UUID.randomUUID());
}
return null;
})
.addAction(path("remote", "address"), (path, value) -> {
if ("auto".equals(value.getString())) {
// Auto-convert back to localhost
value.set("127.0.0.1");
}
return null;
})
.addAction(path("metrics", "enabled"), (path, value) -> {
// Move to the root, not in the Metrics class.
return new Object[]{"enable-metrics"};
})
.addAction(path("bedrock", "motd1"), rename("primary-motd"))
.addAction(path("bedrock", "motd2"), rename("secondary-motd"))
// Legacy config values
@ -139,6 +156,11 @@ public final class ConfigLoader {
CommentedConfigurationNode newRoot = CommentedConfigurationNode.root(loader.defaultOptions());
newRoot.set(config);
// Create the path in a way that Standalone changing the config name will be fine.
int extensionIndex = file.getName().lastIndexOf(".");
File advancedConfigPath = new File(file.getParent(), file.getName().substring(0, extensionIndex) + "_advanced" + file.getName().substring(extensionIndex));
AdvancedConfig advancedConfig = null;
if (originallyEmpty || currentVersion != newVersion) {
if (!originallyEmpty && currentVersion > 4) {
@ -148,10 +170,15 @@ public final class ConfigLoader {
// These get treated as comments on lower nodes, which produces very undesirable results.
ConfigurationCommentMover.moveComments(node, newRoot);
} else if (currentVersion <= 4) {
advancedConfig = migrateToAdvancedConfig(advancedConfigPath, node);
}
loader.save(newRoot);
}
if (advancedConfig == null) {
advancedConfig = loadAdvancedConfig(advancedConfigPath);
}
if (transformer != null) {
// We transform AFTER saving so that these specific transformations aren't applied to file.
@ -159,9 +186,69 @@ public final class ConfigLoader {
config = newRoot.get(configClass);
}
config.advanced(advancedConfig);
return config;
}
private static AdvancedConfig migrateToAdvancedConfig(File file, ConfigurationNode configRoot) throws IOException {
List<NodePath> copyFromOldConfig = Stream.of("max-visible-custom-skulls", "custom-skull-render-distance", "scoreboard-packet-threshold", "mtu",
"floodgate-key-file", "use-direct-connection", "disable-compression")
.map(NodePath::path).toList();
var loader = createLoader(file, ADVANCED_HEADER);
CommentedConfigurationNode advancedNode = CommentedConfigurationNode.root(loader.defaultOptions());
copyFromOldConfig.forEach(path -> {
ConfigurationNode node = configRoot.node(path);
if (!node.virtual()) {
advancedNode.node(path).mergeFrom(node);
configRoot.removeChild(path);
}
});
ConfigurationNode metricsUuid = configRoot.node("metrics", "uuid");
if (!metricsUuid.virtual()) {
advancedNode.node("metrics-uuid").set(metricsUuid.get(UUID.class));
}
advancedNode.node("version").set(Constants.ADVANCED_CONFIG_VERSION);
AdvancedConfig advancedConfig = advancedNode.get(AdvancedConfig.class);
// Ensure all fields get populated
CommentedConfigurationNode newNode = CommentedConfigurationNode.root(loader.defaultOptions());
newNode.set(advancedConfig);
loader.save(newNode);
return advancedConfig;
}
private static AdvancedConfig loadAdvancedConfig(File file) throws IOException {
var loader = createLoader(file, ADVANCED_HEADER);
if (file.exists()) {
ConfigurationNode node = loader.load();
return node.get(AdvancedConfig.class);
} else {
ConfigurationNode node = CommentedConfigurationNode.root(loader.defaultOptions());
node.node("version").set(Constants.ADVANCED_CONFIG_VERSION);
AdvancedConfig advancedConfig = node.get(AdvancedConfig.class);
node.set(advancedConfig);
loader.save(node);
return advancedConfig;
}
}
private static YamlConfigurationLoader createLoader(File file, String header) {
return YamlConfigurationLoader.builder()
.file(file)
.indent(2)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(options -> InterfaceDefaultOptions.addTo(options)
.shouldCopyDefaults(false) // If we use ConfigurationNode#get(type, default), do not write the default back to the node.
.header(header)
.serializers(builder -> builder.register(new LowercaseEnumSerializer())))
.build();
}
private ConfigLoader() {
}
}

View file

@ -33,6 +33,7 @@ import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.util.CooldownUtils;
import org.spongepowered.configurate.interfaces.meta.Exclude;
import org.spongepowered.configurate.interfaces.meta.Field;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultString;
@ -43,7 +44,6 @@ import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ConfigSerializable
public interface GeyserConfig {
@ -51,10 +51,6 @@ public interface GeyserConfig {
JavaConfig java();
// Cannot be type File yet because we want to hide it in plugin instances.
@DefaultString("key.pem")
String floodgateKeyFile();
@Comment("""
For online mode authentication type only.
Stores a list of Bedrock players that should have their Java Edition account saved after login.
@ -128,25 +124,10 @@ public interface GeyserConfig {
@DefaultString("system")
String defaultLocale();
@Comment("""
Specify how many days images will be cached to disk to save downloading them from the internet.
A value of 0 is disabled. (Default: 0)""")
int cacheImages();
@Comment("Allows custom skulls to be displayed. Keeping them enabled may cause a performance decrease on older/weaker devices.")
@DefaultBoolean(true)
boolean allowCustomSkulls();
@Comment("""
The maximum number of custom skulls to be displayed per player. Increasing this may decrease performance on weaker devices.
Setting this to -1 will cause all custom skulls to be displayed regardless of distance or number.""")
@DefaultNumeric(128)
int maxVisibleCustomSkulls();
@Comment("The radius in blocks around the player in which custom skulls are displayed.")
@DefaultNumeric(32)
int customSkullRenderDistance();
@Comment("""
Whether to add any items and blocks which normally does not exist in Bedrock Edition.
This should only need to be disabled if using a proxy that does not use the "transfer packet" style of server switching.
@ -186,18 +167,23 @@ public interface GeyserConfig {
@DefaultBoolean(true)
boolean notifyOnNewBedrockUpdate();
@Comment("""
Which item to use to mark unavailable slots in a Bedrock player inventory. Examples of this are the 2x2 crafting grid while in creative,
or custom inventory menus with sizes different from the usual 3x9. A barrier block is the default item.""")
@DefaultString("minecraft:barrier")
String unusableSpaceBlock();
@Comment("""
bStats is a stat tracker that is entirely anonymous and tracks only basic information
about Geyser, such as how many people are online, how many servers are using Geyser,
what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
https://bstats.org/plugin/server-implementation/GeyserMC""")
MetricsInfo metrics();
@DefaultBoolean(true)
boolean enableMetrics();
/**
* A separate config file added to this class manually.
*/
@Field
@NonNull
AdvancedConfig advanced();
@Field
void advanced(AdvancedConfig config);
@ConfigSerializable
interface BedrockConfig extends BedrockListener {
@ -315,39 +301,14 @@ public interface GeyserConfig {
}
}
@ConfigSerializable
interface MetricsInfo {
@Comment("If metrics should be enabled")
@DefaultBoolean(true)
boolean enabled();
@Comment("UUID of server. Don't change!")
default UUID uuid() { //TODO rename?
return UUID.randomUUID();
}
}
@Comment("""
Geyser updates the Scoreboard after every Scoreboard packet, but when Geyser tries to handle
a lot of scoreboard packets per second can cause serious lag.
This option allows you to specify after how many Scoreboard packets per seconds
the Scoreboard updates will be limited to four updates per second.""")
@DefaultNumeric(20)
int scoreboardPacketThreshold();
@Comment("""
Allow connections from ProxyPass and Waterdog.
See https://www.spigotmc.org/wiki/firewall-guide/ for assistance - use UDP instead of TCP.""")
// if u have offline mode enabled pls be safe
boolean enableProxyConnections();
@Comment("""
The internet supports a maximum MTU of 1492 but could cause issues with packet fragmentation.
1400 is the default.""")
@DefaultNumeric(1400)
int mtu();
@Comment("Do not change!")
@SuppressWarnings("unused")
default int configVersion() {
return Constants.CONFIG_VERSION;
}

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.configuration;
import org.spongepowered.configurate.interfaces.meta.Exclude;
import org.spongepowered.configurate.interfaces.meta.Field;
import org.spongepowered.configurate.interfaces.meta.Hidden;
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
@ -72,10 +71,6 @@ public interface GeyserPluginConfig extends GeyserConfig {
}
}
@Override
@Hidden
String floodgateKeyFile();
@Comment("""
Use server API methods to determine the Java server's MOTD and ping passthrough.
There is no need to disable this unless your MOTD or player count does not appear properly.""")
@ -87,12 +82,4 @@ public interface GeyserPluginConfig extends GeyserConfig {
Only relevant if integrated-ping-passthrough is disabled.""")
@Override
int pingPassthroughInterval();
@Hidden
@DefaultBoolean(true)
boolean useDirectConnection();
@Hidden
@DefaultBoolean(true)
boolean disableCompression();
}

View file

@ -39,14 +39,6 @@ public interface GeyserRemoteConfig extends GeyserConfig {
@Override
RemoteConfig java();
@Override
@Comment("""
Floodgate uses encryption to ensure use from authorized sources.
This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
You can ignore this when not using Floodgate.
If you're using a plugin version of Floodgate on the same server, the key will automatically be picked up from Floodgate.""")
String floodgateKeyFile();
@ConfigSerializable
interface RemoteConfig extends JavaConfig {
@Override

View file

@ -39,6 +39,7 @@ import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.configuration.AdvancedConfig;
import org.geysermc.geyser.configuration.GeyserConfig;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
@ -73,6 +74,7 @@ public class DumpInfo {
private final String systemEncoding;
private final GitInfo gitInfo;
private final GeyserConfig config;
private final AdvancedConfig advancedConfig;
private final Object2IntMap<DeviceOs> userPlatforms;
private final int connectionAttempts;
private final HashInfo hashInfo;
@ -93,6 +95,7 @@ public class DumpInfo {
this.gitInfo = new GitInfo(GeyserImpl.BUILD_NUMBER, GeyserImpl.COMMIT.substring(0, 7), GeyserImpl.COMMIT, GeyserImpl.BRANCH, GeyserImpl.REPOSITORY);
this.config = geyser.config();
this.advancedConfig = geyser.config().advanced();
String md5Hash = "unknown";
String sha256Hash = "unknown";

View file

@ -50,7 +50,7 @@ public abstract class GeyserInjector {
* @param bootstrap the bootstrap of the Geyser instance.
*/
public void initializeLocalChannel(GeyserPluginBootstrap bootstrap) {
if (!bootstrap.config().useDirectConnection()) {
if (!bootstrap.config().advanced().useDirectConnection()) {
bootstrap.getGeyserLogger().debug("Disabling direct injection!");
return;
}

View file

@ -224,7 +224,7 @@ public final class GeyserServer {
GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser);
playerGroup = serverInitializer.getEventLoopGroup();
this.geyser.getLogger().debug("Setting MTU to " + this.geyser.config().mtu());
this.geyser.getLogger().debug("Setting MTU to " + this.geyser.config().advanced().mtu());
int rakPacketLimit = positivePropOrDefault("Geyser.RakPacketLimit", DEFAULT_PACKET_LIMIT);
this.geyser.getLogger().debug("Setting RakNet packet limit to " + rakPacketLimit);
@ -239,7 +239,7 @@ public final class GeyserServer {
.channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel()))
.group(group, childGroup)
.option(RakChannelOption.RAK_HANDLE_PING, true)
.option(RakChannelOption.RAK_MAX_MTU, this.geyser.config().mtu())
.option(RakChannelOption.RAK_MAX_MTU, this.geyser.config().advanced().mtu())
.option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit)
.option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit)
.option(RakChannelOption.RAK_SEND_COOKIE, rakSendCookie)

View file

@ -47,7 +47,7 @@ public final class ScoreboardUpdater extends Thread {
static {
GeyserConfig config = GeyserImpl.getInstance().config();
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD = Math.min(config.scoreboardPacketThreshold(), SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD);
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD = Math.min(config.advanced().scoreboardPacketThreshold(), SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD);
DEBUG_ENABLED = config.debugMode();
}

View file

@ -74,11 +74,11 @@ public class SkullCache {
public SkullCache(GeyserSession session) {
this.session = session;
this.maxVisibleSkulls = session.getGeyser().config().maxVisibleCustomSkulls();
this.maxVisibleSkulls = session.getGeyser().config().advanced().maxVisibleCustomSkulls();
this.cullingEnabled = this.maxVisibleSkulls != -1;
// Normal skulls are not rendered beyond 64 blocks
int distance = Math.min(session.getGeyser().config().customSkullRenderDistance(), 64);
int distance = Math.min(session.getGeyser().config().advanced().customSkullRenderDistance(), 64);
this.skullRenderDistanceSquared = distance * distance;
}

View file

@ -144,7 +144,7 @@ public class SkinProvider {
public static void registerCacheImageTask(GeyserImpl geyser) {
// Schedule Daily Image Expiry if we are caching them
if (geyser.config().cacheImages() > 0) {
if (geyser.config().advanced().cacheImages() > 0) {
geyser.getScheduledThread().scheduleAtFixedRate(() -> {
File cacheFolder = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").toFile();
if (!cacheFolder.exists()) {
@ -152,7 +152,7 @@ public class SkinProvider {
}
int count = 0;
final long expireTime = ((long) GeyserImpl.getInstance().config().cacheImages()) * ((long)1000 * 60 * 60 * 24);
final long expireTime = ((long) GeyserImpl.getInstance().config().advanced().cacheImages()) * ((long)1000 * 60 * 60 * 24);
for (File imageFile : Objects.requireNonNull(cacheFolder.listFiles())) {
if (imageFile.lastModified() < System.currentTimeMillis() - expireTime) {
//noinspection ResultOfMethodCallIgnored
@ -422,7 +422,7 @@ public class SkinProvider {
GeyserImpl.getInstance().getLogger().debug("Downloaded " + imageUrl);
// Write to cache if we are allowed
if (GeyserImpl.getInstance().config().cacheImages() > 0) {
if (GeyserImpl.getInstance().config().advanced().cacheImages() > 0) {
imageFile.getParentFile().mkdirs();
try {
ImageIO.write(image, "png", imageFile);

View file

@ -236,7 +236,7 @@ public class InventoryUtils {
private static ItemDefinition getUnusableSpaceBlockDefinition(int protocolVersion) {
ItemMappings mappings = Registries.ITEMS.forVersion(protocolVersion);
String unusableSpaceBlock = GeyserImpl.getInstance().config().unusableSpaceBlock();
String unusableSpaceBlock = GeyserImpl.getInstance().config().advanced().unusableSpaceBlock();
ItemDefinition itemDefinition = mappings.getDefinition(unusableSpaceBlock);
if (itemDefinition == null) {