9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-28 03:09:07 +00:00
Files
SakuraMC/patches/server/0080-Airplane-Strip-raytracing-for-EntityLiving-hasLineOf.patch
2024-12-01 17:09:32 +00:00

161 lines
9.5 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] Airplane - 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/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index fd7c3b3bd3665a65c8412fd9455c2320878960a7..2111c8cbefadb998734eb1eb0c09492d3752bf66 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3755,7 +3755,10 @@ public abstract class LivingEntity extends Entity {
Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ());
// 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; // Paper - use distanceToSqr
+ // Airplane start
+ //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; // Paper - use distanceToSqr
+ return vec3d1.distanceToSqr(vec3d) > 128D * 128D ? false : this.level.rayTraceDirect(vec3d, vec3d1, net.minecraft.world.phys.shapes.CollisionContext.of(this)) == net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ // Airplane end
}
}
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
index 04d45b2ddc3489c4d0764da1575cb9a373d9a490..5cb899dd7ab92552605e74b2840d57a40f4c1434 100644
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
@@ -73,6 +73,16 @@ public interface BlockGetter extends LevelHeightAccessor {
});
}
+ // Airplane start - broken down variant of below rayTraceBlock, used by World#rayTraceDirect
+ default net.minecraft.world.phys.BlockHitResult.Type rayTraceBlockDirect(Vec3 vec3d, Vec3 vec3d1, BlockPos blockposition, BlockState iblockdata, net.minecraft.world.phys.shapes.CollisionContext voxelshapecoll) {
+ if (iblockdata.isAir()) return null; // Tuinity - optimise air cases
+ VoxelShape voxelshape = ClipContext.Block.COLLIDER.get(iblockdata, this, blockposition, voxelshapecoll);
+ net.minecraft.world.phys.BlockHitResult movingobjectpositionblock = this.clipWithInteractionOverride(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 BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
// Paper start - Prevent raytrace from loading chunks
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 785f621ab4be55cb6f216bf11731aee2f40198c3..7c8c7f74bbb27ed8f23e2f99062e9502a3adf3f6 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -519,6 +519,90 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return x >= bb.minX && x <= bb.maxX && y >= bb.minY && y <= bb.maxY;
}
// Sakura end - physics version api
+ // Airplane start - broken down method of raytracing for EntityLiving#hasLineOfSight, replaces IBlockAccess#rayTrace(RayTrace)
+ public final net.minecraft.world.phys.BlockHitResult.Type rayTraceDirect(net.minecraft.world.phys.Vec3 vec3d, net.minecraft.world.phys.Vec3 vec3d1, net.minecraft.world.phys.shapes.CollisionContext voxelshapecoll) {
+ // most of this code comes from IBlockAccess#a(RayTrace, BiFunction, Function), but removes the needless functions
+ if (vec3d.equals(vec3d1)) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ double endX = Mth.lerp(-1.0E-7D, vec3d1.x, vec3d.x);
+ double endY = Mth.lerp(-1.0E-7D, vec3d1.y, vec3d.y);
+ double endZ = Mth.lerp(-1.0E-7D, vec3d1.z, vec3d.z);
+
+ double startX = Mth.lerp(-1.0E-7D, vec3d.x, vec3d1.x);
+ double startY = Mth.lerp(-1.0E-7D, vec3d.y, vec3d1.y);
+ double startZ = Mth.lerp(-1.0E-7D, vec3d.z, vec3d1.z);
+
+ int currentX = Mth.floor(startX);
+ int currentY = Mth.floor(startY);
+ int currentZ = Mth.floor(startZ);
+
+ 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;
+ }
+
+ net.minecraft.world.phys.BlockHitResult.Type initialCheck = this.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getBlockState(currentBlock), voxelshapecoll);
+
+ if (initialCheck != null) {
+ return initialCheck;
+ }
+
+ double diffX = endX - startX;
+ double diffY = endY - startY;
+ double diffZ = endZ - startZ;
+
+ int xDirection = Mth.sign(diffX);
+ int yDirection = Mth.sign(diffY);
+ int zDirection = Mth.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 - 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.rayTraceBlockDirect(vec3d, vec3d1, currentBlock, chunk.getBlockState(currentBlock), voxelshapecoll);
+ } while (result == null);
+
+ return result;
+ }
+ // Airplane end
protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, Supplier<me.samsuik.sakura.configuration.WorldConfiguration> sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura // Paper - Async-Anti-Xray - Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot