Skip to content

Commit

Permalink
Fix incorrect max player slot check
Browse files Browse the repository at this point in the history
Using the total number of users in the connection set
is not correct since those users may not be logged in
yet. Instead, track separately the number of users
who have passed the slot check.

Fixes #205
  • Loading branch information
Spottedleaf committed Mar 24, 2024
1 parent ad2ef00 commit b843a35
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 37 deletions.
67 changes: 37 additions & 30 deletions patches/server/0003-Threaded-Regions.patch
Original file line number Diff line number Diff line change
Expand Up @@ -15719,7 +15719,7 @@ index 45d4638d568ea2aee805aa1b0542533019e5870d..599feff33b43623d7c6bd22158afa730
date1 = fallback;
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d433ac7df25 100644
index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..08daa5ed0b4b599836b97eef1e53e630e7659443 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -132,10 +132,10 @@ public abstract class PlayerList {
Expand All @@ -15735,7 +15735,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
private final UserBanList bans;
private final IpBanList ipBans;
private final ServerOpList ops;
@@ -156,9 +156,56 @@ public abstract class PlayerList {
@@ -156,9 +156,63 @@ public abstract class PlayerList {

// CraftBukkit start
private CraftServer cserver;
Expand All @@ -15747,6 +15747,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
+ private final Object connectionsStateLock = new Object();
+ private final Map<String, Connection> connectionByName = new java.util.HashMap<>();
+ private final Map<UUID, Connection> connectionById = new java.util.HashMap<>();
+ private final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<Connection> usersCountedAgainstLimit = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>();
+
+ public boolean pushPendingJoin(String userName, UUID byId, Connection conn) {
+ userName = userName.toLowerCase(java.util.Locale.ROOT);
Expand Down Expand Up @@ -15780,20 +15781,26 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
+ synchronized (this.connectionsStateLock) {
+ this.connectionByName.remove(userName, conn);
+ this.connectionById.remove(byId, conn);
+ this.usersCountedAgainstLimit.remove(conn);
+ }
+ }
+
+ private int getTotalConnections() {
+ private boolean countConnection(Connection conn, int limit) {
+ synchronized (this.connectionsStateLock) {
+ return this.connectionById.size();
+ int count = this.usersCountedAgainstLimit.size();
+ if (count >= limit) {
+ return false;
+ }
+ this.usersCountedAgainstLimit.add(conn);
+ return true;
+ }
+ }
+ // Folia end - region threading
+
public PlayerList(MinecraftServer server, LayeredRegistryAccess<RegistryLayer> registryManager, PlayerDataStorage saveHandler, int maxPlayers) {
this.cserver = server.server = new CraftServer((DedicatedServer) server, this);
server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper
@@ -179,7 +226,7 @@ public abstract class PlayerList {
@@ -179,7 +233,7 @@ public abstract class PlayerList {
}
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor

Expand All @@ -15802,7 +15809,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
GameProfile gameprofile = player.getGameProfile();
@@ -258,18 +305,42 @@ public abstract class PlayerList {
@@ -258,18 +312,42 @@ public abstract class PlayerList {
player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
// Paper start - reset to main world spawn if first spawn or invalid world
}
Expand Down Expand Up @@ -15847,7 +15854,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43

Location loc = ev.getSpawnLocation();
worldserver1 = ((CraftWorld) loc.getWorld()).getHandle();
@@ -288,6 +359,10 @@ public abstract class PlayerList {
@@ -288,6 +366,10 @@ public abstract class PlayerList {

player.loadGameTypes(nbttagcompound);
ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, clientData);
Expand All @@ -15858,7 +15865,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
GameRules gamerules = worldserver1.getGameRules();
boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN);
boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
@@ -303,7 +378,7 @@ public abstract class PlayerList {
@@ -303,7 +385,7 @@ public abstract class PlayerList {
this.sendPlayerPermissionLevel(player);
player.getStats().markAllDirty();
player.getRecipeBook().sendInitialRecipeBook(player);
Expand All @@ -15867,7 +15874,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
this.server.invalidateStatus();
MutableComponent ichatmutablecomponent;

@@ -345,7 +420,7 @@ public abstract class PlayerList {
@@ -345,7 +427,7 @@ public abstract class PlayerList {
this.cserver.getPluginManager().callEvent(playerJoinEvent);

if (!player.connection.isAcceptingMessages()) {
Expand All @@ -15876,7 +15883,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
@@ -360,8 +435,7 @@ public abstract class PlayerList {
@@ -360,8 +442,7 @@ public abstract class PlayerList {
ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player

final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
Expand All @@ -15886,7 +15893,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43

if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
// Paper start - Add Listing API for Player
@@ -483,7 +557,7 @@ public abstract class PlayerList {
@@ -483,7 +564,7 @@ public abstract class PlayerList {
// Paper start - Configurable player collision; Add to collideRule team if needed
final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
Expand All @@ -15895,7 +15902,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
}
// Paper end - Configurable player collision
@@ -577,7 +651,7 @@ public abstract class PlayerList {
@@ -577,7 +658,7 @@ public abstract class PlayerList {

protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
Expand All @@ -15904,7 +15911,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit

@@ -617,7 +691,7 @@ public abstract class PlayerList {
@@ -617,7 +698,7 @@ public abstract class PlayerList {
// CraftBukkit end

// Paper start - Configurable player collision; Remove from collideRule team if needed
Expand All @@ -15913,7 +15920,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
if (entityplayer.getTeam() == team && team != null) {
@@ -657,7 +731,7 @@ public abstract class PlayerList {
@@ -657,7 +738,7 @@ public abstract class PlayerList {

entityplayer.unRide();
worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
Expand All @@ -15922,7 +15929,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
entityplayer.getAdvancements().stopListening();
this.players.remove(entityplayer);
this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
@@ -676,8 +750,7 @@ public abstract class PlayerList {
@@ -676,8 +757,7 @@ public abstract class PlayerList {
// CraftBukkit start
// this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())));
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()));
Expand All @@ -15932,7 +15939,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43

if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) {
entityplayer2.connection.send(packet);
@@ -702,19 +775,12 @@ public abstract class PlayerList {
@@ -702,19 +782,12 @@ public abstract class PlayerList {

ServerPlayer entityplayer;

Expand All @@ -15954,7 +15961,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

// Instead of kicking then returning, we need to store the kick reason
@@ -733,7 +799,7 @@ public abstract class PlayerList {
@@ -733,7 +806,7 @@ public abstract class PlayerList {

ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason());
if (gameprofilebanentry.getExpires() != null) {
Expand All @@ -15963,7 +15970,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

// return chatmessage;
@@ -746,14 +812,14 @@ public abstract class PlayerList {
@@ -746,14 +819,14 @@ public abstract class PlayerList {

ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason());
if (ipbanentry.getExpires() != null) {
Expand All @@ -15976,11 +15983,11 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
} else {
// return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null;
- if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) {
+ if (this.getTotalConnections() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { // Folia - region threading - we control connection state here now async, not player list size
+ if (!this.countConnection(loginlistener.connection, this.maxPlayers) && !this.canBypassPlayerLimit(gameprofile)) { // Folia - region threading - we control connection state here now async, not player list size
event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
}
}
@@ -819,6 +885,11 @@ public abstract class PlayerList {
@@ -819,6 +892,11 @@ public abstract class PlayerList {

public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) {
// Paper end - Expand PlayerRespawnEvent
Expand All @@ -15992,7 +15999,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
entityplayer.stopRiding(); // CraftBukkit
this.players.remove(entityplayer);
this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
@@ -1018,10 +1089,10 @@ public abstract class PlayerList {
@@ -1018,10 +1096,10 @@ public abstract class PlayerList {
public void tick() {
if (++this.sendAllPlayerInfoIn > 600) {
// CraftBukkit start
Expand All @@ -16006,7 +16013,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
@Override
public boolean test(ServerPlayer input) {
return target.getBukkitEntity().canSee(input.getBukkitEntity());
@@ -1047,18 +1118,17 @@ public abstract class PlayerList {
@@ -1047,18 +1125,17 @@ public abstract class PlayerList {

// CraftBukkit start - add a world/entity limited version
public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) {
Expand All @@ -16029,7 +16036,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

}
@@ -1102,8 +1172,7 @@ public abstract class PlayerList {
@@ -1102,8 +1179,7 @@ public abstract class PlayerList {
if (scoreboardteam == null) {
this.broadcastSystemMessage(message, false);
} else {
Expand All @@ -16039,7 +16046,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43

if (entityplayer.getTeam() != scoreboardteam) {
entityplayer.sendSystemMessage(message);
@@ -1114,10 +1183,12 @@ public abstract class PlayerList {
@@ -1114,10 +1190,12 @@ public abstract class PlayerList {
}

public String[] getPlayerNamesArray() {
Expand All @@ -16055,7 +16062,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

return astring;
@@ -1136,7 +1207,9 @@ public abstract class PlayerList {
@@ -1136,7 +1214,9 @@ public abstract class PlayerList {
ServerPlayer entityplayer = this.getPlayer(profile.getId());

if (entityplayer != null) {
Expand All @@ -16065,7 +16072,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

}
@@ -1146,7 +1219,10 @@ public abstract class PlayerList {
@@ -1146,7 +1226,10 @@ public abstract class PlayerList {
ServerPlayer entityplayer = this.getPlayer(profile.getId());

if (entityplayer != null) {
Expand All @@ -16076,7 +16083,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}

}
@@ -1207,8 +1283,7 @@ public abstract class PlayerList {
@@ -1207,8 +1290,7 @@ public abstract class PlayerList {
}

public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey<Level> worldKey, Packet<?> packet) {
Expand All @@ -16086,7 +16093,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43

// CraftBukkit start - Test if player receiving packet can see the source of the packet
if (player != null && !entityplayer.getBukkitEntity().canSee(player.getBukkitEntity())) {
@@ -1238,12 +1313,21 @@ public abstract class PlayerList {
@@ -1238,12 +1320,21 @@ public abstract class PlayerList {
io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
MinecraftTimings.savePlayers.startTiming(); // Paper
int numSaved = 0;
Expand All @@ -16113,7 +16120,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
}
// Paper end - Incremental chunk and player saving
}
@@ -1362,6 +1446,20 @@ public abstract class PlayerList {
@@ -1362,6 +1453,20 @@ public abstract class PlayerList {
}

public void removeAll(boolean isRestarting) {
Expand All @@ -16134,7 +16141,7 @@ index 1e5f709115007ff19901c0a6c3cf884d9e4d3a6c..12502d9db5bae29ed642e179f3a19d43
// Paper end
// CraftBukkit start - disconnect safely
for (ServerPlayer player : this.players) {
@@ -1371,7 +1469,7 @@ public abstract class PlayerList {
@@ -1371,7 +1476,7 @@ public abstract class PlayerList {
// CraftBukkit end

// Paper start - Configurable player collision; Remove collideRule team if it exists
Expand Down
4 changes: 2 additions & 2 deletions patches/server/0004-Max-pending-logins.patch
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ index 58cdb65083134680230d7070f9f6209f2d32873b..aa4b461bbb2c8c4753f7c9057bab1740

if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 12502d9db5bae29ed642e179f3a19d433ac7df25..ebbe5dda644a06bfd4769934e33402b2c009c7e2 100644
index 08daa5ed0b4b599836b97eef1e53e630e7659443..a390227e5af1232f2090d2be72f7789805025f76 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -172,6 +172,17 @@ public abstract class PlayerList {
@@ -173,6 +173,17 @@ public abstract class PlayerList {
conflictingId = this.connectionById.get(byId);

if (conflictingName == null && conflictingId == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ This allows the player to be re-positioned before logging into
the world without causing thread checks to trip on Folia.

diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index ebbe5dda644a06bfd4769934e33402b2c009c7e2..754de3a79e1d8f9e8a5aabef78319958a1c37f72 100644
index a390227e5af1232f2090d2be72f7789805025f76..bbf43b5844a75a25c1757cfb1c3c9dbe9b1fadde 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -515,7 +515,13 @@ public abstract class PlayerList {
@@ -522,7 +522,13 @@ public abstract class PlayerList {
CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle");
// CraftBukkit start
ServerLevel finalWorldServer = worldserver1;
Expand Down
6 changes: 3 additions & 3 deletions patches/server/0018-Region-profiler.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1779,18 +1779,18 @@ index f72e3d2decf8eb2a5a802bb1c6c8aa29e08912cf..81749b8da7182abd1bf35629f33388e8
} else {
passenger.stopRiding();
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 754de3a79e1d8f9e8a5aabef78319958a1c37f72..c8f8d41da92c08032ac3f78e002d081d6cd0b763 100644
index bbf43b5844a75a25c1757cfb1c3c9dbe9b1fadde..90be312057221a5a78066d89783c5e22008d797d 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1328,6 +1328,7 @@ public abstract class PlayerList {
@@ -1335,6 +1335,7 @@ public abstract class PlayerList {

public void saveAll(int interval) {
io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
+ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
MinecraftTimings.savePlayers.startTiming(); // Paper
int numSaved = 0;
long now = System.nanoTime(); // Folia - region threading
@@ -1339,7 +1340,9 @@ public abstract class PlayerList {
@@ -1346,7 +1347,9 @@ public abstract class PlayerList {
}
// Folia end - region threading
if (interval == -1 || now - entityplayer.lastSave >= timeInterval) { // Folia - region threading
Expand Down

0 comments on commit b843a35

Please sign in to comment.