diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/Reach.java b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java similarity index 87% rename from src/main/java/dev/brighten/ac/check/impl/combat/Reach.java rename to src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java index c6889d8..e149919 100644 --- a/src/main/java/dev/brighten/ac/check/impl/combat/Reach.java +++ b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java @@ -21,7 +21,7 @@ import java.util.*; import java.util.concurrent.LinkedBlockingQueue; @CheckData(name = "Hitbox", type = CheckType.COMBAT) -public class Reach extends Check { +public class Hitbox extends Check { private float buffer; private int hbuffer; @@ -32,7 +32,7 @@ public class Reach extends Check { EntityType.BLAZE, EntityType.SKELETON, EntityType.PLAYER, EntityType.VILLAGER, EntityType.IRON_GOLEM, EntityType.WITCH, EntityType.COW, EntityType.CREEPER); - public Reach(APlayer player) { + public Hitbox(APlayer player) { super(player); } @@ -57,19 +57,19 @@ public class Reach extends Check { while((target = attacks.poll()) != null) { //Updating new entity loc - Optional optionalEloc = player.getEntityLocationHandler().getEntityLocation(target.one); + Optional> optionalEloc = player.getEntityLocationHandler().getEntityLocation(target.one); if(!optionalEloc.isPresent()) { return; } - final EntityLocation eloc = optionalEloc.get(); + final Tuple eloc = optionalEloc.get(); final KLocation to = target.two; - debug("current loc: %.4f, %.4f, %.4f", eloc.x, eloc.y, eloc.z); + debug("current loc: %.4f, %.4f, %.4f", eloc.one.x, eloc.one.y, eloc.one.z); - if(eloc.x == 0 && eloc.y == 0 & eloc.z == 0) { + if(eloc.one.x == 0 && eloc.one.y == 0 & eloc.one.z == 0) { return; } @@ -77,8 +77,8 @@ public class Reach extends Check { boolean collided = false; //Using this to compare smaller numbers than Double.MAX_VALUE. Slightly faster List boxes = new ArrayList<>(); - if(eloc.oldLocations.size() > 0) { - for (KLocation oldLocation : eloc.oldLocations) { + if(eloc.two != null) { + for (KLocation oldLocation : eloc.one.interpolatedLocations) { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); @@ -87,7 +87,7 @@ public class Reach extends Check { } else box = box.expand(0.0325); boxes.add(box); } - for (KLocation oldLocation : eloc.interpolatedLocations) { + for (KLocation oldLocation : eloc.two.interpolatedLocations) { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); @@ -97,7 +97,7 @@ public class Reach extends Check { boxes.add(box); } } else { - for (KLocation oldLocation : eloc.interpolatedLocations) { + for (KLocation oldLocation : eloc.one.interpolatedLocations) { SimpleCollisionBox box = (SimpleCollisionBox) EntityData.getEntityBox(oldLocation.toVector(), target.one); @@ -163,10 +163,10 @@ public class Reach extends Check { if(collided) { hbuffer = 0; distance = Math.sqrt(distance); - if(distance > 3.05) { - if(++buffer > 2) { - flag("d=%.3f>-3.05", distance); - buffer = Math.min(2, buffer); + if(distance > 3.001) { + if(++buffer > 1) { + flag("d=%.3f>-3.0", distance); + buffer = Math.min(1, buffer); } } else if(buffer > 0) buffer-= 0.05f; @@ -175,7 +175,7 @@ public class Reach extends Check { debug("buffer: %.3f distance=%.2f hits=%s", buffer, distance, hits); } else { if (++hbuffer > 5) { - flag("%.1f;%.1f;%.1f", eloc.x, eloc.y, eloc.z); + flag("%.1f;%.1f;%.1f", eloc.one.x, eloc.one.y, eloc.one.z); } debug("Missed!"); } diff --git a/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java b/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java index 650eb22..f3b5f25 100644 --- a/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java +++ b/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java @@ -55,19 +55,23 @@ public class FlyA extends Check { double deltaPredict = MathUtils.getDelta(player.getMovement().getDeltaY(), predicted); if(!player.getInfo().isGeneralCancel() + && player.getMovement().getTeleportsToConfirm() == 0 && player.getInfo().getBlockAbove().isPassed(1) && !player.getInfo().isOnLadder() + && player.getInfo().climbTimer.isPassed(2) && !player.getBlockInfo().inWeb && !player.getBlockInfo().inScaffolding - && !player.getBlockInfo().inLiquid + && player.getInfo().getLastLiquid().isPassed(2) && !player.getBlockInfo().fenceBelow + && !player.getInfo().isServerGround() && !player.getBlockInfo().onHalfBlock && player.getInfo().getVelocity().isPassed(1) && !player.getBlockInfo().onSlime && deltaPredict > 0.001) { - if(++buffer > 5) { - buffer = 5; + if(++buffer > 3) { + buffer = 3; flag("dY=%.3f p=%.3f dx=%.3f", player.getMovement().getDeltaY(), predicted, player.getMovement().getDeltaXZ()); + cancel(); } } else buffer-= buffer > 0 ? 0.25f : 0; diff --git a/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java b/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java index 9223452..45db4b2 100644 --- a/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java +++ b/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java @@ -2,18 +2,21 @@ package dev.brighten.ac.check.impl.fly; import dev.brighten.ac.check.Action; import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.CheckType; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; -//@CheckData(name = "Fly (B)", type = CheckType.MOVEMENT) +@CheckData(name = "Fly (B)", type = CheckType.MOVEMENT) public class FlyB extends Check { public FlyB(APlayer player) { super(player); } private Timer lastNearGround = new TickTimer(); + private float buffer; @Action public void onFlying(WPacketPlayInFlying packet) { @@ -24,10 +27,14 @@ public class FlyB extends Check { && player.getMovement().getMoveTicks() > 3 && player.getInfo().getLastPlace().isPassed(3) && lastNearGround.isPassed(2) + && player.getInfo().lastLiquid.isPassed(1) + && player.getInfo().climbTimer.isPassed(1) && player.getInfo().getVelocity().isPassed(2) && player.getMovement().getDeltaY() > 0) { - flag("%.4f>-%.4f", - player.getMovement().getDeltaY(), player.getMovement().getLDeltaY()); - } + if(++buffer > 1) { + flag("%.4f>-%.4f", + player.getMovement().getDeltaY(), player.getMovement().getLDeltaY()); + } + } else if(buffer > 0) buffer-= 0.05f; } } diff --git a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java b/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java index a8a98ca..712dc22 100644 --- a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java +++ b/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java @@ -19,7 +19,7 @@ public class NoFallA extends Check { @Action public void onFlying(WPacketPlayInFlying packet) { - if(!player.getInfo().isGeneralCancel() + if(player.getInfo().isGeneralCancel() || (player.getMovement().getDeltaXZ() == 0 && player.getMovement().getDeltaY() == 0) || player.getBlockInfo().inLiquid || player.getMovement().getLastTeleport().isNotPassed(1) diff --git a/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java index be9de5f..b4e2a53 100644 --- a/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java +++ b/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java @@ -54,6 +54,7 @@ public class Horizontal extends Check { .getPossibleMaterials(new IntVector(lastUnderBlock.getX(), lastUnderBlock.getY(), lastUnderBlock.getZ())); if (!packet.isMoved() + || player.getMovement().getMoveTicks() == 0 || player.getInfo().getVelocity().isNotPassed(1) || player.getInfo().isGeneralCancel() || player.getBlockInfo().onClimbable @@ -254,10 +255,8 @@ public class Horizontal extends Check { buffer = Math.min(3.5f, buffer); //Ensuring we don't have a run-away buffer flag("smallest=%s b=%.1f to=%s dxz=%.2f", smallestDelta, buffer, player.getMovement().getTo().getLoc(), player.getMovement().getDeltaXZ()); - } else { - debug("bad movement"); cancel(); - } + } else debug("bad movement"); } else if (buffer > 0) buffer -= 0.1f; debug("smallest=%s pm=%.5f dxz=%.5f b=%.1f f/s=%.2f,%.2f soulsand=%s", smallestDelta, pmotion, diff --git a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java b/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java index 8b7bceb..a5897ea 100644 --- a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java +++ b/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java @@ -158,10 +158,10 @@ public class VelocityB extends Check { && player.getCreation().isPassed(3000L) && player.getMovement().getLastTeleport().isPassed(1) && !player.getBlockInfo().blocksNear) { - if(player.getInfo().lastUseItem.isPassed(2) && ++buffer > 20) { + if(player.getInfo().lastUseItem.isPassed(2) && ++buffer > 11) { flag("pct=%.2f buffer=%.1f forward=%.2f strafe=%.2f", ratio * 100, buffer, moveStrafe, moveForward); - buffer = 21; + buffer = 11; } } else if(buffer > 0) buffer-= 0.5; @@ -170,16 +170,8 @@ public class VelocityB extends Check { buffer, ticks, moveStrafe, moveForward, found, player.getInfo().getVelocity().getPassed()); - pvX *= drag; - pvZ *= drag; - - if(++ticks > 2) { - ticks = 0; - pvX = pvZ = 0; - } - - if(Math.abs(pvX) < 0.005) pvX = 0; - if(Math.abs(pvZ) < 0.005) pvZ = 0; + pvX = 0; + pvZ = 0; } } sprint = player.getInfo().isSprinting(); diff --git a/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java b/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java index 6ec0e65..050438b 100644 --- a/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java +++ b/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java @@ -5,39 +5,97 @@ import dev.brighten.ac.check.Check; import dev.brighten.ac.check.CheckData; import dev.brighten.ac.check.CheckType; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockPlace; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; +import dev.brighten.ac.utils.BlockUtils; +import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.MathUtils; -import org.bukkit.util.Vector; +import dev.brighten.ac.utils.Tuple; +import dev.brighten.ac.utils.math.cond.MaxDouble; +import dev.brighten.ac.utils.world.BlockData; +import dev.brighten.ac.utils.world.CollisionBox; +import dev.brighten.ac.utils.world.types.RayCollision; +import dev.brighten.ac.utils.world.types.SimpleCollisionBox; +import org.bukkit.Location; +import org.bukkit.block.Block; + +import java.util.Optional; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; @CheckData(name = "Block (A)", type = CheckType.INTERACT) public class BlockA extends Check { - public BlockA(APlayer player) { super(player); } - private int buffer; + private final MaxDouble verbose = new MaxDouble(20); + private Queue> blockPlacements = new LinkedBlockingQueue<>(); @Action - public void onPlace(WPacketPlayInBlockPlace packet) { - Vector dir = new Vector(packet.getDirection().getAdjacentX(), 0, packet.getDirection().getAdjacentZ()), - opposite = new Vector(packet.getDirection().opposite().getAdjacentX(), - 0, packet.getDirection().opposite().getAdjacentZ()); + public void onBlockPlace(WPacketPlayInBlockPlace event) { + Location loc = event.getBlockPos().toBukkitVector().toLocation(player.getBukkitPlayer().getWorld()); + Optional optionalBlock = BlockUtils.getBlockAsync(loc); - if(!packet.getItemStack().getType().isBlock()) return; + if(!optionalBlock.isPresent()) return; - Vector delta = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ()); + final Block block = optionalBlock.get(); + CollisionBox box = BlockData.getData(block.getType()).getBox(block, player.getPlayerVersion()); - double dist = delta.distance(dir), dist2 = opposite.distance(MathUtils.getDirection(player.getMovement().getTo().getLoc()).setY(0)); - boolean check = dist <= 1 && dist > 0.7 && dist2 >= 0.5 && dist2 < 1; + debug(event.getBlockPos().toString()); + if(!(box instanceof SimpleCollisionBox)) { + debug("Not SimpleCollisionBox: " + box.getClass().getSimpleName() + ";" + block.getType()); + return; + } - if(check && packet.getDirection().getAdjacentY() == 0 && player.getInfo().isSprinting()) { - if((buffer+= 4) != 15) { - flag("dist=%.3f dist2=%.3f placeVec=%s", dist, dist2, dir.toString()); - buffer = 14; - } - } else if(buffer > 0) buffer--; + final SimpleCollisionBox simpleBox = ((SimpleCollisionBox) box); - debug("dist=%.3f dist2=%.3f buffer=%s", dist, dist2, buffer); + if(Math.abs(simpleBox.yMax - simpleBox.yMin) != 1. + || Math.abs(simpleBox.xMax - simpleBox.xMin) != 1. + || Math.abs(simpleBox.zMax - simpleBox.zMin) != 1.) { + debug("not full block: x=%.1f y=%.1f z=%.1f", + Math.abs(simpleBox.xMax - simpleBox.xMin), + Math.abs(simpleBox.yMax - simpleBox.yMin), + Math.abs(simpleBox.zMax - simpleBox.zMin)); + return; + } + + blockPlacements.add(new Tuple<>(block, simpleBox.expand(0.1))); + } + + @Action + public void onFlying(WPacketPlayInFlying packet) { + Tuple tuple; + + while((tuple = blockPlacements.poll()) != null) { + final SimpleCollisionBox box = tuple.two.copy().expand(0.025); + final Block block = tuple.one; + + final KLocation to = player.getMovement().getTo().getLoc().clone(), + from = player.getMovement().getFrom().getLoc().clone(); + + to.y+= player.getInfo().sneaking ? (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_14) + ? 1.27f : 1.54f) : 1.62f; + from.y+= player.getInfo().lsneaking ? (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_14) + ? 1.27f : 1.54f) : 1.62f; + + final RayCollision rayTo = new RayCollision(to.toVector(), + MathUtils.getDirection(to)), + rayFrom = new RayCollision(from.toVector(), + MathUtils.getDirection(from)); + + final boolean collided = rayTo.isCollided(box) || rayFrom.isCollided(box); + + if(!collided) { + if(verbose.add() > 4) { + flag("to=[x=%.1f y=%.1f z=%.1f yaw=%.1f pitch=%.1f] loc=[%.1f,%.1f,%.1f]", + to.x, to.y, to.z, to.yaw, from.pitch, + block.getLocation().getX(), block.getLocation().getY(), block.getLocation().getZ()); + } + } else verbose.subtract(0.33); + + debug("collided=%s verbose=%s", collided, verbose.value()); + } } } diff --git a/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java b/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java index d65c67a..9e103cb 100644 --- a/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java +++ b/src/main/java/dev/brighten/ac/check/impl/world/BlockB.java @@ -22,9 +22,9 @@ public class BlockB extends Check { Block b = event.getBlock(); double ypos = b.getLocation().getY() - player.getBukkitPlayer().getLocation().getY(); double distance = player.getBukkitPlayer().getLocation().distance(b.getLocation()); - double ab_distance = player.getBukkitPlayer().getLocation().distance(ba.getLocation()) + 0.3; + double ab_distance = player.getBukkitPlayer().getLocation().distance(ba.getLocation()) + 0.4; - if (distance >= 1.4 && distance > ab_distance && ypos <= 0.5) { + if (distance >= 1.3 && distance > ab_distance && ypos <= 0.5) { flag("d:%.4f, ad:%.4f y=%.1f", distance, ab_distance, ypos); } } diff --git a/src/main/java/dev/brighten/ac/data/APlayer.java b/src/main/java/dev/brighten/ac/data/APlayer.java index b6f782f..76a6891 100644 --- a/src/main/java/dev/brighten/ac/data/APlayer.java +++ b/src/main/java/dev/brighten/ac/data/APlayer.java @@ -179,6 +179,7 @@ public class APlayer { } } + public int runKeepaliveAction(Consumer action) { return runKeepaliveAction(action, 0); } diff --git a/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java b/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java index 2eabfe8..a2f2780 100644 --- a/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java +++ b/src/main/java/dev/brighten/ac/data/handlers/GeneralInformation.java @@ -21,14 +21,15 @@ import java.util.Optional; @Getter @Setter public class GeneralInformation { - public Optional blockOnTo, blockBelow; + public Optional blockOnTo = Optional.empty(), blockBelow = Optional.empty(); public Timer lastMove = new TickTimer(), vehicleSwitch = new TickTimer(), lastAbilities = new TickTimer(), lastSneak = new TickTimer(), velocity = new TickTimer(), lastCancel = new TickTimer(), slimeTimer = new TickTimer(), lastElytra = new TickTimer(), blockAbove = new TickTimer(), - lastPlace = new TickTimer(), climbTimer = new TickTimer(), lastUseItem = new TickTimer(); + lastPlace = new TickTimer(), climbTimer = new TickTimer(), lastUseItem = new TickTimer(), + lastLiquid = new TickTimer(); public LivingEntity target; public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative, - sneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity; + sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity; public List nearbyEntities = Collections.emptyList(); public PastLocation targetPastLocation = new PastLocation(); public KLocation lastKnownGoodPosition; diff --git a/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java b/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java index ebeabfc..9bab5eb 100644 --- a/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java +++ b/src/main/java/dev/brighten/ac/data/handlers/MovementHandler.java @@ -49,6 +49,7 @@ public class MovementHandler { @Getter private final Timer lastTeleport = new TickTimer(), lastHighRate = new TickTimer(); + @Getter private int teleportsToConfirm; @Getter @@ -222,14 +223,14 @@ public class MovementHandler { // Resetting glide/sneak timers if (player.getInfo().isGliding()) player.getInfo().getLastElytra().reset(); if (player.getInfo().isSneaking()) player.getInfo().getLastSneak().reset(); + if (player.getBlockInfo().inLiquid) player.getInfo().getLastLiquid().reset(); player.getInfo().setGeneralCancel(player.getBukkitPlayer().getAllowFlight() || moveTicks == 0 || excuseNextFlying + || player.getBukkitPlayer().isFlying() || player.getInfo().isCanFly() || player.getInfo().isCreative() - || lastTeleport.isNotPassed(2) - || teleportsToConfirm > 0 || player.getInfo().isInVehicle() || player.getInfo().getVehicleSwitch().isNotPassed(1) || player.getBukkitPlayer().isSleeping() diff --git a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java index 7517292..e3926a8 100644 --- a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java +++ b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java @@ -6,13 +6,18 @@ import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntity; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityTeleport; import dev.brighten.ac.utils.EntityLocation; +import dev.brighten.ac.utils.Tuple; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; import lombok.RequiredArgsConstructor; +import lombok.val; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import java.util.*; +import java.util.EnumSet; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @RequiredArgsConstructor @@ -20,7 +25,7 @@ public class EntityLocationHandler { private final APlayer data; - private final Map entityLocationMap = new ConcurrentHashMap<>(); + private final Map> entityLocationMap = new ConcurrentHashMap<>(); private final Timer lastFlying = new MillisTimer(); public int streak; @@ -36,7 +41,7 @@ public class EntityLocationHandler { * @param entity Entity * @return Optional */ - public Optional getEntityLocation(Entity entity) { + public Optional> getEntityLocation(Entity entity) { return Optional.ofNullable(entityLocationMap.get(entity.getUniqueId())); } @@ -51,7 +56,10 @@ public class EntityLocationHandler { streak = 1; } - entityLocationMap.values().forEach(EntityLocation::interpolateLocation); + entityLocationMap.values().forEach(eloc -> { + if(eloc.one != null) eloc.one.interpolateLocation(); + if(eloc.two != null) eloc.two.interpolateLocation(); + }); lastFlying.reset(); } @@ -71,15 +79,14 @@ public class EntityLocationHandler { if(!allowedEntityTypes.contains(entity.getType())) return; - EntityLocation eloc = entityLocationMap.computeIfAbsent(entity.getUniqueId(), - key -> new EntityLocation(entity)); + val tuple = entityLocationMap.computeIfAbsent(entity.getUniqueId(), + key -> new Tuple<>(new EntityLocation(entity), null)); + + EntityLocation eloc = tuple.one; + + tuple.two = tuple.one.clone(); runAction(entity, () -> { - eloc.oldLocations.addAll(eloc.interpolatedLocations); - - while(eloc.interpolatedLocations.size() > 1) { - eloc.interpolatedLocations.removeFirst(); - } //We don't need to do version checking here. Atlas handles this for us. eloc.newX += packet.getX(); eloc.newY += packet.getY(); @@ -106,14 +113,14 @@ public class EntityLocationHandler { if(!allowedEntityTypes.contains(entity.getType())) return; - EntityLocation eloc = entityLocationMap.computeIfAbsent(entity.getUniqueId(), - key -> new EntityLocation(entity)); + val tuple = entityLocationMap.computeIfAbsent(entity.getUniqueId(), + key -> new Tuple<>(new EntityLocation(entity), null)); + + EntityLocation eloc = tuple.one; + + tuple.two = tuple.one.clone(); runAction(entity, () -> { - eloc.oldLocations.addAll(eloc.interpolatedLocations); - while(eloc.interpolatedLocations.size() > 1) { - eloc.interpolatedLocations.removeFirst(); - } if(data.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) { if (!(Math.abs(eloc.x - packet.getX()) >= 0.03125D) && !(Math.abs(eloc.y - packet.getY()) >= 0.015625D) @@ -163,12 +170,12 @@ public class EntityLocationHandler { data.runInstantAction(ia -> { if(!ia.isEnd()) { action.run(); - } else entityLocationMap.get(entity.getUniqueId()).oldLocations.clear(); + } else entityLocationMap.get(entity.getUniqueId()).two = null; }); } else { data.runKeepaliveAction(keepalive -> action.run()); data.runKeepaliveAction(keepalive -> - entityLocationMap.get(entity.getUniqueId()).oldLocations.clear(), 1); + entityLocationMap.get(entity.getUniqueId()).two = null, 1); } } } diff --git a/src/main/java/dev/brighten/ac/handler/PacketHandler.java b/src/main/java/dev/brighten/ac/handler/PacketHandler.java index 4c077c7..8b26fd2 100644 --- a/src/main/java/dev/brighten/ac/handler/PacketHandler.java +++ b/src/main/java/dev/brighten/ac/handler/PacketHandler.java @@ -299,5 +299,10 @@ public class PacketHandler { } player.callPacket(packetObject, timestamp); + + // Post flying settings + if(type.equals(PacketType.FLYING)) { + player.getInfo().lsneaking = player.getInfo().sneaking; + } } } diff --git a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java index eb9dd4b..35f271d 100644 --- a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java +++ b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java @@ -6,8 +6,11 @@ import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockPlace; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutBlockChange; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutMultiBlockChange; import dev.brighten.ac.utils.BlockUtils; +import dev.brighten.ac.utils.Materials; import dev.brighten.ac.utils.Tuple; +import dev.brighten.ac.utils.XMaterial; import dev.brighten.ac.utils.math.IntVector; +import dev.brighten.ac.utils.world.types.RayCollision; import lombok.RequiredArgsConstructor; import lombok.val; import org.bukkit.Material; @@ -32,23 +35,32 @@ public class BlockUpdateHandler { */ public void onPlace(WPacketPlayInBlockPlace place) { // Could not possibly be a block placement as it's not a block a player is holding. - if(!place.getItemStack().getType().isBlock()) return; + IntVector pos = place.getBlockPos().clone(); - IntVector pos = place.getBlockPos(); + // Some dumbass shit I have to do because Minecraft with Lilypads + if(place.getItemStack() != null && XMaterial.matchXMaterial(place.getItemStack().getType()).equals(XMaterial.LILY_PAD)) { + RayCollision rayCollision = new RayCollision(player.getBukkitPlayer().getEyeLocation().toVector(), + player.getBukkitPlayer().getLocation().getDirection()); + Block block = rayCollision.getClosestBlockOfType(player.getBukkitPlayer().getWorld(), Materials.LIQUID, 5); - // Not an actual block place, just an interact - if(pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) return; + if(block != null) { + if (Materials.checkFlag(block.getType(), Materials.WATER)) { + pos = new IntVector(block.getX(), block.getY() + 1, block.getZ()); + } + } else return; + } // Not an actual block place, just an interact + else if(pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) { + return; + } else { + pos.setX(pos.getX() + place.getDirection().getAdjacentX()); + pos.setY(pos.getY() + place.getDirection().getAdjacentY()); + pos.setZ(pos.getZ() + place.getDirection().getAdjacentZ()); + } player.getInfo().getLastPlace().reset(); - pos.setX(pos.getX() + place.getDirection().getAdjacentX()); - pos.setY(pos.getY() + place.getDirection().getAdjacentY()); - pos.setZ(pos.getZ() + place.getDirection().getAdjacentZ()); - - Deque possible = getPossibleMaterials(place.getBlockPos()); + Deque possible = getPossibleMaterials(pos); possible.add(place.getItemStack().getType()); - - player.getBukkitPlayer().sendMessage("Placed possible: " + possible + ";" + place.getBlockPos()); } /** diff --git a/src/main/java/dev/brighten/ac/utils/EntityLocation.java b/src/main/java/dev/brighten/ac/utils/EntityLocation.java index 4a00fd8..b47c14e 100644 --- a/src/main/java/dev/brighten/ac/utils/EntityLocation.java +++ b/src/main/java/dev/brighten/ac/utils/EntityLocation.java @@ -17,9 +17,8 @@ public class EntityLocation { public float newYaw, newPitch, yaw, pitch; public int increment = 0; public boolean sentTeleport = false; - public KLocation oldLocation, location; - public Deque oldLocations = new EvictingList<>(3), - interpolatedLocations = new EvictingList<>(3); + public KLocation location; + public Deque interpolatedLocations = new EvictingList<>(2); public void interpolateLocations() { increment = 3; diff --git a/src/main/java/dev/brighten/ac/utils/Helper.java b/src/main/java/dev/brighten/ac/utils/Helper.java index 3e4b259..5f0ad08 100644 --- a/src/main/java/dev/brighten/ac/utils/Helper.java +++ b/src/main/java/dev/brighten/ac/utils/Helper.java @@ -40,8 +40,8 @@ public class Helper { return PlayerSizeHandler.instance.bounds(player, x, y, z); } - public static void drawRay(RayCollision collision, EnumParticle particle, Collection players) { - for (double i = 0; i < 8; i += 0.2) { + public static void drawRay(RayCollision collision, double distance, EnumParticle particle, Collection players) { + for (double i = 0; i < 3; i += 0.2) { float fx = (float) (collision.originX + (collision.directionX * i)); float fy = (float) (collision.originY + (collision.directionY * i)); float fz = (float) (collision.originZ + (collision.directionZ * i)); diff --git a/src/main/java/dev/brighten/ac/utils/MathUtils.java b/src/main/java/dev/brighten/ac/utils/MathUtils.java index db3ebc0..f3418cb 100644 --- a/src/main/java/dev/brighten/ac/utils/MathUtils.java +++ b/src/main/java/dev/brighten/ac/utils/MathUtils.java @@ -33,6 +33,10 @@ public class MathUtils { current - (float)Math.floor(current / previous) * previous); } + public static double lerp(double lerpAmount, double start, double end) { + return start + lerpAmount * (end - start); + } + public static boolean isScientificNotation(double value) { return String.valueOf(value).contains("E"); } diff --git a/src/main/java/dev/brighten/ac/utils/world/BlockData.java b/src/main/java/dev/brighten/ac/utils/world/BlockData.java index 321557c..104ae42 100644 --- a/src/main/java/dev/brighten/ac/utils/world/BlockData.java +++ b/src/main/java/dev/brighten/ac/utils/world/BlockData.java @@ -96,7 +96,10 @@ public enum BlockData { || mat.name().contains("HEAD")).toArray(Material[]::new)), _DOOR(new DoorHandler(), Arrays.stream(Material.values()) - .filter(mat -> !mat.name().contains("TRAP") && mat.name().contains("DOOR")) + .filter(mat -> !mat.name().contains("TRAP") && !mat.name().contains("ITEM") + && mat.name().contains("DOOR") + // Potential cause for ClassCastException to MaterialData instead of Door + && !mat.name().equals("WOOD_DOOR") && !mat.name().equals("IRON_DOOR")) .toArray(Material[]::new)), _HOPPER(new HopperBounding(), XMaterial.HOPPER.parseMaterial()), @@ -216,7 +219,7 @@ public enum BlockData { if (v.isBelow(ProtocolVersion.V1_9)) return new SimpleCollisionBox(0.0f, 0.0F, 0.0f, 1.0f, 0.015625F, 1.0f); return new SimpleCollisionBox(0.0625, 0.0F, 0.0625, 0.9375, 0.015625F, 0.9375); - }, MiscUtils.match("WATER_LILY")), + }, XMaterial.LILY_PAD.parseMaterial()), _BED(new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.5625, 1.0F), Arrays.stream(XMaterial.values()).filter(mat -> mat.name().contains("BED") && !mat.name().contains("ROCK")) diff --git a/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java b/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java index acd8ff0..889513c 100644 --- a/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java +++ b/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java @@ -136,7 +136,7 @@ public class RayCollision implements CollisionBox { @Override public void draw(EnumParticle particle, Player... players) { - Helper.drawRay(this, particle, Arrays.asList(players)); + Helper.drawRay(this, 3, particle, Arrays.asList(players)); } public List boxesOnRay(World world, double distance) { @@ -174,6 +174,40 @@ public class RayCollision implements CollisionBox { return boxes; } + public Block getClosestBlockOfType(World world, int bitmask, double distance) { + int amount = Math.round((float) (distance / 0.5)); + + Location[] locs = new Location[Math.max(2, amount)]; //We do a max to prevent NegativeArraySizeException. + boolean primaryThread = Bukkit.isPrimaryThread(); + ProtocolVersion version = ProtocolVersion.getGameVersion(); + + for (int i = 0; i < locs.length; i++) { + double ix = i / 2d; + + double fx = (originX + (directionX * ix)); + double fy = (originY + (directionY * ix)); + double fz = (originZ + (directionZ * ix)); + + Location loc = new Location(world, fx, fy, fz); + + Block block = primaryThread ? loc.getBlock() : BlockUtils.getBlock(loc); + + if (block == null) continue; + + final Material type = block.getType(); + + if (!Materials.checkFlag(type, bitmask)) continue; + + CollisionBox box = BlockData.getData(type).getBox(block, version); + + if (!isCollided(box)) continue; + + return block; + } + return null; + } + + @Override public void downCast(List list) {/*Do Nothing, Ray cannot be down-casted*/}