mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-05 10:20:53 +01:00
597263fd55
Still need to send keep alives and kick for idle Fixes #3299
259 lines
14 KiB
Diff
259 lines
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/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
|
index 324fd07bcee9fed7bdb5b2b47ef01ce341282c93..01330045c0f3e0993af66c5a34c2a0246003758b 100644
|
|
--- a/src/main/java/net/minecraft/server/Entity.java
|
|
+++ b/src/main/java/net/minecraft/server/Entity.java
|
|
@@ -1382,7 +1382,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
|
this.pitch = MathHelper.a(f1, -90.0F, 90.0F) % 360.0F;
|
|
this.lastYaw = this.yaw;
|
|
this.lastPitch = this.pitch;
|
|
- world.getChunkAt((int) Math.floor(this.locX) >> 4, (int) Math.floor(this.locZ) >> 4); // CraftBukkit
|
|
+ if (valid) world.getChunkAt((int) Math.floor(this.locX) >> 4, (int) Math.floor(this.locZ) >> 4); // CraftBukkit // Paper
|
|
}
|
|
|
|
public void setPositionRotation(BlockPosition blockposition, float f, float f1) {
|
|
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
index 45df816980cd880b257632f0c4a381d475d2dfbd..48bbaec4b64bede8d280bd866436f5528578013e 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
@@ -43,6 +43,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
public String locale = null; // CraftBukkit - lowercase // Paper - default to null
|
|
public PlayerConnection playerConnection;
|
|
+ public NetworkManager networkManager; // Paper
|
|
public final MinecraftServer server;
|
|
public final PlayerInteractManager playerInteractManager;
|
|
public final Deque<Integer> removeQueue = new ArrayDeque<>(); // Paper
|
|
@@ -101,6 +102,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
public boolean joining = true;
|
|
public boolean sentListPacket = false;
|
|
public boolean supressTrackerForLogin = false; // Paper
|
|
+ public boolean didPlayerJoinEvent = false; // Paper
|
|
public Integer clientViewDistance;
|
|
// CraftBukkit end
|
|
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
|
diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java
|
|
index f1222fcb2bd52b8781d0f92c94e1472fa7b1e493..28f48f22522ef8c3c66381abcf017f0859b45290 100644
|
|
--- a/src/main/java/net/minecraft/server/LoginListener.java
|
|
+++ b/src/main/java/net/minecraft/server/LoginListener.java
|
|
@@ -66,7 +66,7 @@ public class LoginListener implements PacketLoginInListener {
|
|
}
|
|
// Paper end
|
|
} else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) {
|
|
- EntityPlayer entityplayer = this.server.getPlayerList().a(this.i.getId());
|
|
+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper
|
|
|
|
if (entityplayer == null) {
|
|
this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT;
|
|
@@ -165,7 +165,7 @@ public class LoginListener implements PacketLoginInListener {
|
|
}
|
|
|
|
this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i));
|
|
- EntityPlayer entityplayer = this.server.getPlayerList().a(this.i.getId());
|
|
+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper
|
|
|
|
if (entityplayer != null) {
|
|
this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT;
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
index 2e81f3a1d93d66c94e9f0d425f9cee6db4940913..d77b28ab4a5fc93a325a0d5594f66f4f143bd318 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
@@ -69,6 +69,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
public final NetworkManager networkManager;
|
|
private final MinecraftServer minecraftServer;
|
|
+ Runnable playerJoinReady; // Paper
|
|
public EntityPlayer player;
|
|
private int e;
|
|
private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER
|
|
@@ -142,6 +143,15 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
// CraftBukkit end
|
|
|
|
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
|
|
this.syncPosition();
|
|
this.player.lastX = this.player.locX();
|
|
this.player.lastY = this.player.locY();
|
|
@@ -183,7 +193,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
this.r = null;
|
|
this.D = false;
|
|
this.E = 0;
|
|
- }
|
|
+ }} // Paper - end if (valid)
|
|
|
|
this.minecraftServer.getMethodProfiler().enter("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/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
|
|
index 6a4e4f93eb36ca388523a36abf38bcae3ad375e8..61c7f5f9528ceea34af8dbf4503b9c320b7f67a1 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
|
@@ -52,11 +52,12 @@ public abstract class PlayerList {
|
|
private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
|
|
private final MinecraftServer server;
|
|
public final List<EntityPlayer> players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety
|
|
- private final Map<UUID, EntityPlayer> j = Maps.newHashMap();
|
|
+ private final Map<UUID, EntityPlayer> j = Maps.newHashMap();Map<UUID, EntityPlayer> getUUIDMap() { return j; } // Paper - OBFHELPER
|
|
private final GameProfileBanList k;
|
|
private final IpBanList l;
|
|
private final OpList operators;
|
|
private final WhiteList whitelist;
|
|
+ private final Map<UUID, EntityPlayer> pendingPlayers = Maps.newHashMap(); // Paper
|
|
// CraftBukkit start
|
|
// private final Map<UUID, ServerStatisticManager> o;
|
|
// private final Map<UUID, AdvancementDataPlayer> p;
|
|
@@ -94,6 +95,11 @@ public abstract class PlayerList {
|
|
}
|
|
|
|
public void a(NetworkManager networkmanager, EntityPlayer entityplayer) {
|
|
+ EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper
|
|
+ if (prev != null) {
|
|
+ disconnectPendingPlayer(prev);
|
|
+ }
|
|
+ entityplayer.networkManager = networkmanager; // Paper
|
|
entityplayer.loginTime = System.currentTimeMillis(); // Paper
|
|
GameProfile gameprofile = entityplayer.getProfile();
|
|
UserCache usercache = this.server.getUserCache();
|
|
@@ -107,7 +113,7 @@ public abstract class PlayerList {
|
|
if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) {
|
|
NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit");
|
|
s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s;
|
|
- }
|
|
+ }String lastKnownName = s; // Paper
|
|
if (nbttagcompound == null) entityplayer.moveToSpawn(worldserver); // Paper - only move to spawn on first login, otherwise, stay where you are....
|
|
// CraftBukkit end
|
|
|
|
@@ -160,6 +166,50 @@ public abstract class PlayerList {
|
|
entityplayer.B().a(entityplayer);
|
|
this.sendScoreboard(worldserver.getScoreboard(), entityplayer);
|
|
this.server.invalidatePingSample();
|
|
+ // Paper start - async load spawn in chunk
|
|
+ WorldServer finalWorldserver = worldserver;
|
|
+ int chunkX = loc.getBlockX() >> 4;
|
|
+ int chunkZ = loc.getBlockZ() >> 4;
|
|
+ worldserver.getChunkProvider().getTickingChunkAsync(chunkX, chunkZ, (chunk -> { // use ticking - as it has at least 1 neighbours loaded
|
|
+ playerconnection.playerJoinReady = () -> {
|
|
+ postChunkLoadJoin(
|
|
+ entityplayer, finalWorldserver, networkmanager, playerconnection,
|
|
+ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName
|
|
+ );
|
|
+ };
|
|
+ }));
|
|
+ // boost the priorities
|
|
+ worldserver.asyncChunkTaskManager.raisePriority(chunkX, chunkZ, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
|
|
+ for (int cx = -1; cx <= 1; cx++) {
|
|
+ for (int cz = -1; cz <= 1; cz++) {
|
|
+ if (cx == 0 && cz == 0) continue;
|
|
+ // we have to directly request it otherwise the task won't be started yet to boost priority
|
|
+ worldserver.getChunkProvider().getFullChunkAsync(chunkX + cx, chunkZ + cz, null);
|
|
+ worldserver.asyncChunkTaskManager.raisePriority(chunkX + cx, chunkZ + cz, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ EntityPlayer getActivePlayer(UUID uuid) {
|
|
+ EntityPlayer player = this.getUUIDMap().get(uuid);
|
|
+ return player != null ? player : pendingPlayers.get(uuid);
|
|
+ }
|
|
+
|
|
+ void disconnectPendingPlayer(EntityPlayer entityplayer) {
|
|
+ ChatMessage msg = new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]);
|
|
+ entityplayer.networkManager.sendPacket(new PacketPlayOutKickDisconnect(msg), (future) -> {
|
|
+ entityplayer.networkManager.close(msg);
|
|
+ entityplayer.networkManager = null;
|
|
+ });
|
|
+ }
|
|
+
|
|
+ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver, NetworkManager networkmanager, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String s) {
|
|
+ pendingPlayers.remove(entityplayer.getUniqueID(), entityplayer);
|
|
+ if (!networkmanager.isConnected()) {
|
|
+ return;
|
|
+ }
|
|
+ entityplayer.didPlayerJoinEvent = true;
|
|
+ // Paper end
|
|
ChatMessage chatmessage;
|
|
|
|
if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) {
|
|
@@ -218,7 +268,6 @@ public abstract class PlayerList {
|
|
}
|
|
entityplayer.sentListPacket = true;
|
|
entityplayer.supressTrackerForLogin = false; // Paper
|
|
- ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now
|
|
// CraftBukkit end
|
|
|
|
entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.datawatcher, true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
|
@@ -245,6 +294,7 @@ public abstract class PlayerList {
|
|
}
|
|
|
|
// Paper start - move vehicle into method so it can be called above - short circuit around that code
|
|
+ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // track entity now
|
|
onPlayerJoinFinish(entityplayer, worldserver, s1);
|
|
}
|
|
private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver, NBTTagCompound nbttagcompound) {
|
|
@@ -390,6 +440,7 @@ public abstract class PlayerList {
|
|
|
|
protected void savePlayerFile(EntityPlayer entityplayer) {
|
|
if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
|
+ if (!entityplayer.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.playerFileData.save(entityplayer);
|
|
ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit
|
|
|
|
@@ -414,7 +465,7 @@ public abstract class PlayerList {
|
|
org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(entityplayer, org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper
|
|
|
|
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game");
|
|
- cserver.getPluginManager().callEvent(playerQuitEvent);
|
|
+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit
|
|
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
|
|
|
if (server.isMainThread()) entityplayer.playerTick();// SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog)
|
|
@@ -466,6 +517,13 @@ public abstract class PlayerList {
|
|
// this.p.remove(uuid);
|
|
// CraftBukkit end
|
|
}
|
|
+ // Paper start
|
|
+ entityplayer1 = pendingPlayers.get(uuid);
|
|
+ if (entityplayer1 == entityplayer) {
|
|
+ pendingPlayers.remove(uuid);
|
|
+ }
|
|
+ entityplayer.networkManager = null;
|
|
+ // Paper end
|
|
|
|
// CraftBukkit start
|
|
// this.sendAll(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer}));
|
|
@@ -483,7 +541,7 @@ public abstract class PlayerList {
|
|
cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
|
|
// CraftBukkit end
|
|
|
|
- return playerQuitEvent.getQuitMessage(); // CraftBukkit
|
|
+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.getQuitMessage() : null; // CraftBukkit // Paper - don't print quit if we never printed join
|
|
}
|
|
|
|
// CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer
|
|
@@ -502,6 +560,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();
|
|
|