Compare commits

...

2 Commits

Author SHA1 Message Date
s809 2a4bfef7a6 Add correct descriptions 2026-01-18 22:38:01 +05:00
s809 7be65a2258 Split off server generation into a separate toggle 2026-01-17 01:43:05 +05:00
4 changed files with 73 additions and 18 deletions
@@ -101,6 +101,7 @@ public class Config
.build(); .build();
public static ConfigUiLinkedEntry quickEnableWorldGenerator = new ConfigUiLinkedEntry(Common.WorldGenerator.enableDistantGeneration); 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); public static ConfigUiLinkedEntry quickShowWorldGenProgress = new ConfigUiLinkedEntry(Common.WorldGenerator.showGenerationProgress);
@@ -1734,6 +1735,15 @@ public class Config
// Generation // Generation
public static ConfigEntry<Boolean> enableServerGeneration = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "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();
public static ConfigEntry<Integer> generationRequestRateLimit = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> generationRequestRateLimit = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.requestRateLimit") .setChatCommandName("generation.requestRateLimit")
.setMinDefaultMax(1, 20, 100) .setMinDefaultMax(1, 20, 100)
@@ -11,6 +11,7 @@ import java.io.Closeable;
import java.util.*; import java.util.*;
import java.util.function.BinaryOperator; import java.util.function.BinaryOperator;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SessionConfig implements INetworkObject public class SessionConfig implements INetworkObject
@@ -31,7 +32,23 @@ public class SessionConfig implements INetworkObject
{ {
// Note: config values are transmitted in the insertion order // 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<Boolean> distantGenerationChanges = new ConfigChangeListener<>(Config.Common.WorldGenerator.enableDistantGeneration, ignored -> runnable.run());
private final ConfigChangeListener<Boolean> 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.Server.maxGenerationRequestDistance, Math::min);
registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y);
registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y);
@@ -90,14 +107,24 @@ public class SessionConfig implements INetworkObject
private static <T> void registerConfigEntry(ConfigEntry<T> configEntry, BinaryOperator<T> valueConstrainer) private static <T> void registerConfigEntry(ConfigEntry<T> configEntry, BinaryOperator<T> valueConstrainer)
{ {
CONFIG_ENTRIES.compute(Objects.requireNonNull(configEntry.getChatCommandName()), (key, existingEntry) -> { registerConfigEntry(
if (existingEntry != null) Objects.requireNonNull(configEntry.getChatCommandName()),
{ new Entry(
throw new IllegalArgumentException("Attempted to register config entry with duplicate chatCommandName: " + key); configEntry::get,
} runnable -> new ConfigChangeListener<>(configEntry, ignored -> runnable.run()),
valueConstrainer
return new Entry(configEntry, 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); T value = (T) this.values.get(name);
if (value == null) if (value == null)
{ {
value = (T) entry.supplier.get(); value = (T) entry.valueSupplier.get();
} }
return (this.constrainingConfig != null return (this.constrainingConfig != null
@@ -210,13 +237,15 @@ public class SessionConfig implements INetworkObject
private static class Entry private static class Entry
{ {
public final ConfigEntry<Object> supplier; public final Supplier<Object> valueSupplier;
public final Function<Runnable, Closeable> changeListenerFactory;
public final BinaryOperator<Object> valueConstrainer; public final BinaryOperator<Object> valueConstrainer;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> Entry(ConfigEntry<T> supplier, BinaryOperator<T> valueConstrainer) private <T> Entry(Supplier<Object> valueSupplier, Function<Runnable, Closeable> changeListenerFactory, BinaryOperator<T> valueConstrainer)
{ {
this.supplier = (ConfigEntry<Object>) supplier; this.valueSupplier = valueSupplier;
this.changeListenerFactory = changeListenerFactory;
this.valueConstrainer = (BinaryOperator<Object>) valueConstrainer; this.valueConstrainer = (BinaryOperator<Object>) valueConstrainer;
} }
@@ -225,23 +254,29 @@ public class SessionConfig implements INetworkObject
/** fires if any config value was changed */ /** fires if any config value was changed */
public static class AnyChangeListener implements Closeable public static class AnyChangeListener implements Closeable
{ {
private final ArrayList<ConfigChangeListener<?>> changeListeners; private final ArrayList<Closeable> changeListeners;
public AnyChangeListener(Runnable runnable) public AnyChangeListener(Runnable runnable)
{ {
this.changeListeners = new ArrayList<>(CONFIG_ENTRIES.size()); this.changeListeners = new ArrayList<>(CONFIG_ENTRIES.size());
for (Entry entry : CONFIG_ENTRIES.values()) for (Entry entry : CONFIG_ENTRIES.values())
{ {
this.changeListeners.add(new ConfigChangeListener<>(entry.supplier, ignored -> runnable.run())); this.changeListeners.add(entry.changeListenerFactory.apply(runnable));
} }
} }
@Override @Override
public void close() public void close()
{ {
for (ConfigChangeListener<?> changeListener : this.changeListeners) for (Closeable changeListener : this.changeListeners)
{ {
changeListener.close(); try
{
changeListener.close();
}
catch (Exception ignored)
{
}
} }
this.changeListeners.clear(); this.changeListeners.clear();
} }
@@ -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.file.fullDatafile.V2.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult; import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.generation.tasks.ERetrievalResultState; 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.level.IDhClientLevel;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
@@ -144,6 +145,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null; this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null;
Config.Common.WorldGenerator.enableDistantGeneration.addListener(this); Config.Common.WorldGenerator.enableDistantGeneration.addListener(this);
Config.Server.enableServerGeneration.addListener(this);
} }
@@ -662,7 +664,9 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
@Override @Override
public void onConfigValueSet() 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) if (generatorEnabled)
{ {
// world gen tasks will need to be re-queued // world gen tasks will need to be re-queued
@@ -920,6 +924,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus); DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
Config.Common.WorldGenerator.enableDistantGeneration.removeListener(this); Config.Common.WorldGenerator.enableDistantGeneration.removeListener(this);
Config.Server.enableServerGeneration.removeListener(this);
ThreadPoolExecutor mainCleanupExecutor = ThreadPoolUtil.getCleanupExecutor(); ThreadPoolExecutor mainCleanupExecutor = ThreadPoolUtil.getCleanupExecutor();
@@ -763,6 +763,11 @@
"distanthorizons.config.server.levelKeyPrefix.@tooltip": "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.", "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": "distanthorizons.config.server.generationRequestRateLimit":
"Rate Limit for Generation Requests", "Rate Limit for Generation Requests",
"distanthorizons.config.server.generationRequestRateLimit.@tooltip": "distanthorizons.config.server.generationRequestRateLimit.@tooltip":