|
|
|
|
@@ -90,7 +90,7 @@ index f617636a22167b06ac8073aa25efd8c7099155f0..0f40793f004639822b9d40521cd21ec5
|
|
|
|
|
return new BlockPosition(this.x << 4, 0, this.z << 4);
|
|
|
|
|
}
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
|
|
|
|
index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd613afce03 100644
|
|
|
|
|
index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..35a4999b2c34ae62cba042885db25dd1837cb127 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
|
|
|
|
@@ -23,6 +23,7 @@ import java.util.concurrent.Executor;
|
|
|
|
|
@@ -101,6 +101,15 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
|
|
|
|
|
public abstract class ChunkMapDistance {
|
|
|
|
|
|
|
|
|
|
@@ -46,7 +47,7 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
private final ChunkTaskQueueSorter i;
|
|
|
|
|
private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> j;
|
|
|
|
|
private final Mailbox<ChunkTaskQueueSorter.b> k;
|
|
|
|
|
- private final LongSet l = new LongOpenHashSet();
|
|
|
|
|
+ private final LongSet l = new LongOpenHashSet(); LongSet getOnPlayerTicketAddQueue() { return l; } // Paper - OBFHELPER
|
|
|
|
|
private final Executor m;
|
|
|
|
|
private long currentTick;
|
|
|
|
|
|
|
|
|
|
@@ -84,6 +85,7 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -163,7 +172,7 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
return removed; // CraftBukkit
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -182,6 +191,113 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
@@ -182,6 +191,135 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -181,8 +190,10 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+
|
|
|
|
|
+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) {
|
|
|
|
|
+ delayDistanceManagerTick = true;
|
|
|
|
|
+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority));
|
|
|
|
|
+ int finalPriority = priority;
|
|
|
|
|
+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> {
|
|
|
|
|
+ addPriorityTicket(coords, TicketType.PRIORITY, priority);
|
|
|
|
|
+ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority);
|
|
|
|
|
+ });
|
|
|
|
|
+ delayDistanceManagerTick = false;
|
|
|
|
|
+ chunkMap.world.getChunkProvider().tickDistanceManager();
|
|
|
|
|
@@ -197,17 +208,37 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+ chunkMap.world.getChunkProvider().tickDistanceManager();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean hasPlayerTicket(ChunkCoordIntPair coords, int level) {
|
|
|
|
|
+ ArraySetSorted<Ticket<?>> tickets = this.tickets.get(coords.pair());
|
|
|
|
|
+ if (tickets == null || tickets.isEmpty()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (Ticket<?> ticket : tickets) {
|
|
|
|
|
+ if (ticket.getTicketType() == TicketType.PLAYER && ticket.getTicketLevel() == level) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType<ChunkCoordIntPair> ticketType, int priority) {
|
|
|
|
|
+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket");
|
|
|
|
|
+ long pair = coords.pair();
|
|
|
|
|
+ PlayerChunk chunk = chunkMap.getUpdatingChunk(pair);
|
|
|
|
|
+ if (chunk != null && chunk.isFullChunkReady() && chunk.getTicketLevel() <= 33) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (chunk != null && chunk.getTicketLevel() > 33 && chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null) {
|
|
|
|
|
+ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33);
|
|
|
|
|
+
|
|
|
|
|
+ if (needsTicket) {
|
|
|
|
|
+ Ticket<?> ticket = new Ticket<>(TicketType.PLAYER, 33, coords);
|
|
|
|
|
+ getOnPlayerTicketAddQueue().add(pair);
|
|
|
|
|
+ addTicket(pair, ticket);
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((chunk != null && chunk.isFullChunkReady())) {
|
|
|
|
|
+ if (needsTicket) {
|
|
|
|
|
+ chunkMap.world.getChunkProvider().tickDistanceManager();
|
|
|
|
|
+ }
|
|
|
|
|
+ return needsTicket;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ boolean success;
|
|
|
|
|
+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) {
|
|
|
|
|
@@ -277,51 +308,75 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
public <T> boolean addTicketAtLevel(TicketType<T> ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) {
|
|
|
|
|
return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier));
|
|
|
|
|
// CraftBukkit end
|
|
|
|
|
@@ -384,24 +500,26 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
Ticket<?> ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance
|
|
|
|
|
@@ -381,27 +519,51 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
|
|
|
|
|
private void a(long i, int j, boolean flag, boolean flag1) {
|
|
|
|
|
if (flag != flag1) {
|
|
|
|
|
- Ticket<?> ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance
|
|
|
|
|
+ ChunkCoordIntPair coords = new ChunkCoordIntPair(i); // Paper
|
|
|
|
|
+ Ticket<?> ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance
|
|
|
|
|
|
|
|
|
|
if (flag1) {
|
|
|
|
|
- ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
|
|
|
|
- ChunkMapDistance.this.m.execute(() -> {
|
|
|
|
|
+ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> { // Paper - smarter ticket delay based on frustum and distance
|
|
|
|
|
+ // Paper start - recheck its still valid if not cancel
|
|
|
|
|
+ if (!isChunkInRange(i)) {
|
|
|
|
|
+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> {
|
|
|
|
|
+ ChunkMapDistance.this.m.execute(() -> {
|
|
|
|
|
+ ChunkMapDistance.this.removeTicket(i, ticket);
|
|
|
|
|
+ ChunkMapDistance.this.clearPriorityTickets(coords);
|
|
|
|
|
+ });
|
|
|
|
|
+ }, i, false));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // abort early if we got a ticket already
|
|
|
|
|
+ if (hasPlayerTicket(coords, 33)) return;
|
|
|
|
|
+ // skip player ticket throttle for near chunks
|
|
|
|
|
+ if (priority <= 3) {
|
|
|
|
|
+ ChunkMapDistance.this.addTicket(i, ticket);
|
|
|
|
|
+ ChunkMapDistance.this.l.add(i);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Paper end
|
|
|
|
|
ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
|
|
|
|
ChunkMapDistance.this.m.execute(() -> {
|
|
|
|
|
- if (this.c(this.c(i))) {
|
|
|
|
|
+ // Paper start - smarter ticket delay based on frustum and distance
|
|
|
|
|
+ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> {
|
|
|
|
|
+ //ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
|
|
|
|
+ if (this.c(this.c(i))) { // Copy c(c()) stuff below
|
|
|
|
|
+ // Paper end
|
|
|
|
|
+ if (isChunkInRange(i)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it
|
|
|
|
|
ChunkMapDistance.this.addTicket(i, ticket);
|
|
|
|
|
ChunkMapDistance.this.l.add(i);
|
|
|
|
|
} else {
|
|
|
|
|
- } else {
|
|
|
|
|
+ }
|
|
|
|
|
+ } else { // Paper
|
|
|
|
|
ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
|
|
|
|
}, i, false));
|
|
|
|
|
}
|
|
|
|
|
-
|
|
|
|
|
- });
|
|
|
|
|
- }, i, () -> {
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}, i, () -> {
|
|
|
|
|
- return j;
|
|
|
|
|
- }));
|
|
|
|
|
+ //}, i, () -> {
|
|
|
|
|
+ //return Math.min(PlayerChunkMap.GOLDEN_TICKET, (priority <= 6 ? 20 : 30) + priority); // Paper - delay new ticket adds to avoid spamming the queue
|
|
|
|
|
+ //})); // Paper
|
|
|
|
|
+ return Math.min(PlayerChunkMap.GOLDEN_TICKET, priority); // Paper
|
|
|
|
|
}));
|
|
|
|
|
+ }); // Paper
|
|
|
|
|
} else {
|
|
|
|
|
ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
|
|
|
|
ChunkMapDistance.this.m.execute(() -> {
|
|
|
|
|
ChunkMapDistance.this.removeTicket(i, ticket);
|
|
|
|
|
+ ChunkMapDistance.this.clearPriorityTickets(new ChunkCoordIntPair(i)); // Paper
|
|
|
|
|
+ ChunkMapDistance.this.clearPriorityTickets(coords); // Paper
|
|
|
|
|
});
|
|
|
|
|
}, i, true));
|
|
|
|
|
}
|
|
|
|
|
@@ -409,6 +527,99 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
@@ -409,6 +571,102 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Paper start - smart scheduling of player tickets
|
|
|
|
|
+ private boolean isChunkInRange(long i) {
|
|
|
|
|
+ return this.isLoadedChunkLevel(this.getChunkLevel(i));
|
|
|
|
|
+ }
|
|
|
|
|
+ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer<Integer> task) {
|
|
|
|
|
+ long elapsed = MinecraftServer.currentTick - startTick;
|
|
|
|
|
+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(i);
|
|
|
|
|
+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(i);
|
|
|
|
|
+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !this.c(this.c(i)) || getChunkPriority(chunkPos) > 0) { // Copied from above
|
|
|
|
|
+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above
|
|
|
|
|
+ // no longer needed
|
|
|
|
|
+ task.accept(1);
|
|
|
|
|
+ return;
|
|
|
|
|
@@ -355,8 +410,7 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+
|
|
|
|
|
+ double dist = Math.min(frontDist, center);
|
|
|
|
|
+ if (!isFront) {
|
|
|
|
|
+
|
|
|
|
|
+ ChunkCoordIntPair pointInBack = player.getChunkInFront(-5);
|
|
|
|
|
+ ChunkCoordIntPair pointInBack = player.getChunkInFront(-7);
|
|
|
|
|
+ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4);
|
|
|
|
|
+ double backDist = MCUtil.distanceSq(pos, blockPos);
|
|
|
|
|
+ if (frontDist < backDist) {
|
|
|
|
|
@@ -375,8 +429,8 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+ }
|
|
|
|
|
+ if (minDist > 4) {
|
|
|
|
|
+ int desiredTimeDelayMax = isFront ?
|
|
|
|
|
+ (minDist < 10 ? 10 : 20) : // Front
|
|
|
|
|
+ (minDist < 10 ? 20 : 40); // Back
|
|
|
|
|
+ (minDist < 10 ? 7 : 15) : // Front
|
|
|
|
|
+ (minDist < 10 ? 15 : 45); // Back
|
|
|
|
|
+ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
@@ -389,7 +443,7 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+ for (int x = -1; x <= 1; x++) {
|
|
|
|
|
+ for (int z = -1; z <= 1; z++) {
|
|
|
|
|
+ if (x == 0 && z == 0) continue;
|
|
|
|
|
+ long pair = new ChunkCoordIntPair(chunkPos.x + x, chunkPos.z + z).pair();
|
|
|
|
|
+ long pair = ChunkCoordIntPair.pair(chunkPos.x + x, chunkPos.z + z);
|
|
|
|
|
+ PlayerChunk neighbor = chunkMap.getUpdatingChunk(pair);
|
|
|
|
|
+ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null;
|
|
|
|
|
+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) {
|
|
|
|
|
@@ -398,13 +452,14 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!hasAnyNeighbor) {
|
|
|
|
|
+ delay += 10;
|
|
|
|
|
+ delay += 20;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (delay <= 0) {
|
|
|
|
|
+ task.accept((int) minDist);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ MCUtil.scheduleTask((int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)), () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer");
|
|
|
|
|
+ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20));
|
|
|
|
|
+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // Paper end
|
|
|
|
|
@@ -412,6 +467,22 @@ index 7702fbefa598bce7e6a2d287f7ec36b78a62bff8..f7be94e801e58a39e0efcc813d95bbd6
|
|
|
|
|
@Override
|
|
|
|
|
public void a() {
|
|
|
|
|
super.a();
|
|
|
|
|
@@ -440,6 +698,7 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private boolean isLoadedChunkLevel(int i) { return c(i); } // Paper - OBFHELPER
|
|
|
|
|
private boolean c(int i) {
|
|
|
|
|
return i <= this.e - 2;
|
|
|
|
|
}
|
|
|
|
|
@@ -456,6 +715,7 @@ public abstract class ChunkMapDistance {
|
|
|
|
|
this.a.defaultReturnValue((byte) (i + 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ protected final int getChunkLevel(long i) { return c(i); } // Paper - OBFHELPER
|
|
|
|
|
@Override
|
|
|
|
|
protected int c(long i) {
|
|
|
|
|
return this.a.get(i);
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
|
|
|
index 7a275bf3260f9fbefc41883c5ebdc1eb2196daf0..b6a7e475c6ebe499c641db5967adb1674323a517 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
|
|
|
@@ -501,18 +572,23 @@ index 7a275bf3260f9fbefc41883c5ebdc1eb2196daf0..b6a7e475c6ebe499c641db5967adb167
|
|
|
|
|
boolean flag1 = this.playerChunkMap.b();
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
|
|
|
index 07a6fc3d88e7d44bfab7f3d6a0eef7dc132ab422..4ed4ad6bc3b4ab6702ca500dc26e889dca6ed2d7 100644
|
|
|
|
|
index 07a6fc3d88e7d44bfab7f3d6a0eef7dc132ab422..39072ebdc9e4be2bb762d81a8bd542dbdb8f6371 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
|
|
|
@@ -55,6 +55,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
@@ -55,6 +55,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
private int lastArmorScored = Integer.MIN_VALUE;
|
|
|
|
|
private int lastExpLevelScored = Integer.MIN_VALUE;
|
|
|
|
|
private int lastExpTotalScored = Integer.MIN_VALUE;
|
|
|
|
|
+ public long lastHighPriorityChecked; // Paper
|
|
|
|
|
+ public void forceCheckHighPriority() {
|
|
|
|
|
+ lastHighPriorityChecked = -1;
|
|
|
|
|
+ getWorldServer().getChunkProvider().playerChunkMap.checkHighPriorityChunks(this);
|
|
|
|
|
+ }
|
|
|
|
|
+ public boolean isRealPlayer; // Paper
|
|
|
|
|
private float lastHealthSent = -1.0E8F;
|
|
|
|
|
private int lastFoodSent = -99999999;
|
|
|
|
|
private boolean lastSentSaturationZero = true;
|
|
|
|
|
@@ -132,6 +133,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
@@ -132,6 +138,21 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
this.maxHealthCache = this.getMaxHealth();
|
|
|
|
|
this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
|
|
|
|
|
}
|
|
|
|
|
@@ -534,11 +610,11 @@ index 07a6fc3d88e7d44bfab7f3d6a0eef7dc132ab422..4ed4ad6bc3b4ab6702ca500dc26e889d
|
|
|
|
|
|
|
|
|
|
// Yes, this doesn't match Vanilla, but it's the best we can do for now.
|
|
|
|
|
// If this is an issue, PRs are welcome
|
|
|
|
|
@@ -441,6 +457,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
@@ -441,6 +462,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
|
if (valid && (!this.isSpectator() || this.world.isLoaded(new BlockPosition(this)))) { // Paper - don't tick dead players that are not in the world currently (pending respawn)
|
|
|
|
|
super.tick();
|
|
|
|
|
}
|
|
|
|
|
+ if (valid && isAlive()) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper
|
|
|
|
|
+ if (valid && isAlive() && playerConnection != null) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < this.inventory.getSize(); ++i) {
|
|
|
|
|
ItemStack itemstack = this.inventory.getItem(i);
|
|
|
|
|
@@ -555,7 +631,7 @@ index ce0bf608b71cf492fc31e89a360ecd83fa5c23a6..87d58002116f361d8255d79fc0dbd120
|
|
|
|
|
chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair()));
|
|
|
|
|
chunkData.addProperty("status", status == null ? "unloaded" : status.toString());
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
|
|
|
index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e09cd238c 100644
|
|
|
|
|
index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..52da9c78c0cc2b21533a1477a25a3dda492700e4 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
|
|
|
@@ -26,8 +26,8 @@ public class PlayerChunk {
|
|
|
|
|
@@ -698,7 +774,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
|
|
|
|
|
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
|
|
|
|
|
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
|
|
|
|
|
@@ -165,6 +280,15 @@ public class PlayerChunk {
|
|
|
|
|
@@ -165,6 +280,18 @@ public class PlayerChunk {
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
@@ -709,12 +785,15 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) {
|
|
|
|
|
+ return MCUtil.ensureMain(getStatusFutureUnchecked(chunkstatus));
|
|
|
|
|
+ return ensureMain(getStatusFutureUnchecked(chunkstatus));
|
|
|
|
|
+ }
|
|
|
|
|
+ public <T> CompletableFuture<T> ensureMain(CompletableFuture<T> future) {
|
|
|
|
|
+ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor);
|
|
|
|
|
+ }
|
|
|
|
|
// Paper end
|
|
|
|
|
|
|
|
|
|
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
|
|
|
|
|
@@ -418,6 +542,7 @@ public class PlayerChunk {
|
|
|
|
|
@@ -418,6 +545,7 @@ public class PlayerChunk {
|
|
|
|
|
return this.n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -722,7 +801,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
private void d(int i) {
|
|
|
|
|
this.n = i;
|
|
|
|
|
}
|
|
|
|
|
@@ -436,7 +561,7 @@ public class PlayerChunk {
|
|
|
|
|
@@ -436,7 +564,7 @@ public class PlayerChunk {
|
|
|
|
|
// CraftBukkit start
|
|
|
|
|
// ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
|
|
|
|
if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
|
|
|
|
|
@@ -731,12 +810,12 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
Chunk chunk = (Chunk)either.left().orElse(null);
|
|
|
|
|
if (chunk != null) {
|
|
|
|
|
playerchunkmap.callbackExecutor.execute(() -> {
|
|
|
|
|
@@ -501,12 +626,13 @@ public class PlayerChunk {
|
|
|
|
|
@@ -501,12 +629,13 @@ public class PlayerChunk {
|
|
|
|
|
if (!flag2 && flag3) {
|
|
|
|
|
// Paper start - cache ticking ready status
|
|
|
|
|
int expectCreateCount = ++this.fullChunkCreateCount;
|
|
|
|
|
- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> {
|
|
|
|
|
+ this.fullChunkFuture = playerchunkmap.b(this); MCUtil.ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main
|
|
|
|
|
+ this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main
|
|
|
|
|
if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) {
|
|
|
|
|
// note: Here is a very good place to add callbacks to logic waiting on this.
|
|
|
|
|
Chunk fullChunk = either.left().get();
|
|
|
|
|
@@ -746,25 +825,25 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@@ -531,7 +657,7 @@ public class PlayerChunk {
|
|
|
|
|
@@ -531,7 +660,7 @@ public class PlayerChunk {
|
|
|
|
|
|
|
|
|
|
if (!flag4 && flag5) {
|
|
|
|
|
// Paper start - cache ticking ready status
|
|
|
|
|
- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> {
|
|
|
|
|
+ this.tickingFuture = playerchunkmap.a(this); MCUtil.ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main
|
|
|
|
|
+ this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main
|
|
|
|
|
if (either.left().isPresent()) {
|
|
|
|
|
// note: Here is a very good place to add callbacks to logic waiting on this.
|
|
|
|
|
Chunk tickingChunk = either.left().get();
|
|
|
|
|
@@ -562,7 +688,7 @@ public class PlayerChunk {
|
|
|
|
|
@@ -562,7 +691,7 @@ public class PlayerChunk {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Paper start - cache ticking ready status
|
|
|
|
|
- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> {
|
|
|
|
|
+ this.entityTickingFuture = playerchunkmap.b(this.location); MCUtil.ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain
|
|
|
|
|
+ this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain
|
|
|
|
|
if (either.left().isPresent()) {
|
|
|
|
|
// note: Here is a very good place to add callbacks to logic waiting on this.
|
|
|
|
|
Chunk entityTickingChunk = either.left().get();
|
|
|
|
|
@@ -581,13 +707,29 @@ public class PlayerChunk {
|
|
|
|
|
@@ -581,13 +710,29 @@ public class PlayerChunk {
|
|
|
|
|
this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage
|
|
|
|
|
this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
|
|
|
|
}
|
|
|
|
|
@@ -797,7 +876,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
Chunk chunk = (Chunk)either.left().orElse(null);
|
|
|
|
|
if (chunk != null) {
|
|
|
|
|
playerchunkmap.callbackExecutor.execute(() -> {
|
|
|
|
|
@@ -669,6 +811,7 @@ public class PlayerChunk {
|
|
|
|
|
@@ -669,6 +814,7 @@ public class PlayerChunk {
|
|
|
|
|
|
|
|
|
|
public interface c {
|
|
|
|
|
|
|
|
|
|
@@ -806,7 +885,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..bc5e380aa37101382c359f1c9a25803e
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
|
|
|
index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c8c1c316c 100644
|
|
|
|
|
index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..3139d55bb801b6c433de7274be4a1d0c0fd1eef7 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
|
|
|
@@ -50,6 +50,7 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
|
|
|
|
|
@@ -841,17 +920,20 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
if (newState.size() != 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@@ -393,7 +397,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -393,7 +397,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
}
|
|
|
|
|
ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ);
|
|
|
|
|
PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update
|
|
|
|
|
- });
|
|
|
|
|
+ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos);
|
|
|
|
|
+ }, (player, prevPos, newPos) -> checkHighPriorityChunks(player));
|
|
|
|
|
+ }, (player, prevPos, newPos) -> {
|
|
|
|
|
+ player.lastHighPriorityChecked = -1; // reset and recheck
|
|
|
|
|
+ checkHighPriorityChunks(player);
|
|
|
|
|
+ });
|
|
|
|
|
this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets);
|
|
|
|
|
this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
|
|
|
|
(EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
|
|
|
|
@@ -410,6 +415,101 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -410,6 +418,116 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
});
|
|
|
|
|
// Paper end - no-tick view distance
|
|
|
|
|
}
|
|
|
|
|
@@ -878,33 +960,41 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
+ return playerchunk == null || unloadQueue.contains(playerchunk.location.pair());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void updateChunkPriorityMap(it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap map, long chunk, int level) {
|
|
|
|
|
+ int prev = map.getOrDefault(chunk, -1);
|
|
|
|
|
+ if (level > prev) {
|
|
|
|
|
+ map.put(chunk, level);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void checkHighPriorityChunks(EntityPlayer player) {
|
|
|
|
|
+ int currentTick = MinecraftServer.currentTick;
|
|
|
|
|
+ if (currentTick - player.lastHighPriorityChecked < 20) {
|
|
|
|
|
+ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ player.lastHighPriorityChecked = currentTick;
|
|
|
|
|
+ it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap priorities = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap();
|
|
|
|
|
+
|
|
|
|
|
+ int viewDistance = getEffectiveNoTickViewDistance();
|
|
|
|
|
+ chunkDistanceManager.delayDistanceManagerTick = true;
|
|
|
|
|
+ BlockPosition.PooledBlockPosition pos = BlockPosition.PooledBlockPosition.acquire();
|
|
|
|
|
+
|
|
|
|
|
+ // Prioritize circular near
|
|
|
|
|
+ double playerChunkX = MathHelper.floor(player.locX()) >> 4;
|
|
|
|
|
+ double playerChunkZ = MathHelper.floor(player.locZ()) >> 4;
|
|
|
|
|
+ pos.setValues(player.locX(), 0, player.locZ());
|
|
|
|
|
+ double twoThirdModifier = 2D / 3D;
|
|
|
|
|
+ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> {
|
|
|
|
|
+ if (shouldSkipPrioritization(coord)) return;
|
|
|
|
|
+
|
|
|
|
|
+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z);
|
|
|
|
|
+ // Prioritize immediate
|
|
|
|
|
+ if (dist <= 4 * 4) {
|
|
|
|
|
+ chunkDistanceManager.markHighPriority(coord, (int) (27 - Math.sqrt(dist)));
|
|
|
|
|
+ updateChunkPriorityMap(priorities, coord.pair(), (int) (27 - Math.sqrt(dist)));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Prioritize nearby chunks
|
|
|
|
|
+ chunkDistanceManager.markHighPriority(coord, (int) (16 - Math.sqrt(dist*(2D/3D))));
|
|
|
|
|
+ updateChunkPriorityMap(priorities, coord.pair(), (int) (20 - Math.sqrt(dist) * twoThirdModifier));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Prioritize Frustum near 3
|
|
|
|
|
@@ -913,7 +1003,8 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
+ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> {
|
|
|
|
|
+ if (shouldSkipPrioritization(coord)) return;
|
|
|
|
|
+
|
|
|
|
|
+ chunkDistanceManager.markHighPriority(coord, 26);
|
|
|
|
|
+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z);
|
|
|
|
|
+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - Math.sqrt(dist) * twoThirdModifier));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Prioritize Frustum near 5
|
|
|
|
|
@@ -923,7 +1014,8 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
+ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> {
|
|
|
|
|
+ if (shouldSkipPrioritization(coord)) return;
|
|
|
|
|
+
|
|
|
|
|
+ chunkDistanceManager.markHighPriority(coord, 20);
|
|
|
|
|
+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z);
|
|
|
|
|
+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - Math.sqrt(dist) * twoThirdModifier));
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
@@ -935,13 +1027,18 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
+ if (shouldSkipPrioritization(coord)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ chunkDistanceManager.markHighPriority(coord, 15);
|
|
|
|
|
+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z);
|
|
|
|
|
+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - Math.sqrt(dist) * twoThirdModifier));
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pos.close();
|
|
|
|
|
+ if (priorities.isEmpty()) return;
|
|
|
|
|
+ chunkDistanceManager.delayDistanceManagerTick = true;
|
|
|
|
|
+ priorities.long2IntEntrySet().fastForEach(entry -> chunkDistanceManager.markHighPriority(new ChunkCoordIntPair(entry.getLongKey()), entry.getIntValue()));
|
|
|
|
|
+ chunkDistanceManager.delayDistanceManagerTick = false;
|
|
|
|
|
+ world.getChunkProvider().tickDistanceManager();
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) {
|
|
|
|
|
@@ -953,7 +1050,7 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
|
|
|
|
|
public void updatePlayerMobTypeMap(Entity entity) {
|
|
|
|
|
if (!this.world.paperConfig.perPlayerMobSpawns) {
|
|
|
|
|
@@ -539,6 +639,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -539,6 +657,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
List<CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> list = Lists.newArrayList();
|
|
|
|
|
int j = chunkcoordintpair.x;
|
|
|
|
|
int k = chunkcoordintpair.z;
|
|
|
|
|
@@ -961,7 +1058,7 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
|
|
|
|
|
for (int l = -i; l <= i; ++l) {
|
|
|
|
|
for (int i1 = -i; i1 <= i; ++i1) {
|
|
|
|
|
@@ -557,6 +658,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -557,6 +676,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
|
|
|
|
|
ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1);
|
|
|
|
|
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = playerchunk.a(chunkstatus, this);
|
|
|
|
|
@@ -976,7 +1073,7 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
|
|
|
|
|
list.add(completablefuture);
|
|
|
|
|
}
|
|
|
|
|
@@ -1022,14 +1131,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -1022,14 +1149,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CompletableFuture<NBTTagCompound> chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z);
|
|
|
|
|
@@ -1004,7 +1101,7 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
return ret;
|
|
|
|
|
// Paper end
|
|
|
|
|
}
|
|
|
|
|
@@ -1158,7 +1275,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
@@ -1158,7 +1293,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
|
|
|
long i = playerchunk.i().pair();
|
|
|
|
|
|
|
|
|
|
playerchunk.getClass();
|
|
|
|
|
@@ -1014,19 +1111,19 @@ index 0aa14bfca6e1845eb6e9f5bd4e0e36335fa7f532..6c0dbad8e06b02b32dcff518cc2a5f7c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
|
|
|
index d52fbda79fe1c52d3ddb53c0f1c1f521d7620702..7123e197c7ed01afd4fbf7aa0760611373039a13 100644
|
|
|
|
|
index d52fbda79fe1c52d3ddb53c0f1c1f521d7620702..f9cb87a3be35575ecf3362b10dc7fe5ebadb56ec 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
|
|
|
|
@@ -1277,6 +1277,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
|
|
|
// CraftBukkit end
|
|
|
|
|
|
|
|
|
|
@@ -1279,6 +1279,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
|
|
|
|
this.A = this.e;
|
|
|
|
|
+ this.player.getWorldServer().getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(MathHelper.floor(d1) >> 4, MathHelper.floor(d3) >> 4), 28, 3); // Paper - load area high priority
|
|
|
|
|
this.player.setLocation(d0, d1, d2, f, f1);
|
|
|
|
|
this.syncPosition(); // Paper
|
|
|
|
|
+ this.player.forceCheckHighPriority(); // Paper
|
|
|
|
|
this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
|
|
|
|
|
index 6daca5c0ffd1d84f9a25cd106e8992a055dfb912..b0585346bf5125bebc482246bbb91c4b08c55816 100644
|
|
|
|
|
index 6daca5c0ffd1d84f9a25cd106e8992a055dfb912..f133e7baf958b031819c2c72ccd21c52ba9a683d 100644
|
|
|
|
|
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
|
|
|
|
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
|
|
|
|
@@ -174,8 +174,8 @@ public abstract class PlayerList {
|
|
|
|
|
@@ -1048,11 +1145,19 @@ index 6daca5c0ffd1d84f9a25cd106e8992a055dfb912..b0585346bf5125bebc482246bbb91c4b
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
@@ -764,6 +763,7 @@ public abstract class PlayerList {
|
|
|
|
|
@@ -585,6 +584,7 @@ public abstract class PlayerList {
|
|
|
|
|
SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress();
|
|
|
|
|
|
|
|
|
|
EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(DimensionManager.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(DimensionManager.OVERWORLD)));
|
|
|
|
|
+ entity.isRealPlayer = true; // Paper
|
|
|
|
|
Player player = entity.getBukkitEntity();
|
|
|
|
|
PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress());
|
|
|
|
|
|
|
|
|
|
@@ -764,6 +764,7 @@ public abstract class PlayerList {
|
|
|
|
|
// CraftBukkit end
|
|
|
|
|
|
|
|
|
|
worldserver.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
|
|
|
|
|
+ worldserver.getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 28, 3); // Paper - load area at high priority
|
|
|
|
|
+ entityplayer1.forceCheckHighPriority(); // Player
|
|
|
|
|
while (avoidSuffocation && !worldserver.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) {
|
|
|
|
|
entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ());
|
|
|
|
|
}
|
|
|
|
|
|