Chunk system patch

This commit is contained in:
Spottedleaf 2023-09-22 13:13:57 -07:00
parent 05f9968013
commit 9bf842c13e
52 changed files with 625 additions and 370 deletions

View file

@ -34,8 +34,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
// Paper start - replace player chunk loader
private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java

View file

@ -2038,10 +2038,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
private ExplosionInteraction() {}
return ret;
}
+
// Paper end
+ // Paper start - optimize redstone (Alternate Current)
+ public alternate.current.wire.WireHandler getWireHandler() {
+ // This method is overridden in ServerLevel.
@ -2051,7 +2050,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // an instance of Level to ServerLevel.
+ return null;
+ }
+ // Paper end
+ // Paper end - optimize redstone (Alternate Current)
}
diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View file

@ -69,7 +69,7 @@ diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
private static WatchdogThread instance;
private long timeoutTime;
private boolean restart;
@ -80,7 +80,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private volatile long lastTick;
private volatile boolean stopping;
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
super( "Paper Watchdog Thread" );
this.timeoutTime = timeoutTime;
this.restart = restart;
@ -89,7 +89,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
private static long monotonicMillis()
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
while ( !this.stopping )
{
//
@ -110,7 +110,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
}
}
// Paper end
@ -122,6 +122,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Different message for short timeout
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
log.log( Level.SEVERE, "------------------------------" );
//

View file

@ -244,7 +244,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause
return;
}
// CraftBukkit end
// Paper start
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
// Paper start - validate pick item position
if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) {

View file

@ -198,9 +198,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
@@ -0,0 +0,0 @@ public final class PaperCommand extends Command {
commands.put(Set.of("version"), new VersionCommand());
commands.put(Set.of("dumpplugins"), new DumpPluginsCommand());
commands.put(Set.of("fixlight"), new FixLightCommand());
commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand());
+ commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
return commands.entrySet().stream()
@ -304,27 +304,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
@Nullable
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) {
+ final int x1 = x; final int z1 = z; // Paper - conflict on variable change
if (Thread.currentThread() != this.mainThread) {
return (ChunkAccess) CompletableFuture.supplyAsync(() -> {
return this.getChunk(x, z, leastStatus, create);
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
Objects.requireNonNull(completablefuture);
if (!completablefuture.isDone()) { // Paper
// Paper start - async chunk io/loading
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system
// Paper end
+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
this.level.timings.syncChunkLoad.startTiming(); // Paper
chunkproviderserver_b.managedBlock(completablefuture::isDone);
this.level.timings.syncChunkLoad.stopTiming(); // Paper
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
this.entityLookup = new io.papermc.paper.chunk.system.entity.EntityLookup(this, new EntityCallbacks()); // Paper - rewrite chunk system
}
+ // Paper start

View file

@ -57,21 +57,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java
@@ -0,0 +0,0 @@ public class DummyGeneratorAccess implements WorldGenLevel {
public boolean destroyBlock(BlockPos pos, boolean drop, Entity breakingEntity, int maxUpdateDepth) {
return false; // SPIGOT-6515
}
+
+ // Paper start
+ @Override
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay) {
+ }
@Override
public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, AABB box, List<? super T> into, Predicate<? super T> predicate) {}
// Paper end
+ // Paper start - add more methods
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay) {}
+
+ @Override
+ public void scheduleTick(BlockPos pos, Block block, int delay, net.minecraft.world.ticks.TickPriority priority) {
+ }
+ public void scheduleTick(BlockPos pos, Block block, int delay, net.minecraft.world.ticks.TickPriority priority) {}
+
+ @Override
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay, net.minecraft.world.ticks.TickPriority priority) {
+ }
+ // Paper end
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay, net.minecraft.world.ticks.TickPriority priority) {}
+ // Paper end - add more methods
}

View file

@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
@@ -0,0 +0,0 @@ public final class PaperCommand extends Command {
commands.put(Set.of("fixlight"), new FixLightCommand());
commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand());
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
commands.put(Set.of("dumpitem"), new DumpItemCommand());
+ commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());

View file

@ -65,7 +65,7 @@ diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" );
log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem );
}
@ -85,4 +85,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system

View file

@ -41,18 +41,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
+import java.util.zip.InflaterInputStream; // Paper
+
import javax.annotation.Nullable;
import net.minecraft.Util;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtIo;
+import net.minecraft.nbt.CompoundTag; // Paper
+import net.minecraft.nbt.NbtIo; // Paper
import net.minecraft.world.level.ChunkPos;
import org.slf4j.Logger;
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
private final IntBuffer timestamps;
@VisibleForTesting
protected final RegionBitmap usedSectors;
public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper
+ public final Path regionFile; // Paper
public RegionFile(Path file, Path directory, boolean dsync) throws IOException {
@ -218,7 +217,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public CompoundTag read(ChunkPos pos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
// CraftBukkit end
try { // Paper
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
+ // Paper start

View file

@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.getProfileCache().save(false); // Paper
}
// Spigot end
io.papermc.paper.chunk.system.io.RegionFileIOThread.close(true); // Paper // Paper - rewrite chunk system
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java

View file

@ -37,6 +37,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam", new Object[0]))); // Paper
return;
}
// Paper start
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
// Paper end
// CraftBukkit end
+ // Paper start - async tab completion
+ TAB_COMPLETE_EXECUTOR.execute(() -> {

View file

@ -559,8 +559,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.papermc.paper.math.BlockPosition;
import io.papermc.paper.math.FinePosition;
@@ -0,0 +0,0 @@ import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.phys.Vec3;
import org.apache.commons.lang.exception.ExceptionUtils;
+import com.mojang.authlib.GameProfile;

View file

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
} // Paper end - add pending task queue
}
+ private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper

View file

@ -23,9 +23,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
RegionFile regionfile = this.getRegionFile(pos, false); // CraftBukkit
}
// Paper end - rewrite chunk system
try { // Paper
+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper
if (nbt == null) {
@ -46,6 +46,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ net.minecraft.server.MinecraftServer.LOGGER.error("Failed to save chunk " + pos, laste);
+ }
+ // Paper end
}
public void close() throws IOException {
} finally { // Paper start
regionfile.fileLock.unlock();
} // Paper end

View file

@ -644,7 +644,7 @@ diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" );
log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" );
log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage());
@ -653,7 +653,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
{
log.log( Level.SEVERE, "\t\t" + stack );
}
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
}
log.log( Level.SEVERE, "\tStack:" );
//

View file

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 18 Jun 2023 23:04:46 -0700
Subject: [PATCH] Do not read tile entities in chunks that are positioned
outside of the chunk
The tile entities are not accessible and so should not be loaded.
This can happen as a result of users moving regionfiles around,
which would cause a crash on Folia but would appear to function
fine on Paper.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -0,0 +0,0 @@ public class ChunkSerializer {
for (int k1 = 0; k1 < nbttaglist3.size(); ++k1) {
CompoundTag nbttagcompound4 = nbttaglist3.getCompound(k1);
+ // Paper start - do not read tile entities positioned outside the chunk
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound4);
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
((ChunkAccess) object1).setBlockEntityNbt(nbttagcompound4);
}
@@ -0,0 +0,0 @@ public class ChunkSerializer {
CompoundTag nbttagcompound1 = nbttaglist1.getCompound(i);
boolean flag = nbttagcompound1.getBoolean("keepPacked");
+ // Paper start - do not read tile entities positioned outside the chunk
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); // moved up
+ ChunkPos chunkPos = chunk.getPos();
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
+
if (flag) {
chunk.setBlockEntityNbt(nbttagcompound1);
} else {
- BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1);
+ // Paper - do not read tile entities positioned outside the chunk - move up
BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1);
if (tileentity != null) {

View file

@ -20,4 +20,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (objectset == null || objectset.isEmpty()) { // Paper
this.playersPerChunk.remove(i);
this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false);
this.playerTicketManager.update(i, Integer.MAX_VALUE, false);
//this.playerTicketManager.update(i, Integer.MAX_VALUE, false); // Paper - no longer used

View file

@ -18,4 +18,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (true) return true; // Paper - this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full"
ChunkPos pos = new ChunkPos(x, z);
if (cps != null) {
com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
//com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe

View file

@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
return;
}
// Paper end
// CraftBukkit end
+ // Paper start - Don't suggest if tab-complete is disabled
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {

View file

@ -39,11 +39,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -0,0 +0,0 @@ public class ActivationRange
ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, worldHeight, villagerActivationRange );
// Paper end
- world.getEntities().get(maxBB, ActivationRange::activateEntity);
+ world.getEntities().get(world.paperConfig().entities.markers.tick ? null : (e) -> !(e instanceof net.minecraft.world.entity.Marker), maxBB, ActivationRange::activateEntity); // Paper - configurable marker ticking
}
MinecraftTimings.entityActivationCheckTimer.stopTiming();
}
// Paper start
java.util.List<Entity> entities = world.getEntities((Entity)null, maxBB, null);
+ boolean tickMarkers = world.paperConfig().entities.markers.tick; // Paper - configurable marker ticking
for (int i = 0; i < entities.size(); i++) {
Entity entity = entities.get(i);
+ // Paper start - configurable marker ticking
+ if (!tickMarkers && entity instanceof net.minecraft.world.entity.Marker) {
+ continue;
+ }
+ // Paper end - configurable marker ticking
ActivationRange.activateEntity(entity);
}
// Paper end

View file

@ -65,10 +65,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ checkDupeUUID(world, entity); // Paper
return !needsRemoval;
}));
}), position); // Paper - rewrite chunk system
// CraftBukkit end
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
});
throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
+ // Paper start
@ -115,5 +115,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> prepareTickingChunk(ChunkHolder holder) {
CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(holder, 1, (i) -> {
return ChunkStatus.FULL;
throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}

View file

@ -28,9 +28,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
+ // Paper end
if (this.position.x != x || this.position.y != y || this.position.z != z) {
this.position = new Vec3(x, y, z);
int i = Mth.floor(x);
// Paper start - rewrite chunk system
if (this.updatingSectionStatus) {
LOGGER.error("Refusing to update position for entity " + this + " to position " + new Vec3(x, y, z) + " since it is processing a section status update", new Throwable());
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.levelCallback.onMove();
}

View file

@ -564,8 +564,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, worldHeight, villagerActivationRange );
+ // Paper end
world.getEntities().get(maxBB, ActivationRange::activateEntity);
}
// Paper start
java.util.List<Entity> entities = world.getEntities((Entity)null, maxBB, null);
@@ -0,0 +0,0 @@ public class ActivationRange
* @param entity
* @return
@ -628,8 +628,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
{
- return true;
+ return 20; // Paper
}
- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() )
+ }
+ // Paper start
+ if (entity instanceof Bee) {
+ Bee bee = (Bee)entity;
@ -657,7 +656,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return config.villagersWorkImmunityFor;
+ }
+ }
+ }
}
- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() )
+ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() )
{
- return true;
@ -685,11 +685,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start
+ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) {
+ return 0;
+ }
}
+ if (entity instanceof Pillager) {
+ Pillager pillager = (Pillager) entity;
+ // TODO:?
}
+ }
+ // Paper end
}
// SPIGOT-6644: Otherwise the target refresh tick will be missed

View file

@ -64,9 +64,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@Nullable
BandwidthDebugMonitor bandwidthDebugMonitor;
public String hostname = ""; // CraftBukkit - add field
}
}
// Paper end - add pending task queue
+ // Paper start - NetworkClient implementation
+ public int protocolVersion;
+ public java.net.InetSocketAddress virtualHost;

View file

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// Paper end
private CompletableFuture<Optional<CompoundTag>> readChunk(ChunkPos chunkPos) {
- return this.read(chunkPos).thenApplyAsync((optional) -> {
@ -97,7 +97,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
protected final RegionBitmap usedSectors;
public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper
public final Path regionFile; // Paper
+ // Paper start - Cache chunk status
@ -135,8 +135,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static int getOffsetIndex(ChunkPos pos) {
return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32;
}
public void close() throws IOException {
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
synchronized (this) {
try {
// Paper end
+ this.closed = true; // Paper
try {
this.padToFullSector();

View file

@ -330,10 +330,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
this.sync = dsync;
}
+ // Paper start
// Paper start
+ @Nullable
+ public static ChunkPos getRegionFileCoordinates(Path file) {
+ String fileName = file.getFileName().toString();
@ -356,11 +355,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return null;
+ }
+ }
+ // Paper end
+
private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) {
return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()));
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java

View file

@ -15,9 +15,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
// Paper end
public boolean updatingSectionStatus = false;
// Paper end
+ // Paper start - make end portalling safe
+ public BlockPos portalBlock;
+ public ServerLevel portalWorld;
@ -48,10 +48,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.teleportTo(worldserver, null);
+ }
+ // Paper end - make end portalling safe
+
public Entity(EntityType<?> type, Level world) {
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
this.passengers = ImmutableList.of();
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}

View file

@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ io.papermc.paper.log.CustomLogManager.forceReset(); // Paper - Reset loggers after shutdown
this.onServerExit();
// Paper end
// Paper end - move final shutdown items here
}
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View file

@ -51,8 +51,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper start
// Paper end - optimize redstone (Alternate Current)
// Paper start - notify observers even if grow failed
public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
- if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) { // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)

View file

@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper End
// Spigot End
protected void runServer() {
public static volatile RuntimeException chunkSystemCrash; // Paper - rewrite chunk system
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Spigot start
@ -99,6 +99,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop
+ lastTick = start - TICK_TIME; // Paper
while (this.running) {
// Paper start - rewrite chunk system
// guarantee that nothing can stop the server from halting if it can at least still tick
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
throw this.chunkSystemCrash;
}
// Paper end - rewrite chunk system
- long i = (curTime = Util.getMillis()) - this.nextTickTime;
+ long i = ((curTime = System.nanoTime()) / (1000L * 1000L)) - this.nextTickTime; // Paper

View file

@ -41,5 +41,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end - block invalid positions
// Paper end
// Paper start - fix MC-4
if (this instanceof ItemEntity) {
// Paper start - rewrite chunk system
if (this.updatingSectionStatus) {

View file

@ -183,7 +183,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
@@ -0,0 +0,0 @@ public class AsyncCatcher
{
if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper
if ( !io.papermc.paper.util.TickThread.isTickThread() ) // Paper // Paper - rewrite chunk system
{
+ MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper
throw new IllegalStateException( "Asynchronous " + reason + "!" );

View file

@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
Thread thread = new Thread(() -> {
Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// CraftBukkit start
@ -122,12 +122,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.metricsRecorder.isRecording()) {
this.cancelRecordingMetrics();
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getProfileCache().save(false); // Paper
}
// Spigot end
+ // Paper start - move final shutdown items here
+ LOGGER.info("Flushing Chunk IO");
+ // TODO chunk system patch has a line here
+ // Paper end - move final shutdown items here
io.papermc.paper.chunk.system.io.RegionFileIOThread.close(true); // Paper // Paper - rewrite chunk system
+ // Paper start - move final shutdown items here
+ LOGGER.info("Closing Thread Pool");
+ Util.shutdownExecutors(); // Paper
+ LOGGER.info("Closing Server");
@ -136,7 +138,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } catch (Exception e) {
+ }
+ this.onServerExit();
+ // Paper end
+ // Paper end - move final shutdown items here
}
public String getLocalIp() {
@ -474,14 +476,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ import org.bukkit.Bukkit;
public class WatchdogThread extends Thread
public final class WatchdogThread extends io.papermc.paper.util.TickThread // Paper - rewrite chunk system
{
+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper
private static WatchdogThread instance;
private long timeoutTime;
private boolean restart;
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
{
if ( WatchdogThread.instance == null )
{
@ -489,7 +491,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
WatchdogThread.instance = new WatchdogThread( timeoutTime * 1000L, restart );
WatchdogThread.instance.start();
} else
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
// Paper start
Logger log = Bukkit.getServer().getLogger();
long currentTime = WatchdogThread.monotonicMillis();
@ -506,7 +508,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
lastEarlyWarning = currentTime;
if (isLongTimeout) {
// Paper end
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
if ( isLongTimeout )
{

View file

@ -32,9 +32,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
// Paper end
return;
}
// Paper end - rewrite chunk system
+ // Paper start - fix MC-4
+ if (this instanceof ItemEntity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) {

View file

@ -35,15 +35,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return null;
}
// Paper end
+
+ // Paper start
// Paper end - optimize redstone (Alternate Current)
+ // Paper start - notify observers even if grow failed
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) { // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
+ }
+ }
+ // Paper end
+ // Paper end - notify observers even if grow failed
}
diff --git a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View file

@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
});
}
// Paper end
+ // Paper start - optimise getPlayerByUUID
+ @Nullable

View file

@ -976,12 +976,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private final Map<Holder<PoiType>, Set<PoiRecord>> byType = Maps.newHashMap(); public final Map<Holder<PoiType>, Set<PoiRecord>> getData() { return this.byType; } // Paper - public accessor
private final Runnable setDirty;
private boolean isValid;
public final Optional<PoiSection> noAllocateOptional = Optional.of(this); // Paper - rewrite chunk system
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
@@ -0,0 +0,0 @@ public class SectionStorage<R> extends RegionFileStorage implements AutoCloseabl
}
@Nullable

View file

@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
gameprofilerfiller.incrementCounter("getChunk");
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
if (Thread.currentThread() != this.mainThread) {
if (!io.papermc.paper.util.TickThread.isTickThread()) { // Paper - rewrite chunk system
return null;
} else {
- this.level.getProfiler().incrementCounter("getChunkNow");

View file

@ -26,5 +26,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ // Paper end
// CraftBukkit end
return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE));
return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && !io.papermc.paper.util.TickThread.isTickThread() ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); // Paper - rewrite chunk system
}

View file

@ -43,7 +43,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return () -> {
return this.getIndirectPassengersStream().iterator();
};
}
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
// Paper end - rewrite chunk system
public boolean hasExactlyOnePlayerPassenger() {
+ if (this.passengers.isEmpty()) { return false; } // Paper

View file

@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
@@ -0,0 +0,0 @@ public final class PaperCommand extends Command {
commands.put(Set.of("dumpplugins"), new DumpPluginsCommand());
commands.put(Set.of("fixlight"), new FixLightCommand());
commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand());
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
+ commands.put(Set.of("dumpitem"), new DumpItemCommand());

View file

@ -9,23 +9,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
+++ b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
@@ -0,0 +0,0 @@ public class PlayerChunkSender {
public void dropChunk(ServerPlayer player, ChunkPos pos) {
if (!this.pendingChunks.remove(pos.toLong()) && player.isAlive()) {
player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
+ // Paper start
+ if(io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){
+ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent();
+ }
+ // Paper end
}
// Paper start - rewrite player chunk loader
public static void dropChunkStatic(ServerPlayer player, ChunkPos pos) {
player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
+ // Paper start
+ if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent();
+ }
+ // Paper end
}
// Paper end - rewrite player chunk loader
@@ -0,0 +0,0 @@ public class PlayerChunkSender {
private static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) {
public static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { // Paper - rewrite chunk loader - public
handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null));
+ // Paper start
+ if(io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), handler.getPlayer().getBukkitEntity()).callEvent();
+ }
+ // Paper end

View file

@ -76,5 +76,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
// Paper start - replace player chunk loader
private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));

View file

@ -38,4 +38,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper - move up
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API
//internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system

View file

@ -2354,9 +2354,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket;
+import net.minecraft.network.protocol.game.ClientboundSetSimulationDistancePacket;
+import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.ChunkTrackingView;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.level.TicketType;
+import net.minecraft.server.network.PlayerChunkSender;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.GameRules;
+import net.minecraft.world.level.chunk.ChunkAccess;
@ -2815,8 +2817,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ private void sendChunk(final int chunkX, final int chunkZ) {
+ if (this.sentChunks.add(CoordinateUtils.getChunkKey(chunkX, chunkZ))) {
+ this.world.getChunkSource().chunkMap.updateChunkTracking(this.player,
+ new ChunkPos(chunkX, chunkZ), new MutableObject<>(), false, true); // unloaded, loaded
+ PlayerChunkSender.sendChunk(this.player.connection, this.world, this.world.getChunkIfLoaded(chunkX, chunkZ));
+ return;
+ }
+ throw new IllegalStateException();
@ -2830,8 +2831,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ private void sendUnloadChunkRaw(final int chunkX, final int chunkZ) {
+ this.player.serverLevel().getChunkSource().chunkMap.updateChunkTracking(this.player,
+ new ChunkPos(chunkX, chunkZ), null, true, false); // unloaded, loaded
+ PlayerChunkSender.dropChunkStatic(this.player, new ChunkPos(chunkX, chunkZ));
+ }
+
+ private final SingleUserAreaMap<PlayerChunkLoaderData> broadcastMap = new SingleUserAreaMap<>(this) {
@ -2900,11 +2900,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private static boolean wantChunkLoaded(final int centerX, final int centerZ, final int chunkX, final int chunkZ,
+ final int sendRadius) {
+ // expect sendRadius to be = 1 + target viewable radius
+ return ChunkMap.isChunkInRange(chunkX, chunkZ, centerX, centerZ, sendRadius);
+ return ChunkTrackingView.isWithinDistance(centerX, centerZ, sendRadius, chunkX, chunkZ, true);
+ }
+
+ private static int getClientViewDistance(final ServerPlayer player) {
+ final Integer vd = player.clientViewDistance;
+ final Integer vd = player.requestedViewDistance();
+ return vd == null ? -1 : Math.max(0, vd.intValue());
+ }
+
@ -3122,20 +3122,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // try to push more chunk generations
+ final long maxGens = Math.max(0L, Math.min(MAX_RATE, Math.min(this.genQueue.size(), this.getMaxChunkGenerates())));
+ final int maxGensThisTick = (int)this.chunkGenerateTicketLimiter.takeAllocation(time, genRate, maxGens);
+ for (int i = 0; i < maxGensThisTick; ++i) {
+ final long chunk = this.genQueue.dequeueLong();
+ final byte prev = this.chunkTicketStage.put(chunk, CHUNK_TICKET_STAGE_GENERATING);
+ int ratedGensThisTick = 0;
+ while (!this.genQueue.isEmpty()) {
+ final long chunkKey = this.genQueue.firstLong();
+ final int chunkX = CoordinateUtils.getChunkX(chunkKey);
+ final int chunkZ = CoordinateUtils.getChunkZ(chunkKey);
+ final ChunkAccess chunk = this.world.chunkSource.getChunkAtImmediately(chunkX, chunkZ);
+ if (chunk.getStatus() != ChunkStatus.FULL) {
+ // only rate limit actual generations
+ if ((ratedGensThisTick + 1) > maxGensThisTick) {
+ break;
+ }
+ ++ratedGensThisTick;
+ }
+
+ this.genQueue.dequeueLong();
+
+ final byte prev = this.chunkTicketStage.put(chunkKey, CHUNK_TICKET_STAGE_GENERATING);
+ if (prev != CHUNK_TICKET_STAGE_LOADED) {
+ throw new IllegalStateException("Previous state should be " + CHUNK_TICKET_STAGE_LOADED + ", not " + prev);
+ }
+ this.pushDelayedTicketOp(
+ ChunkHolderManager.TicketOperation.addAndRemove(
+ chunk,
+ chunkKey,
+ REGION_PLAYER_TICKET, GENERATED_TICKET_LEVEL, this.idBoxed,
+ REGION_PLAYER_TICKET, LOADED_TICKET_LEVEL, this.idBoxed
+ )
+ );
+ this.generatingQueue.enqueue(chunk);
+ this.generatingQueue.enqueue(chunkKey);
+ }
+
+ // try to pull ticking chunks
@ -3783,6 +3797,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.entity.EntityInLevelCallback;
+import net.minecraft.world.level.entity.EntityTypeTest;
+import net.minecraft.world.level.entity.LevelCallback;
@ -3790,6 +3805,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.world.level.entity.LevelEntityGetter;
+import net.minecraft.world.level.entity.Visibility;
+import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
@ -4076,22 +4092,55 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.getChunk(x, z).updateStatus(newStatus, this);
+ }
+
+ public void addLegacyChunkEntities(final List<Entity> entities) {
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ this.addEntity(entities.get(i), true);
+ public void addLegacyChunkEntities(final List<Entity> entities, final ChunkPos forChunk) {
+ this.addEntityChunk(entities, forChunk, true);
+ }
+
+ public void addEntityChunkEntities(final List<Entity> entities, final ChunkPos forChunk) {
+ this.addEntityChunk(entities, forChunk, true);
+ }
+
+ public void addWorldGenChunkEntities(final List<Entity> entities, final ChunkPos forChunk) {
+ this.addEntityChunk(entities, forChunk, false);
+ }
+
+ private void addRecursivelySafe(final Entity root, final boolean fromDisk) {
+ if (!this.addEntity(root, fromDisk)) {
+ // possible we are a passenger, and so should dismount from any valid entity in the world
+ root.stopRiding(true);
+ return;
+ }
+ for (final Entity passenger : root.getPassengers()) {
+ this.addRecursivelySafe(passenger, fromDisk);
+ }
+ }
+
+ public void addEntityChunkEntities(final List<Entity> entities) {
+ private void addEntityChunk(final List<Entity> entities, final ChunkPos forChunk, final boolean fromDisk) {
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ this.addEntity(entities.get(i), true);
+ }
+ }
+ final Entity entity = entities.get(i);
+ if (entity.isPassenger()) {
+ continue;
+ }
+
+ public void addWorldGenChunkEntities(final List<Entity> entities) {
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ this.addEntity(entities.get(i), false);
+ }
+ if (!entity.chunkPosition().equals(forChunk)) {
+ LOGGER.warn("Root entity " + entity + " is outside of serialized chunk " + forChunk);
+ // can't set removed here, as we may not own the chunk position
+ // skip the entity
+ continue;
+ }
+
+ final Vec3 rootPosition = entity.position();
+
+ // always adjust positions before adding passengers in case plugins access the entity, and so that
+ // they are added to the right entity chunk
+ for (final Entity passenger : entity.getIndirectPassengers()) {
+ if (!passenger.chunkPosition().equals(forChunk)) {
+ passenger.setPosRaw(rootPosition.x, rootPosition.y, rootPosition.z, true);
+ }
+ }
+
+ this.addRecursivelySafe(entity, fromDisk);
+ }
+ }
+
+ public boolean addNewEntity(final Entity entity) {
@ -6538,7 +6587,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final ServerLevel world = this.world;
+ final ProtoChunk protoChunk = (ProtoChunk)this.fromChunk;
+ chunk = new LevelChunk(this.world, protoChunk, (final LevelChunk unused) -> {
+ ChunkMap.postLoadProtoChunk(world, protoChunk.getEntities());
+ ChunkMap.postLoadProtoChunk(world, protoChunk.getEntities(), protoChunk.getPos()); // Paper - rewrite chunk system
+ });
+ }
+
@ -11054,7 +11103,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (entityChunk != null) {
+ final List<Entity> entities = EntityStorage.readEntities(this.world, entityChunk);
+
+ this.world.getEntityLookup().addEntityChunkEntities(entities);
+ this.world.getEntityLookup().addEntityChunkEntities(entities, new ChunkPos(this.chunkX, this.chunkZ));
+ }
+ }
+
@ -16775,7 +16824,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@Nullable
private volatile Component delayedDisconnect;
BandwidthDebugMonitor bandwidthDebugMonitor;
public String hostname = ""; // CraftBukkit - add field
+ // Paper start - add pending task queue
+ private final Queue<Runnable> pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>();
@ -16808,7 +16857,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private void flushQueue() {
+ try { // Paper - add pending task queue
if (this.channel != null && this.channel.isOpen()) {
Queue queue = this.queue;
Queue queue = this.pendingActions;
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@ -17067,6 +17116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final ChunkHolder.PlayerProvider playerProvider;
- private boolean wasAccessibleSinceLastSave;
- private CompletableFuture<Void> pendingFullStateConfirmation;
- private CompletableFuture<?> sendSync;
+ // Paper - rewrite chunk system
private final ChunkMap chunkMap; // Paper
@ -17114,6 +17164,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public boolean hasChunkBeenSent() {
+ return this.playersSentChunkTo.size() != 0;
+ }
+
+ public boolean hasBeenSent(ServerPlayer to) {
+ return this.playersSentChunkTo.contains(to);
+ }
+ // Paper end - replace player chunk loader
+ public ChunkHolder(ChunkPos pos, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.PlayerProvider playersWatchingChunkProvider, io.papermc.paper.chunk.system.scheduling.NewChunkHolder newChunkHolder) { // Paper - rewrite chunk system
+ this.newChunkHolder = newChunkHolder; // Paper - rewrite chunk system
@ -17121,6 +17175,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.blockChangedLightSectionFilter = new BitSet();
this.skyChangedLightSectionFilter = new BitSet();
- this.pendingFullStateConfirmation = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error
- this.sendSync = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error
+ // Paper - rewrite chunk system
this.pos = pos;
this.levelHeightAccessor = world;
@ -17216,6 +17271,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - rewrite chunk system
}
public CompletableFuture<?> getChunkSendSyncFuture() {
- return this.sendSync;
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
@Nullable
public LevelChunk getChunkToSend() {
- return !this.sendSync.isDone() ? null : this.getTickingChunk();
+ return this.getSendingChunk(); // Paper - rewrite chunk system
}
@Nullable
public final LevelChunk getFullChunk() { // Paper - final for inline
- CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getFullChunkFuture();
@ -17415,8 +17481,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
});
}
- public void addSendDependency(CompletableFuture<?> postProcessingFuture) {
- if (this.sendSync.isDone()) {
- this.sendSync = postProcessingFuture;
- } else {
- this.sendSync = this.sendSync.thenCombine(postProcessingFuture, (object, object1) -> {
- return null;
- });
- }
-
- }
+ // Paper - rewrite chunk system
+
public FullChunkStatus getFullStatus() {
- return ChunkLevel.fullStatus(this.ticketLevel);
+ return this.newChunkHolder.getChunkStatus(); // Paper - rewrite chunk system) {
@ -17692,7 +17768,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private static final int MIN_VIEW_DISTANCE = 2;
public static final int MIN_VIEW_DISTANCE = 2;
public static final int MAX_VIEW_DISTANCE = 32;
public static final int FORCED_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING);
- public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap();
@ -17725,7 +17801,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private final Queue<Runnable> unloadQueue;
int viewDistance;
private int serverViewDistance;
- // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
- public final CallbackExecutor callbackExecutor = new CallbackExecutor();
@ -17754,8 +17830,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
void addPlayerToDistanceMaps(ServerPlayer player) {
+ this.level.playerChunkLoader.addPlayer(player); // Paper - replace chunk loader
int chunkX = MCUtil.getChunkCoordinate(player.getX());
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
// Note: players need to be explicitly added to distance maps before they can be updated
}
@ -17765,8 +17841,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
int chunkX = MCUtil.getChunkCoordinate(player.getX());
int chunkZ = MCUtil.getChunkCoordinate(player.getZ());
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
// Note: players need to be explicitly added to distance maps before they can be updated
+ this.level.playerChunkLoader.updatePlayer(player); // Paper - replace chunk loader
}
@ -17817,6 +17893,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.overworldDataStorage = persistentStateManagerFactory;
this.poiManager = new PoiManager(path.resolve("poi"), dataFixer, dsync, iregistrycustom, world);
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
boolean isChunkTracked(ServerPlayer player, int chunkX, int chunkZ) {
- return player.getChunkTrackingView().contains(chunkX, chunkZ) && !player.connection.chunkSender.isPending(ChunkPos.asLong(chunkX, chunkZ));
+ // Paper start - rewrite player chunk loader
+ return this.level.playerChunkLoader.isChunkSent(player, chunkX, chunkZ);
+ // Paper end - rewrite player chunk loader
}
private boolean isChunkOnTrackedBorder(ServerPlayer player, int chunkX, int chunkZ) {
- if (!this.isChunkTracked(player, chunkX, chunkZ)) {
- return false;
- } else {
- for (int k = -1; k <= 1; ++k) {
- for (int l = -1; l <= 1; ++l) {
- if ((k != 0 || l != 0) && !this.isChunkTracked(player, chunkX + k, chunkZ + l)) {
- return true;
- }
- }
- }
-
- return false;
- }
+ // Paper start - rewrite player chunk loader
+ return this.level.playerChunkLoader.isChunkSent(player, chunkX, chunkZ, true);
+ // Paper end - rewrite player chunk loader
}
protected ThreadedLevelLightEngine getLightEngine() {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@Nullable
protected ChunkHolder getUpdatingChunkIfPresent(long pos) {
@ -17847,6 +17953,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public String getChunkDebugData(ChunkPos chunkPos) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start
public final int getEffectiveViewDistance() {
- // TODO this needs to be checked on update
- // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want.
- //TODO check if +0 is correct now
- return this.viewDistance;
+ return this.serverViewDistance;
}
// Paper end
private CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction<ChunkStatus> distanceToStatus) {
@ -17903,7 +18018,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
-
- Optional<ChunkAccess> optional = either.left();
-
- if (!optional.isPresent()) {
- if (optional.isEmpty()) {
- return Either.right(new ChunkHolder.ChunkLoadingFailure() {
- public String toString() {
- ChunkPos chunkcoordintpair2 = new ChunkPos(j + l1 % (margin * 2 + 1), k + l1 / (margin * 2 + 1));
@ -18005,7 +18120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void saveAllChunks(boolean flush) {
- if (flush) {
- List<ChunkHolder> list = (List) io.papermc.paper.chunk.system.ChunkSystem.getVisibleChunkHolders(this.level).stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper
- List<ChunkHolder> list = io.papermc.paper.chunk.system.ChunkSystem.getVisibleChunkHolders(this.level).stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).toList(); // Paper
- MutableBoolean mutableboolean = new MutableBoolean();
-
- do {
@ -18286,11 +18401,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
- private static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> nbt) {
+ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> nbt) { // Paper - public
+ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> nbt, ChunkPos position) { // Paper - public and add chunk position parameter
if (!nbt.isEmpty()) {
// CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(nbt, world).filter((entity) -> {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
needsRemoval = true;
}
return !needsRemoval;
- }));
+ }), position); // Paper - rewrite chunk system
// CraftBukkit end
}
}
private CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> protoChunkToFullChunk(ChunkHolder chunkHolder) {
@ -18351,6 +18474,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- return either.ifLeft((chunk) -> {
- chunk.postProcessGeneration();
- this.level.startTickingChunk(chunk);
- CompletableFuture<?> completablefuture2 = holder.getChunkSendSyncFuture();
-
- if (completablefuture2.isDone()) {
- this.onChunkReadyToSend(chunk);
- } else {
- completablefuture2.thenAcceptAsync((object) -> {
- this.onChunkReadyToSend(chunk);
- }, this.mainThreadExecutor);
- }
-
- });
- }, this.mainThreadExecutor);
-
@ -18358,27 +18491,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.tickingGenerated.getAndIncrement();
- return null;
- });
- completablefuture1.thenAcceptAsync((either) -> {
- either.ifLeft((chunk) -> {
- MutableObject<ClientboundLevelChunkWithLightPacket> mutableobject = new MutableObject();
-
- this.getPlayers(holder.getPos(), false).forEach((entityplayer) -> {
- this.playerLoadedChunk(entityplayer, mutableobject, chunk);
- });
- });
- }, (runnable) -> {
- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
- });
- return completablefuture1;
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
private void onChunkReadyToSend(LevelChunk chunk) {
- ChunkPos chunkcoordintpair = chunk.getPos();
- Iterator iterator = this.playerMap.getAllPlayers().iterator();
-
- while (iterator.hasNext()) {
- ServerPlayer entityplayer = (ServerPlayer) iterator.next();
-
- if (entityplayer.getChunkTrackingView().contains(chunkcoordintpair)) {
- ChunkMap.markChunkPendingToSend(entityplayer, chunk);
- }
- }
+ throw new UnsupportedOperationException(); // Paper - rewrite player chunk loader
}
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> prepareAccessibleChunk(ChunkHolder holder) {
- return this.getChunkRangeFuture(holder, 1, ChunkStatus::getStatusAroundFullChunk).thenApplyAsync((either) -> {
- return either.mapLeft((list) -> {
- LevelChunk chunk = (LevelChunk) list.get(list.size() / 2);
-
- return chunk;
- return (LevelChunk) list.get(list.size() / 2);
- });
- }, (runnable) -> {
- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
@ -18474,88 +18609,67 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.markPositionReplaceable(pos);
- return false;
- }
-
- ChunkStatus.ChunkType chunkstatus_type = ChunkSerializer.getChunkTypeFromTag(nbttagcompound);
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
+ }
- ChunkStatus.ChunkType chunkstatus_type = ChunkSerializer.getChunkTypeFromTag(nbttagcompound);
+ // Paper start - replace player loader system
+ public void setTickViewDistance(int distance) {
+ this.level.playerChunkLoader.setTickDistance(distance);
+ }
- return this.markPosition(pos, chunkstatus_type) == 1;
- }
+ // Paper start - replace player loader system
+ public void setTickViewDistance(int distance) {
+ this.level.playerChunkLoader.setTickDistance(distance);
}
+ public void setSendViewDistance(int distance) {
+ this.level.playerChunkLoader.setSendDistance(distance);
+ }
}
+ // Paper end - replace player loader system
public void setViewDistance(int watchDistance) {
- protected void setServerViewDistance(int watchDistance) {
+ public void setServerViewDistance(int watchDistance) { // Paper - replace player loader system
int j = Mth.clamp(watchDistance, 2, 32);
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
int k = this.viewDistance;
this.viewDistance = j;
- this.distanceManager.updatePlayerTickets(this.viewDistance);
- Iterator objectiterator = io.papermc.paper.chunk.system.ChunkSystem.getUpdatingChunkHolders(this.level).iterator(); // Paper
if (j != this.serverViewDistance) {
this.serverViewDistance = j;
- this.distanceManager.updatePlayerTickets(this.serverViewDistance);
- Iterator iterator = this.playerMap.getAllPlayers().iterator();
-
- while (objectiterator.hasNext()) {
- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next();
- ChunkPos chunkcoordintpair = playerchunk.getPos();
- MutableObject<ClientboundLevelChunkWithLightPacket> mutableobject = new MutableObject();
- while (iterator.hasNext()) {
- ServerPlayer entityplayer = (ServerPlayer) iterator.next();
-
- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> {
- SectionPos sectionposition = entityplayer.getLastSectionPos();
- boolean flag = ChunkMap.isChunkInRange(chunkcoordintpair.x, chunkcoordintpair.z, sectionposition.x(), sectionposition.z(), k);
- boolean flag1 = ChunkMap.isChunkInRange(chunkcoordintpair.x, chunkcoordintpair.z, sectionposition.x(), sectionposition.z(), this.viewDistance);
-
- this.updateChunkTracking(entityplayer, chunkcoordintpair, mutableobject, flag, flag1);
- });
- this.updateChunkTracking(entityplayer);
- }
+ this.level.playerChunkLoader.setLoadDistance(this.viewDistance + 1); // Paper - replace player loader system
+ this.level.playerChunkLoader.setLoadDistance(this.serverViewDistance + 1); // Paper - replace player loader system
}
}
- protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, MutableObject<ClientboundLevelChunkWithLightPacket> packet, boolean oldWithinViewDistance, boolean newWithinViewDistance) {
+ public void updateChunkTracking(ServerPlayer player, ChunkPos pos, MutableObject<ClientboundLevelChunkWithLightPacket> packet, boolean oldWithinViewDistance, boolean newWithinViewDistance) { // Paper - public
+ io.papermc.paper.util.TickThread.ensureTickThread(this.level, pos, "May not update chunk tracking for chunk async"); // Paper - replace chunk loader system
+ io.papermc.paper.util.TickThread.ensureTickThread(player, "May not update chunk tracking for player async"); // Paper - replace chunk loader system
if (player.level() == this.level) {
+ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); // Paper - replace chunk loader system - move up
if (newWithinViewDistance && !oldWithinViewDistance) {
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong());
+ // Paper - replace chunk loader system - move up
if (playerchunk != null) {
- LevelChunk chunk = playerchunk.getTickingChunk();
+ LevelChunk chunk = playerchunk.getSendingChunk(); // Paper - replace chunk loader system
if (chunk != null) {
+ playerchunk.addPlayer(player); // Paper - replace chunk loader system
this.playerLoadedChunk(player, packet, chunk);
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
if (!newWithinViewDistance && oldWithinViewDistance) {
+ // Paper start - replace chunk loader system
+ if (playerchunk != null) {
+ playerchunk.removePlayer(player);
+ } else {
+ LOGGER.warn("ChunkHolder at " + pos + " in world '" + this.level.getWorld().getName() + "' does not exist to untrack chunk for " + player, new Throwable());
+ }
+ // Paper end - replace chunk loader system
player.untrackChunk(pos);
}
- }
+ } else { LOGGER.warn("Mismatch in world for chunk " + pos + " in world '" + this.level.getWorld().getName() + "' for player " + player, new Throwable()); } // Paper - replace chunk loader system
int getPlayerViewDistance(ServerPlayer player) {
- return Mth.clamp(player.requestedViewDistance(), 2, this.serverViewDistance);
+ return io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player); // Paper - per player view distance
}
public int size() {
private void markChunkPendingToSend(ServerPlayer player, ChunkPos pos) {
- LevelChunk chunk = this.getChunkToSend(pos.toLong());
-
- if (chunk != null) {
- ChunkMap.markChunkPendingToSend(player, chunk);
- }
+ throw new UnsupportedOperationException(); // Paper - per player view distance
}
private static void markChunkPendingToSend(ServerPlayer player, LevelChunk chunk) {
- player.connection.chunkSender.markChunkPendingToSend(chunk);
+ throw new UnsupportedOperationException(); // Paper - rewrite player chunk loader
}
private static void dropChunk(ServerPlayer player, ChunkPos pos) {
- player.connection.chunkSender.dropChunk(player, pos);
+ // Paper - rewrite player chunk loader
}
@Nullable
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
@ -18625,90 +18739,93 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return this.read(chunkPos).thenApplyAsync((optional) -> {
return optional.map((nbttagcompound) -> this.upgradeChunkTag(nbttagcompound, chunkPos)); // CraftBukkit
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player);
}
- player.setChunkTrackingView(ChunkTrackingView.EMPTY);
- this.updateChunkTracking(player);
+ // Paper - handled by player chunk loader
this.addPlayerToDistanceMaps(player); // Paper - distance maps
} else {
SectionPos sectionposition = player.getLastSectionPos();
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
this.removePlayerFromDistanceMaps(player); // Paper - distance maps
- this.applyChunkTrackingView(player, ChunkTrackingView.EMPTY);
+ // Paper - handled by player chunk loader
}
- for (int k = i - this.viewDistance - 1; k <= i + this.viewDistance + 1; ++k) {
- for (int l = j - this.viewDistance - 1; l <= j + this.viewDistance + 1; ++l) {
- if (ChunkMap.isChunkInRange(k, l, i, j, this.viewDistance)) {
- ChunkPos chunkcoordintpair = new ChunkPos(k, l);
-
- this.updateChunkTracking(player, chunkcoordintpair, new MutableObject(), !added, added);
- }
- }
- }
+ // Paper - handled by player chunk loader
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
SectionPos sectionposition = SectionPos.of((EntityAccess) player);
this.playerMap.unIgnorePlayer(player);
}
player.setLastSectionPos(sectionposition);
- player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z()));
+ //player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); // Paper - handled by player chunk loader
return sectionposition;
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
int l1;
int i2;
- if (Math.abs(i1 - i) <= k1 * 2 && Math.abs(j1 - j) <= k1 * 2) {
- l1 = Math.min(i, i1) - k1;
- i2 = Math.min(j, j1) - k1;
- int j2 = Math.max(i, i1) + k1;
- int k2 = Math.max(j, j1) + k1;
-
- for (int l2 = l1; l2 <= j2; ++l2) {
- for (int i3 = i2; i3 <= k2; ++i3) {
- boolean flag3 = ChunkMap.isChunkInRange(l2, i3, i1, j1, this.viewDistance);
- boolean flag4 = ChunkMap.isChunkInRange(l2, i3, i, j, this.viewDistance);
-
- this.updateChunkTracking(player, new ChunkPos(l2, i3), new MutableObject(), flag3, flag4);
- }
- }
- } else {
- boolean flag5;
- boolean flag6;
-
- for (l1 = i1 - k1; l1 <= i1 + k1; ++l1) {
- for (i2 = j1 - k1; i2 <= j1 + k1; ++i2) {
- if (ChunkMap.isChunkInRange(l1, i2, i1, j1, this.viewDistance)) {
- flag5 = true;
- flag6 = false;
- this.updateChunkTracking(player, new ChunkPos(l1, i2), new MutableObject(), true, false);
- }
- }
- }
-
- for (l1 = i - k1; l1 <= i + k1; ++l1) {
- for (i2 = j - k1; i2 <= j + k1; ++i2) {
- if (ChunkMap.isChunkInRange(l1, i2, i, j, this.viewDistance)) {
- flag5 = false;
- flag6 = true;
- this.updateChunkTracking(player, new ChunkPos(l1, i2), new MutableObject(), false, true);
- }
- }
- }
- }
+ // Paper - replaced by PlayerChunkLoader
- this.updateChunkTracking(player);
+ // Paper - replaced by PlayerChunkLoader
}
this.updateMaps(player); // Paper - distance maps
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private void updateChunkTracking(ServerPlayer player) {
- ChunkPos chunkcoordintpair = player.chunkPosition();
- int i = this.getPlayerViewDistance(player);
- ChunkTrackingView chunktrackingview = player.getChunkTrackingView();
-
- if (chunktrackingview instanceof ChunkTrackingView.Positioned) {
- ChunkTrackingView.Positioned chunktrackingview_a = (ChunkTrackingView.Positioned) chunktrackingview;
-
- if (chunktrackingview_a.center().equals(chunkcoordintpair) && chunktrackingview_a.viewDistance() == i) {
- return;
- }
- }
-
- this.applyChunkTrackingView(player, ChunkTrackingView.of(chunkcoordintpair, i));
+ throw new UnsupportedOperationException(); // Paper - replaced by PlayerChunkLoader
}
private void applyChunkTrackingView(ServerPlayer player, ChunkTrackingView chunkFilter) {
- if (player.level() == this.level) {
- ChunkTrackingView chunktrackingview1 = player.getChunkTrackingView();
-
- if (chunkFilter instanceof ChunkTrackingView.Positioned) {
- label15:
- {
- ChunkTrackingView.Positioned chunktrackingview_a = (ChunkTrackingView.Positioned) chunkFilter;
-
- if (chunktrackingview1 instanceof ChunkTrackingView.Positioned) {
- ChunkTrackingView.Positioned chunktrackingview_a1 = (ChunkTrackingView.Positioned) chunktrackingview1;
-
- if (chunktrackingview_a1.center().equals(chunktrackingview_a.center())) {
- break label15;
- }
- }
-
- player.connection.send(new ClientboundSetChunkCacheCenterPacket(chunktrackingview_a.center().x, chunktrackingview_a.center().z));
- }
- }
-
- ChunkTrackingView.difference(chunktrackingview1, chunkFilter, (chunkcoordintpair) -> {
- this.markChunkPendingToSend(player, chunkcoordintpair);
- }, (chunkcoordintpair) -> {
- ChunkMap.dropChunk(player, chunkcoordintpair);
- });
- player.setChunkTrackingView(chunkFilter);
- }
+ throw new UnsupportedOperationException(); // Paper - replaced by PlayerChunkLoader
}
@Override
public List<ServerPlayer> getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) {
- Set<ServerPlayer> set = this.playerMap.getPlayers(chunkPos.toLong());
- Set<ServerPlayer> set = this.playerMap.getAllPlayers();
- Builder<ServerPlayer> builder = ImmutableList.builder();
- Iterator iterator = set.iterator();
-
- while (iterator.hasNext()) {
- ServerPlayer entityplayer = (ServerPlayer) iterator.next();
- SectionPos sectionposition = entityplayer.getLastSectionPos();
-
- if (onlyOnWatchDistanceEdge && ChunkMap.isChunkOnRangeBorder(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance) || !onlyOnWatchDistanceEdge && ChunkMap.isChunkInRange(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance)) {
- if (onlyOnWatchDistanceEdge && this.isChunkOnTrackedBorder(entityplayer, chunkPos.x, chunkPos.z) || !onlyOnWatchDistanceEdge && this.isChunkTracked(entityplayer, chunkPos.x, chunkPos.z)) {
- builder.add(entityplayer);
- }
+ // Paper start - per player view distance
@ -18725,6 +18842,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void addEntity(Entity entity) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
protected void tick() {
- Iterator iterator = this.playerMap.getAllPlayers().iterator();
-
- while (iterator.hasNext()) {
- ServerPlayer entityplayer = (ServerPlayer) iterator.next();
-
- this.updateChunkTracking(entityplayer);
- }
+ // Paper - replaced by PlayerChunkLoader
List<ServerPlayer> list = Lists.newArrayList();
List<ServerPlayer> list1 = this.level.players();
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void waitForLightBeforeSending(ChunkPos centerPos, int radius) {
- int j = radius + 1;
-
- ChunkPos.rangeClosed(centerPos, j).forEach((chunkcoordintpair1) -> {
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkcoordintpair1.toLong());
-
- if (playerchunk != null) {
- playerchunk.addSendDependency(this.lightEngine.waitForPendingTasks(chunkcoordintpair1.x, chunkcoordintpair1.z));
- }
-
- });
+ // Paper - rewrite player chunk loader
}
private class ChunkDistanceManager extends DistanceManager {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@Override
protected boolean isChunkToRemove(long pos) {
@ -18733,15 +18883,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
@Nullable
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
if (player != this.entity) {
Vec3 vec3d = player.position().subtract(this.entity.position());
- double d0 = (double) Math.min(this.getEffectiveRange(), ChunkMap.this.viewDistance * 16);
+ double d0 = (double) Math.min(this.getEffectiveRange(), io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player) * 16); // Paper - per player view distance
double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player);
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
@ -19048,7 +19189,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void updatePlayerTickets(int viewDistance) {
- this.playerTicketManager.updateViewDistance(viewDistance);
+ this.chunkMap.setViewDistance(viewDistance);// Paper - route to player chunk manager
+ this.chunkMap.setServerViewDistance(viewDistance);// Paper - route to player chunk manager
}
// Paper start
@ -19721,8 +19862,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
java.util.function.Consumer<net.minecraft.world.level.chunk.ChunkAccess> consumer = (net.minecraft.world.level.chunk.ChunkAccess chunk) -> {
if (chunk != null) {
- int ticketLevel = Math.max(33, chunkProvider.chunkMap.getUpdatingChunkIfPresent(chunk.getPos().toLong()).getTicketLevel());
+ synchronized (ret) { // Folia - region threading - make callback thread-safe TODO rebase
ret.add(chunk);
- ticketLevels.add(ticketLevel);
+ } // Folia - region threading - make callback thread-safe TODO rebase
chunkProvider.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunk.getPos(), ticketLevel, holderIdentifier);
}
- if (++loadedChunks[0] == requiredChunks) {
@ -19985,7 +20128,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
});
this.chunkSource.getGeneratorState().ensureStructuresGenerated();
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
}, "random_sequences");
return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences");
});
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
+
@ -20131,14 +20274,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return this.entityLookup; // Paper - rewrite chunk system
}
public void addLegacyChunkEntities(Stream<Entity> entities) {
- public void addLegacyChunkEntities(Stream<Entity> entities) {
- this.entityManager.addLegacyChunkEntities(entities);
+ this.entityLookup.addLegacyChunkEntities(entities.toList()); // Paper - rewrite chunk system
+ public void addLegacyChunkEntities(Stream<Entity> entities, ChunkPos forChunk) { // Paper - rewrite chunk system
+ this.entityLookup.addLegacyChunkEntities(entities.toList(), forChunk); // Paper - rewrite chunk system
}
public void addWorldGenChunkEntities(Stream<Entity> entities) {
- public void addWorldGenChunkEntities(Stream<Entity> entities) {
- this.entityManager.addWorldGenChunkEntities(entities);
+ this.entityLookup.addWorldGenChunkEntities(entities.toList()); // Paper - rewrite chunk system
+ public void addWorldGenChunkEntities(Stream<Entity> entities, ChunkPos forChunk) { // Paper - rewrite chunk system
+ this.entityLookup.addWorldGenChunkEntities(entities.toList(), forChunk); // Paper - rewrite chunk system
}
public void startTickingChunk(LevelChunk chunk) {
@ -20207,6 +20352,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean isRealPlayer; // Paper
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
+ // Paper start - replace player chunk loader
+ private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
+ public io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
+
@ -20248,8 +20394,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return input.setSendViewDistance(distance);
+ });
+ }
+ // Paper end - replace player chunk loader
+
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
this.chatVisibility = ChatVisiblity.FULL;
diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
@ -20425,7 +20572,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
static enum TaskType {
public CompletableFuture<?> waitForPendingTasks(int x, int z) {
diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/Ticket.java
@ -20522,11 +20669,55 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, AABB box, List<? super T> into, Predicate<? super T> predicate) {}
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
+++ b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java
@@ -0,0 +0,0 @@ public class PlayerChunkSender {
this.pendingChunks.add(chunk.getPos().toLong());
}
+ // Paper start - rewrite player chunk loader
+ public static void dropChunkStatic(ServerPlayer player, ChunkPos pos) {
+ player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
+ }
+ // Paper end - rewrite player chunk loader
+
public void dropChunk(ServerPlayer player, ChunkPos pos) {
if (!this.pendingChunks.remove(pos.toLong()) && player.isAlive()) {
- player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
+ dropChunkStatic(player, pos); // Paper - rewrite player chunk loader - move into own method
}
}
public void sendNextChunks(ServerPlayer player) {
+ if (true) return; // Paper - rewrite player chunk loader
if (this.unacknowledgedBatches < this.maxUnacknowledgedBatches) {
float f = Math.max(1.0F, this.desiredChunksPerTick);
this.batchQuota = Math.min(this.batchQuota + this.desiredChunksPerTick, f);
@@ -0,0 +0,0 @@ public class PlayerChunkSender {
}
}
- private static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) {
+ public static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { // Paper - rewrite chunk loader - public
handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null));
ChunkPos chunkPos = chunk.getPos();
DebugPackets.sendPoiPacketsForChunk(world, chunkPos);
@@ -0,0 +0,0 @@ public class PlayerChunkSender {
}
public void onChunkBatchReceivedByClient(float desiredBatchSize) {
+ if (true) return; // Paper - rewrite player chunk loader
--this.unacknowledgedBatches;
this.desiredChunksPerTick = Double.isNaN((double)desiredBatchSize) ? 0.01F : Mth.clamp(desiredBatchSize, 0.01F, 64.0F);
if (this.unacknowledgedBatches == 0) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.disconnect(Component.translatable("disconnect.spam"));
return;
}
@ -20545,25 +20736,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
// Spigot - view distance
- playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.synchronizedRegistries, worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, worldserver1.spigotConfig.simulationDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat(), player.getLastDeathLocation(), player.getPortalCooldown()));
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), this.server.levelKeys(), this.synchronizedRegistries, worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), this.getMaxPlayers(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat(), player.getLastDeathLocation(), player.getPortalCooldown())); // Paper - replace old player chunk management
- playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, worldserver1.spigotConfig.simulationDistance, flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1)));
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1))); // Paper - replace old player chunk management
player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
playerconnection.send(new ClientboundUpdateEnabledFeaturesPacket(FeatureFlags.REGISTRY.toNames(worldserver1.enabledFeatures())));
playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName())));
playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
@@ -0,0 +0,0 @@ public abstract class PlayerList {
// CraftBukkit start
LevelData worlddata = worldserver1.getLevelData();
entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), (byte) i, entityplayer1.getLastDeathLocation(), entityplayer1.getPortalCooldown()));
LevelData worlddata = worldserver2.getLevelData();
entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i));
- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot
- entityplayer1.connection.send(new ClientboundSetSimulationDistancePacket(worldserver1.spigotConfig.simulationDistance)); // Spigot
+ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getWorld().getSendViewDistance())); // Spigot // Paper - replace old player chunk management
+ entityplayer1.connection.send(new ClientboundSetSimulationDistancePacket(worldserver1.getWorld().getSimulationDistance())); // Spigot // Paper - replace old player chunk management
entityplayer1.spawnIn(worldserver1);
entityplayer1.unsetRemoved();
entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver1.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot()));
entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit
entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle()));
entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
@@ -0,0 +0,0 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
@ -21689,6 +21880,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
nbttagcompound.put("PostProcessing", ChunkSerializer.packOffsets(chunk.getPostProcessing()));
CompoundTag nbttagcompound3 = new CompoundTag();
Iterator iterator1 = chunk.getHeightmaps().iterator();
@@ -0,0 +0,0 @@ public class ChunkSerializer {
return nbttaglist == null && nbttaglist1 == null ? null : (chunk) -> {
if (nbttaglist != null) {
- world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, world));
+ world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, world), chunk.getPos()); // Paper - rewrite chunk system
}
if (nbttaglist1 != null) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@ -22798,7 +22998,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
+ }
+ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ chunkMap.setViewDistance(viewDistance);
+ chunkMap.setServerViewDistance(viewDistance);
+ }
+
+ @Override

View file

@ -15,9 +15,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
if (regionfile != null) {
return regionfile;
} else {
return null;
}
// Paper end - cache regionfile does not exist state
- if (this.regionCache.size() >= 256) {
+ if (this.regionCache.size() >= io.papermc.paper.configuration.GlobalConfiguration.get().misc.regionFileCacheSize) { // Paper - configurable
((RegionFile) this.regionCache.removeLast()).close();

View file

@ -66,7 +66,7 @@ diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
private WatchdogThread(long timeoutTime, boolean restart)
{
@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.timeoutTime = timeoutTime;
this.restart = restart;
}
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
{
Logger log = Bukkit.getServer().getLogger();
log.log( Level.SEVERE, "------------------------------" );
@ -93,12 +93,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
//
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
{
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
}
//
log.log( Level.SEVERE, "------------------------------" );
- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" );
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
log.log( Level.SEVERE, "------------------------------" );
//

View file

@ -8,7 +8,7 @@ diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread
@@ -0,0 +0,0 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
while ( !this.stopping )
{
//

View file

@ -19,9 +19,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private QueryThreadGs4 queryThreadGs4;
// private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field
@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
public void handleConsoleInput(String command, CommandSourceStack commandSource) {
return;
}
// Paper end - rewrite chunk system
- this.consoleInput.add(new ConsoleInput(command, commandSource));
+ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); // Paper - use proper queue
}

View file

@ -14,5 +14,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ internal.keepSpawnInMemory = creator.keepSpawnLoaded().toBooleanOrElse(internal.getWorld().getKeepSpawnInMemory()); // Paper
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API
//internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system

View file

@ -261,8 +261,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private int serverViewDistance;
+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobDistanceMap; // Paper
// CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
// Paper - rewrite chunk system
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
@ -275,6 +275,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
void removePlayerFromDistanceMaps(ServerPlayer player) {
this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader
+ // Paper start - per player mob spawning
+ if (this.playerMobDistanceMap != null) {
@ -284,9 +285,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
void updateMaps(ServerPlayer player) {
int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX());
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ());
// Note: players need to be explicitly added to distance maps before they can be updated
this.level.playerChunkLoader.updatePlayer(player); // Paper - replace chunk loader
+
+ // Paper start - per player mob spawning
+ if (this.playerMobDistanceMap != null) {

View file

@ -112,8 +112,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
+
public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) {
ServerChunkCache chunkproviderserver = this.getChunkSource();
// Paper start - rewrite chunk system - add close param
this.save(progressListener, flush, savingDisabled, false);
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java