Improvements to async login

Bump chunk priority to ensure chunks load fast
Handle case where client disconnects before they even fire PlayerJoinEvent
  - no longer call PlayerQuitEvent or print quit message.
  - don't save the player data file if never joined. Nothing has changed.
    CraftBukkit has a bug here that if you do save it, you will lose
    any horse that the player logged off on because the horse hasn't
    been resummoned yet.
This commit is contained in:
Aikar 2020-04-22 05:40:06 -04:00
parent bf698865f7
commit 8a91bfd240
No known key found for this signature in database
GPG key ID: 401ADFC9891FAAFE

View file

@ -1,4 +1,4 @@
From bb23022f8a18e30fb96036e8c6c7517af3ae42d6 Mon Sep 17 00:00:00 2001
From 8a89997b6fd09a04f3085e265e205c0c1c2dcb58 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
@ -17,6 +17,18 @@ index 96a47dd1c2..96ebe0b226 100644
}
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 686fd4cbad..84c6e5b614 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -105,6 +105,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/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 7929fcc800..c3710b73af 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
@ -30,27 +42,67 @@ index 7929fcc800..c3710b73af 100644
this.player.lastX = this.player.locX();
this.player.lastY = this.player.locY();
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index ec45c30dd3..de55423686 100644
index ec45c30dd3..ddecbc0a28 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -173,6 +173,17 @@ public abstract class PlayerList {
@@ -173,6 +173,31 @@ public abstract class PlayerList {
this.players.add(entityplayer);
this.playersByName.put(entityplayer.getName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot
this.j.put(entityplayer.getUniqueID(), entityplayer);
+ // Paper start - async load spawn in chunk
+ WorldServer finalWorldserver = worldserver;
+ worldserver.getChunkProvider().getTickingChunkAsync(loc.getBlockX() >> 4, loc.getBlockZ() >> 4, (chunk -> { // use ticking - as it has at least 1 neighbours loaded
+ 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
+ postChunkLoadJoin(entityplayer, finalWorldserver, playerconnection, nbttagcompound, networkmanager.getSocketAddress().toString(), joinMessage);
+ }));
+ // 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, (c) -> {});
+ worldserver.asyncChunkTaskManager.raisePriority(chunkX + cx, chunkZ + cz, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
+ }
+ }
+
+ }
+ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String joinMessage) {
+ if (!entityplayer.playerConnection.networkManager.isConnected()) {
+ return;
+ }
+ entityplayer.didPlayerJoinEvent = true;
+ // Paper end
// this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below
// Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
@@ -388,6 +413,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
@@ -412,7 +438,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)
@@ -481,7 +507,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
--
2.25.1