Yatopia/patches/Airplane/patches/server/0004-Strip-raytracing-for-E...

219 lines
11 KiB
Diff

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 IBlockAccess#rayTrace 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.
Airplane
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/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java
index cc566784c7dd21cc2c44e0f351347f657e57ddcf..e9e7fcf2b63febe2a7d055826fabb86bc13a5cf3 100644
--- a/src/main/java/net/minecraft/util/MathHelper.java
+++ b/src/main/java/net/minecraft/util/MathHelper.java
@@ -240,6 +240,7 @@ public class MathHelper {
return f - (float) d(f);
}
+ public static double getDecimals(double num) { return h(num); } // Airplane
public static double h(double d0) {
return d0 - (double) d(d0);
}
@@ -418,6 +419,7 @@ public class MathHelper {
return f1 + f * (f2 - f1);
}
+ public static double linearInterpolation(double value1, double value2, double amount) { return d(value1, value2, amount); } // Airplane - OBFHELPER
public static double d(double d0, double d1, double d2) {
return d1 + d0 * (d2 - d1);
}
@@ -434,6 +436,7 @@ public class MathHelper {
return d0 * d0 * d0 * (d0 * (d0 * 6.0D - 15.0D) + 10.0D);
}
+ public static int sign(double num) { return k(num); } // Airplane - OBFHELPER
public static int k(double d0) {
return d0 == 0.0D ? 0 : (d0 > 0.0D ? 1 : -1);
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
index 2ff3297fb8c0e4f8c969ba2727eecb7fe06525c4..56812a96b57586d91c0f218f4720807e2d957627 100644
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
@@ -111,6 +111,7 @@ import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.MovingObjectPosition;
import net.minecraft.world.phys.MovingObjectPositionEntity;
import net.minecraft.world.phys.Vec3D;
+import net.minecraft.world.phys.shapes.VoxelShapeCollision;
import net.minecraft.world.scores.ScoreboardTeam;
import org.apache.logging.log4j.Logger;
@@ -3102,7 +3103,10 @@ public abstract class EntityLiving extends Entity {
Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ());
// Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists
- return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS;
+ // Airplane start - use direct method
+ //return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS;
+ return this.world.rayTraceDirect(vec3d, vec3d1, VoxelShapeCollision.a(this)) == MovingObjectPosition.EnumMovingObjectType.MISS;
+ // Airplane end
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java
index e612e1d30f76e217b1aa23488ab025adce048f57..6109d59c02d0c7877e213213c6aec6f8513ccc47 100644
--- a/src/main/java/net/minecraft/world/level/IBlockAccess.java
+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java
@@ -14,9 +14,11 @@ import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.MovingObjectPosition;
import net.minecraft.world.phys.MovingObjectPositionBlock;
import net.minecraft.world.phys.Vec3D;
import net.minecraft.world.phys.shapes.VoxelShape;
+import net.minecraft.world.phys.shapes.VoxelShapeCollision;
public interface IBlockAccess {
@@ -56,6 +58,16 @@ public interface IBlockAccess {
return BlockPosition.a(axisalignedbb).map(this::getType);
}
+ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect
+ default MovingObjectPosition.EnumMovingObjectType rayTraceBlockDirect(Vec3D vec3d, Vec3D vec3d1, BlockPosition blockposition, IBlockData iblockdata, VoxelShapeCollision voxelshapecoll) {
+ if (iblockdata.isAir()) return null; // Tuinity - optimise air cases
+ VoxelShape voxelshape = RayTrace.BlockCollisionOption.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll);
+ MovingObjectPositionBlock movingobjectpositionblock = this.rayTrace(vec3d, vec3d1, blockposition, voxelshape, iblockdata);
+
+ return movingobjectpositionblock == null ? null : movingobjectpositionblock.getType();
+ }
+ // Airplane end
+
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) {
// Paper start - Prevent raytrace from loading chunks
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index cb8064df7e9f1b8b4d4292486e2193680d83663c..37da32675f0c00c793cd137c9a7305932cefb705 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -69,6 +69,8 @@ import net.minecraft.world.level.saveddata.maps.WorldMap;
import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.WorldDataMutable;
import net.minecraft.world.phys.AxisAlignedBB;
+import net.minecraft.world.phys.MovingObjectPosition;
+import net.minecraft.world.phys.Vec3D;
import net.minecraft.world.phys.shapes.OperatorBoolean;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.shapes.VoxelShapeCollision;
@@ -385,6 +387,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return null;
}
+ // Airplane start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace)
+ public MovingObjectPosition.EnumMovingObjectType rayTraceDirect(Vec3D vec3d, Vec3D vec3d1, VoxelShapeCollision voxelshapecoll) {
+ // most of this code comes from IBlockAccess#a(RayTrace, BiFunction, Function), but removes the needless functions
+ if (vec3d.equals(vec3d1)) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+
+ double endX = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.x, vec3d.x);
+ double endY = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.y, vec3d.y);
+ double endZ = MathHelper.linearInterpolation(-1.0E-7D, vec3d1.z, vec3d.z);
+
+ double startX = MathHelper.linearInterpolation(-1.0E-7D, vec3d.x, vec3d1.x);
+ double startY = MathHelper.linearInterpolation(-1.0E-7D, vec3d.y, vec3d1.y);
+ double startZ = MathHelper.linearInterpolation(-1.0E-7D, vec3d.z, vec3d1.z);
+
+ int currentX = MathHelper.floor(startX);
+ int currentY = MathHelper.floor(startY);
+ int currentZ = MathHelper.floor(startZ);
+
+ BlockPosition.MutableBlockPosition currentBlock = new BlockPosition.MutableBlockPosition(currentX, currentY, currentZ);
+
+ Chunk chunk = this.getChunkIfLoaded(currentBlock);
+ if (chunk == null) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+
+ MovingObjectPosition.EnumMovingObjectType initialCheck = this.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getType(currentBlock), voxelshapecoll);
+
+ if (initialCheck != null) {
+ return initialCheck;
+ }
+
+ double diffX = endX - startX;
+ double diffY = endY - startY;
+ double diffZ = endZ - startZ;
+
+ int xDirection = MathHelper.sign(diffX);
+ int yDirection = MathHelper.sign(diffY);
+ int zDirection = MathHelper.sign(diffZ);
+
+ double normalizedX = xDirection == 0 ? Double.MAX_VALUE : (double) xDirection / diffX;
+ double normalizedY = yDirection == 0 ? Double.MAX_VALUE : (double) yDirection / diffY;
+ double normalizedZ = zDirection == 0 ? Double.MAX_VALUE : (double) zDirection / diffZ;
+
+ double normalizedXDirection = normalizedX * (xDirection > 0 ? 1.0D - MathHelper.getDecimals(startX) : MathHelper.getDecimals(startX));
+ double normalizedYDirection = normalizedY * (yDirection > 0 ? 1.0D - MathHelper.getDecimals(startY) : MathHelper.getDecimals(startY));
+ double normalizedZDirection = normalizedZ * (zDirection > 0 ? 1.0D - MathHelper.getDecimals(startZ) : MathHelper.getDecimals(startZ));
+
+ MovingObjectPosition.EnumMovingObjectType result;
+
+ do {
+ if (normalizedXDirection > 1.0D && normalizedYDirection > 1.0D && normalizedZDirection > 1.0D) {
+ return MovingObjectPosition.EnumMovingObjectType.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.setValues(currentX, currentY, currentZ);
+ if (chunk.getPos().x != currentBlock.getX() >> 4 || chunk.getPos().z != currentBlock.getZ() >> 4) {
+ chunk = this.getChunkIfLoaded(currentBlock);
+ if (chunk == null) {
+ return MovingObjectPosition.EnumMovingObjectType.MISS;
+ }
+ }
+ result = this.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getType(currentBlock), voxelshapecoll);
+ } while (result == null);
+
+ return result;
+ }
+ // Airplane end
+
public static boolean isValidLocation(BlockPosition blockposition) {
return blockposition.isValidLocation(); // Paper - use better/optimized check
}