Fixing tons of issues

- Fixing Velocity B falses
- Fixing lilypad false positives by accounting for it on interact.
- New Block (A) with block place interaction check
- Fixing Block B false positive.
- Fixing Horizontal false positive and bypass
- Fixing Fly (B) on liquids and climables.
- Fixing Fly (A) on liquids and climables
This commit is contained in:
Dawson
2022-08-22 16:37:55 -04:00
parent dccbdc0552
commit bac904f852
19 changed files with 228 additions and 101 deletions
@@ -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<EntityLocation> optionalEloc = player.getEntityLocationHandler().getEntityLocation(target.one);
Optional<Tuple<EntityLocation, EntityLocation>> optionalEloc = player.getEntityLocationHandler().getEntityLocation(target.one);
if(!optionalEloc.isPresent()) {
return;
}
final EntityLocation eloc = optionalEloc.get();
final Tuple<EntityLocation, EntityLocation> 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<SimpleCollisionBox> 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!");
}
@@ -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;
@@ -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;
}
}
@@ -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)
@@ -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,
@@ -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();
@@ -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<Tuple<Block, SimpleCollisionBox>> 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<Block> 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<Block, SimpleCollisionBox> 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());
}
}
}
@@ -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);
}
}
@@ -179,6 +179,7 @@ public class APlayer {
}
}
public int runKeepaliveAction(Consumer<KeepAlive> action) {
return runKeepaliveAction(action, 0);
}
@@ -21,14 +21,15 @@ import java.util.Optional;
@Getter
@Setter
public class GeneralInformation {
public Optional<Block> blockOnTo, blockBelow;
public Optional<Block> 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<Entity> nearbyEntities = Collections.emptyList();
public PastLocation targetPastLocation = new PastLocation();
public KLocation lastKnownGoodPosition;
@@ -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()
@@ -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<UUID, EntityLocation> entityLocationMap = new ConcurrentHashMap<>();
private final Map<UUID, Tuple<EntityLocation, EntityLocation>> entityLocationMap = new ConcurrentHashMap<>();
private final Timer lastFlying = new MillisTimer();
public int streak;
@@ -36,7 +41,7 @@ public class EntityLocationHandler {
* @param entity Entity
* @return Optional<EntityLocation></EntityLocation>
*/
public Optional<EntityLocation> getEntityLocation(Entity entity) {
public Optional<Tuple<EntityLocation, EntityLocation>> 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);
}
}
}
@@ -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;
}
}
}
@@ -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<Material> possible = getPossibleMaterials(place.getBlockPos());
Deque<Material> possible = getPossibleMaterials(pos);
possible.add(place.getItemStack().getType());
player.getBukkitPlayer().sendMessage("Placed possible: " + possible + ";" + place.getBlockPos());
}
/**
@@ -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<KLocation> oldLocations = new EvictingList<>(3),
interpolatedLocations = new EvictingList<>(3);
public KLocation location;
public Deque<KLocation> interpolatedLocations = new EvictingList<>(2);
public void interpolateLocations() {
increment = 3;
@@ -40,8 +40,8 @@ public class Helper {
return PlayerSizeHandler.instance.bounds(player, x, y, z);
}
public static void drawRay(RayCollision collision, EnumParticle particle, Collection<? extends Player> players) {
for (double i = 0; i < 8; i += 0.2) {
public static void drawRay(RayCollision collision, double distance, EnumParticle particle, Collection<? extends Player> 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));
@@ -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");
}
@@ -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"))
@@ -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<CollisionBox> 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<SimpleCollisionBox> list) {/*Do Nothing, Ray cannot be down-casted*/}