[ci skip] Move chunk system patch back

This commit is contained in:
Nassim Jahnke 2024-01-24 22:13:08 +01:00
parent 49feea0525
commit 52438f04a0
19 changed files with 317 additions and 551 deletions

View file

@ -38,7 +38,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @deprecated Use {@link #getViewDistance()}
+ */
+ @Deprecated
+ int getNoTickViewDistance();
+ default int getNoTickViewDistance() {
+ return this.getViewDistance();
+ }
+
+ /**
+ * Sets the no-tick view distance for this world.
@ -50,7 +52,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @deprecated Use {@link #setViewDistance(int)}
+ */
+ @Deprecated
+ void setNoTickViewDistance(int viewDistance);
+ default void setNoTickViewDistance(int viewDistance) {
+ this.setViewDistance(viewDistance);
+ }
+
+ /**
+ * Gets the sending view distance for this world.
@ -123,7 +127,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @deprecated Use {@link #getViewDistance()}
+ */
+ @Deprecated
+ public int getNoTickViewDistance();
+ default int getNoTickViewDistance() {
+ return this.getViewDistance();
+ }
+
+ /**
+ * Sets the no-ticking view distance for this player.
@ -135,7 +141,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @deprecated Use {@link #setViewDistance(int)}
+ */
+ @Deprecated
+ public void setNoTickViewDistance(int viewDistance);
+ default void setNoTickViewDistance(int viewDistance) {
+ this.setViewDistance(viewDistance);
+ }
+
+ /**
+ * Gets the sending view distance for this player.

View file

@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ public static TickThread getCurrentTickThread() {
+ return (TickThread)Thread.currentThread();
+ return (TickThread) Thread.currentThread();
+ }
+
+ public static boolean isTickThread() {
@ -83,11 +83,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ) {
+ return Bukkit.isPrimaryThread();
+ return isTickThread();
+ }
+
+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) {
+ return isTickThread();
+ }
+
+ public static boolean isTickThreadFor(final Entity entity) {
+ return Bukkit.isPrimaryThread();
+ return isTickThread();
+ }
+}
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java

View file

@ -69,7 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ ++valueInMap.times;
+
+ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> {
+ valueInMap.coordinateTimes.compute(io.papermc.paper.util.MCUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> {
+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1);
+ });
+
@ -122,7 +122,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) {
+ final long key = coordinate.getLongKey();
+ final int times = coordinate.getIntValue();
+ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times);
+ coordinates.add("(" + io.papermc.paper.util.MCUtil.getCoordinateX(key) + "," + io.papermc.paper.util.MCUtil.getCoordinateZ(key) + "): " + times);
+ }
+
+ stacktrace.add("coordinates", coordinates);

View file

@ -57,9 +57,10 @@ 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 {
@Override
public <T> void getEntitiesByClass(Class<? extends T> clazz, Entity except, AABB box, List<? super T> into, Predicate<? super T> predicate) {}
// Paper end
public boolean destroyBlock(BlockPos pos, boolean drop, Entity breakingEntity, int maxUpdateDepth) {
return false; // SPIGOT-6515
}
+
+ // Paper start - add more methods
+ public void scheduleTick(BlockPos pos, Fluid fluid, int delay) {}
+

View file

@ -10,9 +10,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("syncloadinfo"), new SyncLoadInfoCommand());
commands.put(Set.of("dumpitem"), new DumpItemCommand());
commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand());
+ commands.put(Set.of("dumplisteners"), new DumpListenersCommand());
return commands.entrySet().stream()

View file

@ -3485,9 +3485,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public String getMotd() {
return this.console.getMotd();
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return this.spigot;
public double[] getTPS() {
return new double[]{0, 0, 0}; // TODO
}
// Spigot end
+
+ // Paper start - adventure sounds
+ @Override
@ -3598,8 +3598,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static Map<String, GameRules.Key<?>> gamerules;
public static synchronized Map<String, GameRules.Key<?>> getGameRulesNMS() {
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return ret;
public void setSendViewDistance(final int viewDistance) {
throw new UnsupportedOperationException("Not implemented yet");
}
+
+ // Paper start - implement pointers

View file

@ -9,7 +9,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 {
public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
protected final RegionBitmap usedSectors;
public RegionFile(Path file, Path directory, boolean dsync) throws IOException {
- this(file, directory, RegionFileVersion.VERSION_DEFLATE, dsync);

View file

@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start - Fix NPE on Boat getStatus
+ final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle();
+ if (handle.status == null) {
+ if (handle.valid && !handle.updatingSectionStatus) {
+ if (handle.valid) {
+ // Don't actually set the status because it would skew the old status check in the next tick
+ return CraftBoat.boatStatusFromNms(handle.getStatus());
+ } else {

View file

@ -1158,7 +1158,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start - Folia scheduler API
+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick();
+ getAllLevels().forEach(level -> {
+ for (final Entity entity : level.getEntityLookup().getAllCopy()) {
+ for (final Entity entity : level.getEntities().getAll()) {
+ if (entity.isRemoved()) {
+ continue;
+ }
@ -1214,16 +1214,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public CommandSender getBukkitSender(CommandSourceStack wrapper) {
return this.getBukkitEntity();
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return;
}
// Paper end - rewrite chunk system
+ final boolean alreadyRemoved = this.removalReason != null;
@Override
public final void setRemoved(Entity.RemovalReason reason) {
+ final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) {
this.removalReason = reason;
}
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
if (reason != RemovalReason.UNLOADED_TO_CHUNK) this.getPassengers().forEach(Entity::stopRiding); // Paper - chunk system - don't adjust passenger state when unloading, it's just not safe (and messes with our logic in entity chunk unload)
this.getPassengers().forEach(Entity::stopRiding);
this.levelCallback.onRemove(reason);
+ // Paper start - Folia schedulers
+ if (!(this instanceof ServerPlayer) && reason != RemovalReason.CHANGED_DIMENSION && !alreadyRemoved) {

View file

@ -145,21 +145,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return this.getServer().tickTimes5s.getAverage();
}
+ @Override
+ public double[] getTPS() {
@Override
public double[] getTPS() {
- return new double[]{0, 0, 0}; // TODO
+ return new double[] {
+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(),
+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(),
+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage()
+ };
+ }
+
// Spigot start
private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot()
{
}
// Paper start - adventure sounds
diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java

View file

@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
GraphData data = RAMGraph.DATA.peekLast();
Vector<String> vector = new Vector<>();
+
+ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()};
+ double[] tps = org.bukkit.Bukkit.getTPS();
+ String[] tpsAvg = new String[tps.length];
+
+ for ( int g = 0; g < tps.length; g++) {

View file

@ -2762,7 +2762,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ };
+
+ final ChunkHolder holder = level.chunkSource.chunkMap.getUpdatingChunkIfPresent(CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
+
+ if (holder == null || holder.getTicketLevel() > minLevel) {
+ loadCallback.accept(null);
@ -2790,7 +2790,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
+ final FullChunkStatus toStatus, final boolean addTicket,
+ final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
+ if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) {
+ // This method goes unused until the chunk system rewrite
+ if (toStatus == FullChunkStatus.INACCESSIBLE) {
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
+ }
+
@ -2829,7 +2830,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ };
+
+ final ChunkHolder holder = level.chunkSource.chunkMap.getUpdatingChunkIfPresent(CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
+
+ if (holder == null || holder.getTicketLevel() > minLevel) {
+ loadCallback.accept(null);
@ -2838,11 +2839,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ final CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> tickingState;
+ switch (toStatus) {
+ case BORDER: {
+ case FULL: {
+ tickingState = holder.getFullChunkFuture();
+ break;
+ }
+ case TICKING: {
+ case BLOCK_TICKING: {
+ tickingState = holder.getTickingChunkFuture();
+ break;
+ }
@ -2942,19 +2943,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ public static int getLoadViewDistance(final ServerPlayer player) {
+ final ServerLevel level = player.getLevel();
+ final ServerLevel level = player.serverLevel();
+ if (level == null) {
+ return Bukkit.getViewDistance() + 1;
+ return Bukkit.getViewDistance();
+ }
+ return level.chunkSource.chunkMap.getEffectiveViewDistance() + 1;
+ return level.chunkSource.chunkMap.getPlayerViewDistance(player);
+ }
+
+ public static int getTickViewDistance(final ServerPlayer player) {
+ final ServerLevel level = player.getLevel();
+ final ServerLevel level = player.serverLevel();
+ if (level == null) {
+ return Bukkit.getSimulationDistance();
+ }
+ return level.chunkSource.chunkMap.distanceManager.getSimulationDistance();
+ return level.chunkSource.chunkMap.distanceManager.simulationDistance;
+ }
+
+ private ChunkSystem() {
@ -6420,18 +6421,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.regionManagers.add(this.dataRegionManager);
+ this.nearbyPlayers = new io.papermc.paper.util.player.NearbyPlayers(this.level);
+ // Paper end
}
+ }
+
+ // Paper start
+ // always use accessor, so folia can override
+ public final io.papermc.paper.util.player.NearbyPlayers getNearbyPlayers() {
+ return this.nearbyPlayers;
+ }
}
+ // Paper end
+
protected ChunkGenerator generator() {
return this.generator;
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
});
}
@ -6443,22 +6443,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) {
double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8);
double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8);
@@ -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;
+ }
+ // Paper end
+
private CompletableFuture<Either<List<ChunkAccess>, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction<ChunkStatus> distanceToStatus) {
if (margin == 0) {
ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(0);
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
};
@ -6554,6 +6538,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
};
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
}
- protected void setServerViewDistance(int watchDistance) {
+ public void setServerViewDistance(int watchDistance) { // Paper - public
int j = Mth.clamp(watchDistance, 2, 32);
if (j != this.serverViewDistance) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
- int getPlayerViewDistance(ServerPlayer player) {
+ public int getPlayerViewDistance(ServerPlayer player) { // Paper - public
return Mth.clamp(player.requestedViewDistance(), 2, this.serverViewDistance);
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
@ -6613,7 +6615,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private void updateChunkTracking(ServerPlayer player) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private class ChunkDistanceManager extends DistanceManager {
});
}
- private class ChunkDistanceManager extends DistanceManager {
+ public class ChunkDistanceManager extends DistanceManager { // Paper - public
protected ChunkDistanceManager(Executor workerExecutor, Executor mainThreadExecutor) {
- super(workerExecutor, mainThreadExecutor);
@ -6644,19 +6650,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
protected void purgeStaleTickets() {
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
this.playerTicketManager.updateViewDistance(viewDistance);
}
+ // Paper start
+ public int getSimulationDistance() {
+ return this.simulationDistance;
+ }
+ // Paper end
+
public void updateSimulationDistance(int simulationDistance) {
if (simulationDistance != this.simulationDistance) {
this.simulationDistance = simulationDistance;
@@ -0,0 +0,0 @@ public abstract class DistanceManager {
}
@ -6683,11 +6676,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
+ // Paper start
+ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<LevelChunk> tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true);
+ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true);
+ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock();
+ final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
+
+ long chunkFutureAwaitCounter;
+ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
+
+ // Paper end
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
this.level = world;
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
return chunk.getFullChunkNow() != null;
}
// CraftBukkit end
+ // Paper start
+ private static int getChunkCacheKey(int x, int z) {
+ return x & 3 | ((z & 3) << 2);
+ }
@ -6745,119 +6748,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return this.loadedChunkMap.get(ChunkPos.asLong(x, z));
+ }
+
+ public final LevelChunk getChunkAtMainThread(int x, int z) {
+ LevelChunk ret = this.getChunkAtIfLoadedMainThread(x, z);
+ if (ret != null) {
+ return ret;
+ }
+ return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true);
+ }
+
+ long chunkFutureAwaitCounter; // Paper - private -> package private
+
+ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
+ io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
+ this.level, x, z, FullChunkStatus.ENTITY_TICKING, true,
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
+ );
+ }
+
+ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
+ io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
+ this.level, x, z, FullChunkStatus.BLOCK_TICKING, true,
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
+ );
+ }
+
+ public void getFullChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
+ io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
+ this.level, x, z, FullChunkStatus.FULL, true,
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
+ );
+ }
+
+ void chunkLoadAccept(int chunkX, int chunkZ, ChunkAccess chunk, java.util.function.Consumer<ChunkAccess> consumer) {
+ try {
+ consumer.accept(chunk);
+ } catch (Throwable throwable) {
+ if (throwable instanceof ThreadDeath) {
+ throw (ThreadDeath)throwable;
+ }
+ LOGGER.error("Load callback for chunk " + chunkX + "," + chunkZ + " in world '" + this.level.getWorld().getName() + "' threw an exception", throwable);
+ }
+ }
+
+ void getChunkAtAsynchronously(int chunkX, int chunkZ, int ticketLevel,
+ java.util.function.Consumer<ChunkAccess> consumer) {
+ if (ticketLevel <= 33) {
+ this.getFullChunkAsync(chunkX, chunkZ, (java.util.function.Consumer)consumer);
+ return;
+ }
+
+ io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(
+ this.level, chunkX, chunkZ, ChunkHolder.getStatus(ticketLevel), true,
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, consumer
+ );
+ }
+
+
+ public final void getChunkAtAsynchronously(int chunkX, int chunkZ, ChunkStatus status, boolean gen, boolean allowSubTicketLevel, java.util.function.Consumer<ChunkAccess> onLoad) {
+ // try to fire sync
+ int chunkStatusTicketLevel = 33 + ChunkStatus.getDistance(status);
+ ChunkHolder playerChunk = this.chunkMap.getUpdatingChunkIfPresent(io.papermc.paper.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
+ if (playerChunk != null) {
+ ChunkStatus holderStatus = playerChunk.getChunkHolderStatus();
+ ChunkAccess immediate = playerChunk.getAvailableChunkNow();
+ if (immediate != null) {
+ if (allowSubTicketLevel ? immediate.getStatus().isOrAfter(status) : (playerChunk.getTicketLevel() <= chunkStatusTicketLevel && holderStatus != null && holderStatus.isOrAfter(status))) {
+ this.chunkLoadAccept(chunkX, chunkZ, immediate, onLoad);
+ return;
+ } else {
+ if (gen || (!allowSubTicketLevel && immediate.getStatus().isOrAfter(status))) {
+ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
+ return;
+ } else {
+ this.chunkLoadAccept(chunkX, chunkZ, null, onLoad);
+ return;
+ }
+ }
+ }
+ }
+
+ // need to fire async
+
+ if (gen && !allowSubTicketLevel) {
+ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
+ return;
+ }
+
+ this.getChunkAtAsynchronously(chunkX, chunkZ, io.papermc.paper.util.MCUtil.getTicketLevelFor(ChunkStatus.EMPTY), (ChunkAccess chunk) -> {
+ if (chunk == null) {
+ throw new IllegalStateException("Chunk cannot be null");
+ }
+
+ if (!chunk.getStatus().isOrAfter(status)) {
+ if (gen) {
+ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
+ return;
+ } else {
+ ServerChunkCache.this.chunkLoadAccept(chunkX, chunkZ, null, onLoad);
+ return;
+ }
+ } else {
+ if (allowSubTicketLevel) {
+ ServerChunkCache.this.chunkLoadAccept(chunkX, chunkZ, chunk, onLoad);
+ return;
+ } else {
+ this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
+ return;
+ }
+ }
+ });
+ }
+ // Paper end
+
+ // Paper start
+ @Nullable
+ public ChunkAccess getChunkAtImmediately(int x, int z) {
+ ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
@ -6868,34 +6758,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return holder.getLastAvailable();
+ }
+
+ // this will try to avoid chunk neighbours for lighting
+ public final ChunkAccess getFullStatusChunkAt(int chunkX, int chunkZ) {
+ LevelChunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
+ if (ifLoaded != null) {
+ return ifLoaded;
+ }
+
+ ChunkAccess empty = this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, true);
+ if (empty != null && empty.getStatus().isOrAfter(ChunkStatus.FULL)) {
+ return empty;
+ }
+ return this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true);
+ }
+
+ public final ChunkAccess getFullStatusChunkAtIfLoaded(int chunkX, int chunkZ) {
+ LevelChunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
+ if (ifLoaded != null) {
+ return ifLoaded;
+ }
+
+ ChunkAccess ret = this.getChunkAtImmediately(chunkX, chunkZ);
+ if (ret != null && ret.getStatus().isOrAfter(ChunkStatus.FULL)) {
+ return ret;
+ } else {
+ return null;
+ }
+ }
+
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
+ this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
+ }
@ -6904,17 +6766,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.distanceManager.removeTicket(ticketType, chunkPos, ticketLevel, identifier);
+ }
+
+ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<LevelChunk> tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true);
+ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true);
+ // Paper end
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
this.level = world;
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
this.lastChunk[0] = chunk;
}
+ // Paper start - "real" get chunk if loaded
+ // "real" get chunk if loaded
+ // Note: Partially copied from the getChunkAt method below
+ @Nullable
+ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) {
@ -6956,10 +6808,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return ret;
+ }
+ // Paper end
+
@Nullable
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) {
public ThreadedLevelLightEngine getLightEngine() {
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
return this.mainThreadProcessor.pollTask();
}
- boolean runDistanceManagerUpdates() {
+ public boolean runDistanceManagerUpdates() { // Paper - public
boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
boolean flag1 = this.chunkMap.promoteChunkMap();
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
}
}
@ -7020,7 +6880,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return;
+ }
+ List<net.minecraft.world.level.chunk.ChunkAccess> ret = new java.util.ArrayList<>();
+ IntArrayList ticketLevels = new IntArrayList();
+ it.unimi.dsi.fastutil.ints.IntArrayList ticketLevels = new it.unimi.dsi.fastutil.ints.IntArrayList();
+
+ int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
+ int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
@ -7876,6 +7736,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!this.addEntityUuid(entity)) {
return false;
} else {
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
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return this.spigot;
}
// Spigot end
+
+ @Override
+ public double[] getTPS() {
+ return new double[]{0, 0, 0}; // TODO
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@ -7931,6 +7805,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ return ret;
+ }
+
+ @Override
+ public void setViewDistance(final int viewDistance) {
+ if (viewDistance < 2 || viewDistance > 32) {
+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
+ }
+ this.getHandle().chunkSource.chunkMap.setServerViewDistance(viewDistance);
+ }
+
+ @Override
+ public void setSimulationDistance(final int simulationDistance) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public int getSendViewDistance() {
+ return this.getViewDistance();
+ }
+
+ @Override
+ public void setSendViewDistance(final int viewDistance) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@ -7975,6 +7872,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this.spigot;
}
// Spigot end
+
+ @Override
+ public int getViewDistance() {
+ return io.papermc.paper.chunk.system.ChunkSystem.getLoadViewDistance(this.getHandle());
+ }
+
+ @Override
+ public void setViewDistance(final int viewDistance) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public int getSimulationDistance() {
+ return io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(this.getHandle());
+ }
+
+ @Override
+ public void setSimulationDistance(final int simulationDistance) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ @Override
+ public int getSendViewDistance() {
+ return io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(this.getHandle());
+ }
+
+ @Override
+ public void setSendViewDistance(final int viewDistance) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java

View file

@ -46,9 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+ // Paper end - notify observers even if grow failed
// Paper start
//protected final io.papermc.paper.world.EntitySliceManager entitySliceManager; // Paper - rewrite chunk system
}
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
--- a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java

View file

@ -686,7 +686,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ @PostProcess
+ private void postProcess() {
+ io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.init(this);
+ //io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.init(this);
+ }
+ }
+

View file

@ -923,23 +923,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static final class LightQueue {
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -0,0 +0,0 @@ public class TimingsExport extends Thread {
pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> {
return pair(rule, world.getWorld().getGameRuleValue(rule));
})),
- pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance())
+ // Paper start - replace chunk loader system
+ pair("ticking-distance", world.getWorld().getSimulationDistance()),
+ pair("no-ticking-distance", world.getWorld().getViewDistance()),
+ pair("sending-distance", world.getWorld().getSendViewDistance())
+ // Paper end - replace chunk loader system
));
}));
diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java
@ -2166,7 +2149,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- }
- };
-
- final ChunkHolder holder = level.chunkSource.chunkMap.getUpdatingChunkIfPresent(CoordinateUtils.getChunkKey(chunkX, chunkZ));
- final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
-
- if (holder == null || holder.getTicketLevel() > minLevel) {
- loadCallback.accept(null);
@ -2195,7 +2178,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
final FullChunkStatus toStatus, final boolean addTicket,
final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
- if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) {
- // This method goes unused until the chunk system rewrite
- if (toStatus == FullChunkStatus.INACCESSIBLE) {
- throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
- }
-
@ -2234,7 +2218,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- }
- };
-
- final ChunkHolder holder = level.chunkSource.chunkMap.getUpdatingChunkIfPresent(CoordinateUtils.getChunkKey(chunkX, chunkZ));
- final ChunkHolder holder = level.chunkSource.chunkMap.updatingChunkMap.get(CoordinateUtils.getChunkKey(chunkX, chunkZ));
-
- if (holder == null || holder.getTicketLevel() > minLevel) {
- loadCallback.accept(null);
@ -2243,11 +2227,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
-
- final CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> tickingState;
- switch (toStatus) {
- case BORDER: {
- case FULL: {
- tickingState = holder.getFullChunkFuture();
- break;
- }
- case TICKING: {
- case BLOCK_TICKING: {
- tickingState = holder.getTickingChunkFuture();
- break;
- }
@ -2340,20 +2324,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static int getLoadViewDistance(final ServerPlayer player) {
- final ServerLevel level = player.getLevel();
- final ServerLevel level = player.serverLevel();
- if (level == null) {
- return Bukkit.getViewDistance() + 1;
- return Bukkit.getViewDistance();
- }
- return level.chunkSource.chunkMap.getEffectiveViewDistance() + 1;
- return level.chunkSource.chunkMap.getPlayerViewDistance(player);
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getLoadViewDistance(player);
}
public static int getTickViewDistance(final ServerPlayer player) {
- final ServerLevel level = player.getLevel();
- final ServerLevel level = player.serverLevel();
- if (level == null) {
- return Bukkit.getSimulationDistance();
- }
- return level.chunkSource.chunkMap.distanceManager.getSimulationDistance();
- return level.chunkSource.chunkMap.distanceManager.simulationDistance;
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPITickViewDistance(player);
}
@ -15286,9 +15270,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("syncloadinfo"), new SyncLoadInfoCommand());
commands.put(Set.of("dumpitem"), new DumpItemCommand());
commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
commands.put(Set.of("dumplisteners"), new DumpListenersCommand());
+ commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand());
return commands.entrySet().stream()
@ -15636,6 +15620,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public UnsupportedSettings unsupportedSettings;
public class UnsupportedSettings extends ConfigurationPart {
@@ -0,0 +0,0 @@ public class GlobalConfiguration extends ConfigurationPart {
@PostProcess
private void postProcess() {
- //io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.init(this);
+ io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.init(this);
}
}
diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
@ -15989,10 +15982,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ) {
- return Bukkit.isPrimaryThread();
+ return isTickThread();
+ }
+
return isTickThread();
}
+ public static boolean isTickThreadFor(final ServerLevel world, final AABB aabb) {
+ return isTickThread();
+ }
@ -16009,14 +16001,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return isTickThread();
+ }
+
+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) {
+ return isTickThread();
}
public static boolean isTickThreadFor(final Entity entity) {
- return Bukkit.isPrimaryThread();
+ return isTickThread();
}
public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) {
return isTickThread();
}
diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
new file mode 100644
@ -16795,6 +16781,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start
if (isOversleep) return canOversleep(); // Paper - because of our changes, this logic is broken
return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos);
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper start - Folia scheduler API
((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick();
getAllLevels().forEach(level -> {
- for (final Entity entity : level.getEntities().getAll()) {
+ for (final Entity entity : level.getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system
if (entity.isRemoved()) {
continue;
}
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// CraftBukkit start
@Override
@ -17715,16 +17710,7 @@ 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) {
- if (margin == 0) {
@ -18391,8 +18377,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
+ // Paper end - replace player loader system
- protected void setServerViewDistance(int watchDistance) {
+ public void setServerViewDistance(int watchDistance) { // Paper - replace player loader system
public void setServerViewDistance(int watchDistance) { // Paper - public
int j = Mth.clamp(watchDistance, 2, 32);
if (j != this.serverViewDistance) {
@ -18410,7 +18395,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
int getPlayerViewDistance(ServerPlayer player) {
public int getPlayerViewDistance(ServerPlayer player) { // Paper - public
- return Mth.clamp(player.requestedViewDistance(), 2, this.serverViewDistance);
+ return io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player); // Paper - per player view distance
}
@ -18639,7 +18624,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper - rewrite player chunk loader
}
private class ChunkDistanceManager extends DistanceManager {
public class ChunkDistanceManager extends DistanceManager { // Paper - public
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@Override
@ -18960,19 +18945,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.chunkMap.setServerViewDistance(viewDistance); // Paper - route to player chunk manager
}
// Paper start
public int getSimulationDistance() {
- return this.simulationDistance;
+ return this.chunkMap.level.playerChunkLoader.getAPITickDistance();
}
// Paper end
public void updateSimulationDistance(int simulationDistance) {
- public void updateSimulationDistance(int simulationDistance) {
- if (simulationDistance != this.simulationDistance) {
- this.simulationDistance = simulationDistance;
- this.tickingTicketsTracker.replacePlayerTicketsLevel(this.getPlayerTicketLevel());
- }
-
+ // Paper start
+ public int getSimulationDistance() {
+ return this.chunkMap.level.playerChunkLoader.getAPITickDistance();
+ }
+ // Paper end
+ public void updateSimulationDistance(int simulationDistance) {
+ this.chunkMap.level.playerChunkLoader.setTickDistance(simulationDistance); // Paper - route to player chunk manager
}
@ -18988,7 +18972,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- private void dumpTickets(String path) {
- try {
- FileOutputStream fileoutputstream = new FileOutputStream(new File(path));
-
+ // Paper - rewrite chunk system
- try {
- ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().iterator();
-
@ -19019,8 +19004,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- }
-
- }
+ // Paper - rewrite chunk system
-
- @VisibleForTesting
- TickingTracker tickingTracker() {
- return this.tickingTicketsTracker;
@ -19115,150 +19099,14 @@ 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 {
return (LevelChunk)this.getChunk(x, z, ChunkStatus.FULL, true);
}
- long chunkFutureAwaitCounter; // Paper - private -> package private
-
- public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
- io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
- this.level, x, z, FullChunkStatus.ENTITY_TICKING, true,
- ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
- );
- }
-
- public void getTickingChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
- io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
- this.level, x, z, FullChunkStatus.BLOCK_TICKING, true,
- ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
- );
- }
-
- public void getFullChunkAsync(int x, int z, java.util.function.Consumer<LevelChunk> onLoad) {
- io.papermc.paper.chunk.system.ChunkSystem.scheduleTickingState(
- this.level, x, z, FullChunkStatus.FULL, true,
- ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, onLoad
- );
- }
-
- void chunkLoadAccept(int chunkX, int chunkZ, ChunkAccess chunk, java.util.function.Consumer<ChunkAccess> consumer) {
- try {
- consumer.accept(chunk);
- } catch (Throwable throwable) {
- if (throwable instanceof ThreadDeath) {
- throw (ThreadDeath)throwable;
- }
- LOGGER.error("Load callback for chunk " + chunkX + "," + chunkZ + " in world '" + this.level.getWorld().getName() + "' threw an exception", throwable);
- }
- }
-
- void getChunkAtAsynchronously(int chunkX, int chunkZ, int ticketLevel,
- java.util.function.Consumer<ChunkAccess> consumer) {
- if (ticketLevel <= 33) {
- this.getFullChunkAsync(chunkX, chunkZ, (java.util.function.Consumer)consumer);
- return;
- }
-
- io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(
- this.level, chunkX, chunkZ, ChunkHolder.getStatus(ticketLevel), true,
- ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, consumer
- );
- }
-
-
- public final void getChunkAtAsynchronously(int chunkX, int chunkZ, ChunkStatus status, boolean gen, boolean allowSubTicketLevel, java.util.function.Consumer<ChunkAccess> onLoad) {
- // try to fire sync
- int chunkStatusTicketLevel = 33 + ChunkStatus.getDistance(status);
- ChunkHolder playerChunk = this.chunkMap.getUpdatingChunkIfPresent(io.papermc.paper.util.CoordinateUtils.getChunkKey(chunkX, chunkZ));
- if (playerChunk != null) {
- ChunkStatus holderStatus = playerChunk.getChunkHolderStatus();
- ChunkAccess immediate = playerChunk.getAvailableChunkNow();
- if (immediate != null) {
- if (allowSubTicketLevel ? immediate.getStatus().isOrAfter(status) : (playerChunk.getTicketLevel() <= chunkStatusTicketLevel && holderStatus != null && holderStatus.isOrAfter(status))) {
- this.chunkLoadAccept(chunkX, chunkZ, immediate, onLoad);
- return;
- } else {
- if (gen || (!allowSubTicketLevel && immediate.getStatus().isOrAfter(status))) {
- this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
- return;
- } else {
- this.chunkLoadAccept(chunkX, chunkZ, null, onLoad);
- return;
- }
- }
- }
- }
-
- // need to fire async
-
- if (gen && !allowSubTicketLevel) {
- this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
- return;
- }
-
- this.getChunkAtAsynchronously(chunkX, chunkZ, io.papermc.paper.util.MCUtil.getTicketLevelFor(ChunkStatus.EMPTY), (ChunkAccess chunk) -> {
- if (chunk == null) {
- throw new IllegalStateException("Chunk cannot be null");
- }
-
- if (!chunk.getStatus().isOrAfter(status)) {
- if (gen) {
- this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
- return;
- } else {
- ServerChunkCache.this.chunkLoadAccept(chunkX, chunkZ, null, onLoad);
- return;
- }
- } else {
- if (allowSubTicketLevel) {
- ServerChunkCache.this.chunkLoadAccept(chunkX, chunkZ, chunk, onLoad);
- return;
- } else {
- this.getChunkAtAsynchronously(chunkX, chunkZ, chunkStatusTicketLevel, onLoad);
- return;
- }
- }
- });
- }
+ final java.util.concurrent.atomic.AtomicLong chunkFutureAwaitCounter = new java.util.concurrent.atomic.AtomicLong(); // Paper - private -> package private
public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<LevelChunk> entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true);
final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock();
final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<LevelChunk> loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
- long chunkFutureAwaitCounter;
+ final java.util.concurrent.atomic.AtomicLong chunkFutureAwaitCounter = new java.util.concurrent.atomic.AtomicLong(); // Paper - chunk system rewrite
private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
// Paper end
// Paper start
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
return holder.getLastAvailable();
}
- // this will try to avoid chunk neighbours for lighting
- public final ChunkAccess getFullStatusChunkAt(int chunkX, int chunkZ) {
- LevelChunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
- if (ifLoaded != null) {
- return ifLoaded;
- }
-
- ChunkAccess empty = this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, true);
- if (empty != null && empty.getStatus().isOrAfter(ChunkStatus.FULL)) {
- return empty;
- }
- return this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true);
- }
-
- public final ChunkAccess getFullStatusChunkAtIfLoaded(int chunkX, int chunkZ) {
- LevelChunk ifLoaded = this.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
- if (ifLoaded != null) {
- return ifLoaded;
- }
-
- ChunkAccess ret = this.getChunkAtImmediately(chunkX, chunkZ);
- if (ret != null && ret.getStatus().isOrAfter(ChunkStatus.FULL)) {
- return ret;
- } else {
- return null;
- }
- }
-
public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) {
this.distanceManager.addTicket(ticketType, chunkPos, ticketLevel, identifier);
}
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) {
long k = ChunkPos.asLong(x, z);
@ -19442,7 +19290,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
}
boolean runDistanceManagerUpdates() {
public boolean runDistanceManagerUpdates() { // Paper - public
- boolean flag = this.distanceManager.runAllUpdates(this.chunkMap);
- boolean flag1 = this.chunkMap.promoteChunkMap();
-
@ -19601,7 +19449,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority priority,
+ java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
List<net.minecraft.world.level.chunk.ChunkAccess> ret = new java.util.ArrayList<>();
- IntArrayList ticketLevels = new IntArrayList();
- it.unimi.dsi.fastutil.ints.IntArrayList ticketLevels = new it.unimi.dsi.fastutil.ints.IntArrayList();
-
- int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
- int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
@ -19938,7 +19786,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void tickTime() {
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Paper end - Incremental chunk and player saving
}
public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) {
+ // Paper start - rewrite chunk system - add close param
@ -20782,9 +20630,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return;
+ }
+ // Paper end - rewrite chunk system
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) {
this.removalReason = reason;
}
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.stopRiding();
}
@ -20792,8 +20640,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.getPassengers().forEach(Entity::stopRiding);
+ if (reason != RemovalReason.UNLOADED_TO_CHUNK) this.getPassengers().forEach(Entity::stopRiding); // Paper - chunk system - don't adjust passenger state when unloading, it's just not safe (and messes with our logic in entity chunk unload)
this.levelCallback.onRemove(reason);
}
// Paper start - Folia schedulers
if (!(this instanceof ServerPlayer) && reason != RemovalReason.CHANGED_DIMENSION && !alreadyRemoved) {
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
@Override
@ -21182,9 +21030,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return range <= 0 ? 64.0 * 64.0 : range * range; // 64 is taken from default in ServerLevel#levelEvent
}
// Paper end - respect global sound events gamerule
}
// Paper end - notify observers even if grow failed
+ // Paper start
+ //protected final io.papermc.paper.world.EntitySliceManager entitySliceManager; // Paper - rewrite chunk system
+
@ -21981,7 +21829,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper
public RegionFile(Path file, Path directory, boolean dsync) throws IOException {
this(file, directory, RegionFileVersion.VERSION_DEFLATE, dsync);
this(file, directory, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
return (byteCount + 4096 - 1) / 4096;
}
@ -22787,101 +22635,74 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public int getSimulationDistance() {
- return this.world.getChunkSource().chunkMap.getDistanceManager().simulationDistance;
+ return this.getHandle().playerChunkLoader.getAPITickDistance(); // Paper - replace player chunk loader
+ }
+ // Paper start - view distance api
+ @Override
+ public void setViewDistance(int viewDistance) {
+ if (viewDistance < 2 || viewDistance > 32) {
+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]");
+ }
+ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ chunkMap.setServerViewDistance(viewDistance);
+ }
+
+ @Override
+ public void setSimulationDistance(int simulationDistance) {
}
public BlockMetadataStore getBlockMetadata() {
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public void setSimulationDistance(final int simulationDistance) {
- throw new UnsupportedOperationException("Not implemented yet");
+ if (simulationDistance < 2 || simulationDistance > 32) {
+ throw new IllegalArgumentException("Simulation distance " + simulationDistance + " is out of range of [2, 32]");
+ }
+ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap;
+ chunkMap.setTickViewDistance(simulationDistance);
+ }
+
+ @Override
+ public int getNoTickViewDistance() {
+ return this.getViewDistance();
+ }
+
+ @Override
+ public void setNoTickViewDistance(int viewDistance) {
+ this.setViewDistance(viewDistance);
+ }
+
+ @Override
+ public int getSendViewDistance() {
+ this.getHandle().chunkSource.chunkMap.setTickViewDistance(simulationDistance);
}
@Override
public int getSendViewDistance() {
- return this.getViewDistance();
+ return this.getHandle().playerChunkLoader.getAPISendViewDistance(); // Paper - replace player chunk loader
+ }
+
+ @Override
+ public void setSendViewDistance(int viewDistance) {
}
@Override
public void setSendViewDistance(final int viewDistance) {
- throw new UnsupportedOperationException("Not implemented yet");
+ this.getHandle().chunkSource.chunkMap.setSendViewDistance(viewDistance); // Paper - replace player chunk loader
}
+ // Paper end - view distance api
public BlockMetadataStore getBlockMetadata() {
return this.blockMetadata;
// Paper start - implement pointers
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.firstPlayed = System.currentTimeMillis();
@Override
public int getViewDistance() {
- return io.papermc.paper.chunk.system.ChunkSystem.getLoadViewDistance(this.getHandle());
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPIViewDistance(this);
}
+ // Paper start - implement view distances
+ @Override
+ public int getViewDistance() {
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPIViewDistance(this);
+ }
+
+ @Override
+ public void setViewDistance(int viewDistance) {
@Override
public void setViewDistance(final int viewDistance) {
- throw new UnsupportedOperationException("Not implemented yet");
+ this.getHandle().setLoadViewDistance(viewDistance < 0 ? viewDistance : viewDistance + 1);
+ }
+
+ @Override
+ public int getSimulationDistance() {
}
@Override
public int getSimulationDistance() {
- return io.papermc.paper.chunk.system.ChunkSystem.getTickViewDistance(this.getHandle());
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPITickViewDistance(this);
+ }
+
+ @Override
+ public void setSimulationDistance(int simulationDistance) {
}
@Override
public void setSimulationDistance(final int simulationDistance) {
- throw new UnsupportedOperationException("Not implemented yet");
+ this.getHandle().setTickViewDistance(simulationDistance);
+ }
+
+ @Override
+ public int getNoTickViewDistance() {
+ return this.getViewDistance();
+ }
+
+ @Override
+ public void setNoTickViewDistance(int viewDistance) {
+ this.setViewDistance(viewDistance);
+ }
+
+ @Override
+ public int getSendViewDistance() {
}
@Override
public int getSendViewDistance() {
- return io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(this.getHandle());
+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPISendViewDistance(this);
+ }
+
+ @Override
+ public void setSendViewDistance(int viewDistance) {
}
@Override
public void setSendViewDistance(final int viewDistance) {
- throw new UnsupportedOperationException("Not implemented yet");
+ this.getHandle().setSendViewDistance(viewDistance);
+ }
+ // Paper end - implement view distances
+
public GameProfile getProfile() {
return this.getHandle().getGameProfile();
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -22948,10 +22769,9 @@ 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
}
+
@Override
public void scheduleTick(BlockPos pos, Fluid fluid, int delay, net.minecraft.world.ticks.TickPriority priority) {}
// Paper end - add more methods
+ // Paper start
+ @Override
+ public List<Entity> getHardCollidingEntities(Entity except, AABB box, Predicate<? super Entity> predicate) {

View file

@ -350,7 +350,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> {
+ return pair(rule, world.getWorld().getGameRuleValue(rule));
+ })),
+ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance())
+ pair("ticking-distance", world.getWorld().getSimulationDistance()),
+ pair("no-ticking-distance", world.getWorld().getViewDistance()),
+ pair("sending-distance", world.getWorld().getSendViewDistance())
+ ));
+ }));
+

View file

@ -72,7 +72,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return config.displayTrackingRange;
} else
{
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getEffectiveViewDistance(); // Paper - enderdragon is exempt
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.serverViewDistance; // Paper - enderdragon is exempt
return config.otherTrackingRange;
}
}

View file

@ -115,8 +115,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - Incremental chunk and player saving
+
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

View file

@ -3,7 +3,7 @@ import sys
# Use inside of server patch dir
# py ../../scripts/moveback.py 'Rewrite chunk system'
patch_target = 750 # TODO: Update this
patch_target = 992 # TODO: Update this
def increment_number(filename):