|
14 | 14 | import ac.grim.grimac.utils.data.*;
|
15 | 15 | import ac.grim.grimac.utils.inventory.Inventory;
|
16 | 16 | import ac.grim.grimac.utils.latency.CompensatedWorld;
|
17 |
| -import ac.grim.grimac.utils.math.GrimMath; |
18 | 17 | import ac.grim.grimac.utils.math.VectorUtils;
|
19 | 18 | import ac.grim.grimac.utils.nmsutil.*;
|
20 | 19 | import com.github.retrooper.packetevents.PacketEvents;
|
|
47 | 46 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAcknowledgeBlockChanges;
|
48 | 47 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetSlot;
|
49 | 48 | import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
50 |
| -import org.bukkit.util.Vector; |
51 |
| - |
52 | 49 | import java.util.ArrayList;
|
53 | 50 | import java.util.List;
|
54 |
| -import java.util.function.BiFunction; |
| 51 | +import org.bukkit.util.Vector; |
55 | 52 |
|
56 | 53 | public class CheckManagerListener extends PacketListenerAbstract {
|
57 | 54 |
|
58 | 55 | public CheckManagerListener() {
|
59 | 56 | super(PacketListenerPriority.LOW);
|
60 | 57 | }
|
61 | 58 |
|
62 |
| - // Copied from MCP... |
63 |
| - // Returns null if there isn't anything. |
64 |
| - // |
65 |
| - // I do have to admit that I'm starting to like bifunctions/new java 8 things more than I originally did. |
66 |
| - // although I still don't understand Mojang's obsession with streams in some of the hottest methods... that kills performance |
67 |
| - public static HitData traverseBlocks(GrimPlayer player, Vector3d start, Vector3d end, BiFunction<WrappedBlockState, Vector3i, HitData> predicate) { |
68 |
| - // I guess go back by the collision epsilon? |
69 |
| - double endX = GrimMath.lerp(-1.0E-7D, end.x, start.x); |
70 |
| - double endY = GrimMath.lerp(-1.0E-7D, end.y, start.y); |
71 |
| - double endZ = GrimMath.lerp(-1.0E-7D, end.z, start.z); |
72 |
| - double startX = GrimMath.lerp(-1.0E-7D, start.x, end.x); |
73 |
| - double startY = GrimMath.lerp(-1.0E-7D, start.y, end.y); |
74 |
| - double startZ = GrimMath.lerp(-1.0E-7D, start.z, end.z); |
75 |
| - int floorStartX = GrimMath.floor(startX); |
76 |
| - int floorStartY = GrimMath.floor(startY); |
77 |
| - int floorStartZ = GrimMath.floor(startZ); |
78 |
| - |
79 |
| - |
80 |
| - if (start.equals(end)) return null; |
81 |
| - |
82 |
| - WrappedBlockState state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ); |
83 |
| - HitData apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ)); |
84 |
| - |
85 |
| - if (apply != null) { |
86 |
| - return apply; |
87 |
| - } |
88 |
| - |
89 |
| - double xDiff = endX - startX; |
90 |
| - double yDiff = endY - startY; |
91 |
| - double zDiff = endZ - startZ; |
92 |
| - double xSign = Math.signum(xDiff); |
93 |
| - double ySign = Math.signum(yDiff); |
94 |
| - double zSign = Math.signum(zDiff); |
95 |
| - |
96 |
| - double posXInverse = xSign == 0 ? Double.MAX_VALUE : xSign / xDiff; |
97 |
| - double posYInverse = ySign == 0 ? Double.MAX_VALUE : ySign / yDiff; |
98 |
| - double posZInverse = zSign == 0 ? Double.MAX_VALUE : zSign / zDiff; |
99 |
| - |
100 |
| - double d12 = posXInverse * (xSign > 0 ? 1.0D - GrimMath.frac(startX) : GrimMath.frac(startX)); |
101 |
| - double d13 = posYInverse * (ySign > 0 ? 1.0D - GrimMath.frac(startY) : GrimMath.frac(startY)); |
102 |
| - double d14 = posZInverse * (zSign > 0 ? 1.0D - GrimMath.frac(startZ) : GrimMath.frac(startZ)); |
103 |
| - |
104 |
| - // Can't figure out what this code does currently |
105 |
| - while (d12 <= 1.0D || d13 <= 1.0D || d14 <= 1.0D) { |
106 |
| - if (d12 < d13) { |
107 |
| - if (d12 < d14) { |
108 |
| - floorStartX += xSign; |
109 |
| - d12 += posXInverse; |
110 |
| - } else { |
111 |
| - floorStartZ += zSign; |
112 |
| - d14 += posZInverse; |
113 |
| - } |
114 |
| - } else if (d13 < d14) { |
115 |
| - floorStartY += ySign; |
116 |
| - d13 += posYInverse; |
117 |
| - } else { |
118 |
| - floorStartZ += zSign; |
119 |
| - d14 += posZInverse; |
120 |
| - } |
121 |
| - |
122 |
| - state = player.compensatedWorld.getWrappedBlockStateAt(floorStartX, floorStartY, floorStartZ); |
123 |
| - apply = predicate.apply(state, new Vector3i(floorStartX, floorStartY, floorStartZ)); |
124 |
| - |
125 |
| - if (apply != null) { |
126 |
| - return apply; |
127 |
| - } |
128 |
| - } |
129 |
| - |
130 |
| - return null; |
131 |
| - } |
132 |
| - |
133 | 59 | private static void placeWaterLavaSnowBucket(GrimPlayer player, ItemStack held, StateType toPlace, InteractionHand hand) {
|
134 |
| - HitData data = getNearestHitResult(player, StateTypes.AIR, false); |
| 60 | + HitData data = BlockRayTrace.getNearestHitResult(player, StateTypes.AIR, false); |
135 | 61 | if (data != null) {
|
136 | 62 | BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), held, data);
|
137 | 63 |
|
@@ -268,7 +194,7 @@ private static void handleBlockPlaceOrUseItem(PacketWrapper packet, GrimPlayer p
|
268 | 194 | // The offhand is unable to interact with blocks like this... try to stop some desync points before they happen
|
269 | 195 | if ((!player.isSneaking || onlyAir) && place.getHand() == InteractionHand.MAIN_HAND) {
|
270 | 196 | Vector3i blockPosition = place.getBlockPosition();
|
271 |
| - BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, getNearestHitResult(player, null, true)); |
| 197 | + BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), place.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true)); |
272 | 198 |
|
273 | 199 | // Right-clicking a trapdoor/door/etc.
|
274 | 200 | StateType placedAgainst = blockPlace.getPlacedAgainstMaterial();
|
@@ -308,7 +234,7 @@ private static void handleBlockPlaceOrUseItem(PacketWrapper packet, GrimPlayer p
|
308 | 234 | placedWith = player.getInventory().getOffHand();
|
309 | 235 | }
|
310 | 236 |
|
311 |
| - BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, getNearestHitResult(player, null, true)); |
| 237 | + BlockPlace blockPlace = new BlockPlace(player, place.getHand(), blockPosition, place.getFaceId(), face, placedWith, BlockRayTrace.getNearestHitResult(player, null, true)); |
312 | 238 | // At this point, it is too late to cancel, so we can only flag, and cancel subsequent block places more aggressively
|
313 | 239 | if (!player.compensatedEntities.getSelf().inVehicle()) {
|
314 | 240 | player.checkManager.onPostFlyingBlockPlace(blockPlace);
|
@@ -508,7 +434,7 @@ public void onPacketReceive(PacketReceiveEvent event) {
|
508 | 434 | player.placeUseItemPackets.add(new BlockPlaceSnapshot(packet, player.isSneaking));
|
509 | 435 | } else {
|
510 | 436 | // Anti-air place
|
511 |
| - BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, getNearestHitResult(player, null, true)); |
| 437 | + BlockPlace blockPlace = new BlockPlace(player, packet.getHand(), packet.getBlockPosition(), packet.getFaceId(), packet.getFace(), placedWith, BlockRayTrace.getNearestHitResult(player, null, true)); |
512 | 438 | blockPlace.setCursor(packet.getCursorPosition());
|
513 | 439 |
|
514 | 440 | if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_11) && player.getClientVersion().isOlderThan(ClientVersion.V_1_11)) {
|
@@ -582,7 +508,7 @@ public void onPacketReceive(PacketReceiveEvent event) {
|
582 | 508 | }
|
583 | 509 |
|
584 | 510 | private static void placeBucket(GrimPlayer player, InteractionHand hand) {
|
585 |
| - HitData data = getNearestHitResult(player, null, true); |
| 511 | + HitData data = BlockRayTrace.getNearestHitResult(player, null, true); |
586 | 512 |
|
587 | 513 | if (data != null) {
|
588 | 514 | BlockPlace blockPlace = new BlockPlace(player, hand, data.getPosition(), data.getClosestDirection().getFaceValue(), data.getClosestDirection(), ItemStack.EMPTY, data);
|
@@ -748,7 +674,7 @@ private void handleFlying(GrimPlayer player, double x, double y, double z, float
|
748 | 674 | }
|
749 | 675 |
|
750 | 676 | private static void placeLilypad(GrimPlayer player, InteractionHand hand) {
|
751 |
| - HitData data = getNearestHitResult(player, null, true); |
| 677 | + HitData data = BlockRayTrace.getNearestHitResult(player, null, true); |
752 | 678 |
|
753 | 679 | if (data != null) {
|
754 | 680 | // A lilypad cannot replace a fluid
|
@@ -778,56 +704,6 @@ private static void placeLilypad(GrimPlayer player, InteractionHand hand) {
|
778 | 704 | }
|
779 | 705 | }
|
780 | 706 |
|
781 |
| - private static HitData getNearestHitResult(GrimPlayer player, StateType heldItem, boolean sourcesHaveHitbox) { |
782 |
| - Vector3d startingPos = new Vector3d(player.x, player.y + player.getEyeHeight(), player.z); |
783 |
| - Vector startingVec = new Vector(startingPos.getX(), startingPos.getY(), startingPos.getZ()); |
784 |
| - Ray trace = new Ray(player, startingPos.getX(), startingPos.getY(), startingPos.getZ(), player.xRot, player.yRot); |
785 |
| - final double distance = player.compensatedEntities.getSelf().getAttributeValue(Attributes.PLAYER_BLOCK_INTERACTION_RANGE); |
786 |
| - Vector endVec = trace.getPointAtDistance(distance); |
787 |
| - Vector3d endPos = new Vector3d(endVec.getX(), endVec.getY(), endVec.getZ()); |
788 |
| - |
789 |
| - return traverseBlocks(player, startingPos, endPos, (block, vector3i) -> { |
790 |
| - CollisionBox data = HitboxData.getBlockHitbox(player, heldItem, player.getClientVersion(), block, vector3i.getX(), vector3i.getY(), vector3i.getZ()); |
791 |
| - List<SimpleCollisionBox> boxes = new ArrayList<>(); |
792 |
| - data.downCast(boxes); |
793 |
| - |
794 |
| - double bestHitResult = Double.MAX_VALUE; |
795 |
| - Vector bestHitLoc = null; |
796 |
| - BlockFace bestFace = null; |
797 |
| - |
798 |
| - for (SimpleCollisionBox box : boxes) { |
799 |
| - Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance)); |
800 |
| - if (intercept.getFirst() == null) continue; // No intercept |
801 |
| - |
802 |
| - Vector hitLoc = intercept.getFirst(); |
803 |
| - |
804 |
| - if (hitLoc.distanceSquared(startingVec) < bestHitResult) { |
805 |
| - bestHitResult = hitLoc.distanceSquared(startingVec); |
806 |
| - bestHitLoc = hitLoc; |
807 |
| - bestFace = intercept.getSecond(); |
808 |
| - } |
809 |
| - } |
810 |
| - if (bestHitLoc != null) { |
811 |
| - return new HitData(vector3i, bestHitLoc, bestFace, block); |
812 |
| - } |
813 |
| - |
814 |
| - if (sourcesHaveHitbox && |
815 |
| - (player.compensatedWorld.isWaterSourceBlock(vector3i.getX(), vector3i.getY(), vector3i.getZ()) |
816 |
| - || player.compensatedWorld.getLavaFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ()) == (8 / 9f))) { |
817 |
| - double waterHeight = player.compensatedWorld.getFluidLevelAt(vector3i.getX(), vector3i.getY(), vector3i.getZ()); |
818 |
| - SimpleCollisionBox box = new SimpleCollisionBox(vector3i.getX(), vector3i.getY(), vector3i.getZ(), vector3i.getX() + 1, vector3i.getY() + waterHeight, vector3i.getZ() + 1); |
819 |
| - |
820 |
| - Pair<Vector, BlockFace> intercept = ReachUtils.calculateIntercept(box, trace.getOrigin(), trace.getPointAtDistance(distance)); |
821 |
| - |
822 |
| - if (intercept.getFirst() != null) { |
823 |
| - return new HitData(vector3i, intercept.getFirst(), intercept.getSecond(), block); |
824 |
| - } |
825 |
| - } |
826 |
| - |
827 |
| - return null; |
828 |
| - }); |
829 |
| - } |
830 |
| - |
831 | 707 | @Override
|
832 | 708 | public void onPacketSend(PacketSendEvent event) {
|
833 | 709 | if (event.getConnectionState() != ConnectionState.PLAY) return;
|
|
0 commit comments