diff --git a/src/main/java/ac/grim/grimac/checks/impl/scaffolding/BlockLOS.java b/src/main/java/ac/grim/grimac/checks/impl/scaffolding/BlockLOS.java index 4dce015ef3..c56aa9060c 100644 --- a/src/main/java/ac/grim/grimac/checks/impl/scaffolding/BlockLOS.java +++ b/src/main/java/ac/grim/grimac/checks/impl/scaffolding/BlockLOS.java @@ -4,34 +4,25 @@ import ac.grim.grimac.checks.type.BlockPlaceCheck; import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.anticheat.update.BlockPlace; -import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; import ac.grim.grimac.utils.data.HitData; -import ac.grim.grimac.utils.data.Pair; import ac.grim.grimac.utils.nmsutil.BlockRayTrace; import ac.grim.grimac.utils.nmsutil.Ray; -import ac.grim.grimac.utils.nmsutil.ReachUtils; import com.github.retrooper.packetevents.protocol.attribute.Attributes; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; -import com.github.retrooper.packetevents.protocol.world.BlockFace; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; -import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.util.Vector3i; -import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.block.Block; import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; @CheckData(name = "ContainerLOS") -public class ContainerLOS extends BlockPlaceCheck { +public class BlockLOS extends BlockPlaceCheck { - public ContainerLOS(GrimPlayer player) { + public BlockLOS(GrimPlayer player) { super(player); } @@ -53,10 +44,9 @@ public void onPostFlyingBlockPlace(BlockPlace place) { private boolean didRayTraceHit(BlockPlace place) { Vector3i interactBlockVec = new Vector3i(place.getPlacedAgainstBlockLocation().getX(), place.getPlacedAgainstBlockLocation().getY(), place.getPlacedAgainstBlockLocation().getZ()); - WrappedBlockState interactBlock = player.compensatedWorld.getWrappedBlockStateAt(interactBlockVec); double maxDistance = player.compensatedEntities.getSelf() - .getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); + .getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE) + player.getMovementThreshold(); List possibleLookDirs = new ArrayList<>(Arrays.asList( new Vector3f(player.lastXRot, player.yRot, 0), new Vector3f(player.xRot, player.yRot, 0) @@ -64,18 +54,15 @@ private boolean didRayTraceHit(BlockPlace place) { for (double eyeHeight : player.getPossibleEyeHeights()) { for (Vector3f lookDir : possibleLookDirs) { Vector eyePosition = new Vector(player.x, player.y + eyeHeight, player.z); - // Why do we have our own vector classes and MC vector classes mixed throughout this codebase? Vector eyeLookDir = new Ray(player, eyePosition.getX(), eyePosition.getY(), eyePosition.getZ(), lookDir.x, lookDir.y).calculateDirection(); - WrappedBlockState targetBlock; - Vector3i targetBlockVec = getTargetBlock(eyePosition, eyeLookDir, maxDistance); + Vector3i rayTracedBlockVec = getTargetBlock(eyePosition, eyeLookDir, maxDistance, interactBlockVec); - if (targetBlockVec == null) { + if (rayTracedBlockVec == null) { continue; } - targetBlock = player.compensatedWorld.getWrappedBlockStateAt(targetBlockVec); - if (interactBlock.equals(targetBlock)) { + if (interactBlockVec.equals(rayTracedBlockVec)) { return true; } } @@ -84,8 +71,8 @@ private boolean didRayTraceHit(BlockPlace place) { return false; } - private Vector3i getTargetBlock(Vector eyePosition, Vector eyeDirection, double maxDistance) { - HitData hitData = BlockRayTrace.getNearestReachHitResult(player, eyePosition, eyeDirection, maxDistance, maxDistance); + private Vector3i getTargetBlock(Vector eyePosition, Vector eyeDirection, double maxDistance, Vector3i targetBlockVec) { + HitData hitData = BlockRayTrace.getNearestReachHitResult003Compensated(player, eyePosition, eyeDirection, maxDistance, maxDistance, targetBlockVec); if (hitData == null) return null; return hitData.getPosition(); } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 476f3252af..64382e1535 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -144,7 +144,7 @@ public CheckManager(GrimPlayer player) { .put(PositionPlace.class, new PositionPlace(player)) .put(RotationPlace.class, new RotationPlace(player)) .put(DuplicateRotPlace.class, new DuplicateRotPlace(player)) - .put(ContainerLOS.class, new ContainerLOS(player)) + .put(BlockLOS.class, new BlockLOS(player)) .put(GhostBlockMitigation.class, new GhostBlockMitigation(player)) .build(); diff --git a/src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java b/src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java index 63c6f13ad9..2c4293e429 100644 --- a/src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java +++ b/src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java @@ -11,6 +11,7 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; +import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3i; import org.bukkit.util.Vector; @@ -115,6 +116,63 @@ public static HitData getNearestReachHitResult(GrimPlayer player, Vector eyePos, return getTraverseResult(player, null, startingPos, startingVec, trace, endPos, false, true, currentDistance); } + @Nullable + public static HitData getNearestReachHitResult003Compensated(GrimPlayer player, Vector eyePos, Vector lookVec, double currentDistance, double maxDistance, Vector3i targetBlockVec) { + Vector3d startingPos = new Vector3d(eyePos.getX(), eyePos.getY(), eyePos.getZ()); + Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ()); + Ray trace = new Ray(eyePos, lookVec); + Vector endVec = trace.getPointAtDistance(maxDistance); + Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ()); + + StateType heldItem = null; +// boolean sourcesHaveHitbox = false; + boolean checkInside = true; + double knownDistance = currentDistance; + + return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> { + CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ()); + List boxes = new ArrayList<>(); + data.downCast(boxes); + + double bestHitResult = Double.MAX_VALUE; + Vector bestHitLoc = null; + BlockFace bestFace = null; + + for (SimpleCollisionBox box : boxes) { + // Expand hitbox + if (vector3i.equals(targetBlockVec)) { + box.expand(player.getMovementThreshold()); + } else { + // TODO figure out a way to shirnk every simplecollisionbox that makes up the CollisionBox by 0.03/0.0002 + // In every direction except faces where they are joined together + } + + + Pair intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(knownDistance)); + if (intercept.getFirst() == null) continue; // No intercept + + Vector hitLoc = intercept.getFirst(); + + // If inside a block, return empty result for reach check (don't bother checking this?) + if (checkInside && ReachUtils.isVecInside(box, trace.getOrigin())) { + return null; + } + + if (hitLoc.distanceSquared(startingVec) < bestHitResult) { + bestHitResult = hitLoc.distanceSquared(startingVec); + bestHitLoc = hitLoc; + bestFace = intercept.getSecond(); + } + } + + if (bestHitLoc != null) { + return new HitData(vector3i, bestHitLoc, bestFace, block); + } + + return null; + }); + } + private static HitData getTraverseResult(GrimPlayer player, @Nullable StateType heldItem, Vector3d startingPos, Vector startingVec, Ray trace, Vector3d endPos, boolean sourcesHaveHitbox, boolean checkInside, double knownDistance) { return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> { CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ());