From 7be65a2258fe570627cf2bd0e4bf89c85ea953fa Mon Sep 17 00:00:00 2001 From: s809 <43530948+s809@users.noreply.github.com> Date: Sat, 17 Jan 2026 01:43:05 +0500 Subject: [PATCH 1/2] Split off server generation into a separate toggle --- .../distanthorizons/core/config/Config.java | 11 +++ .../multiplayer/config/SessionConfig.java | 69 ++++++++++++++----- .../core/render/LodQuadTree.java | 7 +- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 6da68d6e6..37d0883e2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -101,6 +101,7 @@ public class Config .build(); public static ConfigUiLinkedEntry quickEnableWorldGenerator = new ConfigUiLinkedEntry(Common.WorldGenerator.enableDistantGeneration); + public static ConfigUiLinkedEntry quickEnableServerGeneration = new ConfigUiLinkedEntry(Server.enableServerGeneration); public static ConfigUiLinkedEntry quickShowWorldGenProgress = new ConfigUiLinkedEntry(Common.WorldGenerator.showGenerationProgress); @@ -1734,6 +1735,16 @@ public class Config // Generation + public static ConfigEntry enableServerGeneration = new ConfigEntry.Builder() + .set(true) + .comment("" + + " Should Distant Horizons slowly generate LODs \n" + + " outside the vanilla render distance? \n" + + "Depending on the generator mode, this will import existing chunks \n" + + "and/or generating missing chunks." + + "") + .build(); + public static ConfigEntry generationRequestRateLimit = new ConfigEntry.Builder() .setChatCommandName("generation.requestRateLimit") .setMinDefaultMax(1, 20, 100) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java index a0640e183..28c4edcab 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java @@ -11,6 +11,7 @@ import java.io.Closeable; import java.util.*; import java.util.function.BinaryOperator; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; public class SessionConfig implements INetworkObject @@ -31,7 +32,23 @@ public class SessionConfig implements INetworkObject { // Note: config values are transmitted in the insertion order - registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration, Boolean::logicalAnd); + registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration.getChatCommandName(), new Entry( + Config.Server.enableServerGeneration::get, + runnable -> new Closeable() + { + private final ConfigChangeListener distantGenerationChanges = new ConfigChangeListener<>(Config.Common.WorldGenerator.enableDistantGeneration, ignored -> runnable.run()); + private final ConfigChangeListener serverGenerationChanges = new ConfigChangeListener<>(Config.Server.enableServerGeneration, ignored -> runnable.run()); + + @Override + public void close() + { + this.serverGenerationChanges.close(); + this.distantGenerationChanges.close(); + } + }, + (Boolean client, Boolean server) -> client && Config.Common.WorldGenerator.enableDistantGeneration.get() + )); + registerConfigEntry(Config.Server.maxGenerationRequestDistance, Math::min); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y); @@ -90,14 +107,24 @@ public class SessionConfig implements INetworkObject private static void registerConfigEntry(ConfigEntry configEntry, BinaryOperator valueConstrainer) { - CONFIG_ENTRIES.compute(Objects.requireNonNull(configEntry.getChatCommandName()), (key, existingEntry) -> { - if (existingEntry != null) - { - throw new IllegalArgumentException("Attempted to register config entry with duplicate chatCommandName: " + key); - } - - return new Entry(configEntry, valueConstrainer); - }); + registerConfigEntry( + Objects.requireNonNull(configEntry.getChatCommandName()), + new Entry( + configEntry::get, + runnable -> new ConfigChangeListener<>(configEntry, ignored -> runnable.run()), + valueConstrainer + ) + ); + } + + private static void registerConfigEntry(String key, Entry entry) + { + if (CONFIG_ENTRIES.containsKey(key)) + { + throw new IllegalArgumentException("Attempted to register config entry with duplicate key: " + key); + } + + CONFIG_ENTRIES.put(key, entry); } @@ -115,7 +142,7 @@ public class SessionConfig implements INetworkObject T value = (T) this.values.get(name); if (value == null) { - value = (T) entry.supplier.get(); + value = (T) entry.valueSupplier.get(); } return (this.constrainingConfig != null @@ -210,13 +237,15 @@ public class SessionConfig implements INetworkObject private static class Entry { - public final ConfigEntry supplier; + public final Supplier valueSupplier; + public final Function changeListenerFactory; public final BinaryOperator valueConstrainer; @SuppressWarnings("unchecked") - private Entry(ConfigEntry supplier, BinaryOperator valueConstrainer) + private Entry(Supplier valueSupplier, Function changeListenerFactory, BinaryOperator valueConstrainer) { - this.supplier = (ConfigEntry) supplier; + this.valueSupplier = valueSupplier; + this.changeListenerFactory = changeListenerFactory; this.valueConstrainer = (BinaryOperator) valueConstrainer; } @@ -225,23 +254,29 @@ public class SessionConfig implements INetworkObject /** fires if any config value was changed */ public static class AnyChangeListener implements Closeable { - private final ArrayList> changeListeners; + private final ArrayList changeListeners; public AnyChangeListener(Runnable runnable) { this.changeListeners = new ArrayList<>(CONFIG_ENTRIES.size()); for (Entry entry : CONFIG_ENTRIES.values()) { - this.changeListeners.add(new ConfigChangeListener<>(entry.supplier, ignored -> runnable.run())); + this.changeListeners.add(entry.changeListenerFactory.apply(runnable)); } } @Override public void close() { - for (ConfigChangeListener changeListener : this.changeListeners) + for (Closeable changeListener : this.changeListeners) { - changeListener.close(); + try + { + changeListener.close(); + } + catch (Exception ignored) + { + } } this.changeListeners.clear(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java index 20733ea17..b5177e1ef 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult; import com.seibel.distanthorizons.core.generation.tasks.ERetrievalResultState; +import com.seibel.distanthorizons.core.level.DhClientServerLevel; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -144,6 +145,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null; Config.Common.WorldGenerator.enableDistantGeneration.addListener(this); + Config.Server.enableServerGeneration.addListener(this); } @@ -662,7 +664,9 @@ public class LodQuadTree extends QuadTree implements IDebugRen @Override public void onConfigValueSet() { - boolean generatorEnabled = Config.Common.WorldGenerator.enableDistantGeneration.get(); + boolean generatorEnabled = this.level instanceof DhClientServerLevel + ? Config.Common.WorldGenerator.enableDistantGeneration.get() + : Config.Server.enableServerGeneration.get(); if (generatorEnabled) { // world gen tasks will need to be re-queued @@ -920,6 +924,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus); Config.Common.WorldGenerator.enableDistantGeneration.removeListener(this); + Config.Server.enableServerGeneration.removeListener(this); ThreadPoolExecutor mainCleanupExecutor = ThreadPoolUtil.getCleanupExecutor(); From 2a4bfef7a620b69bdba0dbcdf0118056a066e468 Mon Sep 17 00:00:00 2001 From: s809 <43530948+s809@users.noreply.github.com> Date: Sun, 18 Jan 2026 22:38:01 +0500 Subject: [PATCH 2/2] Add correct descriptions --- .../com/seibel/distanthorizons/core/config/Config.java | 7 +++---- .../main/resources/assets/distanthorizons/lang/en_us.json | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 37d0883e2..79371c3f0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -1738,10 +1738,9 @@ public class Config public static ConfigEntry enableServerGeneration = new ConfigEntry.Builder() .set(true) .comment("" - + " Should Distant Horizons slowly generate LODs \n" - + " outside the vanilla render distance? \n" - + "Depending on the generator mode, this will import existing chunks \n" - + "and/or generating missing chunks." + + "When enabled, Distant Horizons will attempt to download missing LODs from the server.\n" + + "\n" + + "Note: the server must have Distant Generation enabled for it to work." + "") .build(); diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 4357d439c..c8df027dd 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -763,6 +763,11 @@ "distanthorizons.config.server.levelKeyPrefix.@tooltip": "Prefix of the level keys sent to the clients.\nIf the mod is running behind a proxy, each backend should use a unique value.\nIf this value is empty, level key will be based on the server's seed hash.", + "distanthorizons.config.server.enableServerGeneration": + "Enable Server Generation", + "distanthorizons.config.server.enableServerGeneration.@tooltip": + "When enabled, Distant Horizons will attempt to download missing LODs from the server.\n\nNote: the server must have Distant Generation enabled for it to work.", + "distanthorizons.config.server.generationRequestRateLimit": "Rate Limit for Generation Requests", "distanthorizons.config.server.generationRequestRateLimit.@tooltip":