From f55b6e04b1af431994aa7879cf0eef86ccf2acbe Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 15:05:18 -0700 Subject: [PATCH] MOAR PATCHES --- .../0188-Add-ThrownEggHatchEvent.patch} | 0 .../0189-Entity-Jump-API.patch} | 0 ...90-add-hand-to-BlockMultiPlaceEvent.patch} | 0 ...re-Entity-is-never-double-registered.patch | 2 + ...ering-entities-from-unloading-chunks.patch | 2 + ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 -- ...ptimize-Collision-to-not-load-chunks.patch | 185 ------- .../0362-Tracking-Range-Improvements.patch} | 8 +- ...-items-vanishing-through-end-portal.patch} | 8 +- ...get-gravity-in-void.-Fixes-MC-167279.patch | 29 ++ ...-getChunkAt-calls-for-loaded-chunks.patch} | 6 +- ...w-overriding-the-java-version-check.patch} | 6 +- .../0367-Add-ThrownEggHatchEvent.patch} | 8 +- .../0368-Optimise-random-block-ticking.patch} | 170 +++--- .../0369-Entity-Jump-API.patch} | 10 +- ...-to-nerf-pigmen-from-nether-portals.patch} | 48 +- .../0371-Make-the-GUI-graph-fancier.patch} | 59 +-- ...72-add-hand-to-BlockMultiPlaceEvent.patch} | 4 +- ...3-Prevent-teleporting-dead-entities.patch} | 10 +- ...ipwire-hook-placement-before-update.patch} | 4 +- ...o-allow-iron-golems-to-spawn-in-air.patch} | 8 +- ...chance-of-villager-zombie-infection.patch} | 31 +- .../0377-Optimise-Chunk-getFluid.patch} | 38 +- ...mise-TickListServer-by-rewriting-it.patch} | 493 ++++++------------ ...pawn-settings-and-per-player-option.patch} | 24 +- ...nections-shouldn-t-hold-up-shutdown.patch} | 4 +- ...ow-bees-to-load-chunks-for-beehives.patch} | 10 +- ...PlayerChunkMap-adds-crashing-server.patch} | 34 +- ...ptimize-Collision-to-not-load-chunks.patch | 133 +++++ .../0384-Don-t-tick-dead-players.patch} | 8 +- ...-Player-s-shouldn-t-be-able-to-move.patch} | 6 +- ...unkMap-memory-use-for-visibleChunks.patch} | 73 +-- ...sks-Speed-up-processing-of-chunk-lo.patch} | 87 ++-- ...ove-existing-players-to-world-spawn.patch} | 27 +- 34 files changed, 623 insertions(+), 967 deletions(-) rename patches/{api-unmapped/0187-Add-ThrownEggHatchEvent.patch => api/0188-Add-ThrownEggHatchEvent.patch} (100%) rename patches/{api-unmapped/0188-Entity-Jump-API.patch => api/0189-Entity-Jump-API.patch} (100%) rename patches/{api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch => api/0190-add-hand-to-BlockMultiPlaceEvent.patch} (100%) rename patches/{server-remapped => removed/1.17}/0420-Ensure-Entity-is-never-double-registered.patch (99%) rename patches/{server-remapped => removed/1.17}/0421-Fix-unregistering-entities-from-unloading-chunks.patch (98%) delete mode 100644 patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch delete mode 100644 patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch rename patches/{server-remapped/0401-Tracking-Range-Improvements.patch => server/0362-Tracking-Range-Improvements.patch} (90%) rename patches/{server-remapped/0403-Fix-items-vanishing-through-end-portal.patch => server/0363-Fix-items-vanishing-through-end-portal.patch} (77%) create mode 100644 patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename patches/{server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch => server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch} (92%) rename patches/{server-remapped/0406-Allow-overriding-the-java-version-check.patch => server/0366-Allow-overriding-the-java-version-check.patch} (76%) rename patches/{server-remapped/0407-Add-ThrownEggHatchEvent.patch => server/0367-Add-ThrownEggHatchEvent.patch} (85%) rename patches/{server-remapped/0408-Optimise-random-block-ticking.patch => server/0368-Optimise-random-block-ticking.patch} (74%) rename patches/{server-remapped/0409-Entity-Jump-API.patch => server/0369-Entity-Jump-API.patch} (87%) rename patches/{server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch => server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch} (58%) rename patches/{server-remapped/0411-Make-the-GUI-graph-fancier.patch => server/0371-Make-the-GUI-graph-fancier.patch} (80%) rename patches/{server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch => server/0372-add-hand-to-BlockMultiPlaceEvent.patch} (89%) rename patches/{server-remapped/0413-Prevent-teleporting-dead-entities.patch => server/0373-Prevent-teleporting-dead-entities.patch} (67%) rename patches/{server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch => server/0374-Validate-tripwire-hook-placement-before-update.patch} (85%) rename patches/{server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch => server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch} (85%) rename patches/{server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch => server/0376-Configurable-chance-of-villager-zombie-infection.patch} (63%) rename patches/{server-remapped/0417-Optimise-Chunk-getFluid.patch => server/0377-Optimise-Chunk-getFluid.patch} (58%) rename patches/{server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch => server/0378-Optimise-TickListServer-by-rewriting-it.patch} (66%) rename patches/{server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch => server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch} (85%) rename patches/{server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch => server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch} (86%) rename patches/{server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch => server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch} (85%) rename patches/{server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch => server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch} (62%) create mode 100644 patches/server/0383-Optimize-Collision-to-not-load-chunks.patch rename patches/{server-remapped/0426-Don-t-tick-dead-players.patch => server/0384-Don-t-tick-dead-players.patch} (59%) rename patches/{server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch => server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch} (70%) rename patches/{server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch => server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch} (84%) rename patches/{server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch => server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch} (79%) rename patches/{server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch => server/0388-Don-t-move-existing-players-to-world-spawn.patch} (65%) diff --git a/patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch b/patches/api/0188-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/api-unmapped/0187-Add-ThrownEggHatchEvent.patch rename to patches/api/0188-Add-ThrownEggHatchEvent.patch diff --git a/patches/api-unmapped/0188-Entity-Jump-API.patch b/patches/api/0189-Entity-Jump-API.patch similarity index 100% rename from patches/api-unmapped/0188-Entity-Jump-API.patch rename to patches/api/0189-Entity-Jump-API.patch diff --git a/patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/api-unmapped/0189-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/0190-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch b/patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch similarity index 99% rename from patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch rename to patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch index 0c956bdb77..a10ff17d78 100644 --- a/patches/server-remapped/0420-Ensure-Entity-is-never-double-registered.patch +++ b/patches/removed/1.17/0420-Ensure-Entity-is-never-double-registered.patch @@ -10,6 +10,8 @@ Vs behavior of non ticking of just overwriting state. We will now simply log a warning when this happens instead of crashing the server. +1.17: Probably not needed? + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch b/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch similarity index 98% rename from patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch rename to patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch index 110790b17f..8d30f4e4f1 100644 --- a/patches/server-remapped/0421-Fix-unregistering-entities-from-unloading-chunks.patch +++ b/patches/removed/1.17/0421-Fix-unregistering-entities-from-unloading-chunks.patch @@ -14,6 +14,8 @@ This then results in dead entities lingering in the Chunk. Combine that with a buggy detail of the previous implementation of the Dupe UUID patch, then this was the likely source of the "Ghost entities" +1.17: Probably not needed? + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index f19be75b52..0000000000 --- a/patches/server-remapped/0404-Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java -@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl { - } - - @Override -- public void tick() { -+ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.operation == MoveControl.Operation.MOVE_TO) { - this.operation = MoveControl.Operation.WAIT; - this.mob.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java -@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class MoveControl { - -- protected final Mob mob; -+ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER - protected double wantedX; - protected double wantedY; - protected double wantedZ; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - - public Bee(EntityType type, Level world) { - super(type, world); -- this.moveControl = new FlyingMoveControl(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveControl = new FlyingMoveControl(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().getY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookControl = new Bee.BeeLookControl(this); - this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); - this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch b/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index 58edb5460d..0000000000 --- a/patches/server-remapped/0425-Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.PlayerAdvancements; - import net.minecraft.server.ServerScoreboard; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.server.level.TicketType; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; -+import net.minecraft.server.network.ServerLoginPacketListenerImpl; -+import net.minecraft.sounds.SoundEvents; -+import net.minecraft.sounds.SoundSource; -+import net.minecraft.stats.ServerStatsCounter; -+import net.minecraft.stats.Stats; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.Tag; - import net.minecraft.util.Mth; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GameType; - import net.minecraft.world.level.Level; -@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - import net.minecraft.server.dedicated.DedicatedServer; --import net.minecraft.server.level.ServerLevel; --import net.minecraft.server.level.ServerPlayer; --import net.minecraft.server.level.ServerPlayerGameMode; --import net.minecraft.server.network.ServerGamePacketListenerImpl; --import net.minecraft.server.network.ServerLoginPacketListenerImpl; --import net.minecraft.sounds.SoundEvents; --import net.minecraft.sounds.SoundSource; --import net.minecraft.stats.ServerStatsCounter; --import net.minecraft.stats.Stats; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - -@@ -805,6 +807,7 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) { - entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - private CraftEntity bukkitEntity; - - ChunkMap.TrackedEntity tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java -index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionGetter.java -+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java -@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter { - } - - default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -index 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644 ---- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -7,6 +7,9 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.Cursor3D; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.WorldGenRegion; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -21,13 +24,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; - public class CollisionSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity source; -+ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER - private final AABB box; - private final CollisionContext context; - private final Cursor3D cursor; -- private final BlockPos.MutableBlockPos pos; -+ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER - private final VoxelShape entityShape; -- private final CollisionGetter collisionGetter; -+ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER - private boolean needsBorderCheck; - private final BiPredicate predicate; - -@@ -64,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator { - boolean collisionCheck(Consumer consumer) { - while (true) { - if (this.cursor.advance()) { -- int i = this.cursor.nextX(); -- int j = this.cursor.nextY(); -- int k = this.cursor.nextZ(); -+ int i = this.cursor.nextX(); final int x = i; -+ int j = this.cursor.nextY(); final int y = j; -+ int k = this.cursor.nextZ(); final int z = k; - int l = this.cursor.getNextType(); - - if (l == 3) { - continue; - } - -- BlockGetter iblockaccess = this.getChunk(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion; -+ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.pos.set(i, j, k); -- BlockState iblockdata = iblockaccess.getBlockState(this.pos); -+ // Paper - moved up -+ // Paper end - - if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.is(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -index fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java -@@ -249,7 +249,8 @@ public final class Shapes { - - if (k2 < 3) { - blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1); -- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) { - initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial); diff --git a/patches/server-remapped/0401-Tracking-Range-Improvements.patch b/patches/server/0362-Tracking-Range-Improvements.patch similarity index 90% rename from patches/server-remapped/0401-Tracking-Range-Improvements.patch rename to patches/server/0362-Tracking-Range-Improvements.patch index ec1d0a178d..b4d6875ed4 100644 --- a/patches/server-remapped/0401-Tracking-Range-Improvements.patch +++ b/patches/server/0362-Tracking-Range-Improvements.patch @@ -8,10 +8,10 @@ Sets tracking range of watermobs to animals instead of misc and simplifies code Also ignores Enderdragon, defaulting it to Mojang's setting diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644 +index fdf5d8ede4b01e399272ddebfbd49258b166f00b..273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1791,6 +1791,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); int j = entity.getType().clientTrackingRange() * 16; @@ -20,7 +20,7 @@ index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c if (j > i) { i = j; diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644 +index 2d5cb8991e368372f1ab227735aac0c060deb199..24b1dfcf91d36947c87e9e5c2524317f8775ba95 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java +++ b/src/main/java/org/spigotmc/TrackingRange.java @@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb; @@ -31,7 +31,7 @@ index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5 public class TrackingRange { -@@ -25,26 +24,26 @@ public class TrackingRange +@@ -29,26 +28,26 @@ public class TrackingRange if ( entity instanceof ServerPlayer ) { return config.playerTrackingRange; diff --git a/patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch b/patches/server/0363-Fix-items-vanishing-through-end-portal.patch similarity index 77% rename from patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch rename to patches/server/0363-Fix-items-vanishing-through-end-portal.patch index 283ad7000c..e32fc1978b 100644 --- a/patches/server-remapped/0403-Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/0363-Fix-items-vanishing-through-end-portal.patch @@ -13,16 +13,16 @@ Quickly loading the exact world spawn chunk before searching the heightmap resolves the issue without having to load all spawn chunks. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644 +index fffeba61e9af5c69876921b48241edb881af2a64..3d3286070c9c4db6d6487e119070794dadf493bd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2983,6 +2983,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n BlockPos blockposition1; if (flag1) { + // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.level.getChunkAt(this.level.getSpawn()); ++ this.level.getChunkAt(this.level.getSharedSpawnPos()); + // Paper end blockposition1 = ServerLevel.END_SPAWN_POINT; } else { - blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn()); + blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); diff --git a/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..adb34b3de2 --- /dev/null +++ b/patches/server/0364-Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 26 Jan 2020 16:30:19 -0600 +Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 + + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -143,7 +143,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public Bee(EntityType type, Level world) { + super(type, world); + this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); +- this.moveControl = new FlyingMoveControl(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ this.moveControl = new FlyingMoveControl(this, 20, true) { ++ @Override ++ public void tick() { ++ if (this.mob.getY() <= 0) { ++ this.mob.setNoGravity(false); ++ } ++ super.tick(); ++ } ++ }; ++ // Paper end + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 92% rename from patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch index 009a0fad66..5eea71802d 100644 --- a/patches/server-remapped/0405-Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ b/patches/server/0365-Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -7,10 +7,10 @@ bypass the need to get a player chunk, then get the either, then unwrap it... diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644 +index c47d1772044913475a60292162ef4be594bed4c6..7cbd3db81c73d466a6e6012c1c91698b53a0cb86 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource { +@@ -451,6 +451,12 @@ public class ServerChunkCache extends ChunkSource { return this.getChunk(x, z, leastStatus, create); }, this.mainThreadProcessor).join(); } else { @@ -23,7 +23,7 @@ index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f9 ProfilerFiller gameprofilerfiller = this.level.getProfiler(); gameprofilerfiller.incrementCounter("getChunk"); -@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -502,39 +508,7 @@ public class ServerChunkCache extends ChunkSource { if (Thread.currentThread() != this.mainThread) { return null; } else { diff --git a/patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch b/patches/server/0366-Allow-overriding-the-java-version-check.patch similarity index 76% rename from patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch rename to patches/server/0366-Allow-overriding-the-java-version-check.patch index 04082e9a36..983fc278c8 100644 --- a/patches/server-remapped/0406-Allow-overriding-the-java-version-check.patch +++ b/patches/server/0366-Allow-overriding-the-java-version-check.patch @@ -6,11 +6,11 @@ Subject: [PATCH] Allow overriding the java version check -DPaper.IgnoreJavaVersion=true diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644 +index f68d44721c91c20a7e4abffe26dabff8b5d2c3ce..fd48cfe3dfaf7c867becfbf90246af2f33a74612 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -181,7 +181,7 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); +@@ -185,7 +185,7 @@ public class Main { + } if (javaVersion > 60.0) { System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); - return; diff --git a/patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch b/patches/server/0367-Add-ThrownEggHatchEvent.patch similarity index 85% rename from patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch rename to patches/server/0367-Add-ThrownEggHatchEvent.patch index 5bc9d2e683..c026427598 100644 --- a/patches/server-remapped/0407-Add-ThrownEggHatchEvent.patch +++ b/patches/server/0367-Add-ThrownEggHatchEvent.patch @@ -7,10 +7,10 @@ Adds a new event similar to PlayerEggThrowEvent, but without the Player requirem (dispensers can throw eggs to hatch them, too). diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644 +index 4e083dcd07e5975c7379035e72ac2f3469e919fd..77941e3981e49cf5662b3e3c86a9c419080b17c8 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java -@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile { +@@ -77,6 +77,14 @@ public class ThrownEgg extends ThrowableItemProjectile { hatchingType = event.getHatchingType(); } @@ -22,8 +22,6 @@ index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c + hatching = event.isHatching(); + hatchingType = event.getHatchingType(); + // Paper end -+ -+ if (hatching) { for (int i = 0; i < b0; ++i) { - Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass()); + Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); diff --git a/patches/server-remapped/0408-Optimise-random-block-ticking.patch b/patches/server/0368-Optimise-random-block-ticking.patch similarity index 74% rename from patches/server-remapped/0408-Optimise-random-block-ticking.patch rename to patches/server/0368-Optimise-random-block-ticking.patch index 881f7be3f4..e6d451fad9 100644 --- a/patches/server-remapped/0408-Optimise-random-block-ticking.patch +++ b/patches/server/0368-Optimise-random-block-ticking.patch @@ -70,23 +70,11 @@ index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b3 + return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i { - return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z)); - } - -+ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER - public BlockPos.MutableBlockPos set(Vec3i pos) { - return this.set(pos.getX(), pos.getY(), pos.getZ()); - } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644 +index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f3fc84534 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -664,7 +664,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl }); } @@ -100,7 +88,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); -@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -672,10 +677,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); @@ -108,12 +96,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15)); -+ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper +- blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper +@@ -698,66 +703,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } gameprofilerfiller.popPush("iceandsnow"); @@ -129,7 +117,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + // Paper end Biome biomebase = this.getBiome(blockposition); -- if (biomebase.shouldFreeze(this, blockposition1)) { +- if (biomebase.shouldFreeze((LevelReader) this, blockposition1)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + // Paper start - optimise chunk ticking + blockposition.setY(downY); @@ -138,18 +126,24 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + // Paper end } -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.shouldSnow(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit - } + if (flag) { ++ blockposition.setY(normalY); // Paper + if (biomebase.shouldSnow(this, blockposition)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } -- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) { -- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) { -+ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition); -+ // Paper end +- BlockState iblockdata = this.getBlockState(blockposition1); ++ blockposition.setY(downY); // Paper ++ BlockState iblockdata = this.getBlockState(blockposition); // Paper + Biome.Precipitation biomebase_precipitation = this.getBiome(blockposition).getPrecipitation(); + +- if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition1)) { ++ if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition)) { // Paper + biomebase_precipitation = Biome.Precipitation.SNOW; + } + +- iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition1, biomebase_precipitation); ++ iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition, biomebase_precipitation); // Paper } } @@ -160,27 +154,27 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; +- +- for (int i1 = 0; i1 < l; ++i1) { +- LevelChunkSection chunksection = achunksection[i1]; + gameprofilerfiller.push("randomTick"); + timings.chunkTicksBlocks.startTiming(); // Paper -- for (int i1 = 0; i1 < l; ++i1) { -- LevelChunkSection chunksection = achunksection[i1]; -+ LevelChunkSection[] sections = chunk.getSections(); - - if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) { - int j1 = chunksection.bottomBlockY(); ++ LevelChunkSection[] sections = chunk.getSections(); + +- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { +- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); + for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { + LevelChunkSection section = sections[sectionIndex]; + if (section == null || section.tickingList.size() == 0) { + continue; + } -- for (int k1 = 0; k1 < randomTickSpeed; ++k1) { -- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - - gameprofilerfiller.push("randomTick"); -- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); +- BlockState iblockdata1 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); ++ int yPos = sectionIndex << 4; + for (int a = 0; a < randomTickSpeed1; ++a) { + int tickingBlocks = section.tickingList.size(); + int index = this.randomTickRandom.nextInt(16 * 16 * 16); @@ -188,8 +182,8 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + continue; + } -- if (iblockdata.isRandomlyTicking()) { -- iblockdata.randomTick(this, blockposition2, this.random); +- if (iblockdata1.isRandomlyTicking()) { +- iblockdata1.randomTick(this, blockposition2, this.random); - } + long raw = section.tickingList.getRaw(index); + int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); @@ -197,7 +191,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e + int randomY = ((location >>> (4 + 4)) & 255) | yPos; + int randomZ = (location >>> 4) & 15; -- FluidState fluid = iblockdata.getFluidState(); +- FluidState fluid = iblockdata1.getFluidState(); + BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); + BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); @@ -220,12 +214,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e - gameprofilerfiller.pop(); } - protected BlockPos findLightingTargetAround(BlockPos pos) { + private Optional findLightningRod(BlockPos pos) { diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644 +index 9b955a027bd2c3cbcfa659a41a6687221c5fea63..6c036335b28258cd8c268173d73707af00d12bf9 100644 --- a/src/main/java/net/minecraft/util/BitStorage.java +++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -112,4 +112,32 @@ public class BitStorage { +@@ -105,4 +105,32 @@ public class BitStorage { } } @@ -259,7 +253,7 @@ index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5 + // Paper end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644 +index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae083e2da95 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java @@ -91,7 +91,7 @@ public class Turtle extends Animal { @@ -272,10 +266,10 @@ index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7 public BlockPos getHomePos() { // Paper - public diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644 +index 07e81fa1119bba4981e34e70b9e67f43280f8071..5fccec12c0325dd9873905c5c3559128c3b4d9ad 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1299,10 +1299,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public abstract TagContainer getTagManager(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { @@ -296,27 +290,24 @@ index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6a public boolean noSave() { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644 +index 922026da8c234427e0322443004d3c32993adfce..88b053d8181d2a5abdb2c5527529a81855e1de7c 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess { - this.entities.remove(entity); // Paper - } +@@ -568,6 +568,7 @@ public class LevelChunk implements ChunkAccess { + @Override + public void addEntity(Entity entity) {} -- @Override -- public int getHeight(Heightmap.Types type, int x, int z) { + public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper + @Override + public int getHeight(Heightmap.Types type, int x, int z) { return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1; - } - diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644 +index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653ac986866b 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState; - public class LevelChunkSection { - +@@ -14,11 +14,12 @@ public class LevelChunkSection { + public static final int SECTION_HEIGHT = 16; + public static final int SECTION_SIZE = 4096; public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); - private final int bottomBlockY; + final int bottomBlockY; // Paper - private -> package-private @@ -325,15 +316,13 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 + short tickingBlockCount; // Paper - private -> package-private private short tickingFluidCount; final PalettedContainer states; // Paper - package-private - + public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) { -@@ -74,6 +76,9 @@ public class LevelChunkSection { + + public LevelChunkSection(int yOffset) { + this(yOffset, (short)0, (short)0, (short)0); +@@ -70,6 +71,9 @@ public class LevelChunkSection { --this.nonEmptyBlockCount; - if (iblockdata1.isRandomlyTicking()) { + if (blockState.isRandomlyTicking()) { --this.tickingBlockCount; + // Paper start + this.tickingList.remove(x, y, z); @@ -341,7 +330,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 } } -@@ -85,6 +90,9 @@ public class LevelChunkSection { +@@ -81,6 +85,9 @@ public class LevelChunkSection { ++this.nonEmptyBlockCount; if (state.isRandomlyTicking()) { ++this.tickingBlockCount; @@ -351,7 +340,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 } } -@@ -120,23 +128,29 @@ public class LevelChunkSection { +@@ -116,22 +123,28 @@ public class LevelChunkSection { } public void recalcBlockCounts() { @@ -361,36 +350,35 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7 this.nonEmptyBlockCount = 0; this.tickingBlockCount = 0; this.tickingFluidCount = 0; -- this.states.count((iblockdata, i) -> { -+ this.states.forEachLocation((iblockdata, location) -> { // Paper - FluidState fluid = iblockdata.getFluidState(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isRandomlyTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); +- this.states.count((state, count) -> { ++ this.states.forEachLocation((state, location) -> { // Paper + FluidState fluidState = state.getFluidState(); + if (!state.isAir()) { +- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count); ++ this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + 1); // Paper + if (state.isRandomlyTicking()) { +- this.tickingBlockCount = (short)(this.tickingBlockCount + count); + // Paper start -+ this.tickingList.add(location, iblockdata); ++ this.tickingBlockCount = (short)(this.tickingBlockCount + 1); ++ this.tickingList.add(location, state); + // Paper end } } - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.isRandomlyTicking()) { -- this.tickingFluidCount = (short) (this.tickingFluidCount + i); -+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); + if (!fluidState.isEmpty()) { +- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count); ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper + if (fluidState.isRandomlyTicking()) { +- this.tickingFluidCount = (short)(this.tickingFluidCount + count); ++ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); // Paper } } diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644 +index 5ea60bbb56450502f1ceb41959239ab579458ac2..5ac948b5b82f3144cdf402af440251cb8c7369d7 100644 --- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -285,6 +285,14 @@ public class PalettedContainer implements PaletteResize { +@@ -259,6 +259,14 @@ public class PalettedContainer implements PaletteResize { }); } @@ -404,4 +392,4 @@ index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b + @FunctionalInterface public interface CountConsumer { - + void accept(T object, int count); diff --git a/patches/server-remapped/0409-Entity-Jump-API.patch b/patches/server/0369-Entity-Jump-API.patch similarity index 87% rename from patches/server-remapped/0409-Entity-Jump-API.patch rename to patches/server/0369-Entity-Jump-API.patch index 15c22b27a5..9a22507440 100644 --- a/patches/server-remapped/0409-Entity-Jump-API.patch +++ b/patches/server/0369-Entity-Jump-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Entity Jump API diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644 +index bd1cc5e6fea4b9a171718c1249f652782b7ce13e..6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity { +@@ -3159,8 +3159,10 @@ public abstract class LivingEntity extends Entity { } else if (this.isInLava() && (!this.onGround || d7 > d8)) { this.jumpInLiquid((Tag) FluidTags.LAVA); } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { @@ -20,10 +20,10 @@ index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5 } else { this.noJumpDelay = 0; diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644 +index 2d59eab846db2c0a624cf6d06a570b2313aa6b13..851ee58e52c6003d6ae7b58c9b6b9a9a9795fa85 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Panda.java +++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java -@@ -489,7 +489,9 @@ public class Panda extends Animal { +@@ -514,7 +514,9 @@ public class Panda extends Animal { Panda entitypanda = (Panda) iterator.next(); if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { @@ -34,7 +34,7 @@ index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a8 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644 +index 5477f288db57d63051f4579b8cd3c19e3af430ee..76e9977f7b2f7fb50631fc56f3318d59d04b1398 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 58% rename from patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch index d66918d012..ede8b0de95 100644 --- a/patches/server-remapped/0410-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0370-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -5,24 +5,26 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644 +index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..e70e0b1115422b9b901c2879138433da2d4f94d8 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -594,4 +594,9 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); +@@ -441,6 +441,11 @@ public class PaperWorldConfig { log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } -+ + + public boolean nerfNetherPortalPigmen = false; + private void nerfNetherPortalPigmen() { + nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); + } - } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644 +index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9a04202a9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -307,6 +307,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public long activatedTick = Integer.MIN_VALUE; public boolean isTemporarilyActive = false; // Paper public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one @@ -30,42 +32,34 @@ index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa57 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1861,6 +1862,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); + nbt.putBoolean("Paper.FromMobSpawner", true); } + if (fromNetherPortal) { -+ tag.putBoolean("Paper.FromNetherPortal", true); ++ nbt.putBoolean("Paper.FromNetherPortal", true); + } // Paper end - return tag; + return nbt; } catch (Throwable throwable) { -@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -1999,6 +2003,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal"); - if (tag.contains("Paper.SpawnReason")) { - String spawnReasonName = tag.getString("Paper.SpawnReason"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = nbt.getBoolean("Paper.FromNetherPortal"); + if (nbt.contains("Paper.SpawnReason")) { + String spawnReasonName = nbt.getString("Paper.SpawnReason"); try { diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644 +index e34716f2a19eb578fef3f19182c124d359deb88f..cfea29f5bf1c5e74a0292c1344baaaa49c2f4403 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.MobSpawnType; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.level.BlockGetter; -@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block { +@@ -66,6 +66,8 @@ public class NetherPortalBlock extends Block { if (entity != null) { entity.setPortalCooldown(); + entity.fromNetherPortal = true; // Paper -+ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper ++ if (world.paperConfig.nerfNetherPortalPigmen) ((net.minecraft.world.entity.Mob) entity).aware = false; // Paper } } } diff --git a/patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch b/patches/server/0371-Make-the-GUI-graph-fancier.patch similarity index 80% rename from patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch rename to patches/server/0371-Make-the-GUI-graph-fancier.patch index c98d2918e6..202d52ab06 100644 --- a/patches/server-remapped/0411-Make-the-GUI-graph-fancier.patch +++ b/patches/server/0371-Make-the-GUI-graph-fancier.patch @@ -109,7 +109,7 @@ index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc +} diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java new file mode 100644 -index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2 +index 0000000000000000000000000000000000000000..537bc6213545e8ff1b7b51bc4b27fd5b2a740883 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java @@ -0,0 +1,41 @@ @@ -149,14 +149,14 @@ index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc + return new Dimension(350, 200); + } + -+ public void stop() { a(); } public void a() { ++ public void close() { + timer.stop(); + ramGraph.stop(); + } +} diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java new file mode 100644 -index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9 +index 0000000000000000000000000000000000000000..23239679d6584f1088b2b94c46eb9a5c1f9ad91d --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java @@ -0,0 +1,73 @@ @@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6 +import java.util.Vector; + +public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format) ++ public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format) + -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); + + private final MinecraftServer server; @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6 + Vector vector = new Vector<>(); + vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); + vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms"); + setListData(vector); + } + @@ -383,57 +383,16 @@ index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e21880 + timer.stop(); + } +} -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -259,6 +259,7 @@ public class Util { - return factory.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER - public static T make(T object, Consumer initializer) { - initializer.accept(object); - return object; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop collection = this.finalizers; // CraftBukkit - decompile error -- this.finalizers.add(guistatscomponent::close); -+ this.finalizers.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); - jpanel.add(this.buildPlayerPanel(), "Center"); - jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats")); -diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java -index 30960738de03edf7aa8745a176b3a2be86eaf282..09414d04208a843f8d337569b53f61b34e64ed92 100644 ---- a/src/main/java/net/minecraft/server/gui/StatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java -@@ -13,7 +13,7 @@ import net.minecraft.server.MinecraftServer; - - public class StatsComponent extends JComponent { - -- private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make((Object) (new DecimalFormat("########0.000")), (decimalformat) -> { -+ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] values = new int[256]; + Objects.requireNonNull(guistatscomponent); diff --git a/patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch similarity index 89% rename from patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch index e93352bf03..02e47511bf 100644 --- a/patches/server-remapped/0412-add-hand-to-BlockMultiPlaceEvent.patch +++ b/patches/server/0372-add-hand-to-BlockMultiPlaceEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add hand to BlockMultiPlaceEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644 +index c3341d1c4e9cda85b0b236461b0a00cbebc9a856..98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -337,13 +337,18 @@ public class CraftEventFactory { +@@ -339,13 +339,18 @@ public class CraftEventFactory { } org.bukkit.inventory.ItemStack item; diff --git a/patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch b/patches/server/0373-Prevent-teleporting-dead-entities.patch similarity index 67% rename from patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch rename to patches/server/0373-Prevent-teleporting-dead-entities.patch index ef6164bd27..59a60c41af 100644 --- a/patches/server-remapped/0413-Prevent-teleporting-dead-entities.patch +++ b/patches/server/0373-Prevent-teleporting-dead-entities.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Prevent teleporting dead entities diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644 +index 9240064a17e7ac2492fe157b759d1f724105cd0e..fcfd57fd7af655aafb330986e8f6f9cc55819165 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -1501,6 +1501,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.removed) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName()); + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set, boolean flag) { ++ if (player.isRemoved()) { ++ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); + return; + } // CraftBukkit start diff --git a/patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch b/patches/server/0374-Validate-tripwire-hook-placement-before-update.patch similarity index 85% rename from patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch rename to patches/server/0374-Validate-tripwire-hook-placement-before-update.patch index 8fbefb7aec..37fe80e7fc 100644 --- a/patches/server-remapped/0414-Validate-tripwire-hook-placement-before-update.patch +++ b/patches/server/0374-Validate-tripwire-hook-placement-before-update.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Validate tripwire hook placement before update diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644 +index 3a5252afa9681fb1956493bead27e6cdb13679ca..0cfa1abca2c5744a4147b05905983ae4acaa569a 100644 --- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java -@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block { +@@ -174,6 +174,7 @@ public class TripWireHookBlock extends Block { this.playSound(world, pos, flag4, flag5, flag2, flag3); if (!beingRemoved) { diff --git a/patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 85% rename from patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 163f5b9240..35a64d65e2 100644 --- a/patches/server-remapped/0415-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/0375-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644 +index e70e0b1115422b9b901c2879138433da2d4f94d8..19e0532ea296d6862ab6508658726e96e05346c9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,11 @@ public class PaperWorldConfig { +@@ -380,6 +380,11 @@ public class PaperWorldConfig { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } @@ -21,10 +21,10 @@ index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644 +index b5481299f551b7150425a4a1b1c21b43d8a1d382..ec00c2dd8f969eb99ec6a014e3bcd09c7484b237 100644 --- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -322,7 +322,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob { BlockPos blockposition1 = blockposition.below(); BlockState iblockdata = world.getBlockState(blockposition1); diff --git a/patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch similarity index 63% rename from patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch index 1bf93843e4..7c01b2f514 100644 --- a/patches/server-remapped/0416-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0376-Configurable-chance-of-villager-zombie-infection.patch @@ -8,37 +8,38 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644 +index 19e0532ea296d6862ab6508658726e96e05346c9..b57d9c84db5685b86cb077e3b42db7a8578d6f62 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -604,4 +604,9 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { +@@ -451,6 +451,11 @@ public class PaperWorldConfig { nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); } -+ + + public double zombieVillagerInfectionChance = -1.0; + private void zombieVillagerInfectionChance() { + zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + } - } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644 +index ee17cba501e0cc4822bd1278d18b561c77fe9674..b036cbb9a1b6bcac91ffc8ee659fc95d6e04d5d4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -447,10 +447,14 @@ public class Zombie extends Monster { +@@ -453,10 +453,13 @@ public class Zombie extends Monster { @Override - public void killed(ServerLevel worldserver, LivingEntity entityliving) { - super.killed(worldserver, entityliving); -- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) { -+ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + public void killed(ServerLevel world, LivingEntity other) { + super.killed(world, other); +- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { +- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { ++ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { return; } + if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { + return; + } // Paper end - Villager entityvillager = (Villager) entityliving; + Villager entityvillager = (Villager) other; // CraftBukkit start diff --git a/patches/server-remapped/0417-Optimise-Chunk-getFluid.patch b/patches/server/0377-Optimise-Chunk-getFluid.patch similarity index 58% rename from patches/server-remapped/0417-Optimise-Chunk-getFluid.patch rename to patches/server/0377-Optimise-Chunk-getFluid.patch index 2ba043c076..13d8263759 100644 --- a/patches/server-remapped/0417-Optimise-Chunk-getFluid.patch +++ b/patches/server/0377-Optimise-Chunk-getFluid.patch @@ -8,22 +8,24 @@ faster on its own, however removing the try catch makes it easier to inline due to code size diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644 +index 88b053d8181d2a5abdb2c5527529a81855e1de7c..59a77541bbda880ae8f84e3535a2b6112caa78fb 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess { +@@ -461,18 +461,20 @@ public class LevelChunk implements ChunkAccess { } public FluidState getFluidState(int x, int y, int z) { - try { -- if (y >= 0 && y >> 4 < this.sections.length) { -- LevelChunkSection chunksection = this.sections[y >> 4]; +- int l = this.getSectionIndex(y); +- +- if (l >= 0 && l < this.sections.length) { +- LevelChunkSection chunksection = this.sections[l]; - - if (!LevelChunkSection.isEmpty(chunksection)) { - return chunksection.getFluidState(x & 15, y & 15, z & 15); -+ //try { // Paper - remove try catch ++ // try { // Paper - remove try catch + // Paper start - reduce the number of ops in this call -+ int index = y >> 4; ++ int index = this.getSectionIndex(y); + if (index >= 0 && index < this.sections.length) { + LevelChunkSection chunksection = this.sections[index]; + @@ -34,17 +36,11 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783 } return Fluids.EMPTY.defaultFluidState(); -- } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); -- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); -+ /*} catch (Throwable throwable) { // Paper - remove try catch -+ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -- crashreportsystemdetails.setDetail("Location", () -> { -- return CrashReportCategory.formatLocation(x, y, z); -+ crashreportsystemdetails.a("Location", () -> { -+ return CrashReportSystemDetails.a(i, j, k); ++ /* // Paper - remove try catch + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); +@@ -482,6 +484,7 @@ public class LevelChunk implements ChunkAccess { }); throw new ReportedException(crashreport); } @@ -53,15 +49,15 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783 // CraftBukkit start diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644 +index b5497272bc03a290298b5a829bdf653ac986866b..fa350db3f4ada07a385d9f57b46aa799effb6039 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -45,7 +45,7 @@ public class LevelChunkSection { +@@ -42,7 +42,7 @@ public class LevelChunkSection { } public FluidState getFluidState(int x, int y, int z) { -- return ((BlockState) this.states.get(x, y, z)).getFluidState(); -+ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. +- return this.states.get(x, y, z).getFluidState(); ++ return this.states.get(x, y, z).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. } public void acquire() { diff --git a/patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch b/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch similarity index 66% rename from patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch index 6cf945010b..b5d38ff419 100644 --- a/patches/server-remapped/0418-Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/0378-Optimise-TickListServer-by-rewriting-it.patch @@ -61,7 +61,7 @@ index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f ConfigurationSection section; diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java new file mode 100644 -index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b +index 0000000000000000000000000000000000000000..da13ff17609b7bc8076d9297edf8decf01a2ed88 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java @@ -0,0 +1,628 @@ @@ -168,7 +168,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { + if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(entry.pos)) { + this.toTickThisTick.add(entry); + entry.tickState = STATE_PENDING_TICK; + } else { @@ -179,13 +179,13 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + private void addToNotTickingReady(final TickNextTickData entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (long keyInMap) -> { + return new ArrayList<>(); + }).add(entry); + } + + private void addToSchedule(final TickNextTickData entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ long delay = entry.triggerTick - (this.currentTick + 1); + if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { + if (delay < 0) { + // longScheduled orders by tick time, short scheduled does not @@ -202,7 +202,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + entry.tickState = STATE_CANCELLED_TICK; + // short/long scheduled will skip the entry + -+ final BlockPos pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -246,7 +246,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ long delay = entry.triggerTick - (this.currentTick + 1); + if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { + this.longScheduled.remove(entry); + } @@ -274,7 +274,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of + // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().triggerTick > currentTick) { + // nothing in longScheduled to worry about + final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; + for (int i = 0, len = interval.byPriority.length; i < len; ++i) { @@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + longScheduledIterator.remove(); + if (longScheduledIterator.hasNext()) { + longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent.triggerTick > currentTick) { + longCurrent = null; + break; + } @@ -316,7 +316,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + // add remaining from long scheduled + for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent == null || longCurrent.triggerTick > currentTick) { + break; + } + longScheduledIterator.remove(); @@ -368,7 +368,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + continue; + } + try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(toTick.pos)) { + toTick.tickState = STATE_TICKING; + this.tickFunction.accept(toTick); + if (toTick.tickState == STATE_TICKING) { @@ -384,7 +384,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); + -+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.world, toTick.pos, (BlockState) null); + throw new ReportedException(crashreport); + // end copy from TickListServer + } @@ -413,7 +413,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + entry.tickState = STATE_UNSCHEDULED; + -+ final BlockPos pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); @@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -446,7 +446,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { ++ public boolean willTickThisTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -455,7 +455,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { ++ if (entry.getType() == data && entry.tickState == STATE_PENDING_TICK) { + return true; + } + } @@ -464,7 +464,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { ++ public boolean hasScheduledTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -473,7 +473,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { ++ if (entry.getType() == data && entry.tickState == STATE_SCHEDULED) { + return true; + } + } @@ -482,22 +482,22 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { ++ public void scheduleTick(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) { + this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); + } + + public void schedule(final TickNextTickData entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); ++ this.schedule(entry.pos, entry.getType(), entry.triggerTick, entry.priority); + } + + public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { + final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { ++ if (this.excludeFromScheduling.test(entry.getType())) { + return; + } + + if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; ++ final long delay = entry.triggerTick - this.currentTick; + if (delay >= EXCESSIVE_DELAY_THRESHOLD) { + MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); + } @@ -514,7 +514,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + final TickNextTickData currentEntry = currentEntries.get(i); + + // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { ++ if (currentEntry.getType() == entry.getType() && currentEntry.tickState == STATE_SCHEDULED) { + // can't add + return; + } @@ -524,7 +524,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + + entry.tickState = STATE_SCHEDULED; + -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (final long keyInMap) -> { + return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); + }).add(entry); + @@ -541,19 +541,19 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + // i.e the y value is ignored? the x, z calc isn't correct? + // however for the copy op they use the correct intersection, after using this one of course... + private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); ++ return pos.getX() >= boundingBox.minX() && pos.getX() < boundingBox.maxX() && pos.getZ() >= boundingBox.minZ() && pos.getZ() < boundingBox.maxZ(); + } + + @Override -+ public List> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ public List> fetchTicksInArea(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.minX() == structureboundingbox.maxX() || structureboundingbox.minZ() == structureboundingbox.maxZ()) { + return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above + } + -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive ++ final int lowerChunkX = structureboundingbox.minX() >> 4; ++ final int upperChunkX = (structureboundingbox.maxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.minZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.maxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive + + final int xChunksLength = (upperChunkX - lowerChunkX + 1); + final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); @@ -579,7 +579,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); + + MCUtil.mergeSortedSets((TickNextTickData entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ if (!isBlockInSortof(structureboundingbox, entry.pos)) { + return; + } + final int tickState = entry.tickState; @@ -603,24 +603,24 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + @Override + public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); + Iterator> iterator = list.iterator(); + + while (iterator.hasNext()) { + TickNextTickData nextticklistentry = iterator.next(); + -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); ++ if (structureboundingbox.isInside( nextticklistentry.pos)) { ++ BlockPos blockposition1 = nextticklistentry.pos.offset(blockposition); ++ T t0 = nextticklistentry.getType(); + -+ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); + } + } + // end copy from TickListServer + } + + @Override -+ public List> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { ++ public List> fetchTicksInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { + // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks + // not at ticking status, and ticking status requires neighbours loaded + // so with this method we will reduce scheduler churning @@ -651,16 +651,16 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 + } + + @Override -+ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ public ListTag save(ChunkPos chunkcoordintpair) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); + -+ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ return ServerTickList.saveTickList(this.getMinecraftKeyFrom, list, this.currentTick); + // end copy from TickListServer + } + + @Override -+ public int getTotalScheduledEntries() { ++ public int size() { + // good thing this is only used in debug reports // TODO check on update + int ret = 0; + @@ -695,7 +695,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2 +} diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java new file mode 100644 -index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c +index 0000000000000000000000000000000000000000..a1e6f49274a7ae8057a9112e0dd6597a8e58e6da --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java @@ -0,0 +1,41 @@ @@ -713,7 +713,7 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972 + public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { + return Long.compare(entry1.getId(), entry2.getId()); + }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.createTimeComparator(); + + // we do not record the interval, this class is meant to be used on a ring buffer + @@ -727,11 +727,11 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972 + } + + public void addEntryLast(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ this.byPriority[entry.priority.ordinal()].addLast(entry); + } + + public void addEntryFirst(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ this.byPriority[entry.priority.ordinal()].addFirst(entry); + } + + public void clear() { @@ -888,64 +888,63 @@ index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f + } + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i { - return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); - } - -+ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER - public BlockPos offset(Vec3i pos) { - return this.offset(pos.getX(), pos.getY(), pos.getZ()); - } diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644 +index 995d7977233f0d7683c00a75c3833f9a1eba7f92..58369d70bcd8b2c25609b6f101d9cbe2031df352 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -495,7 +495,9 @@ public class ChunkHolder { +@@ -86,6 +86,19 @@ public class ChunkHolder { + return null; + } + // Paper end - no-tick view distance ++ // Paper start ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; ++ } ++ // Paper end + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -547,6 +560,10 @@ public class ChunkHolder { + either.ifLeft(chunk -> { + // note: Here is a very good place to add callbacks to logic waiting on this. ChunkHolder.this.isTickingReady = true; - - -- ++ + // Paper start - rewrite ticklistserver + ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); + // Paper end - rewrite ticklistserver - - } + }); }); + // Paper end diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644 +index 7cbd3db81c73d466a6e6012c1c91698b53a0cb86..382a68c76e8946840de62f05483870689de80278 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -21,6 +21,7 @@ import net.minecraft.Util; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.ChunkProgressListener; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; -@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource { +@@ -220,6 +220,12 @@ public class ServerChunkCache extends ChunkSource { + }, this.mainThreadProcessor); } // Paper end - + // Paper start - rewrite ticklistserver + public final boolean isTickingReadyMainThread(BlockPos pos) { -+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos)); ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(net.minecraft.server.MCUtil.getCoordinateKey(pos)); + return chunk != null && chunk.isTickingReady(); + } + // Paper end - rewrite ticklistserver -+ - public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier supplier) { - this.level = worldserver; - this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver); + + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { + this.level = world; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644 +index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719ce93aecf3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -286,6 +286,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // Paper end @@ -960,273 +959,127 @@ index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f0 + // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); - // CraftBukkit end -- this.blockTicks = new ServerTickList<>(this, (block) -> { -- return block == null || block.defaultBlockState().isAir(); -- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == Fluids.EMPTY; -- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +@@ -302,13 +311,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + DefaultedRegistry registryblocks = Registry.BLOCK; + + Objects.requireNonNull(registryblocks); +- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings ++ // this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings // Paper - copied down + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error + return fluidtype == null || fluidtype == Fluids.EMPTY; + }; + registryblocks = Registry.FLUID; + Objects.requireNonNull(registryblocks); + if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper timings + } else { -+ this.blockTicks = new ServerTickList<>(this, (block) -> { -+ return block == null || block.defaultBlockState().isAir(); -+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings -+ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == Fluids.EMPTY; -+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings ++ this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings & copied from above + this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // Paper - Timings + } - this.navigations = Sets.newHashSet(); + this.navigatingMobs = new ObjectOpenHashSet(); this.blockEvents = new ObjectLinkedOpenHashSet(); - this.tickTime = flag1; -@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -629,7 +644,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl if (this.tickTime) { long i = this.levelData.getGameTime() + 1L; -- this.worldDataServer.setGameTime(i); -+ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this +- this.serverLevelData.setGameTime(i); ++ this.serverLevelData.setGameTime(i); ; // Paper - diff on change, we want the below to be ran right after this + this.blockTicks.nextTick(); // Paper + this.liquidTicks.nextTick(); // Paper - this.worldDataServer.getScheduledEvents().tick(this.server, i); + this.serverLevelData.getScheduledEvents().tick(this.server, i); if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { this.setDayTime(this.levelData.getDayTime() + 1L); diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java -index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644 +index 1a05edf041cf4aeee7c165fec564ce45adbdd5c7..febc837d324cbe2cd83aea6c1e0d298c70f45f78 100644 --- a/src/main/java/net/minecraft/world/level/ChunkTickList.java +++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java -@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MinecraftServer; +@@ -15,7 +15,7 @@ public class ChunkTickList implements TickList { - public class ChunkTickList implements TickList { + public ChunkTickList(Function identifierProvider, List> scheduledTicks, long startTime) { + this(identifierProvider, scheduledTicks.stream().map((tickNextTickData) -> { +- return new ChunkTickList.ScheduledTick(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); ++ return new ChunkTickList.ScheduledTick<>(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); // Paper - decompile error + }).collect(Collectors.toList())); + } -@@ -61,6 +62,8 @@ public class ChunkTickList implements TickList { - return nbttaglist; +@@ -56,6 +56,7 @@ public class ChunkTickList implements TickList { + return listTag; } + private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static ChunkTickList create(ListTag ticks, Function function, Function function1) { + public static ChunkTickList create(ListTag ticks, Function function, Function function2) { List> list = Lists.newArrayList(); -@@ -71,7 +74,14 @@ public class ChunkTickList implements TickList { - if (t0 != null) { - BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p")))); +@@ -64,7 +65,14 @@ public class ChunkTickList implements TickList { + T object = function2.apply(new ResourceLocation(compoundTag.getString("i"))); + if (object != null) { + BlockPos blockPos = new BlockPos(compoundTag.getInt("x"), compoundTag.getInt("y"), compoundTag.getInt("z")); +- list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, compoundTag.getInt("t"), TickPriority.byValue(compoundTag.getInt("p")))); + // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); ++ int delay = compoundTag.getInt("t"); + if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ net.minecraft.server.MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockPos + ", tick delay " + delay); + continue; + } -+ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p")))); + // Paper end - clean up broken entries ++ list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, delay, TickPriority.byValue(compoundTag.getInt("p")))); } } diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java -index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644 +index 702203f4a4fa4fc03c35ec974a97e08ed0f3c67c..609c8ece9e9f151875bf8191cc671206ee1e5f68 100644 --- a/src/main/java/net/minecraft/world/level/ServerTickList.java +++ b/src/main/java/net/minecraft/world/level/ServerTickList.java -@@ -50,7 +50,16 @@ public class ServerTickList implements TickList { +@@ -49,6 +49,9 @@ public class ServerTickList implements TickList { private final co.aikar.timings.Timing timingTicking; // Paper // Paper end + // Paper start + public void nextTick() {} + // Paper end -+ -+ public void tick() { -+ // Paper start - allow overriding -+ this.tick(); -+ } public void tick() { -+ // Paper end int i = this.tickNextTickList.size(); - if (false) { // CraftBukkit -@@ -118,28 +127,43 @@ public class ServerTickList implements TickList { - - @Override - public boolean willTickThisTick(BlockPos pos, T object) { -- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(pos, object); -+ } -+ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0)); +@@ -190,7 +193,7 @@ public class ServerTickList implements TickList { + return ServerTickList.saveTickList(this.toId, list, this.level.getGameTime()); } - public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); -+ } -+ public List> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; - int l = k + 16 + 2; - -- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks); -+ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1); - } - - public List> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { -- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); -+ } -+ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end -+ List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag); - -- if (updateState && list != null) { -+ if (flag && list != null) { - this.tickNextTickSet.removeAll(list); - } - -- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState); -- if (!getStaleTicks) { -- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState); -+ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag); -+ if (!flag1) { -+ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag); - } - - return list == null ? Collections.emptyList() : list; -@@ -170,14 +194,19 @@ public class ServerTickList implements TickList { - } - - public void copy(BoundingBox box, BlockPos offset) { -- List> list = this.fetchTicksInArea(box, false, false); -+ // Paper start - allow overriding -+ this.copy(box, offset); -+ } -+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { -+ // Paper end -+ List> list = this.fetchTicksInArea(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - TickNextTickData nextticklistentry = (TickNextTickData) iterator.next(); - -- if (box.isInside((Vec3i) nextticklistentry.pos)) { -- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset); -+ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) { -+ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition); - T t0 = nextticklistentry.getType(); - - this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); -@@ -187,11 +216,17 @@ public class ServerTickList implements TickList { - } - - public ListTag save(ChunkPos chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public ListTag serialize(ChunkPos chunkcoordintpair) { -+ // Paper end - List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); - - return saveTickList(this.toId, list, this.level.getGameTime()); - } - -+ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER - private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { +- private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { ++ public static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { // Paper - private -> public ListTag nbttaglist = new ListTag(); Iterator iterator = scheduledTicks.iterator(); -@@ -214,13 +249,23 @@ public class ServerTickList implements TickList { - @Override - public boolean hasScheduledTick(BlockPos pos, T object) { -- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object)); -+ // Paper start - allow overriding -+ return this.isScheduledForTick(pos, object); -+ } -+ public boolean isScheduledForTick(BlockPos blockposition, T t0) { -+ // Paper end -+ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0)); - } - - @Override - public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) { -- if (!this.ignore.test(object)) { -- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority)); -+ // Paper start - allow overriding -+ this.schedule(pos, object, delay, priority); -+ } -+ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) { -+ // Paper end -+ if (!this.ignore.test(t0)) { -+ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority)); - } - - } -@@ -234,6 +279,11 @@ public class ServerTickList implements TickList { - } - - public int size() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.tickNextTickSet.size(); - } - } diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644 +index 3b8c04f6ffd7e6c197465aa1caf633ba92529472..6b4b7c290b623a9821734ef74a2e566343e3c5bd 100644 --- a/src/main/java/net/minecraft/world/level/TickNextTickData.java +++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos; - public class TickNextTickData { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T type; -- public final BlockPos pos; -- public final long triggerTick; -- public final TickPriority priority; +@@ -9,7 +9,9 @@ public class TickNextTickData { + public final BlockPos pos; + public final long triggerTick; + public final TickPriority priority; - private final long c; -+ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER -+ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER -+ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER -+ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER + private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER + private final int hash; // Paper + public int tickState; // Paper public TickNextTickData(BlockPos pos, T t) { this(pos, t, 0L, TickPriority.NORMAL); -@@ -22,6 +24,7 @@ public class TickNextTickData { +@@ -21,6 +23,7 @@ public class TickNextTickData { this.type = t; this.triggerTick = time; this.priority = priority; + this.hash = this.computeHash(); // Paper } - public boolean equals(Object object) { -@@ -34,19 +37,31 @@ public class TickNextTickData { - } - } + @Override +@@ -35,17 +38,27 @@ public class TickNextTickData { -+ // Paper start - optimize hashcode -+ @Override + @Override public int hashCode() { ++ // Paper start - optimize hashcode + return this.hash; + } + public final int computeHash() { @@ -1234,68 +1087,26 @@ index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6 return this.pos.hashCode(); } -- public static Comparator createTimeComparator() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix + public static Comparator> createTimeComparator() { +- return Comparator.>comparingLong((tickNextTickData) -> { // Paper - decompile fix +- return tickNextTickData.triggerTick; +- }).thenComparing((tickNextTickData) -> { +- return tickNextTickData.priority; +- }).thenComparingLong((tickNextTickData) -> { +- return tickNextTickData.c; - }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER -+ public static Comparator createTimeComparator() { -+ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ // Paper start - let's not use more functional code for no reason. ++ return (Comparator) (Comparator) (TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.triggerTick, nextticklistentry1.triggerTick); + + if (i != 0) { + return i; + } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); ++ i = nextticklistentry.priority.compareTo(nextticklistentry1.priority); + return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); + } + }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java -@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag; - - public class BoundingBox { - -- public int x0; -- public int y0; -- public int z0; -- public int x1; -- public int y1; -- public int z1; -+ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER -+ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER -+ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER -+ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER -+ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER -+ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER - - public BoundingBox() {} - -@@ -92,6 +92,7 @@ public class BoundingBox { - this.y1 = 512; ++ // Paper end - let's not use more functional code for no reason. } -+ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER - public boolean intersects(BoundingBox other) { - return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1; - } -@@ -126,6 +127,7 @@ public class BoundingBox { - this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER - public boolean isInside(Vec3i vec) { - return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1; - } + @Override diff --git a/patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 85% rename from patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch index 6e0269c7f2..ff68539cdb 100644 --- a/patches/server-remapped/0419-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0379-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per world and the world age for the start day. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644 +index b57d9c84db5685b86cb077e3b42db7a8578d6f62..9664786d471b949880030f5c6271bf9c12529326 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -582,10 +582,21 @@ public class PaperWorldConfig { +@@ -428,10 +428,21 @@ public class PaperWorldConfig { } public boolean disablePillagerPatrols = false; @@ -36,10 +36,10 @@ index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644 +index bffc897cb88a54c36432c98264f3416051aeab17..5b5a0c0db79452ee07c40bf7693b6701dbe0b615 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -219,6 +219,7 @@ public class ServerPlayer extends Player { public boolean wonGame; private int containerUpdateDelay; // Paper public long loginTime; // Paper @@ -47,20 +47,8 @@ index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b244 // Paper start - cancellable death event public boolean queueHealthUpdatePacket = false; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java -index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644 ---- a/src/main/java/net/minecraft/stats/StatType.java -+++ b/src/main/java/net/minecraft/stats/StatType.java -@@ -28,6 +28,7 @@ public class StatType implements Iterable> { - return this.map.values().iterator(); - } - -+ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER - public Stat get(T key) { - return this.get(key, StatFormatter.DEFAULT); - } diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644 +index 744b58d59a5f34ed3bd6f2d4a0f876acfa6a7135..d75a04e7a70b7fb2527fdd7d1a45a101d064824f 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -4,11 +4,12 @@ import java.util.Random; @@ -127,7 +115,7 @@ index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef54 + } else { + long days; + if (world.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang + } else { + days = world.getDayTime() / 24000L; + } diff --git a/patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 86% rename from patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch index a83d559354..64931753ef 100644 --- a/patches/server-remapped/0422-Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ b/patches/server/0380-Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Remote Connections shouldn't hold up shutdown Bugs in the connection logic appears to leave stale connections even, preventing shutdown diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644 +index 6f9b7c3cf22d0c44f31b81bcbfa3cb1f8c065083..0511f1921193b78cbf4d8426136bf1f79746f955 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -439,11 +439,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } if (this.rconThread != null) { diff --git a/patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 85% rename from patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch index 044507e1b4..bbc752cdd0 100644 --- a/patches/server-remapped/0423-Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ b/patches/server/0381-Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not allow bees to load chunks for beehives diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644 +index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda2d1f20aa 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -404,6 +404,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { if (this.hivePos == null) { return false; } else { @@ -16,7 +16,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); -@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -436,6 +437,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { } private boolean doesHiveHaveSpace(BlockPos pos) { @@ -24,7 +24,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = this.level.getBlockEntity(pos); return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; -@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -909,6 +911,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { @@ -32,7 +32,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9 BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); if (tileentity instanceof BeehiveBlockEntity) { -@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -932,6 +935,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public void start() { diff --git a/patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 62% rename from patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 720e9dcff9..60f46ed4f2 100644 --- a/patches/server-remapped/0424-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/0382-Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding Stack will identify any causer of this and warn instead of crashing. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644 +index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..d06c6828180b7864bf4d3736a65ea0a2dc7804e2 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1445,6 +1445,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider protected void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot @@ -26,23 +26,23 @@ index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe62379 EntityType entitytypes = entity.getType(); int i = entitytypes.clientTrackingRange() * 16; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644 +index 385b8e707406173ea5258aff87af719ce93aecf3..5944c44eadca550671d7740af5756985afede39d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } +@@ -2100,7 +2100,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void onTrackingStart(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot +- ServerLevel.this.getChunkSource().addEntity(entity); ++ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true + if (entity instanceof ServerPlayer) { + ServerLevel.this.players.add((ServerPlayer) entity); + ServerLevel.this.updateSleepingPlayerList(); +@@ -2122,6 +2122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } -- this.getChunkSource().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof Drowned) { - this.navigations.add(((Drowned) entity).waterNavigation); -@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.navigations.add(((Mob) entity).getNavigation()); - } entity.valid = true; // CraftBukkit -+ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); ++ ServerLevel.this.getChunkSource().addEntity(entity); + } + + public void onTrackingEnd(Entity entity) { diff --git a/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch b/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..d2e15c6828 --- /dev/null +++ b/patches/server/0383-Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 2 Apr 2020 02:37:57 -0400 +Subject: [PATCH] Optimize Collision to not load chunks + +The collision code takes an AABB and generates a cuboid of checks rather +than a cylinder, so at high velocity this can generate a lot of chunk checks. + +Treat an unloaded chunk as a collision for entities, and also for players if +the "prevent moving into unloaded chunks" setting is enabled. + +If that serting is not enabled, collisions will be ignored for players, since +movement will load only the chunk the player enters anyways and avoids loading +massive amounts of surrounding chunks due to large AABB lookups. + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 2730923bd0bf3b0f928765b9e09e2299fa9a393d..f98a1c32e0c209473cf7268cbd8245ab9c134d28 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -783,6 +783,7 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ 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(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index facb09e49d92d22dbcde7d187d4ba1c9a04202a9..85c0656ee8c91cab1e269daea631977c4284295f 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -172,6 +172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper ++ public boolean collisionLoadChunks = false; // Paper + private CraftEntity bukkitEntity; + + public CraftEntity getBukkitEntity() { +diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java +index b980c26ab5cac02e03525177a9dc4fb0b6a2f9f6..2a784a8342e708e0813c7076a2ca8e429446ffd3 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java ++++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java +@@ -55,7 +55,9 @@ public interface CollisionGetter extends BlockGetter { + } + + default boolean noCollision(@Nullable Entity entity, AABB box, Predicate filter) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.getCollisions(entity, box, filter).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream getEntityCollisions(@Nullable Entity entity, AABB box, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index e6190bfb893de12e87e1da49001ebd963b3d6318..90039d01ef481ba206f2e952c99a755e94201ea3 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -21,13 +21,13 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public class CollisionSpliterator extends AbstractSpliterator { + @Nullable +- private final Entity source; ++ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER + private final AABB box; + private final CollisionContext context; + private final Cursor3D cursor; +- private final BlockPos.MutableBlockPos pos; ++ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER + private final VoxelShape entityShape; +- private final CollisionGetter collisionGetter; ++ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER + private boolean needsBorderCheck; + private final BiPredicate predicate; + +@@ -64,21 +64,37 @@ public class CollisionSpliterator extends AbstractSpliterator { + boolean collisionCheck(Consumer action) { + while(true) { + if (this.cursor.advance()) { +- int i = this.cursor.nextX(); +- int j = this.cursor.nextY(); +- int k = this.cursor.nextZ(); ++ int i = this.cursor.nextX(); final int x = i; ++ int j = this.cursor.nextY(); final int y = j; ++ int k = this.cursor.nextZ(); final int z = k; + int l = this.cursor.getNextType(); + if (l == 3) { + continue; + } + +- BlockGetter blockGetter = this.getChunk(i, k); +- if (blockGetter == null) { ++ // Paper start - ensure we don't load chunks ++ Entity entity = this.getEntity(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos(); ++ boolean far = entity != null && net.minecraft.server.MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; ++ blockposition_mutableblockposition.setValues(x, y, z); ++ ++ boolean isRegionLimited = this.getCollisionAccess() instanceof net.minecraft.server.level.WorldGenRegion; ++ BlockState blockState = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof net.minecraft.server.level.ServerPlayer) || (entity != null && entity.collisionLoadChunks) ++ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition) ++ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) ++ ); ++ ++ if (blockState == null) { ++ if (!(entity instanceof net.minecraft.server.level.ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = Shapes.create(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z))); ++ action.accept(voxelshape3); ++ return true; ++ } + continue; + } ++ // Paper - moved up ++ // Paper end + +- this.pos.set(i, j, k); +- BlockState blockState = blockGetter.getBlockState(this.pos); + if (!this.predicate.test(blockState, this.pos) || l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) { + continue; + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 5d4d953f197afc402248ab73daeb6ef59134f48f..95428f13dae909bb7de552aa65e4256bd4049c65 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -238,7 +238,8 @@ public final class Shapes { + + if (s < 3) { + mutableBlockPos.set(axisCycle, q, r, p); +- BlockState blockState = world.getBlockState(mutableBlockPos); ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper ++ if (blockState == null) return 0.0D; // Paper + if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { + initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { diff --git a/patches/server-remapped/0426-Don-t-tick-dead-players.patch b/patches/server/0384-Don-t-tick-dead-players.patch similarity index 59% rename from patches/server-remapped/0426-Don-t-tick-dead-players.patch rename to patches/server/0384-Don-t-tick-dead-players.patch index b748ace1a1..d831e3b2b6 100644 --- a/patches/server-remapped/0426-Don-t-tick-dead-players.patch +++ b/patches/server/0384-Don-t-tick-dead-players.patch @@ -7,15 +7,15 @@ Causes sync chunk loads and who knows what all else. This is safe because Spectators are skipped in unloaded chunks too in vanilla. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644 +index 5b5a0c0db79452ee07c40bf7693b6701dbe0b615..2822d493500dcd01c26ff5b205da83d8d356e119 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -637,7 +637,7 @@ public class ServerPlayer extends Player { public void doTick() { try { -- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { -+ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) +- if (!this.isSpectator() || !this.touchingUnloadedChunk()) { ++ if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn) super.tick(); } diff --git a/patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 70% rename from patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch index 3e2b8e5352..51a1431c6c 100644 --- a/patches/server-remapped/0427-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ b/patches/server/0385-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -7,15 +7,15 @@ This fixes a lot of game state issues where packets were delayed for processing due to 1.15's new queue but processed while dead. diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644 +index 4c9261c68518ab7429325f0366dfb2930663288c..a3d31cec6d1b8de700b6cd2f7f51398debef5b6d 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity { +@@ -1106,7 +1106,7 @@ public abstract class Player extends LivingEntity { @Override protected boolean isImmobile() { - return super.isImmobile() || this.isSleeping(); -+ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move... ++ return super.isImmobile() || this.isSleeping() || this.isRemoved() || !valid; // Paper - player's who are dead or not in a world shouldn't move... } @Override diff --git a/patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 84% rename from patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index a211d40a2c..71138d1089 100644 --- a/patches/server-remapped/0428-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/0386-Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -57,10 +57,10 @@ index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e + } +} diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644 +index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb9973299b723 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -616,7 +616,7 @@ public final class MCUtil { +@@ -614,7 +614,7 @@ public final class MCUtil { ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ChunkMap chunkMap = world.getChunkSource().chunkMap; @@ -70,15 +70,13 @@ index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d0 List allChunks = new ArrayList<>(visibleChunks.values()); List players = world.players; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644 +index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb30a7e112e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - private static final Logger LOGGER = LogManager.getLogger(); +@@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private static final int MIN_VIEW_DISTANCE = 3; + public static final int MAX_VIEW_DISTANCE = 33; public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); -- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + // Paper start - faster copying + public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying + public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying @@ -106,19 +104,24 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 + // Paper end + public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only + public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed + public static final int FORCED_TICKET_LEVEL = 31; +- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up ++ // public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; // Paper - moved up private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; // Paper - private -> public public final ServerLevel level; -@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -231,7 +258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag); + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { + super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); - this.visibleChunkMap = this.updatingChunkMap.clone(); + //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); this.entitiesInLevel = new LongOpenHashSet(); this.toDrop = new LongOpenHashSet(); -@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -350,9 +377,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return (ChunkHolder) this.updatingChunkMap.get(pos); } @@ -159,7 +162,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 + // Paper end + @Nullable - public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public + public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public - return (ChunkHolder) this.visibleChunkMap.get(pos); + // Paper start - mt safe get + if (Thread.currentThread() != this.level.thread) { @@ -172,8 +175,8 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 } protected IntSupplier getChunkQueueLevel(long pos) { -@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end +@@ -509,8 +579,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } protected void saveAllChunks(boolean flush) { + Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) @@ -183,7 +186,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 MutableBoolean mutableboolean = new MutableBoolean(); do { -@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -541,7 +612,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // this.i(); // Paper - nuke IOWorker ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { @@ -192,7 +195,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { -@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -701,7 +772,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.modified) { return false; } else { @@ -214,7 +217,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 this.modified = false; return true; } -@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1110,12 +1194,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected Iterable getChunks() { @@ -223,17 +226,17 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081 } void dumpChunks(Writer writer) throws IOException { - CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer); + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").build(writer); - ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); + ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper while (objectbidirectionaliterator.hasNext()) { Entry entry = (Entry) objectbidirectionaliterator.next(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644 +index 382a68c76e8946840de62f05483870689de80278..8523fbd66ed42cd5b959d57cab515fa4a774a575 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -751,7 +751,7 @@ public class ServerChunkCache extends ChunkSource { }; // Paper end this.level.timings.chunkTicks.startTiming(); // Paper @@ -243,41 +246,43 @@ index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46 if (optional.isPresent()) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644 +index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3986f1250 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -276,6 +276,7 @@ public class CraftWorld implements World { - return ret; - } +@@ -286,6 +286,7 @@ public class CraftWorld implements World { + + @Override public int getTileEntityCount() { + return net.minecraft.server.MCUtil.ensureMain(() -> { // We don't use the full world tile entity list, so we must iterate chunks Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; int size = 0; -@@ -287,11 +288,13 @@ public class CraftWorld implements World { +@@ -297,6 +298,7 @@ public class CraftWorld implements World { size += chunk.blockEntities.size(); } return size; + }); } - public int getTickableTileEntityCount() { - return world.tickableBlockEntities.size(); - } + + @Override +@@ -306,6 +308,7 @@ public class CraftWorld implements World { + + @Override public int getChunkCount() { + return net.minecraft.server.MCUtil.ensureMain(() -> { int ret = 0; for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -@@ -300,7 +303,7 @@ public class CraftWorld implements World { +@@ -314,7 +317,7 @@ public class CraftWorld implements World { } } - return ret; + return ret; }); } - public int getPlayerCount() { - return world.players.size(); -@@ -425,6 +428,14 @@ public class CraftWorld implements World { + + @Override +@@ -441,6 +444,14 @@ public class CraftWorld implements World { @Override public Chunk[] getLoadedChunks() { @@ -289,6 +294,6 @@ index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918a + } + } + // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + Long2ObjectLinkedOpenHashMap chunks = this.world.getChunkSource().chunkMap.visibleChunkMap; return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); } diff --git a/patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 79% rename from patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index b0f42e94cc..395f0c27cf 100644 --- a/patches/server-remapped/0430-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/0387-Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -30,10 +30,10 @@ In a view distance of 15, chunk loading performance was visually faster on the c Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644 +index 72f9e1978394afb6e5cc1c0d085d41586d69b84e..aa0698508de8fba6e84c20ac4d3aebb99a075c25 100644 --- a/src/main/java/co/aikar/timings/MinecraftTimings.java +++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -17,6 +17,7 @@ import java.util.Map; +@@ -16,6 +16,7 @@ import java.util.Map; public final class MinecraftTimings { public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); @@ -56,18 +56,18 @@ index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85 + } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644 +index 494a3afaaa0e3496d30e8d97edbab62b21610dfe..fa3a9d763f7072c68b126ce95fee191aab576e43 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { @@ -108,10 +108,10 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b return !this.canOversleep(); }); isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); if (optional.isPresent()) { -@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource { - //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.level.tickChunk(chunk, k); - //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper +@@ -768,6 +770,7 @@ public class ServerChunkCache extends ChunkSource { + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); + if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper } - } - } -@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource { + + // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper +@@ -935,6 +938,41 @@ public class ServerChunkCache extends ChunkSource { super.doRunTask(task); } @@ -210,7 +202,7 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079 + return false; + } + public void midTickLoadChunks() { -+ MinecraftServer server = ServerChunkCache.this.level.getServer(); ++ net.minecraft.server.MinecraftServer server = ServerChunkCache.this.level.getServer(); + // always try to load chunks, restrain generation/other updates only. don't count these towards tick count + //noinspection StatementWithEmptyBody + while (pollChunkLoadTasks()) {} @@ -231,13 +223,13 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079 + // Paper end + @Override - protected boolean pollTask() { // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644 +index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2dbd4fa92 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -578,6 +578,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } timings.scheduledBlocks.stopTiming(); // Paper @@ -245,27 +237,24 @@ index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a40 gameprofilerfiller.popPush("raid"); this.timings.raids.startTiming(); // Paper - timings this.raids.tick(); -@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -586,6 +587,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.doSounds.startTiming(); // Spigot this.runBlockEvents(); timings.doSounds.stopTiming(); // Spigot + this.getServer().midTickLoadChunks(); // Paper this.handlingTick = false; - gameprofilerfiller.popPush("entities"); + gameprofilerfiller.pop(); boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -632,10 +634,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - timings.tickEntities.stopTiming(); // Spigot + gameprofilerfiller.pop(); + this.getServer().midTickLoadChunks(); // Paper this.tickBlockEntities(); } + gameprofilerfiller.push("entityManagement"); ++ this.getServer().midTickLoadChunks(); // Paper + this.entityManager.tick(); + gameprofilerfiller.pop(); + } diff --git a/patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch b/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch similarity index 65% rename from patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch index 02f8b575b0..6b5d0a25e6 100644 --- a/patches/server-remapped/0431-Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/0388-Don-t-move-existing-players-to-world-spawn.patch @@ -10,28 +10,29 @@ larger than the keep loaded range. By skipping this, we avoid potential for a large spike on server start. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644 +index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623a05325d0 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -309,7 +309,7 @@ public class ServerPlayer extends Player { this.stats = server.getPlayerList().getStatisticManager(this); this.advancements = server.getPlayerList().getPlayerAdvancements(this); this.maxUpStep = 1.0F; - this.fudgeSpawnLocation(world); + //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.textFilter = server.createTextFilterForPlayer(this); this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener { + +@@ -359,7 +359,7 @@ public class ServerPlayer extends Player { } // CraftBukkit end -+ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER - private void fudgeSpawnLocation(ServerLevel world) { - BlockPos blockposition = world.getSpawn(); +- private void fudgeSpawnLocation(ServerLevel world) { ++ public void fudgeSpawnLocation(ServerLevel world) { // Paper - private -> public + BlockPos blockposition = world.getSharedSpawnPos(); -@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener { - position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit +@@ -527,7 +527,7 @@ public class ServerPlayer extends Player { + position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); } this.level = world; - this.setPos(position.x(), position.y(), position.z()); @@ -40,15 +41,15 @@ index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a this.gameMode.setLevel((ServerLevel) world); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644 +index f98a1c32e0c209473cf7268cbd8245ab9c134d28..18485689bcbf7818c3ca5b82086acef51888603b 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -204,6 +204,8 @@ public abstract class PlayerList { +@@ -207,6 +207,8 @@ public abstract class PlayerList { worldserver1 = worldserver; } -+ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ if (nbttagcompound == null) player.fudgeSpawnLocation(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... + player.setLevel(worldserver1); - player.gameMode.setLevel((ServerLevel) player.level); String s1 = "local"; +