9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-27 19:09:22 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0112-Leaves-Replay-Mod-API.patch
Dreeam 9a4efaa230 Drop patch that causes performance regression
Originally vanilla logic is to use stream, and Mojang switched it to Guava's Collections2
since 1.21.4. It is much faster than using stream or manually adding to a new ArrayList.
Manually adding to a new ArrayList requires allocating a new object array. However, the Collections2
lazy handles filter condition on iteration, so much better.
2025-08-04 19:25:56 +08:00

387 lines
25 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Thu, 3 Aug 2023 20:36:38 +0800
Subject: [PATCH] Leaves: Replay Mod API
Co-authored-by: alazeprt <nono135246@126.com>
Original license: GPLv3
Original project: https://github.com/LeavesMC/Leaves
This patch is Powered by ReplayMod(https://github.com/ReplayMod)
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
index 51caf352e77df49fc04bf84f1fab29b6f4f4fc14..3fb3afb4171e6ff57c73cd228c2b41b2cb543ea5 100644
--- a/net/minecraft/commands/CommandSourceStack.java
+++ b/net/minecraft/commands/CommandSourceStack.java
@@ -617,7 +617,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@Override
public Collection<String> getOnlinePlayerNames() {
- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player
}
@Override
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
index b305ba9bab617bf4e52d0e6ddf160bacc5751a94..bbaf1a29f86a9bfc13795249d545b6f7f1bb53eb 100644
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -128,11 +128,12 @@ public class EntitySelector {
return this.findPlayers(source);
} else if (this.playerName != null) {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null ? List.of() : List.of(playerByName);
} else if (this.entityUUID != null) {
for (ServerLevel serverLevel : source.getServer().getAllLevels()) {
Entity entity = serverLevel.getEntity(this.entityUUID);
- if (entity != null) {
+ if (entity != null && !(entity instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // Leaves - skip photographer
if (entity.getType().isEnabled(source.enabledFeatures())) {
return List.of(entity);
}
@@ -146,7 +147,7 @@ public class EntitySelector {
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
if (this.currentEntity) {
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
- return source.getEntity() != null && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of();
+ return source.getEntity() != null && !(source.getEntity() instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of(); // Leaves - skip photographer
} else {
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, source.enabledFeatures());
List<Entity> list = new ObjectArrayList<>();
@@ -157,6 +158,7 @@ public class EntitySelector {
this.addEntities(list, serverLevel1, absoluteAabb, predicate);
}
}
+ list.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
return this.sortAndLimit(vec3, list);
}
@@ -192,27 +194,29 @@ public class EntitySelector {
this.checkPermissions(source);
if (this.playerName != null) {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
} else if (this.entityUUID != null) {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null || !canSee(source, playerByName) ? List.of() : List.of(playerByName); // Purpur - Hide hidden players from entity selector
} else {
Vec3 vec3 = this.position.apply(source.getPosition());
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
if (this.currentEntity) {
- return source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer) && canSee(source, serverPlayer) ? List.of(serverPlayer) : List.of(); // Purpur - Hide hidden players from entity selector
+ return source.getEntity() instanceof ServerPlayer serverPlayer && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(serverPlayer) && canSee(source, serverPlayer) ? List.of(serverPlayer) : List.of(); // Purpur - Hide hidden players from entity selector // Leaves - skip photographer
} else {
int resultLimit = this.getResultLimit();
List<ServerPlayer> players;
if (this.isWorldLimited()) {
- players = source.getLevel().getPlayers(predicate, resultLimit);
+ players = source.getLevel().getPlayers((player -> !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(player)), resultLimit); // Leaves - skip photographer
players.removeIf(entityplayer3 -> !canSee(source, entityplayer3)); // Purpur - Hide hidden players from entity selector
} else {
players = new ObjectArrayList<>();
for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) {
- if (predicate.test(serverPlayer1) && canSee(source, serverPlayer1)) { // Purpur - Hide hidden players from entity selector
+ if (predicate.test(serverPlayer1) && canSee(source, serverPlayer1) && !(serverPlayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // Purpur - Hide hidden players from entity selector // Leaves - skip photographer
players.add(serverPlayer1);
if (players.size() >= resultLimit) {
return players;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 73c63330b67b3d16ceebc644ce177980af25266b..68b72a7461a89ba7bd29fc9bc98171fb7f990df8 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1642,7 +1642,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
private ServerStatus.Players buildPlayerStatus() {
- List<ServerPlayer> players = this.playerList.getPlayers();
+ List<ServerPlayer> players = this.playerList.realPlayers; // Leaves - only real player
int maxPlayers = this.getMaxPlayers();
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
index 9ecc19b8a7d4e6b27335b542308f78e5005b0e15..eee5aaca8219802a56b8ba08986da672c40dc8b4 100644
--- a/net/minecraft/server/PlayerAdvancements.java
+++ b/net/minecraft/server/PlayerAdvancements.java
@@ -167,6 +167,11 @@ public class PlayerAdvancements {
}
public boolean award(AdvancementHolder advancement, String criterionKey) {
+ // Leaves start - photographer can't get advancement
+ if (player instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
+ return false;
+ }
+ // Leaves end - photographer can't get advancement
boolean flag = false;
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
boolean isDone = orStartProgress.isDone();
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
index f2286b96b8f40b4588f817913c42ae7b4a92340f..dbe6c37642d35ac6ee8b428cf1e45878a5dfa9da 100644
--- a/net/minecraft/server/commands/OpCommand.java
+++ b/net/minecraft/server/commands/OpCommand.java
@@ -25,7 +25,7 @@ public class OpCommand {
(commandContext, suggestionsBuilder) -> {
PlayerList playerList = commandContext.getSource().getServer().getPlayerList();
return SharedSuggestionProvider.suggest(
- playerList.getPlayers()
+ playerList.realPlayers // Leaves - only real player
.stream()
.filter(serverPlayer -> !playerList.isOp(serverPlayer.getGameProfile()))
.map(serverPlayer -> serverPlayer.getGameProfile().getName()),
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 95c128f028c3cce7d0b37821a6e75208323fb4e9..2cf0fa70ae3d7675cac3cf7a0002097b4e773fe1 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -215,6 +215,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
public boolean hasRidableMoveEvent = false; // Purpur - Ridables
+ final List<ServerPlayer> realPlayers; // Leaves - skip
@Override
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
@@ -694,6 +695,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - rewrite chunk system
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
+ this.realPlayers = Lists.newArrayList(); // Leaves - skip
}
// Paper start
@@ -2735,6 +2737,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
+ // Leaves start - skip
+ if (!(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
+ ServerLevel.this.realPlayers.add(serverPlayer);
+ }
+ // Leaves end - skip
if (serverPlayer.isReceivingWaypoints()) {
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
}
@@ -2813,6 +2820,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
+ // Leaves start - skip
+ if (!(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
+ ServerLevel.this.realPlayers.remove(serverPlayer);
+ }
+ // Leaves end - skip
ServerLevel.this.getWaypointManager().removePlayer(serverPlayer);
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 880bf83929e636872eeb53c5c3ec9357972267db..47d9495ea2cf347f268bd84bf731c5b5ec63ead1 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -216,7 +216,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private static final boolean DEFAULT_SEEN_CREDITS = false;
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
public ServerGamePacketListenerImpl connection;
- private final MinecraftServer server;
+ public final MinecraftServer server; // Leaves - private -> public
public ServerPlayerGameMode gameMode;
private final PlayerAdvancements advancements;
private final ServerStatsCounter stats;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index a2d5b58eef4b6def8032d2421f8f3d34e64cb70e..10502ed26662f13fafcafc644aecd98828ef4aec 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -131,6 +131,7 @@ public abstract class PlayerList {
private boolean allowCommandsForAllPlayers;
private static final boolean ALLOW_LOGOUTIVATOR = false;
private int sendAllPlayerInfoIn;
+ public final List<ServerPlayer> realPlayers = new java.util.concurrent.CopyOnWriteArrayList(); // Leaves - replay api
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -149,6 +150,112 @@ public abstract class PlayerList {
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
+ // Leaves start - replay mod api
+ public void placeNewPhotographer(Connection connection, org.leavesmc.leaves.replay.ServerPhotographer player, ServerLevel worldserver) {
+ player.isRealPlayer = true; // Paper
+ player.loginTime = System.currentTimeMillis(); // Paper
+
+ ServerLevel worldserver1 = worldserver;
+
+ player.setServerLevel(worldserver1);
+ player.spawnIn(worldserver1);
+ player.gameMode.setLevel((ServerLevel) player.level());
+
+ LevelData worlddata = worldserver1.getLevelData();
+
+ player.loadGameTypes(null);
+ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, CommonListenerCookie.createInitial(player.gameProfile, false));
+ GameRules gamerules = worldserver1.getGameRules();
+ boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN);
+ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
+ boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
+
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1), this.server.enforceSecureProfile())); // Paper - replace old player chunk management
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
+ RecipeManager craftingmanager = this.server.getRecipeManager();
+ playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes()));
+
+ this.sendPlayerPermissionLevel(player);
+ player.getStats().markAllDirty();
+ player.getRecipeBook().sendInitialRecipeBook(player);
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
+ this.server.invalidateStatus();
+
+ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
+ ServerStatus serverping = this.server.getStatus();
+
+ if (serverping != null) {
+ player.sendServerStatus(serverping);
+ }
+
+ this.players.add(player);
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
+ this.playersByUUID.put(player.getUUID(), player);
+
+ player.supressTrackerForLogin = true;
+ worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
+
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
+ if (!player.connection.isAcceptingMessages()) {
+ return;
+ }
+
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
+ for (int i = 0; i < this.players.size(); ++i) {
+ ServerPlayer entityplayer1 = this.players.get(i);
+
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) {
+ continue;
+ }
+
+ // Leaves start - skip photographer
+ if (entityplayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
+ continue;
+ }
+ // Leaves end - skip photographer
+
+ onlinePlayers.add(entityplayer1);
+ }
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
+ }
+
+ player.sentListPacket = true;
+ player.supressTrackerForLogin = false;
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player);
+
+ this.sendLevelInfo(player, worldserver1);
+
+ if (player.level() == worldserver1 && !worldserver1.players().contains(player)) {
+ worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ }
+
+ worldserver1 = player.level();
+ java.util.Iterator<net.minecraft.world.effect.MobEffectInstance> iterator = player.getActiveEffects().iterator();
+ while (iterator.hasNext()) {
+ MobEffectInstance mobeffect = iterator.next();
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect, false));
+ }
+
+ if (player.isDeadOrDying()) {
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
+ worldserver1.getLightEngine(), null, null, false)
+ );
+ }
+ }
+ // Leaves end - replay mod api
+
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -318,6 +425,7 @@ public abstract class PlayerList {
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
+ this.realPlayers.add(player); // Leaves - replay api
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
this.addToSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
@@ -522,6 +630,43 @@ public abstract class PlayerList {
}
}
+ // Leaves start - replay mod api
+ public void removePhotographer(org.leavesmc.leaves.replay.ServerPhotographer entityplayer) {
+ ServerLevel worldserver = entityplayer.level();
+
+ entityplayer.awardStat(Stats.LEAVE_GAME);
+
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT);
+ }
+
+ if (server.isSameThread()) entityplayer.doTick();
+
+ if (this.collideRuleTeamName != null) {
+ 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) {
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
+ }
+ }
+
+ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
+ entityplayer.retireScheduler();
+ entityplayer.getAdvancements().stopListening();
+ this.players.remove(entityplayer);
+ this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT));
+ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer);
+ UUID uuid = entityplayer.getUUID();
+ ServerPlayer entityplayer1 = this.playersByUUID.get(uuid);
+
+ if (entityplayer1 == entityplayer) {
+ this.playersByUUID.remove(uuid);
+ }
+
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
+ }
+ // Leaves stop - replay mod api
+
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
// Paper start - Fix kick event leave message not being sent
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
@@ -596,6 +741,7 @@ public abstract class PlayerList {
player.retireScheduler(); // Paper - Folia schedulers
player.getAdvancements().stopListening();
this.players.remove(player);
+ this.realPlayers.remove(player); // Leaves - replay api
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
this.removeFromSendAllPlayerInfoBuckets(player); // Gale - Purpur - spread out sending all player info
this.server.getCustomBossEvents().onPlayerDisconnect(player);
@@ -1092,7 +1238,7 @@ public abstract class PlayerList {
// Paper start - whitelist verify event / login event
public LoginResult canBypassFullServerLogin(final GameProfile profile, final LoginResult currentResult) {
- final boolean shouldKick = this.players.size() >= this.maxPlayers && !(/*player.hasPermission("purpur.joinfullserver") || */this.canBypassPlayerLimit(profile)); // Purpur - Allow player join full server by permission TODO: this hasn't worked for a while, so comment it out until we can reliably check perms of the player joining
+ final boolean shouldKick = this.realPlayers.size() >= this.maxPlayers && !(/*player.hasPermission("purpur.joinfullserver") || */this.canBypassPlayerLimit(profile)); // Purpur - Allow player join full server by permission TODO: this hasn't worked for a while, so comment it out until we can reliably check perms of the player joining // Leaves - only real player
final io.papermc.paper.event.player.PlayerServerFullCheckEvent fullCheckEvent = new io.papermc.paper.event.player.PlayerServerFullCheckEvent(
com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(profile),
io.papermc.paper.adventure.PaperAdventure.asAdventure(currentResult.message),