diff --git a/patches/server/Add-option-to-fix-items-merging-through-walls.patch b/patches/server/Add-option-to-fix-items-merging-through-walls.patch index 7bff99b5e6..8e346e0352 100644 --- a/patches/server/Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/Add-option-to-fix-items-merging-through-walls.patch @@ -12,14 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ItemEntity entityitem = (ItemEntity) iterator.next(); if (entityitem.isMergable()) { -+ // Paper Start - Fix items merging through walls -+ if (this.level().paperConfig().fixes.fixItemsMergingThroughWalls) { -+ net.minecraft.world.level.ClipContext rayTrace = new net.minecraft.world.level.ClipContext(this.position(), entityitem.position(), -+ net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this); -+ net.minecraft.world.phys.BlockHitResult rayTraceResult = this.level().clip(rayTrace); -+ if (rayTraceResult.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) continue; -+ } -+ // Paper End ++ // Paper start - Fix items merging through walls ++ if (this.level().clipDirect(this.position(), entityitem.position(), ++ net.minecraft.world.phys.shapes.CollisionContext.of(this)) == net.minecraft.world.phys.HitResult.Type.BLOCK) { ++ continue; ++ } ++ // Paper end - Fix items merging through walls this.tryToMerge(entityitem); if (this.isRemoved()) { break; diff --git a/patches/server/Collision-API.patch b/patches/server/Collision-API.patch index bc71a6e8a2..ca56c45ede 100644 --- a/patches/server/Collision-API.patch +++ b/patches/server/Collision-API.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java @@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor { - return this.getHandle().clip(new net.minecraft.world.level.ClipContext(vec3d, vec3d1, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, null)).getType() == net.minecraft.world.phys.HitResult.Type.MISS; + return this.getHandle().clip(new net.minecraft.world.level.ClipContext(start, end, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, null)).getType() == net.minecraft.world.phys.HitResult.Type.MISS; } + + @Override diff --git a/patches/server/Line-Of-Sight-Changes.patch b/patches/server/Line-Of-Sight-Changes.patch index be75468ada..cf2810ff6f 100644 --- a/patches/server/Line-Of-Sight-Changes.patch +++ b/patches/server/Line-Of-Sight-Changes.patch @@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); -- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; +- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper + // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists -+ return vec3d1.distanceToSqr(vec3d) > 128D * 128D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; ++ return vec3d1.distanceToSqr(vec3d) > 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper } } @@ -30,12 +30,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean lineOfSightExists(Location from, Location to) { + Preconditions.checkArgument(from != null, "from parameter in lineOfSightExists cannot be null"); + Preconditions.checkArgument(to != null, "to parameter in lineOfSightExists cannot be null"); -+ if (from.getWorld() != to.getWorld()) return false; -+ net.minecraft.world.phys.Vec3 vec3d = new net.minecraft.world.phys.Vec3(from.getX(), from.getY(), from.getZ()); -+ net.minecraft.world.phys.Vec3 vec3d1 = new net.minecraft.world.phys.Vec3(to.getX(), to.getY(), to.getZ()); -+ if (vec3d1.distanceToSqr(vec3d) > 128D * 128D) return false; //Return early if the distance is greater than 128 blocks ++ if (from.getWorld() != to.getWorld()) { ++ return false; ++ } + -+ return this.getHandle().clip(new net.minecraft.world.level.ClipContext(vec3d, vec3d1, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, null)).getType() == net.minecraft.world.phys.HitResult.Type.MISS; ++ net.minecraft.world.phys.Vec3 start = new net.minecraft.world.phys.Vec3(from.getX(), from.getY(), from.getZ()); ++ net.minecraft.world.phys.Vec3 end = new net.minecraft.world.phys.Vec3(to.getX(), to.getY(), to.getZ()); ++ if (end.distanceToSqr(start) > 128D * 128D) { ++ return false; // Return early if the distance is greater than 128 blocks ++ } ++ ++ return this.getHandle().clip(new net.minecraft.world.level.ClipContext(start, end, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, null)).getType() == net.minecraft.world.phys.HitResult.Type.MISS; + } // Paper end } @@ -50,12 +55,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override + public boolean hasLineOfSight(Location loc) { -+ if (this.getHandle().level() != ((CraftWorld) loc.getWorld()).getHandle()) return false; -+ net.minecraft.world.phys.Vec3 vec3d = new net.minecraft.world.phys.Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); -+ net.minecraft.world.phys.Vec3 vec3d1 = new net.minecraft.world.phys.Vec3(loc.getX(), loc.getY(), loc.getZ()); -+ if (vec3d1.distanceToSqr(vec3d) > 128D * 128D) return false; //Return early if the distance is greater than 128 blocks ++ if (this.getHandle().level() != ((CraftWorld) loc.getWorld()).getHandle()) { ++ return false; ++ } + -+ return this.getHandle().level().clip(new net.minecraft.world.level.ClipContext(vec3d, vec3d1, net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this.getHandle())).getType() == net.minecraft.world.phys.HitResult.Type.MISS; ++ net.minecraft.world.phys.Vec3 start = new net.minecraft.world.phys.Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); ++ net.minecraft.world.phys.Vec3 end = new net.minecraft.world.phys.Vec3(loc.getX(), loc.getY(), loc.getZ()); ++ if (end.distanceToSqr(start) > 128D * 128D) { ++ return false; // Return early if the distance is greater than 128 blocks ++ } ++ ++ return this.getHandle().level().clipDirect(start, end, net.minecraft.world.phys.shapes.CollisionContext.of(this.getHandle())) == net.minecraft.world.phys.HitResult.Type.MISS; + } + // Paper end + diff --git a/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch index 6ab9647327..79a4ab726e 100644 --- a/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch +++ b/patches/server/Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } + // Paper end public boolean isInWorldBounds(BlockPos pos) { - return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos); diff --git a/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch b/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch new file mode 100644 index 0000000000..a3aeca8dbd --- /dev/null +++ b/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Thu, 18 Feb 2021 13:13:27 -0600 +Subject: [PATCH] Skip POI finding if stuck in vehicle + +Copyright (C) 2020 Technove LLC + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +@@ -0,0 +0,0 @@ public class AcquirePoi { + return false; + } else { + mutableLong.setValue(time + 20L + (long)world.getRandom().nextInt(20)); ++ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Wait an additional 10s to check again if they're stuck + PoiManager poiManager = world.getPoiManager(); + long2ObjectMap.long2ObjectEntrySet().removeIf((entry) -> { + return !entry.getValue().isStillValid(time); diff --git a/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch b/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch new file mode 100644 index 0000000000..eb3f9cf954 --- /dev/null +++ b/patches/server/Strip-raytracing-for-EntityLiving-hasLineOfSight.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Sat, 31 Oct 2020 18:43:02 -0500 +Subject: [PATCH] Strip raytracing for EntityLiving#hasLineOfSight + +The BlockGetter#clip method is very wasteful in both allocations, +and in logic. While EntityLiving#hasLineOfSight provides static +parameters for collisions with blocks and fluids, the method still does +a lot of dynamic checks for both of these, which result in extra work. +As well, since the fluid collision option is set to NONE, the entire +fluid collision system is completely unneeded, yet used anyways. + +Copyright (C) 2020 Technove LLC + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + +- return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; ++ return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clipDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == HitResult.Type.MISS; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor { + }); + } + ++ // Paper start - Broken down variant of the method below, used by Level#clipDirect ++ @Nullable ++ default BlockHitResult.Type clipDirect(Vec3 start, Vec3 end, BlockPos pos, BlockState state, net.minecraft.world.phys.shapes.CollisionContext collisionContext) { ++ if (state.isAir()) { ++ return null; ++ } ++ ++ final VoxelShape voxelshape = ClipContext.Block.COLLIDER.get(state, this, pos, collisionContext); ++ final BlockHitResult hitResult = this.clipWithInteractionOverride(start, end, pos, voxelshape, state); ++ return hitResult == null ? null : hitResult.getType(); ++ } ++ // Paper end ++ + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { + BlockState iblockdata = this.getBlockState(blockposition); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return null; + } + ++ // Paper start - Broken down method of raytracing for EntityLiving#hasLineOfSight, replaces BlockGetter#clip(CollisionContext) ++ public net.minecraft.world.phys.BlockHitResult.Type clipDirect(Vec3 start, Vec3 end, net.minecraft.world.phys.shapes.CollisionContext collisionContext) { ++ // most of this code comes from BlockGetter#clip(CollisionContext, BiFunction, Function), but removes the needless functions ++ if (start.equals(end)) { ++ return net.minecraft.world.phys.BlockHitResult.Type.MISS; ++ } ++ ++ final double endX = Mth.lerp(-1.0E-7D, end.x, start.x); ++ final double endY = Mth.lerp(-1.0E-7D, end.y, start.y); ++ final double endZ = Mth.lerp(-1.0E-7D, end.z, start.z); ++ ++ final double startX = Mth.lerp(-1.0E-7D, start.x, end.x); ++ final double startY = Mth.lerp(-1.0E-7D, start.y, end.y); ++ final double startZ = Mth.lerp(-1.0E-7D, start.z, end.z); ++ ++ int currentX = Mth.floor(startX); ++ int currentY = Mth.floor(startY); ++ int currentZ = Mth.floor(startZ); ++ ++ final BlockPos.MutableBlockPos currentBlock = new BlockPos.MutableBlockPos(currentX, currentY, currentZ); ++ ++ LevelChunk chunk = this.getChunkIfLoaded(currentBlock); ++ if (chunk == null) { ++ return net.minecraft.world.phys.BlockHitResult.Type.MISS; ++ } ++ ++ final net.minecraft.world.phys.BlockHitResult.Type initialCheck = this.clipDirect(start, end, currentBlock, chunk.getBlockState(currentBlock), collisionContext); ++ if (initialCheck != null) { ++ return initialCheck; ++ } ++ ++ final double diffX = endX - startX; ++ final double diffY = endY - startY; ++ final double diffZ = endZ - startZ; ++ ++ final int xDirection = Mth.sign(diffX); ++ final int yDirection = Mth.sign(diffY); ++ final int zDirection = Mth.sign(diffZ); ++ ++ final double normalizedX = xDirection == 0 ? Double.MAX_VALUE : (double) xDirection / diffX; ++ final double normalizedY = yDirection == 0 ? Double.MAX_VALUE : (double) yDirection / diffY; ++ final double normalizedZ = zDirection == 0 ? Double.MAX_VALUE : (double) zDirection / diffZ; ++ ++ double normalizedXDirection = normalizedX * (xDirection > 0 ? 1.0D - Mth.frac(startX) : Mth.frac(startX)); ++ double normalizedYDirection = normalizedY * (yDirection > 0 ? 1.0D - Mth.frac(startY) : Mth.frac(startY)); ++ double normalizedZDirection = normalizedZ * (zDirection > 0 ? 1.0D - Mth.frac(startZ) : Mth.frac(startZ)); ++ ++ net.minecraft.world.phys.BlockHitResult.Type result; ++ ++ do { ++ if (normalizedXDirection > 1.0D && normalizedYDirection > 1.0D && normalizedZDirection > 1.0D) { ++ return net.minecraft.world.phys.BlockHitResult.Type.MISS; ++ } ++ ++ if (normalizedXDirection < normalizedYDirection) { ++ if (normalizedXDirection < normalizedZDirection) { ++ currentX += xDirection; ++ normalizedXDirection += normalizedX; ++ } else { ++ currentZ += zDirection; ++ normalizedZDirection += normalizedZ; ++ } ++ } else if (normalizedYDirection < normalizedZDirection) { ++ currentY += yDirection; ++ normalizedYDirection += normalizedY; ++ } else { ++ currentZ += zDirection; ++ normalizedZDirection += normalizedZ; ++ } ++ ++ currentBlock.set(currentX, currentY, currentZ); ++ if (chunk.getPos().x != currentBlock.getX() >> 4 || chunk.getPos().z != currentBlock.getZ() >> 4) { ++ chunk = this.getChunkIfLoaded(currentBlock); ++ if (chunk == null) { ++ return net.minecraft.world.phys.BlockHitResult.Type.MISS; ++ } ++ } ++ result = this.clipDirect(start, end, currentBlock, chunk.getBlockState(currentBlock), collisionContext); ++ } while (result == null); ++ ++ return result; ++ } ++ // Paper end ++ + public boolean isInWorldBounds(BlockPos pos) { + return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos); + }