Add global bandwidth limit setting
This commit is contained in:
@@ -1722,11 +1722,19 @@ public class Config
|
||||
|
||||
|
||||
// Common
|
||||
public static ConfigEntry<Integer> maxDataTransferSpeed = new ConfigEntry.Builder<Integer>()
|
||||
.setChatCommandName("common.maxDataTransferSpeed")
|
||||
public static ConfigEntry<Integer> playerBandwidthLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setChatCommandName("common.playerBandwidthLimit")
|
||||
.setMinDefaultMax(0, 500, 1000000 /* 1 GB/s */)
|
||||
.comment(""
|
||||
+ "Maximum speed for uploading LODs to the clients, in KB/s.\n"
|
||||
+ "Maximum per-player speed for uploading LODs to the clients, in KB/s.\n"
|
||||
+ "Value of 0 disables the limit."
|
||||
+ "")
|
||||
.build();
|
||||
public static ConfigEntry<Integer> globalBandwidthLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setChatCommandName("common.globalBandwidthLimit")
|
||||
.setMinDefaultMax(0, 0, 10000000 /* 10 GB/s */)
|
||||
.comment(""
|
||||
+ "Maximum global speed for uploading LODs to the clients, in KB/s.\n"
|
||||
+ "Value of 0 disables the limit."
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ public class ClientNetworkState implements Closeable
|
||||
|
||||
if (Config.Server.enableAdaptiveTransferSpeed.get())
|
||||
{
|
||||
sessionConfig.constrainValue(Config.Server.maxDataTransferSpeed, this.congestionControl.getDesiredRate());
|
||||
sessionConfig.constrainValue(Config.Server.playerBandwidthLimit, this.congestionControl.getDesiredRate());
|
||||
}
|
||||
|
||||
if (blocking)
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class SessionConfig implements INetworkObject
|
||||
registerConfigEntry(Config.Server.maxSyncOnLoadRequestDistance, Math::min);
|
||||
registerConfigEntry(Config.Server.syncOnLoadRateLimit, Math::min);
|
||||
|
||||
registerConfigEntry(Config.Server.maxDataTransferSpeed, (x, y) -> {
|
||||
registerConfigEntry(Config.Server.playerBandwidthLimit, (x, y) -> {
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -80,7 +80,7 @@ public class SessionConfig implements INetworkObject
|
||||
public int getMaxSyncOnLoadDistance() { return this.getValue(Config.Server.maxSyncOnLoadRequestDistance); }
|
||||
public int getSyncOnLoginRateLimit() { return this.getValue(Config.Server.syncOnLoadRateLimit); }
|
||||
|
||||
public int getMaxDataTransferSpeed() { return this.getValue(Config.Server.maxDataTransferSpeed); }
|
||||
public int getPlayerBandwidthLimit() { return this.getValue(Config.Server.playerBandwidthLimit); }
|
||||
|
||||
|
||||
|
||||
|
||||
+12
-5
@@ -8,7 +8,6 @@ import io.netty.buffer.ByteBuf;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.*;
|
||||
|
||||
public class FullDataPayloadSender implements AutoCloseable
|
||||
@@ -26,11 +25,14 @@ public class FullDataPayloadSender implements AutoCloseable
|
||||
private final IntSupplier maxKBpsSupplier;
|
||||
private final ConcurrentLinkedQueue<PendingTransfer> transferQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private final SharedBandwidthLimit sharedBandwidthLimit;
|
||||
|
||||
public FullDataPayloadSender(NetworkSession session, IntSupplier maxKBpsSupplier)
|
||||
|
||||
public FullDataPayloadSender(NetworkSession session, IntSupplier maxKBpsSupplier, SharedBandwidthLimit sharedBandwidthLimit)
|
||||
{
|
||||
this.session = session;
|
||||
this.maxKBpsSupplier = maxKBpsSupplier;
|
||||
this.sharedBandwidthLimit = sharedBandwidthLimit;
|
||||
UPLOAD_TIMER.scheduleAtFixedRate(this.tickTimerTask, 0, 1000 / TICK_RATE);
|
||||
}
|
||||
|
||||
@@ -48,11 +50,16 @@ public class FullDataPayloadSender implements AutoCloseable
|
||||
|
||||
private void tick()
|
||||
{
|
||||
int convertedMaxRate = this.maxKBpsSupplier.getAsInt();
|
||||
convertedMaxRate = convertedMaxRate > 0 ? convertedMaxRate : Integer.MAX_VALUE / 1000;
|
||||
int bandwidthShare = this.sharedBandwidthLimit.getBandwidthShare();
|
||||
int maxPlayerRate = Math.min(this.maxKBpsSupplier.getAsInt(), bandwidthShare);
|
||||
|
||||
// + 1 to account for rounding errors on values of < 4
|
||||
int bytesToSend = (convertedMaxRate * 1000) / TICK_RATE + 1;
|
||||
int bytesToSend = maxPlayerRate > 0
|
||||
? (maxPlayerRate * 1000) / TICK_RATE + 1
|
||||
: Integer.MAX_VALUE;
|
||||
|
||||
this.sharedBandwidthLimit.setSenderActive(this, bytesToSend > 0);
|
||||
|
||||
while (bytesToSend > 0)
|
||||
{
|
||||
PendingTransfer pendingTransfer = this.transferQueue.peek();
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.seibel.distanthorizons.core.multiplayer.fullData;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SharedBandwidthLimit
|
||||
{
|
||||
private final Set<FullDataPayloadSender> senders = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
public void setSenderActive(FullDataPayloadSender sender, boolean active)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
this.senders.add(sender);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.senders.remove(sender);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBandwidthShare()
|
||||
{
|
||||
int globalBandwidthLimit = Config.Server.globalBandwidthLimit.get();
|
||||
if (globalBandwidthLimit == 0)
|
||||
{
|
||||
globalBandwidthLimit = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
return globalBandwidthLimit / Math.max(this.senders.size(), 1);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -5,6 +5,7 @@ import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
|
||||
import com.seibel.distanthorizons.core.level.AbstractDhServerLevel;
|
||||
import com.seibel.distanthorizons.core.multiplayer.config.SessionConfig;
|
||||
import com.seibel.distanthorizons.core.multiplayer.fullData.FullDataPayloadSender;
|
||||
import com.seibel.distanthorizons.core.multiplayer.fullData.SharedBandwidthLimit;
|
||||
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.CloseReasonMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.LevelInitMessage;
|
||||
@@ -48,10 +49,10 @@ public class ServerPlayerState implements Closeable
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public ServerPlayerState(IServerPlayerWrapper serverPlayer)
|
||||
public ServerPlayerState(IServerPlayerWrapper serverPlayer, SharedBandwidthLimit sharedBandwidthLimit)
|
||||
{
|
||||
this.networkSession = new NetworkSession(serverPlayer);
|
||||
this.fullDataPayloadSender = new FullDataPayloadSender(this.networkSession, this.sessionConfig::getMaxDataTransferSpeed);
|
||||
this.fullDataPayloadSender = new FullDataPayloadSender(this.networkSession, this.sessionConfig::getPlayerBandwidthLimit, sharedBandwidthLimit);
|
||||
|
||||
this.networkSession.registerHandler(SessionConfigMessage.class, (sessionConfigMessage) ->
|
||||
{
|
||||
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
package com.seibel.distanthorizons.core.multiplayer.server;
|
||||
|
||||
import com.seibel.distanthorizons.core.multiplayer.fullData.SharedBandwidthLimit;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -16,6 +17,7 @@ public class ServerPlayerStateManager
|
||||
private final ConcurrentMap<IServerPlayerWrapper, ServerPlayerState> connectedPlayerStateByPlayerWrapper = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<IServerPlayerWrapper, MessageQueueState> messageQueueByPlayerWrapper = new ConcurrentHashMap<>();
|
||||
|
||||
private final SharedBandwidthLimit sharedBandwidthLimit = new SharedBandwidthLimit();
|
||||
|
||||
|
||||
//========================//
|
||||
@@ -24,7 +26,7 @@ public class ServerPlayerStateManager
|
||||
|
||||
public ServerPlayerState registerJoinedPlayer(IServerPlayerWrapper serverPlayer)
|
||||
{
|
||||
ServerPlayerState playerState = new ServerPlayerState(serverPlayer);
|
||||
ServerPlayerState playerState = new ServerPlayerState(serverPlayer, this.sharedBandwidthLimit);
|
||||
this.connectedPlayerStateByPlayerWrapper.put(serverPlayer, playerState);
|
||||
return playerState;
|
||||
}
|
||||
|
||||
@@ -750,10 +750,14 @@
|
||||
"distanthorizons.config.server.maxSyncOnLoadRequestDistance.@tooltip":
|
||||
"Defines the distance allowed to be synchronized around the player.\nShould be the same or larger than maxGenerationRequestDistance in most cases.",
|
||||
|
||||
"distanthorizons.config.server.maxDataTransferSpeed":
|
||||
"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.playerBandwidthLimit":
|
||||
"Per-player Bandwidth Limit, KB/s",
|
||||
"distanthorizons.config.server.playerBandwidthLimit.@tooltip":
|
||||
"Maximum per-player speed for uploading LODs to the clients, in KB/s.\nValue of 0 disables the limit.",
|
||||
"distanthorizons.config.server.globalBandwidthLimit":
|
||||
"Global Bandwidth Limit, KB/s",
|
||||
"distanthorizons.config.server.globalBandwidthLimit.@tooltip":
|
||||
"Maximum global 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":
|
||||
|
||||
Reference in New Issue
Block a user