geforkt von Mirrors/Paper
a207d14a0e
Signed-off-by: Mariell Hoversholm <proximyst@proximyst.com>
417 Zeilen
25 KiB
Diff
417 Zeilen
25 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/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index b3ca4300b280a24f3ed2acaffdd6ae2cdffd140d..97a582614ad28f9fa864ae9be4860658e5979214 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -145,7 +145,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> worldgenMailbox;
|
|
private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mainThreadMailbox;
|
|
public final ChunkProgressListener progressListener;
|
|
- public final ChunkMap.ChunkDistanceManager distanceManager;
|
|
+ public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER
|
|
private final AtomicInteger tickingGenerated;
|
|
public final StructureManager structureManager; // Paper - private -> public
|
|
private final File storageFolder;
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index b45fe750c8ca838e1beebff4077e5819eec2836c..79fb63c40dd0543a6f629e78f390f23f34992ba1 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -629,7 +629,7 @@ public class ServerChunkCache extends ChunkSource {
|
|
return this.mainThreadProcessor.pollTask();
|
|
}
|
|
|
|
- private boolean runDistanceManagerUpdates() {
|
|
+ public boolean runDistanceManagerUpdates() { // Paper - private -> public
|
|
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
|
|
boolean flag1 = this.chunkMap.promoteChunkMap();
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
index 75a095e0c2177dc1b46b080597ff8f12f1480acc..24c508ade61a6ad90b0ef73cdc995f531ef18263 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -32,6 +32,7 @@ import net.minecraft.core.Vec3i;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.nbt.Tag;
|
|
+import net.minecraft.network.Connection;
|
|
import net.minecraft.network.chat.ChatType;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.HoverEvent;
|
|
@@ -172,6 +173,7 @@ public class ServerPlayer extends Player implements ContainerListener {
|
|
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
public ServerGamePacketListenerImpl connection;
|
|
+ public Connection networkManager; // Paper
|
|
public final MinecraftServer server;
|
|
public final ServerPlayerGameMode gameMode;
|
|
public final Deque<Integer> removeQueue = new ArrayDeque<>(); // Paper
|
|
@@ -238,6 +240,7 @@ public class ServerPlayer extends Player implements ContainerListener {
|
|
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/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java
|
|
index d09e4857b6c40410d134fa81b48e95919a7373bd..583587457790df826a8a3239a4bd1d0f1dcab1da 100644
|
|
--- a/src/main/java/net/minecraft/server/level/TicketType.java
|
|
+++ b/src/main/java/net/minecraft/server/level/TicketType.java
|
|
@@ -21,6 +21,7 @@ public class TicketType<T> {
|
|
public static final TicketType<ChunkPos> FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong));
|
|
public static final TicketType<ChunkPos> LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong));
|
|
public static final TicketType<BlockPos> PORTAL = create("portal", Vec3i::compareTo, 300);
|
|
+ public static final TicketType<Long> LOGIN = create("login", Long::compareTo, 100); // Paper
|
|
public static final TicketType<Integer> POST_TELEPORT = create("post_teleport", Integer::compareTo, 5);
|
|
public static final TicketType<ChunkPos> UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1);
|
|
public static final TicketType<Unit> PLUGIN = 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
|
|
index 09a663cc53cdf8ae45352b280200c8170dbbcdfc..1bed6e69bf3cc1ab9b0c1259de4f643bf58371aa 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -220,6 +220,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
public final Connection connection;
|
|
private final MinecraftServer server;
|
|
+ public Runnable playerJoinReady; // Paper
|
|
public ServerPlayer player;
|
|
private int tickCount;
|
|
private long keepAliveTime = Util.getMillis(); private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER
|
|
@@ -298,6 +299,15 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
|
|
// 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.resetPosition();
|
|
this.player.xo = this.player.getX();
|
|
this.player.yo = this.player.getY();
|
|
@@ -339,7 +349,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
|
|
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
|
|
index 9631fa93b821c7f6bc6dc707c2c82cce2ae8291e..e229c7735ba88be3d8721440104958408a2a075e 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
@@ -86,7 +86,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
|
}
|
|
// 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;
|
|
@@ -186,7 +186,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
|
|
}
|
|
|
|
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
|
|
|
|
if (entityplayer != null) {
|
|
this.state = ServerLoginPacketListenerImpl.State.DELAY_ACCEPT;
|
|
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
index 454d60566743e02e7e55868c7bb45e30583dfa8f..ffc8c9ee8b1768dd809189858ee45658fb9bf1c5 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -36,6 +36,7 @@ import net.minecraft.network.protocol.Packet;
|
|
import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundChatPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
|
+import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
|
|
@@ -59,6 +60,8 @@ import net.minecraft.server.MCUtil;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.PlayerAdvancements;
|
|
import net.minecraft.server.ServerScoreboard;
|
|
+import net.minecraft.server.level.ChunkHolder;
|
|
+import net.minecraft.server.level.ChunkMap;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.server.level.ServerPlayerGameMode;
|
|
@@ -124,11 +127,12 @@ public abstract class PlayerList {
|
|
private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
|
|
private final MinecraftServer server;
|
|
public final List<ServerPlayer> players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety
|
|
- private final Map<UUID, ServerPlayer> playersByUUID = Maps.newHashMap();
|
|
+ private final Map<UUID, ServerPlayer> playersByUUID = Maps.newHashMap();Map<UUID, ServerPlayer> getUUIDMap() { return playersByUUID; } // Paper - OBFHELPER
|
|
private final UserBanList bans;
|
|
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> o;
|
|
// private final Map<UUID, AdvancementDataPlayer> p;
|
|
@@ -167,6 +171,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();
|
|
@@ -180,7 +189,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) {
|
|
@@ -255,34 +264,79 @@ 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 ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
|
+ ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap;
|
|
+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong());
|
|
+ worldserver1.getChunkSource().runDistanceManagerUpdates();
|
|
+ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> {
|
|
+ ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong());
|
|
+ if (updatingChunk != null) {
|
|
+ return updatingChunk.getEntityTickingFuture();
|
|
+ } else {
|
|
+ return java.util.concurrent.CompletableFuture.completedFuture(chunk);
|
|
+ }
|
|
+ }).thenAccept(chunk -> {
|
|
+ playerconnection.playerJoinReady = () -> {
|
|
+ postChunkLoadJoin(
|
|
+ player, finalWorldserver, connection, playerconnection,
|
|
+ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName
|
|
+ );
|
|
+ };
|
|
+ });
|
|
+ }
|
|
+
|
|
+ public ServerPlayer getActivePlayer(UUID uuid) {
|
|
+ ServerPlayer player = this.getUUIDMap().get(uuid);
|
|
+ return player != null ? player : pendingPlayers.get(uuid);
|
|
+ }
|
|
+
|
|
+ void disconnectPendingPlayer(ServerPlayer entityplayer) {
|
|
+ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]);
|
|
+ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> {
|
|
+ entityplayer.networkManager.disconnect(msg);
|
|
+ entityplayer.networkManager = null;
|
|
+ });
|
|
+ }
|
|
+
|
|
+ private void postChunkLoadJoin(ServerPlayer entityplayer, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) {
|
|
+ pendingPlayers.remove(entityplayer.getUUID(), entityplayer);
|
|
+ if (!networkmanager.isConnected()) {
|
|
+ return;
|
|
+ }
|
|
+ entityplayer.didPlayerJoinEvent = true;
|
|
+ // Paper end
|
|
TranslatableComponent chatmessage;
|
|
|
|
- if (player.getGameProfile().getName().equalsIgnoreCase(s)) {
|
|
- chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{player.getDisplayName()});
|
|
+ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) {
|
|
+ chatmessage = new TranslatableComponent("multiplayer.player.joined", new Object[]{entityplayer.getDisplayName()});
|
|
} else {
|
|
- chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{player.getDisplayName(), s});
|
|
+ chatmessage = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[]{entityplayer.getDisplayName(), s});
|
|
}
|
|
// CraftBukkit start
|
|
chatmessage.withStyle(ChatFormatting.YELLOW);
|
|
Component joinMessage = chatmessage; // Paper - Adventure
|
|
|
|
- playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.yRot, player.xRot);
|
|
- this.players.add(player);
|
|
- this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
|
- this.playersByUUID.put(player.getUUID(), player);
|
|
+ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.yRot, entityplayer.xRot);
|
|
+ this.players.add(entityplayer);
|
|
+ this.playersByName.put(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT), entityplayer); // Spigot
|
|
+ this.playersByUUID.put(entityplayer.getUUID(), entityplayer);
|
|
// 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
|
|
- player.supressTrackerForLogin = true;
|
|
- worldserver1.addNewPlayer(player);
|
|
- this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer);
|
|
- mountSavedVehicle(player, worldserver1, nbttagcompound);
|
|
+ entityplayer.supressTrackerForLogin = true;
|
|
+ worldserver1.addNewPlayer(entityplayer);
|
|
+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer);
|
|
+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound);
|
|
// Paper end
|
|
// CraftBukkit start
|
|
- PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
|
|
+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
|
|
cserver.getPluginManager().callEvent(playerJoinEvent);
|
|
|
|
- if (!player.connection.connection.isConnected()) {
|
|
+ if (!entityplayer.connection.connection.isConnected()) {
|
|
return;
|
|
}
|
|
|
|
@@ -297,51 +351,51 @@ public abstract class PlayerList {
|
|
// CraftBukkit end
|
|
|
|
// CraftBukkit start - sendAll above replaced with this loop
|
|
- ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, player);
|
|
+ ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entityplayer);
|
|
|
|
for (int i = 0; i < this.players.size(); ++i) {
|
|
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
|
|
|
|
- if (entityplayer1.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
|
+ if (entityplayer1.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) {
|
|
entityplayer1.connection.send(packet);
|
|
}
|
|
|
|
- if (!player.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) {
|
|
+ if (!entityplayer.getBukkitEntity().canSee(entityplayer1.getBukkitEntity())) {
|
|
continue;
|
|
}
|
|
|
|
- player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1}));
|
|
+ entityplayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1}));
|
|
}
|
|
- player.sentListPacket = true;
|
|
- player.supressTrackerForLogin = false; // Paper
|
|
- ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now
|
|
+ entityplayer.sentListPacket = true;
|
|
+ entityplayer.supressTrackerForLogin = false; // Paper
|
|
+ ((ServerLevel)entityplayer.level).getChunkSource().chunkMap.addEntity(entityplayer); // Paper - track entity now
|
|
// CraftBukkit end
|
|
|
|
- player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
|
+ entityplayer.connection.send(new ClientboundSetEntityDataPacket(entityplayer.getId(), entityplayer.getEntityData(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
|
|
|
// CraftBukkit start - Only add if the player wasn't moved in the event
|
|
- if (player.level == worldserver1 && !worldserver1.players().contains(player)) {
|
|
- worldserver1.addNewPlayer(player);
|
|
- this.server.getCustomBossEvents().onPlayerConnect(player);
|
|
+ if (entityplayer.level == worldserver1 && !worldserver1.players().contains(entityplayer)) {
|
|
+ worldserver1.addNewPlayer(entityplayer);
|
|
+ this.server.getCustomBossEvents().onPlayerConnect(entityplayer);
|
|
}
|
|
|
|
- worldserver1 = player.getLevel(); // CraftBukkit - Update in case join event changed it
|
|
+ worldserver1 = entityplayer.getLevel(); // CraftBukkit - Update in case join event changed it
|
|
// CraftBukkit end
|
|
- this.sendLevelInfo(player, worldserver1);
|
|
+ this.sendLevelInfo(entityplayer, worldserver1);
|
|
if (!this.server.getResourcePack().isEmpty()) {
|
|
- player.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash());
|
|
+ entityplayer.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash());
|
|
}
|
|
|
|
- Iterator iterator = player.getActiveEffects().iterator();
|
|
+ Iterator iterator = entityplayer.getActiveEffects().iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
MobEffectInstance mobeffect = (MobEffectInstance) iterator.next();
|
|
|
|
- playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect));
|
|
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect));
|
|
}
|
|
|
|
// Paper start - move vehicle into method so it can be called above - short circuit around that code
|
|
- onPlayerJoinFinish(player, worldserver1, s1);
|
|
+ onPlayerJoinFinish(entityplayer, worldserver1, s1);
|
|
}
|
|
private void mountSavedVehicle(ServerPlayer entityplayer, ServerLevel worldserver1, CompoundTag nbttagcompound) {
|
|
// Paper end
|
|
@@ -492,6 +546,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
|
|
|
|
@@ -519,7 +574,7 @@ public abstract class PlayerList {
|
|
}
|
|
|
|
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())));
|
|
- 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.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog)
|
|
@@ -572,6 +627,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(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer}));
|
|
@@ -589,7 +651,7 @@ public abstract class PlayerList {
|
|
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
|
|
@@ -608,6 +670,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();
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index b8dcc91a191f25ca578e0858abf6c1b874fee15d..9f0371282f5829d26dc9618c3d466bccaa4cd3af 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -1371,7 +1371,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
|
this.yo = y;
|
|
this.zo = d4;
|
|
this.setPos(d3, y, d4);
|
|
- level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit
|
|
+ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper
|
|
}
|
|
|
|
public void moveTo(Vec3 vec3d) {
|