--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
@@ -4,11 +4,13 @@
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.mojang.logging.LogUtils;
+import com.mojang.serialization.DataResult;
 import com.mojang.serialization.Dynamic;
 import com.mojang.serialization.JsonOps;
 import java.nio.file.Path;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
@@ -35,9 +37,15 @@
 import net.minecraft.world.level.levelgen.structure.StructureSet;
 import org.slf4j.Logger;
 
+// CraftBukkit start
+import joptsimple.OptionSet;
+// CraftBukkit end
+
 public class DedicatedServerProperties extends Settings<DedicatedServerProperties> {
+
     static final Logger LOGGER = LogUtils.getLogger();
     private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$");
+    public final boolean debug = this.get("debug", false); // CraftBukkit
     public final boolean onlineMode = this.get("online-mode", true);
     public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false);
     public final String serverIp = this.get("server-ip", "");
@@ -48,72 +56,122 @@
     public final String motd = this.get("motd", "A Minecraft Server");
     public final boolean forceGameMode = this.get("force-gamemode", false);
     public final boolean enforceWhitelist = this.get("enforce-whitelist", false);
-    public final Difficulty difficulty = this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY);
-    public final GameType gamemode = this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL);
-    public final String levelName = this.get("level-name", "world");
-    public final int serverPort = this.get("server-port", 25565);
+    public final Difficulty difficulty;
+    public final GameType gamemode;
+    public final String levelName;
+    public final int serverPort;
     @Nullable
-    public final Boolean announcePlayerAchievements = this.getLegacyBoolean("announce-player-achievements");
-    public final boolean enableQuery = this.get("enable-query", false);
-    public final int queryPort = this.get("query.port", 25565);
-    public final boolean enableRcon = this.get("enable-rcon", false);
-    public final int rconPort = this.get("rcon.port", 25575);
-    public final String rconPassword = this.get("rcon.password", "");
-    public final boolean hardcore = this.get("hardcore", false);
-    public final boolean allowNether = this.get("allow-nether", true);
-    public final boolean spawnMonsters = this.get("spawn-monsters", true);
-    public final boolean useNativeTransport = this.get("use-native-transport", true);
-    public final boolean enableCommandBlock = this.get("enable-command-block", false);
-    public final int spawnProtection = this.get("spawn-protection", 16);
-    public final int opPermissionLevel = this.get("op-permission-level", 4);
-    public final int functionPermissionLevel = this.get("function-permission-level", 2);
-    public final long maxTickTime = this.get("max-tick-time", TimeUnit.MINUTES.toMillis(1L));
-    public final int maxChainedNeighborUpdates = this.get("max-chained-neighbor-updates", 1000000);
-    public final int rateLimitPacketsPerSecond = this.get("rate-limit", 0);
-    public final int viewDistance = this.get("view-distance", 10);
-    public final int simulationDistance = this.get("simulation-distance", 10);
-    public final int maxPlayers = this.get("max-players", 20);
-    public final int networkCompressionThreshold = this.get("network-compression-threshold", 256);
-    public final boolean broadcastRconToOps = this.get("broadcast-rcon-to-ops", true);
-    public final boolean broadcastConsoleToOps = this.get("broadcast-console-to-ops", true);
-    public final int maxWorldSize = this.get("max-world-size", (maxWorldSize) -> {
-        return Mth.clamp(maxWorldSize, 1, 29999984);
-    }, 29999984);
-    public final boolean syncChunkWrites = this.get("sync-chunk-writes", true);
-    public final boolean enableJmxMonitoring = this.get("enable-jmx-monitoring", false);
-    public final boolean enableStatus = this.get("enable-status", true);
-    public final boolean hideOnlinePlayers = this.get("hide-online-players", false);
-    public final int entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (percentage) -> {
-        return Mth.clamp(percentage, 10, 1000);
-    }, 100);
-    public final String textFilteringConfig = this.get("text-filtering-config", "");
+    public final Boolean announcePlayerAchievements;
+    public final boolean enableQuery;
+    public final int queryPort;
+    public final boolean enableRcon;
+    public final int rconPort;
+    public final String rconPassword;
+    public final boolean hardcore;
+    public final boolean allowNether;
+    public final boolean spawnMonsters;
+    public final boolean useNativeTransport;
+    public final boolean enableCommandBlock;
+    public final int spawnProtection;
+    public final int opPermissionLevel;
+    public final int functionPermissionLevel;
+    public final long maxTickTime;
+    public final int maxChainedNeighborUpdates;
+    public final int rateLimitPacketsPerSecond;
+    public final int viewDistance;
+    public final int simulationDistance;
+    public final int maxPlayers;
+    public final int networkCompressionThreshold;
+    public final boolean broadcastRconToOps;
+    public final boolean broadcastConsoleToOps;
+    public final int maxWorldSize;
+    public final boolean syncChunkWrites;
+    public final boolean enableJmxMonitoring;
+    public final boolean enableStatus;
+    public final boolean hideOnlinePlayers;
+    public final int entityBroadcastRangePercentage;
+    public final String textFilteringConfig;
     public Optional<MinecraftServer.ServerResourcePackInfo> serverResourcePackInfo;
-    public final boolean previewsChat = this.get("previews-chat", false);
-    public final Settings<DedicatedServerProperties>.MutableValue<Integer> playerIdleTimeout = this.getMutable("player-idle-timeout", 0);
-    public final Settings<DedicatedServerProperties>.MutableValue<Boolean> whiteList = this.getMutable("white-list", false);
-    public final boolean enforceSecureProfile = this.get("enforce-secure-profile", true);
-    private final DedicatedServerProperties.WorldGenProperties worldGenProperties = new DedicatedServerProperties.WorldGenProperties(this.get("level-seed", ""), this.get("generator-settings", (generatorSettings) -> {
-        return GsonHelper.parse(!generatorSettings.isEmpty() ? generatorSettings : "{}");
-    }, new JsonObject()), this.get("generate-structures", true), this.get("level-type", (type) -> {
-        return type.toLowerCase(Locale.ROOT);
-    }, WorldPresets.NORMAL.location().toString()));
+    public final boolean previewsChat;
+    public final Settings<DedicatedServerProperties>.MutableValue<Integer> playerIdleTimeout;
+    public final Settings<DedicatedServerProperties>.MutableValue<Boolean> whiteList;
+    public final boolean enforceSecureProfile;
+    private final DedicatedServerProperties.WorldGenProperties worldGenProperties;
     @Nullable
     private WorldGenSettings worldGenSettings;
 
-    public DedicatedServerProperties(Properties properties) {
-        super(properties);
-        this.serverResourcePackInfo = getServerPackInfo(this.get("resource-pack", ""), this.get("resource-pack-sha1", ""), this.getLegacyString("resource-pack-hash"), this.get("require-resource-pack", false), this.get("resource-pack-prompt", ""));
+    public final String rconIp; // Paper - Add rcon ip
+
+    // CraftBukkit start
+    public DedicatedServerProperties(Properties properties, OptionSet optionset) {
+        super(properties, optionset);
+        // CraftBukkit end
+        this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY);
+        this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL);
+        this.levelName = this.get("level-name", "world");
+        this.serverPort = this.get("server-port", 25565);
+        this.announcePlayerAchievements = this.getLegacyBoolean("announce-player-achievements");
+        this.enableQuery = this.get("enable-query", false);
+        this.queryPort = this.get("query.port", 25565);
+        this.enableRcon = this.get("enable-rcon", false);
+        this.rconPort = this.get("rcon.port", 25575);
+        this.rconPassword = this.get("rcon.password", "");
+        this.hardcore = this.get("hardcore", false);
+        this.allowNether = this.get("allow-nether", true);
+        this.spawnMonsters = this.get("spawn-monsters", true);
+        this.useNativeTransport = this.get("use-native-transport", true);
+        this.enableCommandBlock = this.get("enable-command-block", false);
+        this.spawnProtection = this.get("spawn-protection", 16);
+        this.opPermissionLevel = this.get("op-permission-level", 4);
+        this.functionPermissionLevel = this.get("function-permission-level", 2);
+        this.maxTickTime = this.get("max-tick-time", TimeUnit.MINUTES.toMillis(1L));
+        this.maxChainedNeighborUpdates = this.get("max-chained-neighbor-updates", 1000000);
+        this.rateLimitPacketsPerSecond = this.get("rate-limit", 0);
+        this.viewDistance = this.get("view-distance", 10);
+        this.simulationDistance = this.get("simulation-distance", 10);
+        this.maxPlayers = this.get("max-players", 20);
+        this.networkCompressionThreshold = this.get("network-compression-threshold", 256);
+        this.broadcastRconToOps = this.get("broadcast-rcon-to-ops", true);
+        this.broadcastConsoleToOps = this.get("broadcast-console-to-ops", true);
+        this.maxWorldSize = this.get("max-world-size", (integer) -> {
+            return Mth.clamp(integer, (int) 1, 29999984);
+        }, 29999984);
+        this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag
+        this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false);
+        this.enableStatus = this.get("enable-status", true);
+        this.hideOnlinePlayers = this.get("hide-online-players", false);
+        this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> {
+            return Mth.clamp(integer, (int) 10, (int) 1000);
+        }, 100);
+        this.textFilteringConfig = this.get("text-filtering-config", "");
+        this.previewsChat = this.get("previews-chat", false);
+        this.playerIdleTimeout = this.getMutable("player-idle-timeout", 0);
+        this.whiteList = this.getMutable("white-list", false);
+        this.enforceSecureProfile = this.get("enforce-secure-profile", true);
+        this.worldGenProperties = new DedicatedServerProperties.WorldGenProperties(this.get("level-seed", ""), (JsonObject) this.get("generator-settings", (s) -> {
+            return GsonHelper.parse(!s.isEmpty() ? s : "{}");
+        }, new JsonObject()), this.get("generate-structures", true), (String) this.get("level-type", (s) -> {
+            return s.toLowerCase(Locale.ROOT);
+        }, WorldPresets.NORMAL.location().toString()));
+        this.serverResourcePackInfo = DedicatedServerProperties.getServerPackInfo(this.get("resource-pack", ""), this.get("resource-pack-sha1", ""), this.getLegacyString("resource-pack-hash"), this.get("require-resource-pack", false), this.get("resource-pack-prompt", ""));
+        // Paper start - Configurable rcon ip
+        final String rconIp = this.getStringRaw("rcon.ip");
+        this.rconIp = rconIp == null ? this.serverIp : rconIp;
+        // Paper end
     }
 
-    public static DedicatedServerProperties fromFile(Path path) {
-        return new DedicatedServerProperties(loadFromFile(path));
+    // CraftBukkit start
+    public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) {
+        return new DedicatedServerProperties(loadFromFile(path), optionset);
     }
 
     @Override
-    protected DedicatedServerProperties reload(RegistryAccess registryAccess, Properties properties) {
-        DedicatedServerProperties dedicatedServerProperties = new DedicatedServerProperties(properties);
-        dedicatedServerProperties.getWorldGenSettings(registryAccess);
-        return dedicatedServerProperties;
+    protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) {
+        DedicatedServerProperties dedicatedserverproperties = new DedicatedServerProperties(properties, optionset);
+        // CraftBukkit end
+
+        dedicatedserverproperties.getWorldGenSettings(iregistrycustom);
+        return dedicatedserverproperties;
     }
 
     @Nullable
@@ -121,8 +179,8 @@
         if (!Strings.isNullOrEmpty(prompt)) {
             try {
                 return Component.Serializer.fromJson(prompt);
-            } catch (Exception var2) {
-                LOGGER.warn("Failed to parse resource pack prompt '{}'", prompt, var2);
+            } catch (Exception exception) {
+                DedicatedServerProperties.LOGGER.warn("Failed to parse resource pack prompt '{}'", prompt, exception);
             }
         }
 
@@ -133,27 +191,29 @@
         if (url.isEmpty()) {
             return Optional.empty();
         } else {
-            String string;
+            String s4;
+
             if (!sha1.isEmpty()) {
-                string = sha1;
+                s4 = sha1;
                 if (!Strings.isNullOrEmpty(hash)) {
-                    LOGGER.warn("resource-pack-hash is deprecated and found along side resource-pack-sha1. resource-pack-hash will be ignored.");
+                    DedicatedServerProperties.LOGGER.warn("resource-pack-hash is deprecated and found along side resource-pack-sha1. resource-pack-hash will be ignored.");
                 }
             } else if (!Strings.isNullOrEmpty(hash)) {
-                LOGGER.warn("resource-pack-hash is deprecated. Please use resource-pack-sha1 instead.");
-                string = hash;
+                DedicatedServerProperties.LOGGER.warn("resource-pack-hash is deprecated. Please use resource-pack-sha1 instead.");
+                s4 = hash;
             } else {
-                string = "";
+                s4 = "";
             }
 
-            if (string.isEmpty()) {
-                LOGGER.warn("You specified a resource pack without providing a sha1 hash. Pack will be updated on the client only if you change the name of the pack.");
-            } else if (!SHA1.matcher(string).matches()) {
-                LOGGER.warn("Invalid sha1 for resource-pack-sha1");
+            if (s4.isEmpty()) {
+                DedicatedServerProperties.LOGGER.warn("You specified a resource pack without providing a sha1 hash. Pack will be updated on the client only if you change the name of the pack.");
+            } else if (!DedicatedServerProperties.SHA1.matcher(s4).matches()) {
+                DedicatedServerProperties.LOGGER.warn("Invalid sha1 for resource-pack-sha1");
             }
 
-            Component component = parseResourcePackPrompt(prompt);
-            return Optional.of(new MinecraftServer.ServerResourcePackInfo(url, string, required, component));
+            Component ichatbasecomponent = DedicatedServerProperties.parseResourcePackPrompt(prompt);
+
+            return Optional.of(new MinecraftServer.ServerResourcePackInfo(url, s4, required, ichatbasecomponent));
         }
     }
 
@@ -166,37 +226,48 @@
     }
 
     public static record WorldGenProperties(String levelSeed, JsonObject generatorSettings, boolean generateStructures, String levelType) {
+
         private static final Map<String, ResourceKey<WorldPreset>> LEGACY_PRESET_NAMES = Map.of("default", WorldPresets.NORMAL, "largebiomes", WorldPresets.LARGE_BIOMES);
 
         public WorldGenSettings create(RegistryAccess dynamicRegistryManager) {
-            long l = WorldGenSettings.parseSeed(this.levelSeed()).orElse(RandomSource.create().nextLong());
-            Registry<WorldPreset> registry = dynamicRegistryManager.registryOrThrow(Registry.WORLD_PRESET_REGISTRY);
-            Holder<WorldPreset> holder = registry.getHolder(WorldPresets.NORMAL).or(() -> {
-                return registry.holders().findAny();
+            long i = WorldGenSettings.parseSeed(this.levelSeed()).orElse(RandomSource.create().nextLong());
+            Registry<WorldPreset> iregistry = dynamicRegistryManager.registryOrThrow(Registry.WORLD_PRESET_REGISTRY);
+            Holder<WorldPreset> holder = (Holder) iregistry.getHolder(WorldPresets.NORMAL).or(() -> {
+                return iregistry.holders().findAny();
             }).orElseThrow(() -> {
                 return new IllegalStateException("Invalid datapack contents: can't find default preset");
             });
-            Holder<WorldPreset> holder2 = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)).map((levelTypeId) -> {
-                return ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, levelTypeId);
+            Optional<ResourceKey<WorldPreset>> optional = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)).map((minecraftkey) -> { // CraftBukkit - decompile error
+                return ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, minecraftkey);
             }).or(() -> {
-                return Optional.ofNullable(LEGACY_PRESET_NAMES.get(this.levelType));
-            }).flatMap(registry::getHolder).orElseGet(() -> {
-                DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, holder.unwrapKey().map((key) -> {
-                    return key.location().toString();
+                return Optional.ofNullable(DedicatedServerProperties.WorldGenProperties.LEGACY_PRESET_NAMES.get(this.levelType)); // CraftBukkit - decompile error
+            });
+
+            Objects.requireNonNull(iregistry);
+            Holder<WorldPreset> holder1 = (Holder) optional.flatMap(iregistry::getHolder).orElseGet(() -> {
+                DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, holder.unwrapKey().map((resourcekey) -> {
+                    return resourcekey.location().toString();
                 }).orElse("[unnamed]"));
                 return holder;
             });
-            WorldGenSettings worldGenSettings = holder2.value().createWorldGenSettings(l, this.generateStructures, false);
-            if (holder2.is(WorldPresets.FLAT)) {
-                RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, dynamicRegistryManager);
-                Optional<FlatLevelGeneratorSettings> optional = FlatLevelGeneratorSettings.CODEC.parse(new Dynamic<>(registryOps, this.generatorSettings())).resultOrPartial(DedicatedServerProperties.LOGGER::error);
-                if (optional.isPresent()) {
-                    Registry<StructureSet> registry2 = dynamicRegistryManager.registryOrThrow(Registry.STRUCTURE_SET_REGISTRY);
-                    return WorldGenSettings.replaceOverworldGenerator(dynamicRegistryManager, worldGenSettings, new FlatLevelSource(registry2, optional.get()));
+            WorldGenSettings generatorsettings = ((WorldPreset) holder1.value()).createWorldGenSettings(i, this.generateStructures, false);
+
+            if (holder1.is(WorldPresets.FLAT)) {
+                RegistryOps<JsonElement> registryops = RegistryOps.create(JsonOps.INSTANCE, dynamicRegistryManager);
+                DataResult<FlatLevelGeneratorSettings> dataresult = FlatLevelGeneratorSettings.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); // CraftBukkit - decompile error
+                Logger logger = DedicatedServerProperties.LOGGER;
+
+                Objects.requireNonNull(logger);
+                Optional<FlatLevelGeneratorSettings> optional1 = dataresult.resultOrPartial(logger::error);
+
+                if (optional1.isPresent()) {
+                    Registry<StructureSet> iregistry1 = dynamicRegistryManager.registryOrThrow(Registry.STRUCTURE_SET_REGISTRY);
+
+                    return WorldGenSettings.replaceOverworldGenerator(dynamicRegistryManager, generatorsettings, new FlatLevelSource(iregistry1, (FlatLevelGeneratorSettings) optional1.get()));
                 }
             }
 
-            return worldGenSettings;
+            return generatorsettings;
         }
     }
 }
