mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 23:38:25 +01:00
Strip raytracing for EntityLiving#hasLineOfSight
Co-authored-by: Paul Sauve <paul@technove.co>
This commit is contained in:
parent
68b63a9341
commit
1f4c201c00
6 changed files with 221 additions and 22 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
+
|
||||
|
|
|
@ -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);
|
||||
|
|
32
patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch
Normal file
32
patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch
Normal file
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Sauve <paul@technove.co>
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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);
|
|
@ -0,0 +1,159 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Sauve <paul@technove.co>
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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);
|
||||
}
|
Loading…
Reference in a new issue