From 52438f04a083a54c6c5e2181d2b3bbc9f7b429df Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Wed, 24 Jan 2024 22:13:08 +0100 Subject: [PATCH] [ci skip] Move chunk system patch back --- patches/api/Add-view-distance-API.patch | 16 +- patches/server/Add-TickThread.patch | 10 +- .../Add-debug-for-sync-chunk-loads.patch | 4 +- ...rtant-BlockStateListPopulator-method.patch | 7 +- .../Add-paper-dumplisteners-command.patch | 2 +- patches/server/Adventure.patch | 8 +- ...nfigurable-Region-Compression-Format.patch | 2 +- .../server/Fix-NPE-on-Boat-getStatus.patch | 2 +- ...Folia-scheduler-and-owned-region-API.patch | 12 +- .../Further-improve-server-tick-loop.patch | 23 +- patches/server/Improve-ServerGUI.patch | 2 +- patches/server/MC-Utils.patch | 342 ++++++-------- .../Only-capture-actual-tree-growth.patch | 4 +- patches/server/Paper-config-files.patch | 2 +- patches/server/Rewrite-chunk-system.patch | 420 +++++------------- patches/server/Timings-v2.patch | 4 +- .../server/Tracking-Range-Improvements.patch | 2 +- .../incremental-chunk-and-player-saving.patch | 4 +- scripts/moveback.py | 2 +- 19 files changed, 317 insertions(+), 551 deletions(-) diff --git a/patches/api/Add-view-distance-API.patch b/patches/api/Add-view-distance-API.patch index ac83f6e87e..784c2eadd6 100644 --- a/patches/api/Add-view-distance-API.patch +++ b/patches/api/Add-view-distance-API.patch @@ -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. diff --git a/patches/server/Add-TickThread.patch b/patches/server/Add-TickThread.patch index a2a44bf0c8..40e3068554 100644 --- a/patches/server/Add-TickThread.patch +++ b/patches/server/Add-TickThread.patch @@ -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 diff --git a/patches/server/Add-debug-for-sync-chunk-loads.patch b/patches/server/Add-debug-for-sync-chunk-loads.patch index e64841d090..60ffec6c04 100644 --- a/patches/server/Add-debug-for-sync-chunk-loads.patch +++ b/patches/server/Add-debug-for-sync-chunk-loads.patch @@ -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); diff --git a/patches/server/Add-missing-important-BlockStateListPopulator-method.patch b/patches/server/Add-missing-important-BlockStateListPopulator-method.patch index d88ae4415a..d9561cfc1e 100644 --- a/patches/server/Add-missing-important-BlockStateListPopulator-method.patch +++ b/patches/server/Add-missing-important-BlockStateListPopulator-method.patch @@ -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 void getEntitiesByClass(Class clazz, Entity except, AABB box, List into, Predicate 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) {} + diff --git a/patches/server/Add-paper-dumplisteners-command.patch b/patches/server/Add-paper-dumplisteners-command.patch index c3c64903cc..125268c076 100644 --- a/patches/server/Add-paper-dumplisteners-command.patch +++ b/patches/server/Add-paper-dumplisteners-command.patch @@ -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() diff --git a/patches/server/Adventure.patch b/patches/server/Adventure.patch index 2f96f79cd5..3e57cccd49 100644 --- a/patches/server/Adventure.patch +++ b/patches/server/Adventure.patch @@ -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> gamerules; public static synchronized Map> 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 diff --git a/patches/server/Configurable-Region-Compression-Format.patch b/patches/server/Configurable-Region-Compression-Format.patch index 9acd9767fc..ab6eda47f6 100644 --- a/patches/server/Configurable-Region-Compression-Format.patch +++ b/patches/server/Configurable-Region-Compression-Format.patch @@ -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); diff --git a/patches/server/Fix-NPE-on-Boat-getStatus.patch b/patches/server/Fix-NPE-on-Boat-getStatus.patch index 5b53d219b3..6fc79a2d2c 100644 --- a/patches/server/Fix-NPE-on-Boat-getStatus.patch +++ b/patches/server/Fix-NPE-on-Boat-getStatus.patch @@ -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 { diff --git a/patches/server/Folia-scheduler-and-owned-region-API.patch b/patches/server/Folia-scheduler-and-owned-region-API.patch index 3cc5ec388b..3bcfd65597 100644 --- a/patches/server/Folia-scheduler-and-owned-region-API.patch +++ b/patches/server/Folia-scheduler-and-owned-region-API.patch @@ -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) { diff --git a/patches/server/Further-improve-server-tick-loop.patch b/patches/server/Further-improve-server-tick-loop.patch index 1a574af82d..3a2c595c30 100644 --- a/patches/server/Further-improve-server-tick-loop.patch +++ b/patches/server/Further-improve-server-tick-loop.patch @@ -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() { +- 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() ++ }; } -+ @Override -+ public double[] getTPS() { -+ 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 diff --git a/patches/server/Improve-ServerGUI.patch b/patches/server/Improve-ServerGUI.patch index 8645d9e11a..fdaf15d93c 100644 --- a/patches/server/Improve-ServerGUI.patch +++ b/patches/server/Improve-ServerGUI.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 GraphData data = RAMGraph.DATA.peekLast(); Vector 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++) { diff --git a/patches/server/MC-Utils.patch b/patches/server/MC-Utils.patch index e6c170e787..a7bdf63f85 100644 --- a/patches/server/MC-Utils.patch +++ b/patches/server/MC-Utils.patch @@ -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 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> 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, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction 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 tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); ++ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet 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 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 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 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 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 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 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 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 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 void addTicketAtLevel(TicketType 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 tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); -+ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet 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 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 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 diff --git a/patches/server/Only-capture-actual-tree-growth.patch b/patches/server/Only-capture-actual-tree-growth.patch index 8fb4959f40..cf47deabea 100644 --- a/patches/server/Only-capture-actual-tree-growth.patch +++ b/patches/server/Only-capture-actual-tree-growth.patch @@ -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 diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch index ba7b27468d..f029a57424 100644 --- a/patches/server/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -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); + } + } + diff --git a/patches/server/Rewrite-chunk-system.patch b/patches/server/Rewrite-chunk-system.patch index 6257841c2e..97f95d986a 100644 --- a/patches/server/Rewrite-chunk-system.patch +++ b/patches/server/Rewrite-chunk-system.patch @@ -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 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> 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,15 +16001,9 @@ 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 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/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -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 { +- 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, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction 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 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 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 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 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 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 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 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 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 void addTicketAtLevel(TicketType 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> onLoad) { List 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,102 +22635,75 @@ 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() { -+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPITickViewDistance(this); -+ } -+ -+ @Override -+ public void setSimulationDistance(int simulationDistance) { -+ this.getHandle().setTickViewDistance(simulationDistance); -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return this.getViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ this.setViewDistance(viewDistance); -+ } -+ -+ @Override -+ public int getSendViewDistance() { -+ return io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.getAPISendViewDistance(this); -+ } -+ -+ @Override -+ public void setSendViewDistance(int viewDistance) { -+ this.getHandle().setSendViewDistance(viewDistance); -+ } -+ // Paper end - implement view distances -+ - public GameProfile getProfile() { - return this.getHandle().getGameProfile(); } + + @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(final int simulationDistance) { +- throw new UnsupportedOperationException("Not implemented yet"); ++ this.getHandle().setTickViewDistance(simulationDistance); + } + + @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(final int viewDistance) { +- throw new UnsupportedOperationException("Not implemented yet"); ++ this.getHandle().setSendViewDistance(viewDistance); + } + } 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 --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java @@ -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 getHardCollidingEntities(Entity except, AABB box, Predicate predicate) { diff --git a/patches/server/Timings-v2.patch b/patches/server/Timings-v2.patch index 7c4be6e83a..0985d6c8f4 100644 --- a/patches/server/Timings-v2.patch +++ b/patches/server/Timings-v2.patch @@ -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()) + )); + })); + diff --git a/patches/server/Tracking-Range-Improvements.patch b/patches/server/Tracking-Range-Improvements.patch index 8fdfc73b8d..b627a5b134 100644 --- a/patches/server/Tracking-Range-Improvements.patch +++ b/patches/server/Tracking-Range-Improvements.patch @@ -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; } } diff --git a/patches/server/incremental-chunk-and-player-saving.patch b/patches/server/incremental-chunk-and-player-saving.patch index cf1f4fe2c8..105200bc08 100644 --- a/patches/server/incremental-chunk-and-player-saving.patch +++ b/patches/server/incremental-chunk-and-player-saving.patch @@ -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 diff --git a/scripts/moveback.py b/scripts/moveback.py index b0f7e2cca3..6c7fca436c 100644 --- a/scripts/moveback.py +++ b/scripts/moveback.py @@ -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):