diff --git a/patches/server/Add-API-for-quit-reason.patch b/patches/server/Add-API-for-quit-reason.patch index 5e1b6d843b..9204e98066 100644 --- a/patches/server/Add-API-for-quit-reason.patch +++ b/patches/server/Add-API-for-quit-reason.patch @@ -34,8 +34,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public @Nullable String clientBrandName = null; // Paper - Brand support + public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event - // Paper start - replace player chunk loader - private final java.util.concurrent.atomic.AtomicReference viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1)); + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java diff --git a/patches/server/Add-PlayerKickEvent-causes.patch b/patches/server/Add-PlayerKickEvent-causes.patch index 147eff441a..3a5133a03e 100644 --- a/patches/server/Add-PlayerKickEvent-causes.patch +++ b/patches/server/Add-PlayerKickEvent-causes.patch @@ -265,7 +265,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - AsyncTabCompleteEvent & kick event cause return; } - // Paper start + // CraftBukkit end @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper start - validate pick item position if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) { diff --git a/patches/server/Add-paper-dumplisteners-command.patch b/patches/server/Add-paper-dumplisteners-command.patch index 2ebe3444fa..c3c64903cc 100644 --- a/patches/server/Add-paper-dumplisteners-command.patch +++ b/patches/server/Add-paper-dumplisteners-command.patch @@ -11,8 +11,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -0,0 +0,0 @@ public final class PaperCommand extends Command { commands.put(Set.of("dumpitem"), new DumpItemCommand()); - commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); 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/Add-paper-mobcaps-and-paper-playermobcaps.patch b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch index b8c3f86045..b244006d98 100644 --- a/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch +++ b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch @@ -14,9 +14,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("fixlight"), new FixLightCommand()); commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand()); commands.put(Set.of("dumpitem"), new DumpItemCommand()); - commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); + commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand()); return commands.entrySet().stream() diff --git a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index 6274175cc6..b20c53dfd9 100644 --- a/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -46,14 +46,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { + + public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) { this.fixerUpper = dataFixer; - // Paper start - async chunk io - // remove IO worker -- this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker -+ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - nuke IOWorker // Paper - Attempt to recalculate regionfile header if it is corrupt - // Paper end - async chunk io +- this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - rewrite chunk system; async chunk IO ++ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - rewrite chunk system; async chunk IO & Attempt to recalculate regionfile header if it is corrupt } + public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionBitmap.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionBitmap.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionBitmap.java diff --git a/patches/server/Brand-support.patch b/patches/server/Brand-support.patch index 569c55c6ac..fb7081f111 100644 --- a/patches/server/Brand-support.patch +++ b/patches/server/Brand-support.patch @@ -14,8 +14,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent + public @Nullable String clientBrandName = null; // Paper - Brand support - // Paper start - replace player chunk loader - private final java.util.concurrent.atomic.AtomicReference viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1)); + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java diff --git a/patches/server/Correctly-check-if-bucket-dispenses-will-succeed-for.patch b/patches/server/Correctly-check-if-bucket-dispenses-will-succeed-for.patch index 8768319c41..d5c67db37c 100644 --- a/patches/server/Correctly-check-if-bucket-dispenses-will-succeed-for.patch +++ b/patches/server/Correctly-check-if-bucket-dispenses-will-succeed-for.patch @@ -24,5 +24,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) { + // Paper end - correctly check if the bucket place will succeed org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); - CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); diff --git a/patches/server/Distance-manager-tick-timings.patch b/patches/server/Distance-manager-tick-timings.patch index 71bb4f3302..232113d1b4 100644 --- a/patches/server/Distance-manager-tick-timings.patch +++ b/patches/server/Distance-manager-tick-timings.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search + public static final Timing distanceManagerTick = Timings.ofSafe("Distance Manager Tick"); // Paper - add timings for distance manager - private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); + public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch index 00925563c4..c210d96d72 100644 --- a/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch +++ b/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -13,16 +13,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -0,0 +0,0 @@ public class ChunkSerializer { - InProgressChunkHolder holder = readInProgressChunkHolder(world, poiStorage, chunkPos, nbt); - return holder.protoChunk; - } + private static final String SKYLIGHT_STATE_TAG = "starlight.skylight_state"; + private static final String STARLIGHT_VERSION_TAG = "starlight.light_version"; + // Paper end - replace light engine impl + // Paper start - Do not let the server load chunks from newer versions + private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion(); + private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); + // Paper end - Do not let the server load chunks from newer versions - public static InProgressChunkHolder readInProgressChunkHolder(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) { - // Paper end - rewrite chunk system + public ChunkSerializer() {} + +@@ -0,0 +0,0 @@ public class ChunkSerializer { + } + // Paper end - guard against serializing mismatching coordinates + public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) { + // Paper start - Do not let the server load chunks from newer versions + if (nbt.contains("DataVersion", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) { + final int dataVersion = nbt.getInt("DataVersion"); diff --git a/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch b/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch index db53abdddf..39f90f6371 100644 --- a/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch +++ b/patches/server/Don-t-read-neighbour-chunk-data-off-disk-when-conver.patch @@ -18,4 +18,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full" ChunkPos pos = new ChunkPos(x, z); if (cps != null) { - //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe + com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); diff --git a/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch b/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch index 2a8350cde3..f903a12e79 100644 --- a/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch +++ b/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch @@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + return; } - // Paper end // CraftBukkit end + // Paper start - Don't suggest if tab-complete is disabled + if (org.spigotmc.SpigotConfig.tabComplete < 0) { diff --git a/patches/server/Don-t-tick-markers.patch b/patches/server/Don-t-tick-markers.patch index 359a0b0801..570f90081e 100644 --- a/patches/server/Don-t-tick-markers.patch +++ b/patches/server/Don-t-tick-markers.patch @@ -34,22 +34,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ServerLevel.this.entityTickList.add(entity); } -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ public class ActivationRange - - // Paper start - java.util.List entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); -+ boolean tickMarkers = world.paperConfig().entities.markers.tick; // Paper - Configurable marker ticking - for (int i = 0; i < entities.size(); i++) { - Entity entity = entities.get(i); -+ // Paper start - Configurable marker ticking -+ if (!tickMarkers && entity instanceof net.minecraft.world.entity.Marker) { -+ continue; -+ } -+ // Paper end - Configurable marker ticking - ActivationRange.activateEntity(entity); - } - // Paper end diff --git a/patches/server/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch index 18c5aba33e..d22acba756 100644 --- a/patches/server/Entity-Activation-Range-2.0.patch +++ b/patches/server/Entity-Activation-Range-2.0.patch @@ -546,8 +546,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, worldHeight, villagerActivationRange ); + // Paper end - // Paper start - java.util.List entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); +- world.getEntities().get(ActivationRange.maxBB, ActivationRange::activateEntity); ++ // Paper start ++ java.util.List entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); ++ boolean tickMarkers = world.paperConfig().entities.markers.tick; // Paper - Configurable marker ticking ++ for (Entity entity : entities) { ++ // Paper start - Configurable marker ticking ++ if (!tickMarkers && entity instanceof net.minecraft.world.entity.Marker) { ++ continue; ++ } ++ // Paper end - Configurable marker ticking ++ ActivationRange.activateEntity(entity); ++ } ++ // Paper end + } + MinecraftTimings.entityActivationCheckTimer.stopTiming(); + } @@ -0,0 +0,0 @@ public class ActivationRange * @param entity * @return @@ -621,7 +635,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) { + return 20; + } -+ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) + if ( entity instanceof Villager ) { + Brain behaviorController = ((Villager) entity).getBrain(); + @@ -638,8 +653,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return config.villagersWorkImmunityFor; + } + } - } -- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ } + if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) { - return true; diff --git a/patches/server/Execute-chunk-tasks-mid-tick.patch b/patches/server/Execute-chunk-tasks-mid-tick.patch index 0d4c269a7e..cd6b7a69fb 100644 --- a/patches/server/Execute-chunk-tasks-mid-tick.patch +++ b/patches/server/Execute-chunk-tasks-mid-tick.patch @@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/co/aikar/timings/MinecraftTimings.java +++ b/src/main/java/co/aikar/timings/MinecraftTimings.java @@ -0,0 +0,0 @@ public final class MinecraftTimings { + public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search - public static final Timing distanceManagerTick = Timings.ofSafe("Distance Manager Tick"); // Paper - add timings for distance manager + public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); + diff --git a/patches/server/Fix-and-optimise-world-force-upgrading.patch b/patches/server/Fix-and-optimise-world-force-upgrading.patch index e38005af80..6b3dce9336 100644 --- a/patches/server/Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/Fix-and-optimise-world-force-upgrading.patch @@ -364,7 +364,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } + // Paper - fix and optimise world upgrading; move down - long j = BiomeManager.obfuscateSeed(creator.seed()); + long j = BiomeManager.obfuscateSeed(worlddata.worldGenOptions().seed()); // Paper - use world seed List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { biomeProvider = generator.getDefaultBiomeProvider(worldInfo); diff --git a/patches/server/Fix-dangerous-end-portal-logic.patch b/patches/server/Fix-dangerous-end-portal-logic.patch index 64ef2a85e6..8d1c3f46b0 100644 --- a/patches/server/Fix-dangerous-end-portal-logic.patch +++ b/patches/server/Fix-dangerous-end-portal-logic.patch @@ -15,9 +15,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - - public boolean updatingSectionStatus = false; - // Paper end + return this.originWorld; + } + // Paper end - Entity origin API + // Paper start - make end portalling safe + public BlockPos portalBlock; + public ServerLevel portalWorld; @@ -48,9 +48,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.teleportTo(worldserver, null); + } + // Paper end - make end portalling safe - - public Entity(EntityType type, Level world) { - this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + public float getBukkitYaw() { + return this.yRot; + } @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } diff --git a/patches/server/Fix-inconsistencies-in-dispense-events-regarding-sta.patch b/patches/server/Fix-inconsistencies-in-dispense-events-regarding-sta.patch index 74fbbd51d3..be658bd9f9 100644 --- a/patches/server/Fix-inconsistencies-in-dispense-events-regarding-sta.patch +++ b/patches/server/Fix-inconsistencies-in-dispense-events-regarding-sta.patch @@ -325,8 +325,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return stack; } @@ -0,0 +0,0 @@ public interface DispenseItemBehavior { - BlockState iblockdata = worldserver.getBlockState(blockposition); - if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) { + if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) { + // Paper end - correctly check if the bucket place will succeed org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); - CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event diff --git a/patches/server/Improve-and-expand-AsyncCatcher.patch b/patches/server/Improve-and-expand-AsyncCatcher.patch index 12851c6776..95181ef737 100644 --- a/patches/server/Improve-and-expand-AsyncCatcher.patch +++ b/patches/server/Improve-and-expand-AsyncCatcher.patch @@ -219,7 +219,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/spigotmc/AsyncCatcher.java @@ -0,0 +0,0 @@ public class AsyncCatcher { - if ( !io.papermc.paper.util.TickThread.isTickThread() ) // Paper // Paper - rewrite chunk system + if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper { + MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper throw new IllegalStateException( "Asynchronous " + reason + "!" ); diff --git a/patches/server/MC-4-Fix-item-position-desync.patch b/patches/server/MC-4-Fix-item-position-desync.patch index d345411d04..e73295dd02 100644 --- a/patches/server/MC-4-Fix-item-position-desync.patch +++ b/patches/server/MC-4-Fix-item-position-desync.patch @@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S return; } - // Paper end - rewrite chunk system + // Paper end - Block invalid positions and bounding box + // Paper start - Fix MC-4 + if (this instanceof ItemEntity) { + if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) { diff --git a/patches/server/Optimize-indirect-passenger-iteration.patch b/patches/server/Optimize-indirect-passenger-iteration.patch index ed969dd1af..4f126a1516 100644 --- a/patches/server/Optimize-indirect-passenger-iteration.patch +++ b/patches/server/Optimize-indirect-passenger-iteration.patch @@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.getIndirectPassengersStream().iterator(); }; @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - // Paper end - rewrite chunk system + } public boolean hasExactlyOnePlayerPassenger() { + if (this.passengers.isEmpty()) { return false; } // Paper - Optimize indirect passenger iteration diff --git a/patches/server/Player-Chunk-Load-Unload-Events.patch b/patches/server/Player-Chunk-Load-Unload-Events.patch index b455284dca..a9cc82675a 100644 --- a/patches/server/Player-Chunk-Load-Unload-Events.patch +++ b/patches/server/Player-Chunk-Load-Unload-Events.patch @@ -9,20 +9,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java +++ b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java @@ -0,0 +0,0 @@ public class PlayerChunkSender { - public static void dropChunkStatic(ServerPlayer player, ChunkPos pos) { - player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(pos.toLong()).removePlayer(player); - player.connection.send(new ClientboundForgetLevelChunkPacket(pos)); -+ // Paper start - PlayerChunkUnloadEvent -+ if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - PlayerChunkUnloadEvent - } - // Paper end - rewrite player chunk loader + public void dropChunk(ServerPlayer player, ChunkPos pos) { + if (!this.pendingChunks.remove(pos.toLong()) && player.isAlive()) { + player.connection.send(new ClientboundForgetLevelChunkPacket(pos)); ++ // Paper start - PlayerChunkUnloadEvent ++ if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) { ++ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent(); ++ } ++ // Paper end - PlayerChunkUnloadEvent + } + } @@ -0,0 +0,0 @@ public class PlayerChunkSender { - public static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { // Paper - rewrite chunk loader - public - handler.player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(chunk.getPos().toLong()).addPlayer(handler.player); + + private static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null)); + // Paper start - PlayerChunkLoadEvent + if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { diff --git a/patches/server/Put-world-into-worldlist-before-initing-the-world.patch b/patches/server/Put-world-into-worldlist-before-initing-the-world.patch index 4972cd8cd3..15758c20a0 100644 --- a/patches/server/Put-world-into-worldlist-before-initing-the-world.patch +++ b/patches/server/Put-world-into-worldlist-before-initing-the-world.patch @@ -38,4 +38,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper - Put world into worldlist before initing the world; move up this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal); - //internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system + internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API diff --git a/patches/server/Rewrite-chunk-system.patch b/patches/server/Rewrite-chunk-system.patch index c74863e543..6257841c2e 100644 --- a/patches/server/Rewrite-chunk-system.patch +++ b/patches/server/Rewrite-chunk-system.patch @@ -15286,9 +15286,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("fixlight"), new FixLightCommand()); 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()); return commands.entrySet().stream() @@ -20130,8 +20130,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -0,0 +0,0 @@ public class ServerPlayer extends Player { - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent + public @Nullable String clientBrandName = null; // Paper - Brand support + public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event + // Paper start - replace player chunk loader + private final java.util.concurrent.atomic.AtomicReference viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1)); @@ -20455,23 +20455,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/network/PlayerChunkSender.java +++ b/src/main/java/net/minecraft/server/network/PlayerChunkSender.java @@ -0,0 +0,0 @@ public class PlayerChunkSender { - this.pendingChunks.add(chunk.getPos().toLong()); - } -+ // Paper start - rewrite player chunk loader -+ public static void dropChunkStatic(ServerPlayer player, ChunkPos pos) { -+ player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(pos.toLong()).removePlayer(player); -+ player.connection.send(new ClientboundForgetLevelChunkPacket(pos)); -+ } -+ // Paper end - rewrite player chunk loader -+ public void dropChunk(ServerPlayer player, ChunkPos pos) { if (!this.pendingChunks.remove(pos.toLong()) && player.isAlive()) { -- player.connection.send(new ClientboundForgetLevelChunkPacket(pos)); -+ dropChunkStatic(player, pos); // Paper - rewrite player chunk loader - move into own method - } - ++ // Paper start - rewrite player chunk loader ++ dropChunkStatic(player, pos); ++ } ++ } ++ public static void dropChunkStatic(ServerPlayer player, ChunkPos pos) { ++ player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(pos.toLong()).removePlayer(player); + player.connection.send(new ClientboundForgetLevelChunkPacket(pos)); + // Paper start - PlayerChunkUnloadEvent + if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) { + new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(pos.longKey), player.getBukkitEntity()).callEvent(); + } + // Paper end - PlayerChunkUnloadEvent +- } +- } ++ // Paper end - rewrite player chunk loader public void sendNextChunks(ServerPlayer player) { + if (true) return; // Paper - rewrite player chunk loader @@ -20486,8 +20488,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void sendChunk(ServerGamePacketListenerImpl handler, ServerLevel world, LevelChunk chunk) { // Paper - rewrite chunk loader - public + handler.player.serverLevel().chunkSource.chunkMap.getVisibleChunkIfPresent(chunk.getPos().toLong()).addPlayer(handler.player); handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null)); - ChunkPos chunkPos = chunk.getPos(); - DebugPackets.sendPoiPacketsForChunk(world, chunkPos); + // Paper start - PlayerChunkLoadEvent + if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { @@ -0,0 +0,0 @@ public class PlayerChunkSender { } @@ -20501,19 +20503,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper - AsyncTabCompleteEvent return; } -+ // Paper start -+ String str = packet.getCommand(); int index = -1; -+ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -+ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"))); // Paper + // Paper end - Don't suggest if tab-complete is disabled ++ // Paper start - rewrite chunk system ++ int index; ++ if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) { ++ server.scheduleOnMain(() -> this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); + return; + } -+ // Paper end - // CraftBukkit end ++ // Paper end - rewrite chunk system // Paper start - AsyncTabCompleteEvent TAB_COMPLETE_EXECUTOR.execute(() -> { + StringReader stringreader = new StringReader(packet.getCommand()); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java @@ -20750,15 +20752,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean hasAnyPlayerPassengers() { + // copied from below + if (this.passengers.isEmpty()) { return false; } -+ return this.getIndirectPassengersStream().anyMatch((entity) -> { -+ return entity instanceof Player; -+ }); ++ return this.getIndirectPassengersStream().anyMatch((entity) -> entity instanceof Player); + } + // Paper end - rewrite chunk system -+ public boolean hasExactlyOnePlayerPassenger() { + if (this.passengers.isEmpty()) { return false; } // Paper - Optimize indirect passenger iteration return this.countPlayerPassengers() == 1; - } @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S return; } @@ -20769,9 +20768,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + // Paper end - rewrite chunk system - if (this.position.x != x || this.position.y != y || this.position.z != z) { - this.position = new Vec3(x, y, z); - int i = Mth.floor(x); + // Paper start - Fix MC-4 + if (this instanceof ItemEntity) { + if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) { @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S @Override @@ -21542,6 +21541,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) { + // Paper start - Do not let the server load chunks from newer versions + if (nbt.contains("DataVersion", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) { +@@ -0,0 +0,0 @@ public class ChunkSerializer { + } + } + // Paper end - Do not let the server load chunks from newer versions + InProgressChunkHolder holder = readInProgressChunkHolder(world, poiStorage, chunkPos, nbt); + return holder.protoChunk; + } @@ -21686,37 +21691,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493; - private final IOWorker worker; -+ // Paper - nuke IO worker ++ // Paper start - rewrite chunk system; async chunk IO ++ private final Object persistentDataLock = new Object(); ++ public final RegionFileStorage regionFileCache; ++ // Paper end - rewrite chunk system protected final DataFixer fixerUpper; @Nullable private volatile LegacyStructureDataHandler legacyStructureHandler; -+ // Paper start - async chunk loading -+ private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileStorage regionFileCache; -+ // Paper end - async chunk loading public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) { this.fixerUpper = dataFixer; - this.worker = new IOWorker(directory, dsync, "chunk"); -+ // Paper start - async chunk io -+ // remove IO worker -+ this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker -+ // Paper end - async chunk io ++ this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - rewrite chunk system; async chunk IO } public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { - return this.worker.isOldChunkAround(chunkPos, checkRadius); -+ return true; // Paper - (for now, old unoptimised behavior) TODO implement later? the chunk status that blender uses SHOULD already have this radius loaded, no need to go back for it... ++ return true; // Paper - rewrite chunk system; (for now, unoptimised behavior) TODO implement later? the chunk status that blender uses SHOULD already have this radius loaded, no need to go back later for it... } // CraftBukkit start - private boolean check(ServerChunkCache cps, int x, int z) { +@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { + if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full" ChunkPos pos = new ChunkPos(x, z); if (cps != null) { - com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); - if (cps.hasChunk(x, z)) { -+ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe -+ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! ++ // Paper start - rewrite chunk system; async chunk IO ++ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // isLoaded is a ticket level check, not a chunk loaded check! ++ // Paper end - rewrite chunk system return true; } } @@ -22684,11 +22687,10 @@ 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 { - this.console.addLevel(internal); + internal.keepSpawnInMemory = creator.keepSpawnLoaded().toBooleanOrElse(internal.getWorld().getKeepSpawnInMemory()); // Paper this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal); - internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API -+ //internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system this.pluginManager.callEvent(new WorldLoadEvent(internal.getWorld())); return internal.getWorld(); @@ -22966,25 +22968,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void getEntitiesByClass(Class clazz, Entity except, AABB box, List into, Predicate predicate) {} + // Paper end } -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ public class ActivationRange - ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); - ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); - -- world.getEntities().get(ActivationRange.maxBB, ActivationRange::activateEntity); -+ // Paper start -+ java.util.List entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); -+ for (int i = 0; i < entities.size(); i++) { -+ Entity entity = entities.get(i); -+ ActivationRange.activateEntity(entity); -+ } -+ // Paper end - } - MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/AsyncCatcher.java @@ -22994,10 +22977,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static void catchOp(String reason) { - if ( (AsyncCatcher.enabled || io.papermc.paper.util.TickThread.STRICT_THREAD_CHECKS) && Thread.currentThread() != MinecraftServer.getServer().serverThread ) // Paper -+ if ( !io.papermc.paper.util.TickThread.isTickThread() ) // Paper // Paper - rewrite chunk system ++ if (!(io.papermc.paper.util.TickThread.isTickThread())) // Paper { + MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper throw new IllegalStateException( "Asynchronous " + reason + "!" ); - } diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java diff --git a/patches/server/Use-correct-seed-on-api-world-load.patch b/patches/server/Use-correct-seed-on-api-world-load.patch index 48b2384c9f..2fb8319cd0 100644 --- a/patches/server/Use-correct-seed-on-api-world-load.patch +++ b/patches/server/Use-correct-seed-on-api-world-load.patch @@ -9,8 +9,8 @@ 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 { - - // Paper - fix and optimise world upgrading; move down + net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), this.console.options.has("eraseCache"), () -> true, iregistry); + } - long j = BiomeManager.obfuscateSeed(creator.seed()); + long j = BiomeManager.obfuscateSeed(worlddata.worldGenOptions().seed()); // Paper - use world seed diff --git a/patches/server/Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch index 0a2581d9b1..51b3f5f6be 100644 --- a/patches/server/Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch @@ -283,9 +283,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return chunkMap.playerEntityTrackerTrackMaps[type.ordinal()].getObjectsInRange(MCUtil.getCoordinateKey(this)); + } + // Paper end - optimise entity tracking - - public Entity(EntityType type, Level world) { - this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + public float getBukkitYaw() { + return this.yRot; + } diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java diff --git a/patches/server/WorldCreator-keepSpawnLoaded.patch b/patches/server/WorldCreator-keepSpawnLoaded.patch index 8d8e08515f..50be64fe1b 100644 --- a/patches/server/WorldCreator-keepSpawnLoaded.patch +++ b/patches/server/WorldCreator-keepSpawnLoaded.patch @@ -23,5 +23,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + internal.keepSpawnInMemory = creator.keepSpawnLoaded().toBooleanOrElse(internal.getWorld().getKeepSpawnInMemory()); // Paper this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal); - //internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API // Paper - rewrite chunk system + internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API diff --git a/scripts/moveback.py b/scripts/moveback.py index 6135e33d8b..b0f7e2cca3 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 = 400 # TODO: Update this +patch_target = 750 # TODO: Update this def increment_number(filename):