From d8d13a67c42be60527d7ddc61b176f406f46c1cc Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 28 Feb 2022 13:43:31 -0800 Subject: [PATCH] moar fixes --- patches/server/Actually-unload-POI-data.patch | 2 +- ...llow-delegation-to-vanilla-chunk-gen.patch | 21 +--------- .../Asynchronous-chunk-IO-and-loading.patch | 40 +++++++++---------- .../Distance-manager-tick-timings.patch | 2 +- ...ket-level-changes-while-unloading-pl.patch | 4 +- .../server/Do-not-copy-visible-chunks.patch | 21 ++++++++++ .../Ensure-commands-are-not-ran-async.patch | 4 +- .../server/Entity-getEntitySpawnReason.patch | 2 +- ...x-and-optimise-world-force-upgrading.patch | 12 +++--- ...k-Priority-Urgency-System-for-Chunks.patch | 18 ++++----- ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 6 ++- ...Load-Chunks-for-Login-Asynchronously.patch | 2 +- .../Make-CallbackExecutor-strict-again.patch | 2 +- patches/server/More-World-API.patch | 4 +- .../server/Player.setPlayerProfile-API.patch | 2 +- ...alls-removing-tickets-for-sync-loads.patch | 6 +-- .../Replace-player-chunk-loader-system.patch | 15 +++++++ .../Use-a-Shared-Random-for-Entities.patch | 2 +- 18 files changed, 92 insertions(+), 73 deletions(-) diff --git a/patches/server/Actually-unload-POI-data.patch b/patches/server/Actually-unload-POI-data.patch index f689d5e27c..dcb1fb3679 100644 --- a/patches/server/Actually-unload-POI-data.patch +++ b/patches/server/Actually-unload-POI-data.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.updatingChunks.queueUpdate(pos, holder); // Paper - Don't copy this.modified = true; @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); + return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunks.getUpdatingValuesCopy().isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); // Paper } - private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more diff --git a/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch index 30e6e58de9..318889128d 100644 --- a/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch @@ -26,24 +26,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + net.minecraft.world.level.chunk.ChunkStatus.LIGHT + ); + -+ @net.minecraft.MethodsReturnNonnullByDefault -+ private static final class PaperEmptyLevelChunk extends net.minecraft.world.level.chunk.EmptyLevelChunk { -+ private final net.minecraft.world.level.biome.Biome biome; -+ -+ public PaperEmptyLevelChunk(net.minecraft.world.level.Level world, net.minecraft.world.level.ChunkPos pos) { -+ super(world, pos); -+ this.biome = this.level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS); -+ } -+ -+ @Override -+ public net.minecraft.world.level.biome.Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { -+ return this.biome; -+ } -+ -+ @Override -+ public void markPosForPostprocessing(BlockPos pos) {} -+ } -+ + @Override + @Deprecated(forRemoval = true) + public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { @@ -79,7 +61,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (xx == chunkPos.x && zz == chunkPos.z) { + chunks.add(protoChunk); + } else { -+ final net.minecraft.world.level.chunk.ChunkAccess chunk = new PaperEmptyLevelChunk(serverLevel, new net.minecraft.world.level.ChunkPos(xx, zz)); ++ final Holder biomeHolder = serverLevel.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getHolderOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS); ++ final net.minecraft.world.level.chunk.ChunkAccess chunk = new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, new net.minecraft.world.level.ChunkPos(xx, zz), biomeHolder); + chunks.add(chunk); + } + } diff --git a/patches/server/Asynchronous-chunk-IO-and-loading.patch b/patches/server/Asynchronous-chunk-IO-and-loading.patch index 333df5bc61..eb27a63b51 100644 --- a/patches/server/Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/Asynchronous-chunk-IO-and-loading.patch @@ -306,12 +306,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.io; + ++import com.mojang.logging.LogUtils; +import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.storage.RegionFile; -+import org.apache.logging.log4j.Logger; ++import org.slf4j.Logger; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; @@ -343,7 +343,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +public final class PaperFileIOThread extends QueueExecutorThread { + -+ public static final Logger LOGGER = MinecraftServer.LOGGER; ++ public static final Logger LOGGER = LogUtils.getLogger(); + public static final CompoundTag FAILURE_VALUE = new CompoundTag(); + + public static final class Holder { @@ -362,7 +362,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.setName("Paper RegionFile IO Thread"); + this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us + this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { -+ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); ++ LOGGER.error("Uncaught exception thrown from IO thread, report this!", thr); + }); + } + @@ -717,7 +717,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (throwable instanceof ThreadDeath) { + throw (ThreadDeath)throwable; + } -+ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); ++ LOGGER.error("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); + } + } + } @@ -816,7 +816,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (thr instanceof ThreadDeath) { + throw (ThreadDeath)thr; + } -+ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); ++ LOGGER.error("Failed to read chunk data for task: " + this.toString(), thr); + // fall through to complete with null data + } + read.readFuture.complete(compound); @@ -874,7 +874,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (thr instanceof ThreadDeath) { + throw (ThreadDeath)thr; + } -+ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); ++ LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr); + failedWrite = true; + } + @@ -1222,8 +1222,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.io; + -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Logger; ++import com.mojang.logging.LogUtils; ++import org.slf4j.Logger; + +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; @@ -1231,7 +1231,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public class QueueExecutorThread extends Thread { + -+ private static final Logger LOGGER = MinecraftServer.LOGGER; ++ private static final Logger LOGGER = LogUtils.getLogger(); + + protected final PrioritizedTaskQueue queue; + protected final long spinWaitTime; @@ -1342,7 +1342,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (throwable instanceof ThreadDeath) { + throw (ThreadDeath)throwable; + } -+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); ++ LOGGER.error("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); + } + } + @@ -1876,16 +1876,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void dumpAllChunkLoadInfo() { + ChunkInfo[] chunks = getChunkInfos(); + if (chunks.length > 0) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); ++ PaperFileIOThread.LOGGER.error("Chunk wait task info below: "); + + for (final ChunkInfo chunkInfo : chunks) { + final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); + final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); + final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); + -+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); ++ PaperFileIOThread.LOGGER.error(chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); ++ PaperFileIOThread.LOGGER.error("Load Task - " + (loadTask == null ? "none" : loadTask.toString())); ++ PaperFileIOThread.LOGGER.error("Save Task - " + (saveTask == null ? "none" : saveTask.toString())); + // log current status of chunk to indicate whether we're waiting on generation or loading + ChunkHolder chunkHolder = chunkInfo.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(key); + @@ -1908,14 +1908,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + seenChunks.add(chunkHolder); + String indentStr = StringUtils.repeat(" ", indent); + if (chunkHolder == null) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Holder - null for (" + x +"," + z +")"); + } else { + ChunkAccess chunk = chunkHolder.getLastAvailable(); + ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Holder - non-null"); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); + } + } + diff --git a/patches/server/Distance-manager-tick-timings.patch b/patches/server/Distance-manager-tick-timings.patch index 7af0b68df4..4e553437b9 100644 --- a/patches/server/Distance-manager-tick-timings.patch +++ b/patches/server/Distance-manager-tick-timings.patch @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { public boolean runDistanceManagerUpdates() { if (distanceManager.delayDistanceManagerTick) return false; // Paper - Chunk priority - if (this.chunkMap.unloadingPlayerChunk) { net.minecraft.server.MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper + if (this.chunkMap.unloadingPlayerChunk) { LOGGER.error("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper + co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Paper - add timings for distance manager boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch b/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch index 11cae988fa..b7cf1719cd 100644 --- a/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch +++ b/patches/server/Do-not-allow-ticket-level-changes-while-unloading-pl.patch @@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Nullable ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k) { -+ if (this.unloadingPlayerChunk) { net.minecraft.server.MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper ++ if (this.unloadingPlayerChunk) { net.minecraft.server.MinecraftServer.LOGGER.error("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper if (k > ChunkMap.MAX_CHUNK_DISTANCE && level > ChunkMap.MAX_CHUNK_DISTANCE) { return holder; } else { @@ -56,7 +56,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean runDistanceManagerUpdates() { if (distanceManager.delayDistanceManagerTick) return false; // Paper - Chunk priority -+ if (this.chunkMap.unloadingPlayerChunk) { net.minecraft.server.MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper ++ if (this.chunkMap.unloadingPlayerChunk) { LOGGER.error("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Paper boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/patches/server/Do-not-copy-visible-chunks.patch b/patches/server/Do-not-copy-visible-chunks.patch index aab2372150..61df0041a0 100644 --- a/patches/server/Do-not-copy-visible-chunks.patch +++ b/patches/server/Do-not-copy-visible-chunks.patch @@ -81,6 +81,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } protected IntSupplier getChunkQueueLevel(long pos) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + + stringbuilder.append("Updating:").append(System.lineSeparator()); +- this.updatingChunkMap.values().forEach(consumer); ++ this.updatingChunks.getUpdatingValuesCopy().forEach(consumer); // Paper + stringbuilder.append("Visible:").append(System.lineSeparator()); +- this.visibleChunkMap.values().forEach(consumer); ++ this.updatingChunks.getVisibleValuesCopy().forEach(consumer); // Paper + CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading"); + @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper end } @@ -108,6 +120,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public boolean hasWork() { +- return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); ++ return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunks.getUpdatingValuesCopy().isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); // Paper + } + + private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider while (longiterator.hasNext()) { // Spigot long j = longiterator.nextLong(); diff --git a/patches/server/Ensure-commands-are-not-ran-async.patch b/patches/server/Ensure-commands-are-not-ran-async.patch index 6eda570629..cd8f61c950 100644 --- a/patches/server/Ensure-commands-are-not-ran-async.patch +++ b/patches/server/Ensure-commands-are-not-ran-async.patch @@ -24,8 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper Start + if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { + final String fCommandLine = s; -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); ++ LOGGER.error("Command Dispatched Async: " + fCommandLine); ++ LOGGER.error("Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); + Waitable wait = new Waitable() { + @Override + protected Object evaluate() { diff --git a/patches/server/Entity-getEntitySpawnReason.patch b/patches/server/Entity-getEntitySpawnReason.patch index 0d6bafc0ec..88acd7a5f5 100644 --- a/patches/server/Entity-getEntitySpawnReason.patch +++ b/patches/server/Entity-getEntitySpawnReason.patch @@ -74,7 +74,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + try { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); + } catch (Exception ignored) { -+ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); ++ LOGGER.error("Unknown SpawnReason " + spawnReasonName + " for " + this); + } + } + if (spawnReason == null) { diff --git a/patches/server/Fix-and-optimise-world-force-upgrading.patch b/patches/server/Fix-and-optimise-world-force-upgrading.patch index 79cdbcaa29..8ec1db529c 100644 --- a/patches/server/Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/Fix-and-optimise-world-force-upgrading.patch @@ -70,7 +70,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final Logger LOGGER = LogManager.getLogger(); + + private final ResourceKey dimensionType; -+ private final ResourceKey worldKey; + private final String worldName; + private final File worldDir; + private final ExecutorService threadPool; @@ -78,10 +77,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final Optional>> generatorKey; + private final boolean removeCaches; + -+ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final File worldDir, final int threads, ++ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final String worldName, final File worldDir, final int threads, + final DataFixer dataFixer, final Optional>> generatorKey, final boolean removeCaches) { + this.dimensionType = dimensionType; -+ this.worldKey = worldKey; + this.worldName = worldName; + this.worldDir = worldDir; + this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { @@ -262,10 +260,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper end + // Paper start - fix and optimise world upgrading -+ public static void convertWorldButItWorks(net.minecraft.resources.ResourceKey dimensionType, net.minecraft.resources.ResourceKey worldKey, net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess worldSession, ++ public static void convertWorldButItWorks(net.minecraft.resources.ResourceKey dimensionType, net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess worldSession, + DataFixer dataFixer, Optional>> generatorKey, boolean removeCaches) { + int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; -+ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldSession.getLevelId(), worldSession.levelPath.toFile(), threads, dataFixer, generatorKey, removeCaches); ++ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldSession.getLevelId(), worldSession.levelPath.toFile(), threads, dataFixer, generatorKey, removeCaches); + worldUpgrader.convert(); + } + // Paper end - fix and optimise world upgrading @@ -297,7 +295,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - fix and optimise world upgrading + if (options.has("forceUpgrade")) { + net.minecraft.server.Main.convertWorldButItWorks( -+ dimensionKey, Level.getDimensionKey(holder.value()), worldSession, DataFixers.getDataFixer(), chunkgenerator.getTypeNameForDataFixer(), options.has("eraseCache") ++ dimensionKey, worldSession, DataFixers.getDataFixer(), chunkgenerator.getTypeNameForDataFixer(), options.has("eraseCache") + ); + } + // Paper end - fix and optimise world upgrading @@ -383,7 +381,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - fix and optimise world upgrading + if (console.options.has("forceUpgrade")) { + net.minecraft.server.Main.convertWorldButItWorks( -+ actualDimension, net.minecraft.world.level.Level.getDimensionKey(dimensionmanager), worldSession, DataFixers.getDataFixer(), chunkgenerator.getTypeNameForDataFixer(), console.options.has("eraseCache") ++ actualDimension, worldSession, DataFixers.getDataFixer(), chunkgenerator.getTypeNameForDataFixer(), console.options.has("eraseCache") + ); + } + // Paper end - fix and optimise world upgrading diff --git a/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index 6b29499007..2a243bad5f 100644 --- a/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -36,18 +36,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { @@ -0,0 +0,0 @@ public final class ChunkTaskManager { - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); + PaperFileIOThread.LOGGER.error(indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); + PaperFileIOThread.LOGGER.error(indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.error(indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); + // Paper start -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.queueLevel); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Holder Priority - " + chunkHolder.queueLevel); + + if (!chunkHolder.neighbors.isEmpty()) { + if (indent >= maxDepth) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); + return; + } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); ++ PaperFileIOThread.LOGGER.error(indentStr + "Chunk Neighbors: "); + for (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { + ChunkStatus status = neighbor.getChunkHolderStatus(); + if (status != null && status.isOrAfter(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { @@ -56,10 +56,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + int nx = neighbor.pos.x; + int nz = neighbor.pos.z; + if (seenChunks.contains(neighbor)) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); ++ PaperFileIOThread.LOGGER.error(indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); + continue; + } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); ++ PaperFileIOThread.LOGGER.error(indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); + dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); + } + } @@ -1126,7 +1126,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class PlayerList { net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; - distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); + distanceManager.addTicket(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); - worldserver1.getChunkSource().runDistanceManagerUpdates(); - worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { + worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); // Paper - Chunk priority diff --git a/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch index a561b68a08..1e6b2d0bc7 100644 --- a/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ b/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -356,9 +356,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + -+ net.minecraft.resources.ResourceLocation key; ++ net.minecraft.resources.ResourceLocation key = null; + if (isTag) { -+ key = blockParser.getTag(); ++ if (blockParser.getTag() != null) { ++ key = blockParser.getTag().location(); ++ } + } else { + key = blockParser.id; + } diff --git a/patches/server/Load-Chunks-for-Login-Asynchronously.patch b/patches/server/Load-Chunks-for-Login-Asynchronously.patch index 0ee441f9b6..786150edb4 100644 --- a/patches/server/Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/Load-Chunks-for-Login-Asynchronously.patch @@ -164,7 +164,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final net.minecraft.world.level.ChunkPos pos = new net.minecraft.world.level.ChunkPos(chunkX, chunkZ); + net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; + net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; -+ distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); ++ distanceManager.addTicket(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); + worldserver1.getChunkSource().runDistanceManagerUpdates(); + worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { + net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); diff --git a/patches/server/Make-CallbackExecutor-strict-again.patch b/patches/server/Make-CallbackExecutor-strict-again.patch index 7266cf0c7f..b7c0435254 100644 --- a/patches/server/Make-CallbackExecutor-strict-again.patch +++ b/patches/server/Make-CallbackExecutor-strict-again.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - revert CB changes + org.spigotmc.AsyncCatcher.catchOp("Callback Executor execute"); + if (this.queued != null) { -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to schedule runnable", new IllegalStateException("Already queued")); ++ LOGGER.error("Failed to schedule runnable", new IllegalStateException("Already queued")); + throw new IllegalStateException("Already queued"); + } + this.queued = runnable; diff --git a/patches/server/More-World-API.patch b/patches/server/More-World-API.patch index 0a2e2bd78e..7a2c7b1d17 100644 --- a/patches/server/More-World-API.patch +++ b/patches/server/More-World-API.patch @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { + BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPos nearest = getHandle().findNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().registryAccess().registryOrThrow(net.minecraft.core.Registry.BIOME_REGISTRY), biome), originPos, radius, step); ++ BlockPos nearest = getHandle().findNearestBiome( holder -> holder.is(CraftNamespacedKey.toMinecraft(biome.getKey())), originPos, radius, step).getFirst(); + return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); + } + @@ -62,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().infiniburn().getValues().iterator(), CraftMagicNumbers::getMaterial)); ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(net.minecraft.core.Registry.BLOCK.getTagOrEmpty(this.getHandle().dimensionType().infiniburn()).iterator(), blockHolder -> CraftMagicNumbers.getMaterial(blockHolder.value()))); + } + + @Override diff --git a/patches/server/Player.setPlayerProfile-API.patch b/patches/server/Player.setPlayerProfile-API.patch index 551e95e669..cc6fa3ee5d 100644 --- a/patches/server/Player.setPlayerProfile-API.patch +++ b/patches/server/Player.setPlayerProfile-API.patch @@ -129,7 +129,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + //Respawn the player then update their position and selected slot + ServerLevel worldserver = handle.getLevel(); -+ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionTypeRegistration(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); + handle.onUpdateAbilities(); + connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), java.util.Collections.emptySet(), 0, false)); + net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); diff --git a/patches/server/Prevent-unload-calls-removing-tickets-for-sync-loads.patch b/patches/server/Prevent-unload-calls-removing-tickets-for-sync-loads.patch index 5a1c8e7b48..a0d61c60ba 100644 --- a/patches/server/Prevent-unload-calls-removing-tickets-for-sync-loads.patch +++ b/patches/server/Prevent-unload-calls-removing-tickets-for-sync-loads.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); + identifier = Long.valueOf(this.syncLoadCounter++); // Paper - prevent plugin unloads from removing our ticket -+ this.distanceManager.addTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper - prevent plugin unloads from removing our ticket ++ this.distanceManager.addTicket(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper - prevent plugin unloads from removing our ticket if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper - Chunk priority if (this.chunkAbsent(playerchunk, l)) { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); @@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 playerchunk = this.getVisibleChunkIfPresent(k); gameprofilerfiller.pop(); if (this.chunkAbsent(playerchunk, l)) { -+ this.distanceManager.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper ++ this.distanceManager.removeTicket(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); } } @@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - prevent plugin unloads from removing our ticket + if (create && !currentlyUnloading) { + future.thenAcceptAsync((either) -> { -+ ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); ++ ServerChunkCache.this.distanceManager.removeTicket(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); + }, ServerChunkCache.this.mainThreadProcessor); + } + // Paper end - prevent plugin unloads from removing our ticket diff --git a/patches/server/Replace-player-chunk-loader-system.patch b/patches/server/Replace-player-chunk-loader-system.patch index a0da4693e5..cff9215032 100644 --- a/patches/server/Replace-player-chunk-loader-system.patch +++ b/patches/server/Replace-player-chunk-loader-system.patch @@ -1785,6 +1785,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void removeTicketsOnClosing() { ImmutableSet> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.LIGHT); +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + if (!immutableset.contains(ticket.getType())) { + iterator.remove(); + flag = true; +- this.tickingTicketsTracker.removeTicket(entry.getLongKey(), ticket); ++ // this.tickingTicketsTracker.removeTicket(entry.getLongKey(), ticket); // Paper - no longer used + } + } + + if (flag) { +- this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt((SortedArraySet) entry.getValue()), false); ++ // this.ticketTracker.update(entry.getLongKey(), DistanceManager.getTicketLevelAt((SortedArraySet) entry.getValue()), false); // Paper - no longer used + } + + if (((SortedArraySet) entry.getValue()).isEmpty()) { @@ -0,0 +0,0 @@ public abstract class DistanceManager { } } diff --git a/patches/server/Use-a-Shared-Random-for-Entities.patch b/patches/server/Use-a-Shared-Random-for-Entities.patch index cfb6679600..9f486440be 100644 --- a/patches/server/Use-a-Shared-Random-for-Entities.patch +++ b/patches/server/Use-a-Shared-Random-for-Entities.patch @@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public synchronized void setSeed(long seed) { + if (locked) { -+ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); ++ LOGGER.error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); + } else { + super.setSeed(seed); + locked = true;