geforkt von Mirrors/Paper
26734e83b0
* Updated Upstream (Bukkit/CraftBukkit/Spigot) Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 8085edde SPIGOT-6918: Add SpawnCategory API and configurations for Axolotls 04c7e13c PR-719: Add Player Profile API 71564210 SPIGOT-6910: Add BlockDamageAbortEvent CraftBukkit Changes: febaa1c6 SPIGOT-6918: Add SpawnCategory API and configurations for Axolotls 9dafd109 Don't send updates over large distances bdac46b0 SPIGOT-6782: EntityPortalEvent should not destroy entity when setTo() uses same world as getFrom() 8f361ece PR-1002: Add Player Profile API 911875d4 Increase outdated build delay e5f8a767 SPIGOT-6917: Use main scoreboard for /trigger a672a531 Clean up callBlockDamageEvent 8e1bdeef SPIGOT-6910: Add BlockDamageAbortEvent Spigot Changes: 6edb62f3 Rebuild patches 7fbc6a1e Rebuild patches * Updated Upstream (CraftBukkit) Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing CraftBukkit Changes: de951355 SPIGOT-6927: Fix default value of spawn-limits in Worlds
263 Zeilen
15 KiB
Diff
263 Zeilen
15 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
|
|
index 6d59a813aa752b4233dbe1894cfc8273473c24e9..beebb7a0e6b8b1fa4e7d2f9fdf1962357cc2ebc3 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -174,6 +174,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;
|
|
@@ -247,6 +248,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;
|
|
// 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 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
|
|
index 78804497375740189d01c594c26786254288ef19..f0630bf6502d0b7be1c63e9c610ca2c8e1edc9d5 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -219,6 +219,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
|
private static final int LATENCY_CHECK_INTERVAL = 15000;
|
|
public final Connection connection;
|
|
private final MinecraftServer server;
|
|
+ public Runnable playerJoinReady; // Paper
|
|
public ServerPlayer player;
|
|
private int tickCount;
|
|
private long keepAliveTime = Util.getMillis();
|
|
@@ -292,6 +293,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
|
// 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();
|
|
@@ -333,7 +343,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
|
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 bb767f5b626225e70a8af273384bb74dbd21430d..301042e7a0d372a914f27ec0988dd938cf2a8262 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
@@ -88,7 +88,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;
|
|
@@ -194,7 +194,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
|
|
|
|
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
|
|
index f096fbe48d8cc70e3749f48bc9972def42b0068d..b84124abaca401406fbffc8bc6bd21245c303156 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -39,6 +39,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.ClientboundInitializeBorderPacket;
|
|
@@ -134,6 +135,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;
|
|
@@ -173,6 +175,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();
|
|
@@ -186,7 +193,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) {
|
|
@@ -213,11 +220,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();
|
|
@@ -259,6 +270,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;
|
|
+ distanceManager.addTicketAtLevel(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) {
|
|
+ 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) {
|
|
+ ServerPlayer player = this.playersByUUID.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 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
|
|
TranslatableComponent chatmessage;
|
|
|
|
if (player.getGameProfile().getName().equalsIgnoreCase(s)) {
|
|
@@ -502,6 +559,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
|
|
|
|
@@ -529,7 +587,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, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? 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)
|
|
@@ -574,6 +632,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}));
|
|
@@ -591,7 +656,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
|
|
@@ -610,6 +675,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();
|
|
|