diff --git a/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch index 9327db7125..27d23f2b36 100644 --- a/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ b/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -85,37 +85,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return true; @@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot - // Paper start - Optimize this method - ChunkPos chunkPos = new ChunkPos(x, z); -+ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper -+ if (immediate != null) return true; // Paper - - if (!generate) { -- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); -+ -+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper - if (immediate == null) { - immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); - } -@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { - return false; // not full status - } -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunk(x, z); // make sure we're at ticket level 32 or lower - return true; - } -@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - // we do this so we do not re-read the chunk data on disk } -- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); - return true; - // Paper end - Optimize this method + if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { +- this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); ++ this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper + return true; + } + @@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> { net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> { diff --git a/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch index f85ca861e0..ba44792916 100644 --- a/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -9,9 +9,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 + // Spigot end + // Paper start protected int numCollisions = 0; // Paper - Cap entity collisions - public long activatedImmunityTick = Integer.MIN_VALUE; // Paper - public boolean isTemporarilyActive; // Paper + public boolean fromNetherPortal; // Paper - Add option to nerf pigmen from nether portals public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one @javax.annotation.Nullable diff --git a/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch index ea6a2a6a7d..fb01b3c2dd 100644 --- a/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch +++ b/patches/server/Add-paper-mobcaps-and-paper-playermobcaps.patch @@ -275,8 +275,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Add mobcaps commands + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { - // Paper start - Optional per player mob spawns - spawnCategoryForChunk(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); + BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk); + 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 diff --git a/patches/server/Allow-Saving-of-Oversized-Chunks.patch b/patches/server/Allow-Saving-of-Oversized-Chunks.patch index 26f5a5a3eb..cbbbdb1967 100644 --- a/patches/server/Allow-Saving-of-Oversized-Chunks.patch +++ b/patches/server/Allow-Saving-of-Oversized-Chunks.patch @@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public final Path regionFile; // 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 { public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { @@ -66,9 +66,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.version = outputChunkStreamVersion; if (!Files.isDirectory(directory, new LinkOption[0])) { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - } + public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails + // Paper start + private final byte[] oversized = new byte[1024]; + private int oversizedCount; @@ -206,6 +206,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 try { NbtIo.write(nbt, (DataOutput) dataoutputstream); + regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable) { - if (dataoutputstream != null) { - try { + // Paper start - don't write garbage data to disk if writing serialization fails + dataoutputstream.close(); // Only write if successful + } catch (final RegionFileSizeException e) { diff --git a/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch index c77d717819..9419bd139c 100644 --- a/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch @@ -9,7 +9,7 @@ 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 new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME), world); // Paper - Anti-Xray - Add parameters + return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME)); } + // Paper start - Allow delegation to vanilla chunk gen diff --git a/patches/server/Anti-Xray.patch b/patches/server/Anti-Xray.patch index 57457923da..73ea9cef4b 100644 --- a/patches/server/Anti-Xray.patch +++ b/patches/server/Anti-Xray.patch @@ -1151,9 +1151,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final boolean shouldModify = world.chunkPacketBlockController.shouldModify(handler.player, chunk); + handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null, shouldModify)); + // Paper end - Anti-Xray - ChunkPos chunkPos = chunk.getPos(); - DebugPackets.sendPoiPacketsForChunk(world, chunkPos); - } + // Paper start - PlayerChunkLoadEvent + if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { + new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), handler.getPlayer().getBukkitEntity()).callEvent(); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/Level.java @@ -1277,9 +1277,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final T @org.jetbrains.annotations.Nullable [] presetValues; // Paper - Anti-Xray - Add preset values private volatile PalettedContainer.Data data; private final PalettedContainer.Strategy strategy; - private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); + // private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); // Paper - unused @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer - this.threadingDetector.checkAndUnlock(); + // this.threadingDetector.checkAndUnlock(); // Paper - disable this } - public static Codec> codecRW(IdMap idList, Codec entryCodec, PalettedContainer.Strategy paletteProvider, T defaultValue) { @@ -1359,7 +1359,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.data = this.createOrReuseData((PalettedContainer.Data)null, 0); @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer @Override - public int onResize(int newBits, T object) { + public synchronized int onResize(int newBits, T object) { // Paper - synchronize PalettedContainer.Data data = this.data; + + // Paper start - Anti-Xray - Add preset values @@ -1403,12 +1403,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -+ // Paper start - Anti-Xray - Add chunk packet info ++ // Paper start - Anti-Xray; Add chunk packet info + @Override + @Deprecated @io.papermc.paper.annotation.DoNotUse public void write(FriendlyByteBuf buf) { this.write(buf, null, 0); } @Override -- public void write(FriendlyByteBuf buf) { -+ public void write(FriendlyByteBuf buf, @Nullable com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { +- public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize ++ public synchronized void write(FriendlyByteBuf buf, @Nullable com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - Synchronize this.acquire(); try { @@ -1569,7 +1569,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME), world); // Paper - Anti-Xray - Add parameters } - @Override + // Paper start - Allow delegation to vanilla chunk gen 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 diff --git a/patches/server/Buffer-joins-to-world.patch b/patches/server/Buffer-joins-to-world.patch index 6318e1f1ae..fa1c8179e6 100644 --- a/patches/server/Buffer-joins-to-world.patch +++ b/patches/server/Buffer-joins-to-world.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + } } - // Paper end - Optimize network + private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world + private static int joinAttemptsThisTick; // Paper - Buffer joins to world diff --git a/patches/server/Configurable-Region-Compression-Format.patch b/patches/server/Configurable-Region-Compression-Format.patch index 4e8a3fa2c2..9acd9767fc 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 { - // Paper end - Cache chunk status + 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); diff --git a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch index eff4570a03..196722f5f4 100644 --- a/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch +++ b/patches/server/Deobfuscate-stacktraces-in-log-messages-crash-report.patch @@ -514,7 +514,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper }); private final PacketFlow receiving; - private final Queue pendingActions = Queues.newConcurrentLinkedQueue(); + private final Queue> pendingActions = Queues.newConcurrentLinkedQueue(); @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { } diff --git a/patches/server/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch index b6b79e9472..b7260421ce 100644 --- a/patches/server/Entity-Activation-Range-2.0.patch +++ b/patches/server/Entity-Activation-Range-2.0.patch @@ -116,11 +116,11 @@ 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 - // Spigot end // Paper start protected int numCollisions = 0; // Paper - Cap entity collisions -+ public long activatedImmunityTick = Integer.MIN_VALUE; // Paper -+ public boolean isTemporarilyActive; // Paper + public boolean fromNetherPortal; // Paper - Add option to nerf pigmen from nether portals ++ public long activatedImmunityTick = Integer.MIN_VALUE; // Paper - EAR ++ public boolean isTemporarilyActive; // Paper - EAR public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one @javax.annotation.Nullable private org.bukkit.util.Vector origin; @@ -344,7 +344,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public Map capturedTileEntities = new HashMap<>(); + public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates public List captureDrops; public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); + // Paper start diff --git a/patches/server/Fix-World-isChunkGenerated-calls.patch b/patches/server/Fix-World-isChunkGenerated-calls.patch index b6b6061509..b6d154b052 100644 --- a/patches/server/Fix-World-isChunkGenerated-calls.patch +++ b/patches/server/Fix-World-isChunkGenerated-calls.patch @@ -36,7 +36,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Nullable + public CompoundTag readConvertChunkSync(ChunkPos pos) throws IOException { + CompoundTag nbttagcompound = this.readSync(pos); -+ // Paper start - Cache chunk status on disk + if (nbttagcompound == null) { + return null; + } @@ -49,10 +48,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.updateChunkStatusOnDisk(pos, nbttagcompound); + + return nbttagcompound; -+ // Paper end + } + -+ // Paper start - chunk status cache "api" + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { + net.minecraft.world.level.chunk.storage.RegionFile regionFile = regionFileCache.getRegionFileIfLoaded(chunkPos); + @@ -89,7 +86,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - Cache chunk status on disk + - boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { + public boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { // Paper - public // Spigot start return this.anyPlayerCloseEnoughForSpawning(pos, false); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java @@ -125,7 +122,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Cache chunk status + 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 this.getOffset(pos) != 0; @@ -153,8 +150,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 NbtIo.write(nbt, (DataOutput) dataoutputstream); + regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(nbt)); // Paper - Cache chunk status regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable) { - if (dataoutputstream != null) { + // Paper start - don't write garbage data to disk if writing serialization fails + dataoutputstream.close(); // Only write if successful 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 @@ -186,35 +183,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + warnUnsafeChunk("loading a faraway chunk", x, z); // Paper - ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkPos chunkPos = new ChunkPos(x, z); - +- - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ImposterProtoChunk) { - // We then cycle through again to get the full chunk immediately, rather than after the ticket addition - chunk = this.world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); - } +- +- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { +- this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper ++ // Paper start - Optimize this method ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (immediate != null) { ++ // Plugins should use plugin tickets instead of this method to keep a chunk perpetually loaded + return true; + } + +- return false; + if (!generate) { -+ ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); -+ } ++ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); + if (immediate != null) { + if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; // not full status + } -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunk(x, z); // make sure we're at ticket level 32 or lower + return true; + } - -- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { -- this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); -- return true; + net.minecraft.world.level.chunk.storage.RegionFile file; + try { + file = world.getChunkSource().chunkMap.regionFileCache.getRegionFile(chunkPos, false); @@ -234,10 +234,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // fall through to load + // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ } ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); + return true; + // Paper end - Optimize this method diff --git a/patches/server/Fix-a-bunch-of-vanilla-bugs.patch b/patches/server/Fix-a-bunch-of-vanilla-bugs.patch index b813c76e00..f879fa02e8 100644 --- a/patches/server/Fix-a-bunch-of-vanilla-bugs.patch +++ b/patches/server/Fix-a-bunch-of-vanilla-bugs.patch @@ -117,8 +117,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // CraftBukkit end } - // Paper end - Cache chunk status on disk - boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { + public boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { // Paper - public diff --git a/patches/server/Line-Of-Sight-Changes.patch b/patches/server/Line-Of-Sight-Changes.patch index f9ed855c77..11ab979d47 100644 --- a/patches/server/Line-Of-Sight-Changes.patch +++ b/patches/server/Line-Of-Sight-Changes.patch @@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); -- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper +- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; + // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists -+ return vec3d1.distanceToSqr(vec3d) > 128.0D * 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper - Perf: Use distance squared ++ return vec3d1.distanceToSqr(vec3d) > 128.0D * 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; // Paper - Perf: Use distance squared } } diff --git a/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch b/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch index 0750d26d25..e6b20d86bd 100644 --- a/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch +++ b/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch @@ -12,19 +12,17 @@ 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 static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails -+ - // Paper end private class ChunkBuffer extends ByteArrayOutputStream { + private final ChunkPos pos; @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + super.write(RegionFile.this.version.getId()); this.pos = chunkcoordintpair; } - + // Paper start - don't write garbage data to disk if writing serialization fails + @Override + public void write(final int b) { @@ -42,21 +40,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super.write(b, off, len); + } + // Paper end - don't write garbage data to disk if writing serialization fails -+ + public void close() throws IOException { ByteBuffer bytebuffer = ByteBuffer.wrap(this.buf, 0, this.count); - diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + + try { NbtIo.write(nbt, (DataOutput) dataoutputstream); - regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(nbt)); // Paper - Cache chunk status - regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone -+ dataoutputstream.close(); // Paper - only write if successful + // Paper start - don't write garbage data to disk if writing serialization fails -+ } catch (RegionFileSizeException e) { ++ dataoutputstream.close(); // Only write if successful ++ } catch (final RegionFileSizeException e) { + attempts = 5; // Don't retry + regionfile.clear(pos); + throw e; diff --git a/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch index 60a5061bb9..2f74ef2a24 100644 --- a/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { - return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); + return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()); // Paper }); private final PacketFlow receiving; - private final Queue> pendingActions = Queues.newConcurrentLinkedQueue(); @@ -210,8 +210,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper end - Optimize network - public void tick() { - this.flushQueue(); + private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world + private static int joinAttemptsThisTick; // Paper - Buffer joins to world @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { public void disconnect(Component disconnectReason) { // Spigot Start diff --git a/patches/server/Optional-per-player-mob-spawns.patch b/patches/server/Optional-per-player-mob-spawns.patch index 10612f971c..14282ee3ee 100644 --- a/patches/server/Optional-per-player-mob-spawns.patch +++ b/patches/server/Optional-per-player-mob-spawns.patch @@ -152,7 +152,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @@ -0,0 +0,0 @@ public final class NaturalSpawner { - } + // Paper end - Add mobcaps commands public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { + // Paper start - Optional per player mob spawns diff --git a/patches/server/Player-Chunk-Load-Unload-Events.patch b/patches/server/Player-Chunk-Load-Unload-Events.patch index cf2c428b22..b455284dca 100644 --- a/patches/server/Player-Chunk-Load-Unload-Events.patch +++ b/patches/server/Player-Chunk-Load-Unload-Events.patch @@ -21,9 +21,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper end - rewrite player chunk loader @@ -0,0 +0,0 @@ public class PlayerChunkSender { - final boolean shouldModify = world.chunkPacketBlockController.shouldModify(handler.player, chunk); - handler.send(new ClientboundLevelChunkWithLightPacket(chunk, world.getLightEngine(), (BitSet)null, (BitSet)null, shouldModify)); - // Paper end - Anti-Xray + 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)); + // Paper start - PlayerChunkLoadEvent + if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { + new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), handler.getPlayer().getBukkitEntity()).callEvent(); diff --git a/patches/server/Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/Retain-block-place-order-when-capturing-blockstates.patch index 55f59750c5..5faeb66c2d 100644 --- a/patches/server/Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/Retain-block-place-order-when-capturing-blockstates.patch @@ -21,4 +21,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates public List captureDrops; public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); - // Paper start + public boolean populating; diff --git a/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch b/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch index eb3f9cf954..db2f8e2981 100644 --- a/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch +++ b/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch @@ -30,11 +30,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); -- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; -+ return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper + // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists +- return vec3d1.distanceToSqr(vec3d) > 128.0D * 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; // Paper - Perf: Use distance squared ++ return vec3d1.distanceToSqr(vec3d) > 128.0D * 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper - Perf: Use distance squared & strip raytracing } } @@ -58,10 +58,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return hitResult == null ? null : hitResult.getType(); + } + // Paper end -+ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { - BlockState iblockdata = this.getBlockState(blockposition); + // Paper start - Add predicate for blocks when raytracing diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/Level.java diff --git a/patches/server/Synchronize-PalettedContainer-instead-of-ThreadingDe.patch b/patches/server/Synchronize-PalettedContainer-instead-of-ThreadingDe.patch index 61d806d98a..1685367dfe 100644 --- a/patches/server/Synchronize-PalettedContainer-instead-of-ThreadingDe.patch +++ b/patches/server/Synchronize-PalettedContainer-instead-of-ThreadingDe.patch @@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer - private final T @org.jetbrains.annotations.Nullable [] presetValues; // Paper - Anti-Xray - Add preset values + public final IdMap registry; private volatile PalettedContainer.Data data; private final PalettedContainer.Strategy strategy; - private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); @@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // this.threadingDetector.checkAndUnlock(); // Paper - disable this } - // Paper start - Anti-Xray - Add preset values + public static Codec> codecRW(IdMap idList, Codec entryCodec, PalettedContainer.Strategy paletteProvider, T defaultValue) { @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer } @@ -42,8 +42,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - public int onResize(int newBits, T object) { + public synchronized int onResize(int newBits, T object) { // Paper - synchronize PalettedContainer.Data data = this.data; - - // Paper start - Anti-Xray - Add preset values + PalettedContainer.Data data2 = this.createOrReuseData(data, newBits); + data2.copyFrom(data.palette, data.storage); @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer return this.getAndSet(this.strategy.getIndex(x, y, z), value); } @@ -72,11 +72,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 try { @@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + } + @Override - @Deprecated @io.papermc.paper.annotation.DoNotUse public void write(FriendlyByteBuf buf) { this.write(buf, null, 0); } - @Override -- public void write(FriendlyByteBuf buf, @Nullable com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { -+ public synchronized void write(FriendlyByteBuf buf, @Nullable com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize +- public void write(FriendlyByteBuf buf) { ++ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize this.acquire(); try { diff --git a/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch b/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch index 69569b6fe9..a5c41de0ea 100644 --- a/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch +++ b/patches/server/Use-getChunkIfLoadedImmediately-in-places.patch @@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public abstract ResourceKey getTypeKey(); - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator) { // Paper - create paper world config diff --git a/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java b/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/gameevent/GameEventDispatcher.java diff --git a/patches/server/Warn-on-plugins-accessing-faraway-chunks.patch b/patches/server/Warn-on-plugins-accessing-faraway-chunks.patch index eadb2566df..ce2c2e336e 100644 --- a/patches/server/Warn-on-plugins-accessing-faraway-chunks.patch +++ b/patches/server/Warn-on-plugins-accessing-faraway-chunks.patch @@ -59,9 +59,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + warnUnsafeChunk("loading a faraway chunk", x, z); // Paper - // Paper start - Optimize this method - ChunkPos chunkPos = new ChunkPos(x, z); - ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper + ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + + // If generate = false, but the chunk already exists, we will get this back. @@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override diff --git a/scripts/moveback.py b/scripts/moveback.py index ee8d04838a..ca2a47481d 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 '' -patch_target = 1009 # TODO: Update this +patch_target = 998 # TODO: Update this def increment_number(filename):