From 37b7551e48e039ddf59fa34b42113a43d2ac9df2 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Thu, 4 Jul 2024 12:34:11 +0200 Subject: [PATCH] Readd more patches --- gradle.properties | 2 +- ...Chunk-System-Starlight-from-Moonrise.patch | 2 + .../Improve-boat-collision-performance.patch | 49 ++-- .../server/Optimise-general-POI-access.patch | 59 +++-- .../Optimise-random-block-ticking.patch | 14 +- ...ptimize-Collision-to-not-load-chunks.patch | 12 +- .../optimize-dirt-and-snow-spreading.patch | 0 .../server/Execute-chunk-tasks-mid-tick.patch | 176 ------------- .../Fix-World-isChunkGenerated-calls.patch | 243 ------------------ ...on-checking-in-player-move-packet-ha.patch | 18 +- 10 files changed, 79 insertions(+), 496 deletions(-) rename patches/{unapplied => }/server/Improve-boat-collision-performance.patch (59%) rename patches/{unapplied => }/server/Optimise-general-POI-access.patch (96%) rename patches/{unapplied => }/server/Optimise-random-block-ticking.patch (98%) rename patches/{unapplied => }/server/Optimize-Collision-to-not-load-chunks.patch (90%) rename patches/{unapplied => }/server/optimize-dirt-and-snow-spreading.patch (100%) delete mode 100644 patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch delete mode 100644 patches/unapplied/server/Fix-World-isChunkGenerated-calls.patch diff --git a/gradle.properties b/gradle.properties index 067fcc6c85..7aa001f7cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ version=1.21-R0.1-SNAPSHOT mcVersion=1.21 # Set to true while updating Minecraft version -updatingMinecraft=true +updatingMinecraft=false org.gradle.caching=true org.gradle.parallel=true diff --git a/patches/server/Chunk-System-Starlight-from-Moonrise.patch b/patches/server/Chunk-System-Starlight-from-Moonrise.patch index d6b800ea96..afdb656158 100644 --- a/patches/server/Chunk-System-Starlight-from-Moonrise.patch +++ b/patches/server/Chunk-System-Starlight-from-Moonrise.patch @@ -27493,9 +27493,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Spigot end } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { tickingblockentity.tick(); ++ // Paper start - rewrite chunk system + if ((++tickedEntities & 7) == 0) { + ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); + } ++ // Paper end - rewrite chunk system } } this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 diff --git a/patches/unapplied/server/Improve-boat-collision-performance.patch b/patches/server/Improve-boat-collision-performance.patch similarity index 59% rename from patches/unapplied/server/Improve-boat-collision-performance.patch rename to patches/server/Improve-boat-collision-performance.patch index e91650e41a..52acd46aa0 100644 --- a/patches/unapplied/server/Improve-boat-collision-performance.patch +++ b/patches/server/Improve-boat-collision-performance.patch @@ -30,26 +30,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.blockUsingShield(entityliving); @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - } - - if (entity1 != null && !source.is(DamageTypeTags.NO_KNOCKBACK)) { -- double d0 = entity1.getX() - this.getX(); -+ final boolean far = entity1.distanceToSqr(this) > (200.0 * 200.0); // Paper - Improve boat collision performance -+ double d0 = far ? (Math.random() - Math.random()) : entity1.getX() - this.getX(); // Paper - Improve boat collision performance - - double d1; - -- for (d1 = entity1.getZ() - this.getZ(); d0 * d0 + d1 * d1 < 1.0E-4D; d1 = (Math.random() - Math.random()) * 0.01D) { -+ for (d1 = far ? Math.random() - Math.random() : entity1.getZ() - this.getZ(); d0 * d0 + d1 * d1 < 1.0E-4D; d1 = (Math.random() - Math.random()) * 0.01D) { // Paper - Improve boat collision performance - d0 = (Math.random() - Math.random()) * 0.01D; - } + double d0 = 0.0D; + double d1 = 0.0D; + Entity entity2 = source.getDirectEntity(); +- +- if (entity2 instanceof Projectile) { ++ // Paper start - improve boat collision performance ++ final boolean far = entity2.distanceToSqr(this) > (200.0D * 200.0D); ++ if (far) { ++ d0 = Math.random() - Math.random(); ++ d1 = Math.random() - Math.random(); ++ } else if (entity2 instanceof Projectile) { ++ // Paper end - improve boat collision performance + Projectile iprojectile = (Projectile) entity2; + DoubleDoubleImmutablePair doubledoubleimmutablepair = iprojectile.calculateHorizontalHurtKnockbackDirection(this, source); @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); Entity entity = damagesource.getDirectEntity(); -- if (entity instanceof LivingEntity) { -+ if (entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Improve boat collision performance +- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity) { // Paper - Fix shield disable inconsistency ++ if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Fix shield disable inconsistency & improve boat collision performance this.blockUsingShield((LivingEntity) entity); } } @@ -57,12 +58,12 @@ diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -0,0 +0,0 @@ public class Boat extends VehicleEntity implements VariantHolder { - this.invFriction = 0.05F; - if (this.oldStatus == Boat.Status.IN_AIR && this.status != Boat.Status.IN_AIR && this.status != Boat.Status.ON_LAND) { - this.waterLevel = this.getY(1.0D); -- this.setPos(this.getX(), (double) (this.getWaterLevelAbove() - this.getBbHeight()) + 0.101D, this.getZ()); -+ this.move(MoverType.SELF, new Vec3(0.0, ((double) (this.getWaterLevelAbove() - this.getBbHeight()) + 0.101D) - this.getY(), 0.0)); // Paper - Improve boat collision performance - this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); - this.lastYd = 0.0D; - this.status = Boat.Status.IN_WATER; +@@ -0,0 +0,0 @@ public class Boat extends VehicleEntity implements Leashable, VariantHolder> 4; -+ final int lowerY = WorldUtil.getMinSection(poiStorage.world); ++ final int lowerY = WorldUtil.getMinSection(poiStorage.moonrise$getWorld()); + final int lowerZ = Mth.floor(sourcePosition.getZ() - range) >> 4; + final int upperX = Mth.floor(sourcePosition.getX() + range) >> 4; -+ final int upperY = WorldUtil.getMaxSection(poiStorage.world); ++ final int upperY = WorldUtil.getMaxSection(poiStorage.moonrise$getWorld()); + final int upperZ = Mth.floor(sourcePosition.getZ() + range) >> 4; + + final int centerX = sourcePosition.getX() >> 4; @@ -492,10 +492,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + double furthestDistanceSquared = maxDistanceSquared; + + final int lowerX = Mth.floor(sourcePosition.getX() - range) >> 4; -+ final int lowerY = WorldUtil.getMinSection(poiStorage.world); ++ final int lowerY = WorldUtil.getMinSection(poiStorage.moonrise$getWorld()); + final int lowerZ = Mth.floor(sourcePosition.getZ() - range) >> 4; + final int upperX = Mth.floor(sourcePosition.getX() + range) >> 4; -+ final int upperY = WorldUtil.getMaxSection(poiStorage.world); ++ final int upperY = WorldUtil.getMaxSection(poiStorage.moonrise$getWorld()); + final int upperZ = Mth.floor(sourcePosition.getZ() + range) >> 4; + + final int centerX = sourcePosition.getX() >> 4; @@ -769,10 +769,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // First up, we need to iterate the chunks + // all the values here are in chunk sections + final int lowerX = Mth.floor(sourcePosition.getX() - range) >> 4; -+ final int lowerY = Math.max(WorldUtil.getMinSection(poiStorage.world), Mth.floor(sourcePosition.getY() - range) >> 4); ++ final int lowerY = Math.max(WorldUtil.getMinSection(poiStorage.moonrise$getWorld()), Mth.floor(sourcePosition.getY() - range) >> 4); + final int lowerZ = Mth.floor(sourcePosition.getZ() - range) >> 4; + final int upperX = Mth.floor(sourcePosition.getX() + range) >> 4; -+ final int upperY = Math.min(WorldUtil.getMaxSection(poiStorage.world), Mth.floor(sourcePosition.getY() + range) >> 4); ++ final int upperY = Math.min(WorldUtil.getMaxSection(poiStorage.moonrise$getWorld()), Mth.floor(sourcePosition.getY() + range) >> 4); + final int upperZ = Mth.floor(sourcePosition.getZ() + range) >> 4; + + // Vanilla iterates by x until max is reached then increases z @@ -887,7 +887,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager. index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage { +@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage implements ca.spotted public Optional find( Predicate> typePredicate, Predicate posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus ) { @@ -947,7 +947,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 .map(poi -> { poi.acquireTicket(); return poi.getPos(); -@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage { +@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage implements ca.spotted int radius, RandomSource random ) { @@ -976,19 +976,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java @@ -0,0 +0,0 @@ import org.slf4j.Logger; - public class PoiSection { + public class PoiSection implements ca.spottedleaf.moonrise.patches.chunk_system.level.poi.ChunkSystemPoiSection { // Paper - rewrite chunk system private static final Logger LOGGER = LogUtils.getLogger(); private final Short2ObjectMap records = new Short2ObjectOpenHashMap<>(); - private final Map, Set> byType = Maps.newHashMap(); + private final Map, Set> byType = Maps.newHashMap(); public final Map, Set> getData() { return this.byType; } // Paper - public accessor private final Runnable setDirty; private boolean isValid; - public final Optional noAllocateOptional = Optional.of(this); // Paper - rewrite chunk system + diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -@@ -0,0 +0,0 @@ public class SectionStorage extends RegionFileStorage implements AutoCloseabl +@@ -0,0 +0,0 @@ public abstract class SectionStorage implements AutoCloseable, ca.spottedleaf } @Nullable @@ -1011,17 +1011,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end - villageplace.ensureLoadedAndValid(this.level, blockposition, i); -- Optional optional = villageplace.getInSquare((holder) -> { +- Stream stream = villageplace.getInSquare((holder) -> { // CraftBukkit - decompile error - return holder.is(PoiTypes.NETHER_PORTAL); -- }, blockposition, i, PoiManager.Occupancy.ANY).filter((villageplacerecord) -> { -- return worldborder.isWithinBounds(villageplacerecord.getPos()) && !(this.level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> villageplacerecord.getPos().getY() >= v)); // Paper - Configurable nether ceiling damage -- }).sorted(Comparator.comparingDouble((PoiRecord villageplacerecord) -> { // CraftBukkit - decompile error -- return villageplacerecord.getPos().distSqr(blockposition); -- }).thenComparingInt((villageplacerecord) -> { -- return villageplacerecord.getPos().getY(); -- })).filter((villageplacerecord) -> { -- return this.level.getBlockState(villageplacerecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); -- }).findFirst(); +- }, blockposition, i, PoiManager.Occupancy.ANY).map(PoiRecord::getPos); +- +- Objects.requireNonNull(worldborder); +- return stream.filter(worldborder::isWithinBounds).filter(pos -> !(this.level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> pos.getY() >= v))).filter((blockposition1) -> { // Paper - Configurable nether ceiling damage +- return this.level.getBlockState(blockposition1).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); +- }).min(Comparator.comparingDouble((BlockPos blockposition1) -> { // CraftBukkit - decompile error +- return blockposition1.distSqr(blockposition); +- }).thenComparingInt(Vec3i::getY)); + // Paper start - optimise portals + Optional optional; + java.util.List records = new java.util.ArrayList<>(); @@ -1030,7 +1029,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + type -> type.is(PoiTypes.NETHER_PORTAL), + (BlockPos pos) -> { + net.minecraft.world.level.chunk.ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY); -+ if (!lowest.getStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.FULL) ++ if (!lowest.getPersistedStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.FULL) + && (lowest.getBelowZeroRetrogen() == null || !lowest.getBelowZeroRetrogen().targetStatus().isOrAfter(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN))) { + // why would we generate the chunk? + return false; @@ -1044,17 +1043,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ); + + // this gets us most of the way there, but we bias towards lower y values. -+ PoiRecord lowestYRecord = null; ++ BlockPos lowestPos = null; + for (PoiRecord record : records) { -+ if (lowestYRecord == null) { -+ lowestYRecord = record; -+ } else if (lowestYRecord.getPos().getY() > record.getPos().getY()) { -+ lowestYRecord = record; ++ if (lowestPos == null) { ++ lowestPos = record.getPos(); ++ } else if (lowestPos.getY() > record.getPos().getY()) { ++ lowestPos = record.getPos(); + } + } + // now we're done -+ optional = Optional.ofNullable(lowestYRecord); ++ return Optional.ofNullable(lowestPos); + // Paper end - optimise portals + } - return optional.map((villageplacerecord) -> { - BlockPos blockposition1 = villageplacerecord.getPos(); + public Optional createPortal(BlockPos pos, Direction.Axis axis) { diff --git a/patches/unapplied/server/Optimise-random-block-ticking.patch b/patches/server/Optimise-random-block-ticking.patch similarity index 98% rename from patches/unapplied/server/Optimise-random-block-ticking.patch rename to patches/server/Optimise-random-block-ticking.patch index 4be93dc764..e634e805c5 100644 --- a/patches/unapplied/server/Optimise-random-block-ticking.patch +++ b/patches/server/Optimise-random-block-ticking.patch @@ -93,7 +93,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/mai index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. entityplayer.stopSleepInBed(false, false); }); } @@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ChunkPos chunkcoordintpair = chunk.getPos(); -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); @@ -116,7 +116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow for (int l = 0; l < randomTickSpeed; ++l) { if (this.random.nextInt(48) == 0) { @@ -128,7 +128,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } } // Paper - Option to disable ice and snow -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.popPush("tickBlocks"); timings.chunkTicksBlocks.startTiming(); // Paper if (randomTickSpeed > 0) { @@ -190,7 +190,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 timings.chunkTicksBlocks.stopTiming(); // Paper gameprofilerfiller.pop(); -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @VisibleForTesting public void tickPrecipitation(BlockPos pos) { @@ -220,7 +220,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (i > 0 && biomebase.shouldSnow(this, blockposition1)) { BlockState iblockdata = this.getBlockState(blockposition1); -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } } @@ -327,7 +327,7 @@ diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/ index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- 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 { +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public abstract RecipeManager getRecipeManager(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { diff --git a/patches/unapplied/server/Optimize-Collision-to-not-load-chunks.patch b/patches/server/Optimize-Collision-to-not-load-chunks.patch similarity index 90% rename from patches/unapplied/server/Optimize-Collision-to-not-load-chunks.patch rename to patches/server/Optimize-Collision-to-not-load-chunks.patch index d71189a1d3..0c3bd2e6f8 100644 --- a/patches/unapplied/server/Optimize-Collision-to-not-load-chunks.patch +++ b/patches/server/Optimize-Collision-to-not-load-chunks.patch @@ -18,13 +18,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer1.setShiftKeyDown(false); - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + Vec3 vec3d = dimensiontransition.pos(); -+ worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { - // CraftBukkit end - entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + entityplayer1.forceSetPositionRotation(vec3d.x, vec3d.y, vec3d.z, dimensiontransition.yRot(), dimensiontransition.xRot()); ++ worldserver.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + // CraftBukkit end + if (dimensiontransition.missingRespawnBlock()) { + entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/patches/unapplied/server/optimize-dirt-and-snow-spreading.patch b/patches/server/optimize-dirt-and-snow-spreading.patch similarity index 100% rename from patches/unapplied/server/optimize-dirt-and-snow-spreading.patch rename to patches/server/optimize-dirt-and-snow-spreading.patch diff --git a/patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch b/patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch deleted file mode 100644 index cd6b7a69fb..0000000000 --- a/patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 04:20:44 -0700 -Subject: [PATCH] Execute chunk tasks mid-tick - -This will help the server load chunks if tick times are high. - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- 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 midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); -+ - private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); - - private MinecraftTimings() {} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= MAX_CHUNK_EXEC_TIME) { -+ if (!moreTasks) { -+ lastMidTickExecuteFailure = currTime; -+ } -+ -+ // note: negative values reduce the time -+ long overuse = diff - MAX_CHUNK_EXEC_TIME; -+ if (overuse >= (10L * 1000L * 1000L)) { // 10ms -+ // make sure something like a GC or dumb plugin doesn't screw us over... -+ overuse = 10L * 1000L * 1000L; // 10ms -+ } -+ -+ double overuseCount = (double)overuse/(double)MAX_CHUNK_EXEC_TIME; -+ long extraSleep = (long)Math.round(overuseCount*CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME); -+ -+ lastMidTickExecute = currTime + extraSleep; -+ return; -+ } -+ } -+ } finally { -+ co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming(); -+ } -+ } -+ // Paper end - execute chunk tasks mid tick -+ - private boolean pollTaskInternal() { - if (super.pollTask()) { -+ this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick - return true; - } else { - boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit - Iterator iterator1 = list.iterator(); - -+ int chunksTicked = 0; // Paper - while (iterator1.hasNext()) { - ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next(); - LevelChunk chunk1 = chunkproviderserver_a.chunk; -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - - if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { - this.level.tickChunk(chunk1, l); -+ if ((chunksTicked++ & 1) == 0) net.minecraft.server.MinecraftServer.getServer().executeMidTickTasks(); // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { - private final StructureCheck structureCheck; - private final boolean tickTime; - private final RandomSequences randomSequences; -+ public long lastMidTickExecuteFailure; // Paper - execute chunk tasks mid tick - - // CraftBukkit start - public final LevelStorageSource.LevelStorageAccess convertable; -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { - if (fluid1.is(fluid)) { - fluid1.tick(this, pos); - } -+ MinecraftServer.getServer().executeMidTickTasks(); // Paper - exec chunk tasks during world tick - - } - -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { - if (iblockdata.is(block)) { - iblockdata.tick(this, pos, this.random); - } -+ MinecraftServer.getServer().executeMidTickTasks(); // Paper - exec chunk tasks during world tick - - } - -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 -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // Spigot end - } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { - tickingblockentity.tick(); -+ // Paper start - execute chunk tasks during tick -+ if ((this.tileTickPosition & 7) == 0) { -+ MinecraftServer.getServer().executeMidTickTasks(); -+ } -+ // Paper end - execute chunk tasks during tick - } - } - this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public void guardEntityTick(Consumer tickConsumer, T entity) { - try { - tickConsumer.accept(entity); -+ MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick - } catch (Throwable throwable) { - if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent block entity and entity crashes diff --git a/patches/unapplied/server/Fix-World-isChunkGenerated-calls.patch b/patches/unapplied/server/Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index 67e917d59d..0000000000 --- a/patches/unapplied/server/Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,243 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- 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 - // Paper end - - private CompletableFuture> readChunk(ChunkPos chunkPos) { -- return this.read(chunkPos).thenApplyAsync((optional) -> { -- return optional.map((nbttagcompound) -> this.upgradeChunkTag(nbttagcompound, chunkPos)); // CraftBukkit -- }, Util.backgroundExecutor()); -+ // Paper start - Cache chunk status on disk -+ try { -+ return CompletableFuture.completedFuture(Optional.ofNullable(this.readConvertChunkSync(chunkPos))); -+ } catch (Throwable thr) { -+ return CompletableFuture.failedFuture(thr); -+ } -+ // Paper end - Cache chunk status on disk - } - - // CraftBukkit start -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // CraftBukkit end - } - -+ // Paper start - Cache chunk status on disk -+ @Nullable -+ public CompoundTag readConvertChunkSync(ChunkPos pos) throws IOException { -+ CompoundTag nbttagcompound = this.readSync(pos); -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.upgradeChunkTag(nbttagcompound, pos); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(pos, nbttagcompound); -+ -+ return nbttagcompound; -+ } -+ -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { -+ net.minecraft.world.level.chunk.storage.RegionFile regionFile = regionFileCache.getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -+ net.minecraft.world.level.chunk.storage.RegionFile regionFile = regionFileCache.getRegionFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFileCache.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunk(chunkPos); -+ -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -+ net.minecraft.world.level.chunk.storage.RegionFile regionFile = regionFileCache.getRegionFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); -+ } -+ -+ public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ ChunkHolder chunkHolder = io.papermc.paper.chunk.system.ChunkSystem.getUnloadingChunkHolder(this.level, chunkX, chunkZ); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); -+ } -+ // Paper end - Cache chunk status on disk -+ - 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 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- 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 { - @VisibleForTesting - protected final RegionBitmap usedSectors; - public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper -+ // Paper start - Cache chunk status -+ private final net.minecraft.world.level.chunk.status.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.status.ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, net.minecraft.world.level.chunk.status.ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[getChunkLocation(x, z)] = status; -+ } -+ -+ public net.minecraft.world.level.chunk.status.ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = getChunkLocation(x, z); -+ return this.statuses[location]; -+ } -+ // Paper end - Cache chunk status - - public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException { - this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return this.getOffset(pos) != 0; - } - -+ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - Cache chunk status; OBFHELPER - sort of, mirror of logic below - private static int getOffsetIndex(ChunkPos pos) { - return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; - } -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - synchronized (this) { - try { - // Paper end -+ this.closed = true; // Paper - Cache chunk status - try { - this.padToFullSector(); - } finally { -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 - // 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 -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return java.util.concurrent.CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkSource().mainThreadProcessor).join(); -+ } -+ ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; -+ } - try { -- return this.isChunkLoaded(x, z) || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)).get().isPresent(); -- } catch (InterruptedException | ExecutionException ex) { -+ return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(x, z)) == ChunkStatus.FULL; -+ } catch (java.io.IOException ex) { -+ // Paper end - Fix this method - throw new RuntimeException(ex); - } - } -@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World { - 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 -- -- // 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) { -+ 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, 0, Unit.INSTANCE); // Paper -+ world.getChunk(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } -+ net.minecraft.world.level.chunk.storage.RegionFile file; -+ try { -+ file = world.getChunkSource().chunkMap.regionFileCache.getRegionFile(chunkPos, false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk -+ } -+ 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 - } - - @Override diff --git a/patches/unapplied/server/Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/unapplied/server/Optimise-collision-checking-in-player-move-packet-ha.patch index 974448e717..acfb03e4c3 100644 --- a/patches/unapplied/server/Optimise-collision-checking-in-player-move-packet-ha.patch +++ b/patches/unapplied/server/Optimise-collision-checking-in-player-move-packet-ha.patch @@ -89,15 +89,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Override -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - if (this.awaitingPositionFromClient != null) { -- if (this.tickCount - this.awaitingTeleportTime > 20) { -+ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT - this.awaitingTeleportTime = this.tickCount; - this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); - } @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } } @@ -135,6 +126,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, toX, toY, toZ, toYaw, toPitch, false); @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + private boolean updateAwaitingTeleport() { + if (this.awaitingPositionFromClient != null) { +- if (this.tickCount - this.awaitingTeleportTime > 20) { ++ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT + this.awaitingTeleportTime = this.tickCount; + this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } }