Added manual-max-players to the config, which allows you to set a max player count for servers/groups

This commit is contained in:
ajgeiss0702
2023-07-31 17:53:28 -07:00
parent f3349426a2
commit 7ff604f005
9 changed files with 159 additions and 52 deletions
@@ -598,9 +598,10 @@ public class QueueManagerImpl implements QueueManager {
final ConcurrentHashMap<AdaptedPlayer, Long> sendingNowAntiSpam = new ConcurrentHashMap<>();
final Map<QueuePlayer, Integer> sendingAttempts = new WeakHashMap<>();
final Map<QueuePlayer, Long> makeRoomAntispam = new WeakHashMap<>();
@Override
public void sendPlayers(QueueServer queueServer) {
public synchronized void sendPlayers(QueueServer queueServer) {
List<QueueServer> sendingServers;
if(queueServer == null) {
sendingServers = new ArrayList<>(servers);
@@ -633,7 +634,10 @@ public class QueueManagerImpl implements QueueManager {
continue;
}
if(selected.isFull() && !selected.canJoinFull(p.getPlayer())) continue;
if(
(selected.isFull() && !selected.canJoinFull(player)) ||
(server.isManuallyFull() && !AdaptedServer.canJoinFull(player, server.getName()))
) continue;
player.sendMessage(msgs.getComponent("status.sending-now", "SERVER:"+server.getAlias()));
Debug.info("Calling player.connect for " + player.getName() + "(send when back online)");
@@ -683,23 +687,33 @@ public class QueueManagerImpl implements QueueManager {
if(!server.canAccess(nextPlayer)) continue;
if(
selected.isFull() &&
!selected.canJoinFull(nextPlayer) &&
(
(selected.isFull() && !selected.canJoinFull(nextPlayer)) ||
(server.isManuallyFull() && !AdaptedServer.canJoinFull(nextPlayer, server.getName()))
) &&
!(
nextPlayer.hasPermission("ajqueue.make-room") &&
main.getConfig().getBoolean("enable-make-room-permission")
main.getConfig().getBoolean("enable-make-room-permission") &&
(!server.isGroup() || server.isManuallyFull()) // only use make-room on groups if the server is manually full
)
) continue;
// ajqueue.make-room logic
if(
selected.isFull() &&
!selected.canJoinFull(nextPlayer) &&
(
(selected.isFull() && !selected.canJoinFull(nextPlayer)) ||
(server.isManuallyFull() && !AdaptedServer.canJoinFull(nextPlayer, server.getName()))
) &&
main.getConfig().getBoolean("enable-make-room-permission") &&
nextPlayer.hasPermission("ajqueue.make-room") &&
!server.isGroup()
(!server.isGroup() || server.isManuallyFull()) && // only use make-room on groups if the server is manually full
( // don't make room more than the minimum ping time
System.currentTimeMillis() - makeRoomAntispam.getOrDefault(nextQueuePlayer, 0L)
>= (main.getConfig().getDouble("minimum-ping-time") * 1e3)
)
) {
makeRoomAntispam.put(nextQueuePlayer, System.currentTimeMillis());
List<AdaptedPlayer> players = selected.getPlayers();
// first, we need to find what the lowest priority on the server is
@@ -11,14 +11,13 @@ import us.ajg0702.queue.api.server.AdaptedServerPing;
import us.ajg0702.queue.common.QueueMain;
import us.ajg0702.queue.common.players.QueuePlayerImpl;
import us.ajg0702.queue.common.queues.balancers.DefaultBalancer;
import us.ajg0702.queue.common.queues.balancers.FirstBalancer;
import us.ajg0702.queue.common.queues.balancers.MinigameBalancer;
import us.ajg0702.queue.common.utils.Debug;
import us.ajg0702.utils.common.Messages;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
public class QueueServerImpl implements QueueServer {
@@ -38,6 +37,9 @@ public class QueueServerImpl implements QueueServer {
private long lastSentTime = 0;
private int manualMaxPlayers = Integer.MAX_VALUE;
public QueueServerImpl(String name, QueueMain main, AdaptedServer server, List<QueuePlayer> previousPlayers) {
this(name, main, Collections.singletonList(server), previousPlayers);
}
@@ -55,11 +57,13 @@ public class QueueServerImpl implements QueueServer {
String balancerType = type.substring(colon+1);
if(groupName.equals(name)) {
//noinspection SwitchStatementWithTooFewBranches
switch(balancerType.toLowerCase(Locale.ROOT)) {
case "minigame":
balancer = new MinigameBalancer(this, main);
break;
case "first":
balancer = new FirstBalancer(this, main);
break;
default:
balancerType = "default";
balancer = new DefaultBalancer(this, main);
@@ -73,6 +77,26 @@ public class QueueServerImpl implements QueueServer {
Debug.info("Using default balancer for "+name);
}
List<String> manualLimits = main.getConfig().getStringList("manual-max-players");
for (String manualLimit : manualLimits) {
String[] parts = manualLimit.split(":");
if(parts.length != 2) {
main.getLogger().warn("Invalid manual limit: " + manualLimit);
continue;
}
String limitFor = parts[0];
if(!limitFor.equals(name)) continue;
String limitStr = parts[1];
try {
manualMaxPlayers = Integer.parseInt(limitStr);
} catch(NumberFormatException e) {
main.getLogger().warn("Invalid limit number for " + limitFor);
}
break;
}
for(QueuePlayer queuePlayer : previousPlayers) {
if(queuePlayer.getPlayer() == null) {
addPlayer(
@@ -123,7 +147,7 @@ public class QueueServerImpl implements QueueServer {
return msgs.getString("status.offline.whitelisted");
}
if(server.isFull() && !server.canJoinFull(p)) {
if((server.isFull() && !server.canJoinFull(p)) || (isManuallyFull() && !AdaptedServer.canJoinFull(p, getName()))) {
return msgs.getString("status.offline.full");
}
@@ -159,7 +183,7 @@ public class QueueServerImpl implements QueueServer {
return "whitelisted";
}
if(server.isFull() && !server.canJoinFull(p)) {
if(((server.isFull() && !server.canJoinFull(p)) || (isManuallyFull() && !AdaptedServer.canJoinFull(p, getName())))) {
return "full";
}
@@ -186,11 +210,31 @@ public class QueueServerImpl implements QueueServer {
@Override
public boolean isJoinable(AdaptedPlayer p) {
if(isManuallyFull() && !AdaptedServer.canJoinFull(p, getName())) return false;
AdaptedServer server = getIdealServer(p);
if(server == null) return false;
return server.isJoinable(p) && !isPaused();
}
@Override
public int getManualMaxPlayers() {
return manualMaxPlayers;
}
@Override
public boolean isManuallyFull() {
int total = 0;
for (AdaptedServer server : servers) {
Optional<AdaptedServerPing> lastPing = server.getLastPing();
if(!lastPing.isPresent()) continue;
total += lastPing.get().getPlayerCount();
}
// Debug.info(total + " >= " + getManualMaxPlayers() + " = " + (total >= getManualMaxPlayers()));
return total >= getManualMaxPlayers();
}
@Override
public synchronized void setPaused(boolean paused) {
this.paused = paused;
@@ -272,6 +316,11 @@ public class QueueServerImpl implements QueueServer {
return ImmutableList.copyOf(names);
}
@Override
public boolean isOnline() {
return QueueServer.super.isOnline();
}
@Override
public boolean isGroup() {
return servers.size() > 1;
@@ -0,0 +1,37 @@
package us.ajg0702.queue.common.queues.balancers;
import org.jetbrains.annotations.Nullable;
import us.ajg0702.queue.api.players.AdaptedPlayer;
import us.ajg0702.queue.api.queues.Balancer;
import us.ajg0702.queue.api.queues.QueueServer;
import us.ajg0702.queue.api.server.AdaptedServer;
import us.ajg0702.queue.common.QueueMain;
public class FirstBalancer implements Balancer {
private final QueueServer server;
private final QueueMain main;
public FirstBalancer(QueueServer server, QueueMain main) {
this.server = server;
this.main = main;
}
@Override
public AdaptedServer getIdealServer(@Nullable AdaptedPlayer player) {
AdaptedServer alreadyConnected;
if(player == null) {
alreadyConnected = null;
} else {
alreadyConnected = player.getCurrentServer();
}
for (AdaptedServer sv : server.getServers()) {
if(!sv.isOnline()) continue;
if(sv.equals(alreadyConnected)) continue;
if(!sv.isJoinable(player)) continue;
return sv;
}
// If all servers are unavailable, just select the first one
return server.getServers().get(0);
}
}
+15 -5
View File
@@ -91,6 +91,14 @@ queue-servers:
# Default: true
kick-kicked-players: true
# This option allows you to manually set player caps for servers
# Note that this does NOT override the player cap returned by the server.
# Format: - '<server>:<max-players>'
# Example: - 'lobbys:50'
# The example above will limit the lobbys group to have a total of 50 players.
# This works on both groups and individual servers
manual-max-players: []
# Server groups are a group of servers that you can queue for. It will send you to the server that is the least full.
# If all servers in the group are full, it will act the same as it would when a single server is full.
@@ -101,10 +109,12 @@ server-groups:
# What balancer should we use for groups?
# If a group is not specified here, then the default one is used
# Example entry: - "bedwars:minigame"
# Example: - "bedwars:minigame"
# The example above will set the bedwars group to use the minigame balancer
# Balancers:
# default - Will send the player to the server in the group with the least number of players
# minigame - Will send the player to the server with the most players, until that server is full, which it will then send to the next server
# first - Will send the player to the first available server in the group (as long as it is joinable)
balancer-types:
- "bedwars:minigame"
@@ -211,12 +221,12 @@ wait-to-load-servers: false
# How long should we wait after the server finishes loading to load the server list?
# Only works if the above is enabled.
# This is in miliseconds so 1000 = 1 second
# This is in milliseconds so 1000 = 1 second
# Default: 500
wait-to-load-servers-delay: 500
# How often (in seconds) we should check for new servers to add queues for.
# If you dynamicly add servers, set this to something other than 0.
# If you dynamically add servers, set this to something other than 0.
# To disable, set to 0
# Default: 0
reload-servers-interval: 0
@@ -296,7 +306,7 @@ make-room-kick-to: lobby
# For the make-room permission, players with the lowest priority are kicked first.
# Of those players, this option decides which to kick.
# true - kick players who have been on the server the longest
# false - kick players who have been on nthe server the shortest
# false - kick players who have been on the server the shortest
# Default: true
make-room-kick-longest-playtime: true
@@ -367,7 +377,7 @@ debug: false
# Don't touch this number please
config-version: 41
config-version: 42
# This is ONLY here so that they can be moved to messages.yml. Please edit these in messages.yml!