Paper/patches/server/0396-Load-Chunks-for-Login-Asynchronously.patch

255 Zeilen
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 19 Apr 2020 04:28:29 -0400
Subject: [PATCH] Load Chunks for Login Asynchronously
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
2022-08-06 00:58:34 +02:00
index 084521ed853fc2b15be355a17da8421c54716815..acc64abd9420b81ed4c8c17cf6a9f5bc5d35f116 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
2022-07-27 22:17:18 +02:00
@@ -182,6 +182,7 @@ public class ServerPlayer extends Player {
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
public ServerGamePacketListenerImpl connection;
+ public net.minecraft.network.Connection networkManager; // Paper
public final MinecraftServer server;
public final ServerPlayerGameMode gameMode;
private final PlayerAdvancements advancements;
2022-07-27 22:17:18 +02:00
@@ -255,6 +256,7 @@ public class ServerPlayer extends Player {
public boolean joining = true;
public boolean sentListPacket = false;
public boolean supressTrackerForLogin = false; // Paper
+ public boolean didPlayerJoinEvent = false; // Paper
public Integer clientViewDistance;
public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java
index be677d437d17b74c6188ce1bd5fc6fdc228fd92f..78fbb4c3e52e900956ae0811aaf934c81ee5ea48 100644
--- a/src/main/java/net/minecraft/server/level/TicketType.java
+++ b/src/main/java/net/minecraft/server/level/TicketType.java
@@ -23,6 +23,7 @@ public class TicketType<T> {
public static final TicketType<ChunkPos> FORCED = TicketType.create("forced", Comparator.comparingLong(ChunkPos::toLong));
public static final TicketType<ChunkPos> LIGHT = TicketType.create("light", Comparator.comparingLong(ChunkPos::toLong));
public static final TicketType<BlockPos> PORTAL = TicketType.create("portal", Vec3i::compareTo, 300);
+ public static final TicketType<Long> LOGIN = create("login", Long::compareTo, 100); // Paper
public static final TicketType<Integer> POST_TELEPORT = TicketType.create("post_teleport", Integer::compareTo, 5);
public static final TicketType<ChunkPos> UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
public static final TicketType<Unit> PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
2022-08-06 00:58:34 +02:00
index 256a6734455e89154e817bbf82de0d1c928b21cd..76100b605715ae530339da61bde8af634aa60017 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
2022-07-27 22:17:18 +02:00
@@ -251,6 +251,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
private static final int PENDING_MESSAGE_DISCONNECT_THRESHOLD = 4096;
public final Connection connection;
private final MinecraftServer server;
+ public Runnable playerJoinReady; // Paper
public ServerPlayer player;
private int tickCount;
2022-06-08 06:39:43 +02:00
private int ackBlockChangesUpTo = -1;
2022-07-27 22:17:18 +02:00
@@ -343,6 +344,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
2022-07-27 22:17:18 +02:00
@Override
public void tick() {
+ // Paper start - login async
+ Runnable playerJoinReady = this.playerJoinReady;
+ if (playerJoinReady != null) {
+ this.playerJoinReady = null;
+ playerJoinReady.run();
+ }
+ // Don't tick if not valid (dead), otherwise we load chunks below
+ if (this.player.valid) {
+ // Paper end
2022-06-08 06:39:43 +02:00
if (this.ackBlockChangesUpTo > -1) {
this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo));
this.ackBlockChangesUpTo = -1;
2022-07-27 22:17:18 +02:00
@@ -389,7 +399,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
this.lastVehicle = null;
this.clientVehicleIsFloating = false;
this.aboveGroundVehicleTickCount = 0;
- }
+ }} // Paper - end if (valid)
this.server.getProfiler().push("keepAlive");
// Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
2022-08-06 00:58:34 +02:00
index 6629fee181b8d0c6ece3d23a028b971e98f8799b..ed384e8ce0050ace3a96a8a5cc6007a1af1720bb 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
2022-08-06 00:58:34 +02:00
@@ -91,7 +91,7 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
}
// Paper end
} else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId());
+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper
if (entityplayer == null) {
this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT;
2022-08-06 00:58:34 +02:00
@@ -200,7 +200,7 @@ public class ServerLoginPacketListenerImpl implements TickablePacketListener, Se
}
this.connection.send(new ClientboundGameProfilePacket(this.gameProfile));
- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId());
+ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper
try {
ServerPlayer entityplayer1 = this.server.getPlayerList().getPlayerForLogin(this.gameProfile, s); // CraftBukkit - add player reference
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
2022-08-06 00:58:34 +02:00
index b48641bbe371ffacbbd659a0ee1783437267a4dc..0d86536696657ba6eee5f12d3d3afa8e5a167060 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
2022-07-27 22:17:18 +02:00
@@ -139,6 +139,7 @@ public abstract class PlayerList {
private final IpBanList ipBans;
private final ServerOpList ops;
private final UserWhiteList whitelist;
+ private final Map<UUID, ServerPlayer> pendingPlayers = Maps.newHashMap(); // Paper
// CraftBukkit start
// private final Map<UUID, ServerStatisticManager> stats;
// private final Map<UUID, AdvancementDataPlayer> advancements;
2022-07-27 22:17:18 +02:00
@@ -178,6 +179,11 @@ public abstract class PlayerList {
}
public void placeNewPlayer(Connection connection, ServerPlayer player) {
+ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper
+ if (prev != null) {
+ disconnectPendingPlayer(prev);
+ }
+ player.networkManager = connection; // Paper
player.loginTime = System.currentTimeMillis(); // Paper
GameProfile gameprofile = player.getGameProfile();
GameProfileCache usercache = this.server.getProfileCache();
2022-07-27 22:17:18 +02:00
@@ -191,7 +197,7 @@ public abstract class PlayerList {
if (nbttagcompound != null && nbttagcompound.contains("bukkit")) {
CompoundTag bukkit = nbttagcompound.getCompound("bukkit");
s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s;
- }
+ }String lastKnownName = s; // Paper
// CraftBukkit end
if (nbttagcompound != null) {
2022-07-27 22:17:18 +02:00
@@ -218,11 +224,15 @@ public abstract class PlayerList {
if (nbttagcompound == null) player.fudgeSpawnLocation(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are....
player.setLevel(worldserver1);
- String s1 = "local";
+ // Paper start - make s1 final
+ final String s1;
if (connection.getRemoteAddress() != null) {
s1 = connection.getRemoteAddress().toString();
+ } else {
+ s1 = "local";
}
+ // Paper end
// Spigot start - spawn location event
Player spawnPlayer = player.getBukkitEntity();
2022-07-27 22:17:18 +02:00
@@ -264,6 +274,52 @@ public abstract class PlayerList {
player.getRecipeBook().sendInitialRecipeBook(player);
this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
this.server.invalidateStatus();
+ // Paper start - async load spawn in chunk
+ ServerLevel finalWorldserver = worldserver1;
+ int chunkX = loc.getBlockX() >> 4;
+ int chunkZ = loc.getBlockZ() >> 4;
+ final net.minecraft.world.level.ChunkPos pos = new net.minecraft.world.level.ChunkPos(chunkX, chunkZ);
+ net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap;
+ net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager;
2022-02-28 22:43:31 +01:00
+ distanceManager.addTicket(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong());
+ worldserver1.getChunkSource().runDistanceManagerUpdates();
+ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> {
+ net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong());
+ if (updatingChunk != null) {
2021-06-17 23:39:36 +02:00
+ return updatingChunk.getEntityTickingChunkFuture();
+ } else {
+ return java.util.concurrent.CompletableFuture.completedFuture(chunk);
+ }
+ }).thenAccept(chunk -> {
+ playerconnection.playerJoinReady = () -> {
+ postChunkLoadJoin(
+ player, finalWorldserver, connection, playerconnection,
+ nbttagcompound, s1, lastKnownName
+ );
+ };
+ });
+ }
+
+ public ServerPlayer getActivePlayer(UUID uuid) {
2021-06-17 19:11:00 +02:00
+ ServerPlayer player = this.playersByUUID.get(uuid);
+ return player != null ? player : pendingPlayers.get(uuid);
+ }
+
+ void disconnectPendingPlayer(ServerPlayer entityplayer) {
2022-06-08 06:39:43 +02:00
+ Component msg = Component.translatable("multiplayer.disconnect.duplicate_login");
2022-07-28 00:20:14 +02:00
+ entityplayer.networkManager.send(new net.minecraft.network.protocol.game.ClientboundDisconnectPacket(msg), net.minecraft.network.PacketSendListener.thenRun(() -> {
+ entityplayer.networkManager.disconnect(msg);
+ entityplayer.networkManager = null;
2022-07-28 00:20:14 +02:00
+ }));
+ }
+
+ private void postChunkLoadJoin(ServerPlayer player, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) {
+ pendingPlayers.remove(player.getUUID(), player);
+ if (!networkmanager.isConnected()) {
+ return;
+ }
+ player.didPlayerJoinEvent = true;
+ // Paper end
2022-06-08 06:39:43 +02:00
MutableComponent ichatmutablecomponent;
if (player.getGameProfile().getName().equalsIgnoreCase(s)) {
2022-07-28 00:10:27 +02:00
@@ -505,6 +561,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
+ if (!player.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug)
this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
2022-07-28 00:10:27 +02:00
@@ -532,7 +589,7 @@ public abstract class PlayerList {
}
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())));
- this.cserver.getPluginManager().callEvent(playerQuitEvent);
+ if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog)
2022-07-28 00:10:27 +02:00
@@ -577,6 +634,13 @@ public abstract class PlayerList {
// this.advancements.remove(uuid);
// CraftBukkit end
}
+ // Paper start
+ entityplayer1 = pendingPlayers.get(uuid);
+ if (entityplayer1 == entityplayer) {
+ pendingPlayers.remove(uuid);
+ }
+ entityplayer.networkManager = null;
+ // Paper end
// CraftBukkit start
// this.broadcastAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer}));
2022-07-28 00:10:27 +02:00
@@ -594,7 +658,7 @@ public abstract class PlayerList {
this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
// CraftBukkit end
- return playerQuitEvent.quitMessage(); // Paper - Adventure
+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join
}
// CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer
2022-07-28 00:10:27 +02:00
@@ -613,6 +677,13 @@ public abstract class PlayerList {
list.add(entityplayer);
}
}
+ // Paper start - check pending players too
+ entityplayer = pendingPlayers.get(uuid);
+ if (entityplayer != null) {
+ this.pendingPlayers.remove(uuid);
+ disconnectPendingPlayer(entityplayer);
+ }
+ // Paper end
Iterator iterator = list.iterator();