Add a config entry and refactor

This commit is contained in:
s809
2025-04-20 18:25:27 +05:00
parent 3ca5efadc9
commit dd30a8274a
6 changed files with 50 additions and 30 deletions
@@ -1713,6 +1713,15 @@ public class Config
+ "Value of 0 disables the limit."
+ "")
.build();
public static ConfigEntry<Boolean> enableAdaptiveTransferSpeed = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "Enables adaptive transfer speed based on client performance.\n"
+ "If true, DH will automatically adjust transfer rate to minimize connection lag.\n"
+ "If false, transfer speed will remain fixed.\n"
+ "")
.build();
public static ConfigCategory experimental = new ConfigCategory.Builder().set(Experimental.class).build();
@@ -16,65 +16,63 @@ public class ClientCongestionControl
private final AtomicLong bytesReceived = new AtomicLong(0);
private volatile double lastIntervalThroughput = 0;
private double currentRate = 50000;
private double desiredRate = 50000;
private long lastAdjustTime = System.currentTimeMillis();
private final IntSupplier currentMaxRateSupplier;
private final BooleanSupplier hasIncompleteBuffersSupplier;
private final IntConsumer rateUpdateConsumer;
private final IntSupplier currentRateSupplier;
private final Runnable rateUpdateHandler;
public ClientCongestionControl(
IntSupplier currentMaxRateSupplier,
BooleanSupplier hasIncompleteBuffersSupplier,
IntConsumer rateUpdateConsumer
IntSupplier currentRateSupplier,
Runnable rateUpdateHandler
)
{
this.currentMaxRateSupplier = currentMaxRateSupplier;
this.hasIncompleteBuffersSupplier = hasIncompleteBuffersSupplier;
this.rateUpdateConsumer = rateUpdateConsumer;
this.currentRateSupplier = currentRateSupplier;
this.rateUpdateHandler = rateUpdateHandler;
}
public void onPayloadReceived(FullDataSplitMessage message)
{
this.bytesReceived.addAndGet(message.buffer.readableBytes());
long now = System.currentTimeMillis();
if (now - this.lastAdjustTime >= INTERVAL_MS)
{
this.adjustRate(now);
}
this.bytesReceived.addAndGet(message.buffer.readableBytes());
}
private void adjustRate(long now)
{
this.desiredRate = this.currentRateSupplier.getAsInt() * 1000;
double throughput = this.bytesReceived.getAndSet(0);
if (throughput != 0 && throughput >= this.lastIntervalThroughput)
{
this.currentRate = Math.min(this.currentRate, this.currentMaxRateSupplier.getAsInt() * 1000) + ADDITIVE_INCREASE;
this.desiredRate += ADDITIVE_INCREASE;
}
else if (this.hasIncompleteBuffersSupplier.getAsBoolean())
else
{
this.currentRate *= MULTIPLICATIVE_DECREASE;
this.desiredRate *= MULTIPLICATIVE_DECREASE;
throughput *= MULTIPLICATIVE_DECREASE;
if (this.currentRate < 1)
if (this.desiredRate < 1)
{
this.currentRate = 1;
this.desiredRate = 1;
}
}
this.lastIntervalThroughput = throughput;
this.lastAdjustTime = now;
this.rateUpdateConsumer.accept((int) this.currentRate / 1000);
this.rateUpdateHandler.run();
}
public double getCurrentRate()
public int getDesiredRate()
{
return this.currentRate;
return (int) (this.desiredRate / 1000);
}
}
@@ -1,6 +1,7 @@
package com.seibel.distanthorizons.core.multiplayer.client;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.multiplayer.config.SessionConfig;
@@ -58,9 +59,14 @@ public class ClientNetworkState implements Closeable
private final ClientCongestionControl congestionControl = new ClientCongestionControl(
() -> this.sessionConfig.getMaxDataTransferSpeed(),
this.fullDataPayloadReceiver::hasIncompleteBuffers,
x -> this.sendConfigMessage(false)
() -> {
if (Config.Server.enableAdaptiveTransferSpeed.get())
{
this.sendConfigMessage(false);
}
}
);
private final ConfigChangeListener<Boolean> adaptiveTransferSpeedListener = new ConfigChangeListener<>(Config.Server.enableAdaptiveTransferSpeed, this::sendConfigMessage);
@@ -138,7 +144,11 @@ public class ClientNetworkState implements Closeable
public void sendConfigMessage(boolean blocking)
{
SessionConfig sessionConfig = new SessionConfig();
sessionConfig.overrideValue(Config.Server.maxDataTransferSpeed, (int) this.congestionControl.getCurrentRate() / 1000);
if (Config.Server.enableAdaptiveTransferSpeed.get())
{
sessionConfig.constrainValue(Config.Server.maxDataTransferSpeed, this.congestionControl.getDesiredRate());
}
if (blocking)
{
@@ -181,6 +191,7 @@ public class ClientNetworkState implements Closeable
public void close()
{
this.fullDataPayloadReceiver.close();
this.adaptiveTransferSpeedListener.close();
this.configAnyChangeListener.close();
this.networkSession.close();
}
@@ -106,7 +106,7 @@ public class SessionConfig implements INetworkObject
// internal getters //
//==================//
public <T> T getValue(ConfigEntry<T> configEntry) { return this.getValue(configEntry.getChatCommandName()); }
private <T> T getValue(ConfigEntry<T> configEntry) { return this.getValue(configEntry.getChatCommandName()); }
@SuppressWarnings("unchecked")
private <T> T getValue(String name)
{
@@ -123,10 +123,11 @@ public class SessionConfig implements INetworkObject
: value);
}
public <T> void overrideValue(ConfigEntry<T> configEntry, T value) { this.overrideValue(configEntry.getChatCommandName(), value); }
private void overrideValue(String name, Object value)
public <T> void constrainValue(ConfigEntry<T> configEntry, T value) { this.constrainValue(configEntry.getChatCommandName(), value); }
private void constrainValue(String name, Object value)
{
this.values.put(name, value);
Entry entry = CONFIG_ENTRIES.get(name);
this.values.put(name, entry.valueConstrainer.apply(this.getValue(name), value));
}
private Map<String, ?> getValues()
@@ -34,9 +34,6 @@ public class FullDataPayloadReceiver implements AutoCloseable
})
.build().asMap();
public boolean hasIncompleteBuffers() { return !this.buffersById.isEmpty(); }
@Override
public void close()
{
@@ -746,6 +746,10 @@
"Maximum Data Transfer Speed, KB/s",
"distanthorizons.config.server.maxDataTransferSpeed.@tooltip":
"Maximum speed for uploading LODs to the clients, in KB/s.\nValue of 0 disables the limit.",
"distanthorizons.config.server.enableAdaptiveTransferSpeed":
"Enable Adaptive Transfer Speed",
"distanthorizons.config.server.enableAdaptiveTransferSpeed.@tooltip":
"Enables adaptive transfer speed based on client performance.\nIf true, DH will automatically adjust transfer rate to minimize connection lag.\nIf false, transfer speed will remain fixed.",
"distanthorizons.config.server.experimental":