lots of changes

- Added inventory check type in API
- Added Inventory (A) detection
- Added Inventory (B) detection
- Improved the flag rate and accuracy of Aim check
- Added other bot check that flies around player to Killaura (Bot) to account for clients not doing a proper RayCast and opting to just turn on attack invisibles and mobs.
- Added comments to Killaura (Trace)
- Optimized Fly (A) detection and added comments
- Fixed false positive caused by incorrect acceleration prediction in Fly (A). I used the current onGround when that is actually never a factor in vertical acceleration, only the product of what the client moves to.
- Removed "optimization" in Fly (A) that basically just stopped prediction when client sends onGround and sets motionY to 0. Changed this behavior to it still do the acceleration subtraction 0.08 times 0.98 but run a collision check that will set the y to 0 if necessary; more closely replicates vanilla mechanics.
- Optimized Horizontal check and fixing field name motionX to more appropriate motion name.
- Optimized Velocity (B) by using current Horizontal optimizations and applying them to this check.
- Moved logs command in AnticheatCommand class to its own LogsCommand class. Added other kinds of logs commands like /kauri logs paste to send it to pastebin and /kauri logs web to view logs on the website.
- Fixed error on plugin shutdown caused by NPE. This was due to an order of operations issue with PlayerRegistry and PacketHandler
- Added wrapper for PacketPlayInWindowClick, PacketPlayInClientCommand.
- Added KLocation#getDirection() method as a shorthand to doing MathUtils.getDirection(KLocation field);
- Moved Helper#angularDistance to MathUtils#angularDistance
- Added CollisionBox#downcast() method as a shorthand method to not have to create a new List field every time I want to get the downcasted SimpleCollisionBox of any wrapped CollisionBox.
This commit is contained in:
Dawson
2022-11-29 10:00:44 -05:00
parent dfb04d50a2
commit a04577b194
35 changed files with 1154 additions and 582 deletions
+13 -12
View File
@@ -114,16 +114,18 @@ public class Anticheat extends LoaderPlugin {
getAnticheatConfig().set("database.password", UUID.randomUUID().toString());
}
this.keepaliveProcessor = new KeepaliveProcessor();
this.fakeTracker = new FakeEntityTracker();
this.checkManager = new CheckManager();
this.playerRegistry = new PlayerRegistry();
HandlerAbstract.init();
Bukkit.getOnlinePlayers().forEach(playerRegistry::generate);
this.packetHandler = new PacketHandler();
logManager = new LoggerManager();
keepaliveProcessor.start();
HandlerAbstract.init();
logManager.init();
alog(Color.Green + "Loading WorldInfo system...");
@@ -136,19 +138,12 @@ public class Anticheat extends LoaderPlugin {
e.printStackTrace();
}
fakeTracker = new FakeEntityTracker();
Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::add);
}
public void onDisable() {
scheduler.shutdown();
commandManager.unregisterCommands();
// Unregistering packet listeners for players
HandlerAbstract.getHandler().shutdown();
HandlerList.unregisterAll(getPluginInstance());
packetProcessor.shutdown();
packetProcessor = null;
checkManager.getCheckClasses().clear();
Check.alertsEnabled.clear();
Check.debugInstances.clear();
@@ -158,9 +153,6 @@ public class Anticheat extends LoaderPlugin {
ProtocolAPI.INSTANCE = null;
tps = null;
fakeTracker.despawnAll();
fakeTracker = null;
logManager.shutDown();
Bukkit.getScheduler().cancelTasks(getPluginInstance());
@@ -176,6 +168,15 @@ public class Anticheat extends LoaderPlugin {
throw new RuntimeException(e);
}
fakeTracker.despawnAll();
fakeTracker = null;
// Unregistering packet listeners for players
HandlerAbstract.getHandler().shutdown();
HandlerList.unregisterAll(getPluginInstance());
packetProcessor.shutdown();
packetProcessor = null;
AnticheatAPI.INSTANCE = null;
onTickEnd.clear();
@@ -49,8 +49,6 @@ public class Aim extends Check {
return;
}
boolean increasing = deltaYaw > deltaX || deltaPitch > deltaY;
boolean flagged = false;
if(player.getMovement().getPitchGCD() < 0.007 && lastGrid.isPassed()
&& !player.getMovement().isCinematic()
@@ -69,7 +67,7 @@ public class Aim extends Check {
/*
* This is an attempt to reverse the logistics of cinematic camera without having to run a full on prediction using
* mouse filters. Otherwise, we would need to run more heavy calculations which is not really production friendly.
* It may be more accurate but it is not really worth it if in the end of the day we're eating server performance.
* It may be more accurate, but it is not really worth it if in the end of the day we're eating server performance.
*/
protected static double getGrid(final List<Float> entry) {
/*
@@ -5,6 +5,7 @@ import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.WAction;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInArmAnimation;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity;
import lombok.val;
@@ -16,6 +17,12 @@ public class KABot extends Check {
}
private int buffer = 0;
private float buffer2;
WAction<WPacketPlayInArmAnimation> arm = packet -> {
// We want to go ahead and lower the buffer every time they miss the bot to help prevent false positives
if(buffer2 > 0) buffer2-= 0.25f;
};
WAction<WPacketPlayInUseEntity> packet = packet -> {
val optional = player.getEntityLocationHandler().getFakeMob(packet.getEntityId());
@@ -25,5 +32,12 @@ public class KABot extends Check {
flag("Attacked player without attacking bot!");
}
} else buffer = 0;
if(player.getMob().getEntityId() == packet.getEntityId()) {
if(++buffer2 > 3) {
buffer = 2;
flag("Player attacked bot");
}
} else buffer2 = 0;
};
}
@@ -8,13 +8,18 @@ import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.EntityData;
import dev.brighten.ac.utils.world.types.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.util.Vector;
/**
* @author funkemunky
* @since 12/31/2020
* This check is designed to detect an attack through solid blocks, which would be impossible under normal
* circumstances.
*/
@CheckData(name = "KillAura (Trace)", checkId = "katrace", type = CheckType.KILLAURA)
public class KATrace extends Check {
@@ -22,6 +27,7 @@ public class KATrace extends Check {
public KATrace(APlayer player) {
super(player);
// We're caching the player's sneak height here, so we don't have to do it every time.
sneakY = player.getPlayerVersion().isBelow(ProtocolVersion.V1_14) ? 1.27f : 1.54f;
}
@@ -32,33 +38,42 @@ public class KATrace extends Check {
|| packet.getAction() != WPacketPlayInUseEntity.EnumEntityUseAction.ATTACK)
return;
// If the player isn't looking at the target, then a raytrace check wouldn't work.
if(player.getMovement().getLookingAtBoxes().size() == 0) {
debug("No boxes to look at!");
buffer = 0;
return;
}
SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget().getLocation(),
// Getting the target's bounding box
SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget()
.getLocation(),
player.getInfo().target);
if(targetBox == null) return;
final KLocation origin = player.getMovement().getTo().getLoc().clone();
// Setting the player's eye height based on their sneak status
origin.y+= player.getInfo().isSneaking() ? sneakY : 1.62f;
final Vector originVec = origin.toVector();
RayCollision collision = new RayCollision(originVec, MathUtils.getDirection(origin));
// Setting a trace based on their view direction
RayCollision collision = new RayCollision(originVec, origin.getDirection());
Vector targetPoint = collision.collisionPoint(targetBox);
//If the ray isn't collided, we might as well not run this check. Just a simple boxes on array check
if(targetPoint == null) return;
// The distance bteween the player's eye and the intersect point of the ray and the target's bounding box.
// We don't do the square root to save on performance.
double dist = originVec.distanceSquared(targetPoint);
boolean rayCollidedOnBlock = false;
// Grabbing the boxes found on the ray trace. This is already grabbed in MovementProcessor so we can use
// the result from there in this check to save on compute time.
synchronized (player.getMovement().getLookingAtBoxes()) {
for (CollisionBox lookingAtBox : player.getMovement().getLookingAtBoxes()) {
if((lookingAtBox instanceof SimpleCollisionBox)) {
@@ -67,6 +82,7 @@ public class KATrace extends Check {
|| box.maxX % 1 != 0 || box.maxY % 1 != 0 || box.maxZ % 1 != 0)
continue;
// We want to shrink the box slightly since there is a bit of a margin of error in the ray trace.
Vector point = collision.collisionPoint(box.copy().shrink(0.005f, 0.005f, 0.005f));
if (point != null && originVec.distanceSquared(point) < dist - 0.2) {
@@ -78,6 +94,7 @@ public class KATrace extends Check {
}
if(rayCollidedOnBlock) {
// The buffer is here to smooth out false positives.
if(++buffer > 2) {
flag("Attacker hit through block! [b=%s s=%s]",
buffer, player.getMovement().getLookingAtBoxes().size());
@@ -0,0 +1,19 @@
package dev.brighten.ac.check.impl.misc.inventory;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.data.APlayer;
/**
* Check runs inside {@link dev.brighten.ac.check.impl.movement.speed.Horizontal}
*/
@CheckData(name = "Inventory (A)", checkId = "inventoryA", type = CheckType.INVENTORY)
public class InventoryA extends Check {
public InventoryA(APlayer player) {
super(player);
}
public int buffer;
}
@@ -0,0 +1,24 @@
package dev.brighten.ac.check.impl.misc.inventory;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.WAction;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInWindowClick;
@CheckData(name = "Inventory (B)", checkId = "inventoryB", type = CheckType.INVENTORY)
public class InventoryB extends Check {
public InventoryB(APlayer player) {
super(player);
}
WAction<WPacketPlayInWindowClick> windowClick = packet -> {
if(!player.getInfo().isInventoryOpen()) {
flag("Inventory not open");
}
debug("inv=%s", player.getInfo().isInventoryOpen());
};
}
@@ -36,10 +36,30 @@ public class FlyA extends Check {
return;
}
// This stuff will false flag the detection and cause a buffer decrease, so we're just going to prevent
// the check from processing to save resources.
if(player.getInfo().isGeneralCancel()
|| player.getMovement().getTeleportsToConfirm() > 0
|| player.getInfo().isOnLadder()
|| player.getInfo().climbTimer.isNotPassed(2)
|| player.getBlockInfo().inWeb
|| player.getBlockInfo().inScaffolding
|| player.getInfo().getLastLiquid().isNotPassed(2)
|| player.getBlockInfo().fenceBelow
|| !player.getInfo().worldLoaded
|| player.getBlockInfo().onHalfBlock
|| player.getInfo().getVelocity().isNotPassed(1)
|| player.getBlockInfo().onSlime) {
if(buffer > 0) buffer-= 0.25f;
return;
}
boolean onGround = player.getMovement().getTo().isOnGround() && player.getBlockInfo().blocksBelow,
fromGround = player.getMovement().getFrom().isOnGround();
double lDeltaY = fromGround ? 0 : player.getMovement().getLDeltaY();
double predicted = onGround ? lDeltaY : (lDeltaY - 0.08) * mult;
double lDeltaY = player.getMovement().getLDeltaY();
// Initial acceleration prediction the vanilla client does
double predicted = (lDeltaY - 0.08) * mult;
if(fromGround && !onGround && player.getMovement().getDeltaY() > 0) {
predicted = MovementUtils.getJumpHeight(player);
@@ -50,6 +70,9 @@ public class FlyA extends Check {
boolean willBeWeirdNext = didNextPrediction;
didNextPrediction = false;
// Since the player skipped a flying packet, the client likely didn't send a small position update
// This is to go ahead and account for that just in case the >60ms delta is caused by a < 9.0E-4 small movement
// on all axis. See net.minecraft.client.entity.EntityPlayerSP#onUpdateWalkingPlayer method
if(lastPos.isPassed(60L)) {
double toCheck = (predicted - 0.08) * mult;
@@ -60,6 +83,7 @@ public class FlyA extends Check {
}
}
// Vanilla wrapping the deltaY to 0 if it's less than a certain amount.
if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) {
if(Math.abs(predicted) < 0.005)
predicted = 0;
@@ -68,6 +92,8 @@ public class FlyA extends Check {
debug("Setting y to 0");
}
// Vanilla collision algorithm to correct any false positives related to modified deltaY related to ground
// collision.
if(player.getBlockInfo().blocksBelow || player.getInfo().isNearGround()) {
List<SimpleCollisionBox> list = Helper.getCollisions(player,
player.getMovement().getFrom().getBox().copy().addCoord(player.getMovement().getDeltaX(), predicted,
@@ -90,20 +116,13 @@ public class FlyA extends Check {
double deltaPredict = MathUtils.getDelta(player.getMovement().getDeltaY(), predicted);
if(!player.getInfo().isGeneralCancel()
&& player.getMovement().getTeleportsToConfirm() == 0
&& !player.getInfo().isOnLadder()
&& player.getInfo().climbTimer.isPassed(2)
&& !player.getBlockInfo().inWeb
&& !willBeWeirdNext
&& !player.getBlockInfo().inScaffolding
&& player.getInfo().getLastLiquid().isPassed(2)
&& !player.getBlockInfo().fenceBelow
&& player.getInfo().worldLoaded
&& !player.getBlockInfo().onHalfBlock
&& player.getInfo().getVelocity().isPassed(1)
&& !player.getBlockInfo().onSlime
&& deltaPredict > (player.getInfo().getClientAirTicks() < 3 ? 0.017 : 0.001)) {
// We want it to be at 0.005 since that is the maximum variance from loss of precision
// We also don't really want to flag if there was a skip in flying related to < 9.0E-4 movement.
if(!willBeWeirdNext
&& deltaPredict > 0.005) {
// This slight buffer is to account for anything this check may have not accounted for
// It is not a permanent fix. However, Java Edition is quite a fickle game to work with; it's quite
// difficult to reliably check that vanilla behavior is vanilla behavior without weird outliers.
if(++buffer > 1) {
buffer = 1;
flag("dY=%.3f p=%.3f dx=%.3f", player.getMovement().getDeltaY(), predicted,
@@ -112,8 +131,10 @@ public class FlyA extends Check {
}
} else buffer-= buffer > 0 ? 0.25f : 0;
debug("dY=%.3f p=%.3f dx=%.3f b=%s velocity=%s", player.getMovement().getDeltaY(), predicted,
player.getMovement().getDeltaXZ(), buffer, player.getInfo().getVelocity().getPassed());
debug("dY=%.3f p=%.3f dx=%.3f b=%s velocity=%s g=%s bbelow=%s ng=%s",
player.getMovement().getDeltaY(), predicted, player.getMovement().getDeltaXZ(), buffer,
player.getInfo().getVelocity().getPassed(), packet.isOnGround(), player.getBlockInfo().blocksBelow,
player.getInfo().isNearGround());
lastPos.reset();
};
@@ -4,6 +4,7 @@ import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.WAction;
import dev.brighten.ac.check.impl.misc.inventory.InventoryA;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
@@ -21,6 +22,7 @@ import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@CheckData(name = "Horizontal", checkId = "horizontala", type = CheckType.MOVEMENT, experimental = true)
public class Horizontal extends Check {
@@ -31,7 +33,7 @@ public class Horizontal extends Check {
private int lastFlying;
private KLocation previousFrom;
private Vector motionX = new Vector(0, 0, 0);
private Vector motion = new Vector(0, 0, 0);
private static final boolean[] TRUE_FALSE = new boolean[]{true, false};
public double strafe, forward;
@@ -44,6 +46,12 @@ public class Horizontal extends Check {
check:
{
if(!packet.isMoved() || (player.getMovement().getDeltaXZ() == 0)) {
forward = strafe = 0;
}
Optional<InventoryA> inventoryA = find(InventoryA.class);
if (!packet.isMoved()
|| player.getMovement().getMoveTicks() == 0
|| player.getMovement().getLastTeleport().isNotPassed(1)
@@ -54,8 +62,12 @@ public class Horizontal extends Check {
|| player.getMovement().getTo().getLoc()
.distanceSquared(player.getMovement().getFrom().getLoc()) > 2500
|| player.getInfo().lastLiquid.isNotPassed(2)) {
motionX = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(),
motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(),
player.getMovement().getDeltaZ());
inventoryA.ifPresent(check -> {
if(check.buffer > 0)
check.buffer--;
});
break check;
}
@@ -70,6 +82,9 @@ public class Horizontal extends Check {
double precision = getPrecision();
TagsBuilder tags = null;
val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED);
val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW);
for (Iteration it : iterations) {
TagsBuilder tagsBuilder = new TagsBuilder();
@@ -100,9 +115,17 @@ public class Horizontal extends Check {
double aiMoveSpeed = player.getBukkitPlayer().getWalkSpeed() / 2;
float drag = 0.91f;
double lmotionX = motionX.getX(),
lmotionY = motionX.getY(),
lmotionZ = motionX.getZ();
double lmotionX = motion.getX(),
lmotionY = motion.getY(),
lmotionZ = motion.getZ();
double totalMotion = Math.abs(lmotionX) + Math.abs(lmotionY) + Math.abs(lmotionZ);
if(totalMotion > 30) {
motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(),
player.getMovement().getDeltaZ());
return;
}
lmotionY -= 0.08;
lmotionY *= 0.98f;
@@ -152,17 +175,12 @@ public class Horizontal extends Check {
tagsBuilder.addTag("sprinting");
}
if (player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED)) {
aiMoveSpeed += (player.getPotionHandler().getEffectByType(PotionEffectType.SPEED)
.map(pe -> pe.getAmplifier() + 1)).orElse(0)
* 0.20000000298023224D * aiMoveSpeed;
if (speed.isPresent()) {
aiMoveSpeed += (speed.get().getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
tagsBuilder.addTag("speedPotion");
}
if (player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW)) {
aiMoveSpeed += (player.getPotionHandler().getEffectByType(PotionEffectType.SLOW)
.map(pe -> pe.getAmplifier() + 1)).orElse(0)
* -0.15000000596046448D * aiMoveSpeed;
if (slow.isPresent()) {
aiMoveSpeed += (slow.get().getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
tagsBuilder.addTag("slowPotion");
}
@@ -439,17 +457,11 @@ public class Horizontal extends Check {
double delta = (diffX * diffX) + (diffZ * diffZ);
double deltaAll = delta + (diffY * diffY);
if(forward > 0 && strafe == 0 && !it.attack && !it.sneaking && !it.using && it.sprinting
&& !it.edge && !it.jumped) {
debug("Shit: tags=[%s] diffX=%.6f diffZ=%.6f oy=%.3f ly=%.3f", tagsBuilder.build(), diffX, diffZ,
originalY, lmotionY);
}
if (delta < smallestDeltaXZ) {
smallDelta = deltaAll;
//smallDelta = deltaAll;
smallestDeltaXZ = delta;
predictedMotionX = lmotionX;
predictedMotionY = lmotionY;
//predictedMotionY = lmotionY;
predictedMotionZ = lmotionZ;
tags = tagsBuilder;
@@ -459,9 +471,9 @@ public class Horizontal extends Check {
this.forward = it.f * 0.98f;
if (precision < 1E-11)
motionX = new Vector(lmotionX, lmotionY, lmotionZ);
motion = new Vector(lmotionX, lmotionY, lmotionZ);
else
motionX = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ());
motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ());
if (player.getInfo().getLastCancel().isPassed(2))
player.getInfo()
@@ -476,10 +488,24 @@ public class Horizontal extends Check {
}
}
}
// Inventory (A) check
inventoryA.ifPresent(check -> {
if((strafe != 0 || forward != 0) && player.getInfo().isInventoryOpen()) {
if(check.buffer++ > 6) {
check.buffer = Math.min(8, check.buffer);
check.flag("s=%.2f f=%.2f", strafe, forward);
}
} else if(check.buffer > 0) check.buffer--;
check.debug("buffer=%d inv=%s s=%.2f f=%.2f", check.buffer,
player.getInfo().isInventoryOpen(), strafe, forward);
});
iterations.clear();
if (!found) {
motionX = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ());
motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ());
}
final String builtTags = tags == null ? "null" : tags.build();
@@ -489,17 +515,15 @@ public class Horizontal extends Check {
&& player.getMovement().getDeltaXZ() > 0.1) {
if ((buffer += smallestDeltaXZ > 58E-5 ? 1 : 0.5) > 1) {
buffer = Math.min(3.5f, buffer); //Ensuring we don't have a run-away buffer
flag("smallest=%s b=%.1f to=%s dxz=%.2f tags=[%s]", smallestDeltaXZ, buffer,
player.getMovement().getTo().getLoc(), player.getMovement().getDeltaXZ(), builtTags);
flag("smallest=%.7f b=%.1f dxz=%.2f tags=[%s]", smallestDeltaXZ, buffer,
player.getMovement().getDeltaXZ(), builtTags);
cancel();
} else debug("bad movement");
} else if (buffer > 0) buffer -= 0.05f;
/*debug("(%s): py=%.5f dy=%.5f pm=%.5f dxz=%.5f skip=%s b=%.1f tags=[%s]",
precision, predictedMotionY, player.getMovement().getDeltaY(), pmotion,
player.getMovement().getDeltaXZ(), maybeSkippedPos, buffer, builtTags);*/
debug("x=%s z=%s tags=[%s]", predictedMotionX, predictedMotionZ, builtTags);
debug("[%.1f] smallest=%.7f dxz=%.2f tags=[%s]", buffer, smallestDeltaXZ,
player.getMovement().getDeltaXZ(), builtTags);
}
if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) {
@@ -586,7 +610,7 @@ public class Horizontal extends Check {
}
private static boolean[] getJumpingIteration(boolean onGround) {
return onGround ? new boolean[]{true, false} : new boolean[]{false};
return new boolean[]{true, false};
}
private static final float[] SIN_TABLE_FAST = new float[4096], SIN_TABLE_FAST_NEW = new float[4096];
@@ -12,11 +12,15 @@ import dev.brighten.ac.utils.MathHelper;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.AllArgsConstructor;
import lombok.val;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.List;
@CheckData(name = "Velocity (Horizontal)", checkId = "velocityb", type = CheckType.MOVEMENT)
public class VelocityB extends Check {
private Timer lastVelocity = new TickTimer();
@@ -37,7 +41,6 @@ public class VelocityB extends Check {
}
private double pvX, pvZ;
private boolean useEntity, sprint;
private int ticks;
private double buffer;
private float friction;
@@ -74,155 +77,128 @@ public class VelocityB extends Check {
double pmotionx = 0, pmotionz = 0;
boolean onGround = player.getMovement().getFrom().isOnGround();
loop:
{
for (int f = -1; f < 2; f++) {
for (int s = -1; s < 2; s++) {
for (boolean sprinting : TRUE_FALSE) {
for (int fastMath = 0; fastMath <= 2; fastMath++) {
for (boolean attack : TRUE_FALSE) {
for (boolean using : TRUE_FALSE) {
for (boolean sneaking : TRUE_FALSE) {
for (boolean jumped : TRUE_FALSE) {
val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED);
val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW);
float forward = f, strafe = s;
for (Iteration iteration : iterations) {
float forward = iteration.f, strafe = iteration.s;
if (sprinting && forward <= 0) {
continue;
}
if (iteration.sneaking) {
forward *= 0.3;
strafe *= 0.3;
}
if (sneaking) {
forward *= 0.3;
strafe *= 0.3;
}
float friction = CraftMagicNumbers.getBlock(underMaterial).frictionFactor;
float friction = CraftMagicNumbers.getBlock(underMaterial).frictionFactor;
if (iteration.using) {
forward *= 0.2;
strafe *= 0.2;
}
if (using) {
forward *= 0.2;
strafe *= 0.2;
}
//Multiplying by 0.98 like in client
forward *= 0.9800000190734863F;
strafe *= 0.9800000190734863F;
//Multiplying by 0.98 like in client
forward *= 0.9800000190734863F;
strafe *= 0.9800000190734863F;
double aiMoveSpeed = player.getBukkitPlayer().getWalkSpeed() / 2;
double aiMoveSpeed = player.getBukkitPlayer().getWalkSpeed() / 2;
float drag = 0.91f;
double lmotionX = pvX,
lmotionZ = pvZ;
float drag = 0.91f;
double lmotionX = pvX,
lmotionZ = pvZ;
//Running multiplication done after previous prediction
if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
if (Math.abs(lmotionX) < 0.003)
lmotionX = 0;
if (Math.abs(lmotionZ) < 0.003)
lmotionZ = 0;
} else {
if (Math.abs(lmotionX) < 0.005)
lmotionX = 0;
if (Math.abs(lmotionZ) < 0.005)
lmotionZ = 0;
}
//lmotionX *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
//lmotionZ *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D;
//Less than 0.05
if (((lmotionX * lmotionX) + (lmotionZ * lmotionZ)) < 0.0025 && player.getMovement().getDeltaXZ() < 0.2) {
break check;
}
// Attack slowdown
if (iteration.attack) {
lmotionX *= 0.6;
lmotionZ *= 0.6;
}
//Running multiplication done after previous prediction
if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
if (Math.abs(lmotionX) < 0.003)
lmotionX = 0;
if (Math.abs(lmotionZ) < 0.003)
lmotionZ = 0;
} else {
if (Math.abs(lmotionX) < 0.005)
lmotionX = 0;
if (Math.abs(lmotionZ) < 0.005)
lmotionZ = 0;
}
if (iteration.sprinting)
aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
//Less than 0.05
if (((lmotionX * lmotionX) + (lmotionZ * lmotionZ)) < 0.0025 && player.getMovement().getDeltaXZ() < 0.2) {
break check;
}
// Attack slowdown
if (attack) {
lmotionX *= 0.6;
lmotionZ *= 0.6;
}
if (speed.isPresent())
aiMoveSpeed += (speed.get().getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
if (slow.isPresent())
aiMoveSpeed += (slow.get().getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
if (sprinting)
aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
float f5;
if (onGround) {
drag *= friction;
if (player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
aiMoveSpeed += (player.getPotionHandler().getEffectByType(PotionEffectType.SPEED)
.get()
.getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed;
if (player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
aiMoveSpeed += (player.getPotionHandler().getEffectByType(PotionEffectType.SLOW)
.get()
.getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed;
f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag)));
float f5;
if (onGround) {
drag *= friction;
f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag)));
if (sprinting && jumped) {
float rot = player.getMovement().getTo().getLoc().yaw * 0.017453292F;
lmotionX -= sin(fastMath, rot) * 0.2F;
lmotionZ += cos(fastMath, rot) * 0.2F;
}
} else f5 = sprinting ? 0.025999999F : 0.02f;
if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
double keyedMotion = forward * forward + strafe * strafe;
if (keyedMotion >= 1.0E-4F) {
keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion));
forward *= keyedMotion;
strafe *= keyedMotion;
final float yawSin = sin(fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
yawCos = cos(fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
lmotionX += (strafe * yawCos - forward * yawSin);
lmotionZ += (forward * yawCos + strafe * yawSin);
}
} else {
float keyedMotion = forward * forward + strafe * strafe;
if (keyedMotion >= 1.0E-4F) {
keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion));
forward *= keyedMotion;
strafe *= keyedMotion;
final float yawSin = sin(fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
yawCos = cos(fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
lmotionX += (strafe * yawCos - forward * yawSin);
lmotionZ += (forward * yawCos + strafe * yawSin);
}
}
double diffX = player.getMovement().getDeltaX() - lmotionX,
diffZ = player.getMovement().getDeltaZ() - lmotionZ;
double delta = (diffX * diffX) + (diffZ * diffZ);
if (delta < smallestDelta) {
smallestDelta = delta;
pmotionx = lmotionX;
pmotionz = lmotionZ;
this.friction = friction;
if (delta < 4E-17) {
this.strafe = s * 0.98f;
this.forward = f * 0.98f;
break loop;
}
}
}
}
}
}
}
}
if (iteration.sprinting && iteration.jumped) {
float rot = player.getMovement().getTo().getLoc().yaw * 0.017453292F;
lmotionX -= sin(iteration.fastMath, rot) * 0.2F;
lmotionZ += cos(iteration.fastMath, rot) * 0.2F;
}
} else f5 = iteration.sprinting ? 0.025999999F : 0.02f;
if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
double keyedMotion = forward * forward + strafe * strafe;
if (keyedMotion >= 1.0E-4F) {
keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion));
forward *= keyedMotion;
strafe *= keyedMotion;
final float yawSin = sin(iteration.fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
yawCos = cos(iteration.fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
lmotionX += (strafe * yawCos - forward * yawSin);
lmotionZ += (forward * yawCos + strafe * yawSin);
}
} else {
float keyedMotion = forward * forward + strafe * strafe;
if (keyedMotion >= 1.0E-4F) {
keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion));
forward *= keyedMotion;
strafe *= keyedMotion;
final float yawSin = sin(iteration.fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F),
yawCos = cos(iteration.fastMath,
player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F);
lmotionX += (strafe * yawCos - forward * yawSin);
lmotionZ += (forward * yawCos + strafe * yawSin);
}
}
double diffX = player.getMovement().getDeltaX() - lmotionX,
diffZ = player.getMovement().getDeltaZ() - lmotionZ;
double delta = (diffX * diffX) + (diffZ * diffZ);
if (delta < smallestDelta) {
smallestDelta = delta;
pmotionx = lmotionX;
pmotionz = lmotionZ;
this.friction = friction;
if (delta < 4E-17) {
this.strafe = iteration.s * 0.98f;
this.forward = iteration.f * 0.98f;
break;
}
}
}
@@ -250,6 +226,48 @@ public class VelocityB extends Check {
previousFrom = player.getMovement().getFrom().getLoc().clone();
};
/*
for (int f = -1; f < 2; f++) {
for (int s = -1; s < 2; s++) {
for (boolean sprinting : TRUE_FALSE) {
for (int fastMath = 0; fastMath <= 2; fastMath++) {
for (boolean attack : TRUE_FALSE) {
for (boolean using : TRUE_FALSE) {
for (boolean sneaking : TRUE_FALSE) {
for (boolean jumped : TRUE_FALSE) {
*/
@AllArgsConstructor
private static class Iteration {
final int f, s, fastMath;
final boolean sprinting, attack, using, sneaking, jumped;
}
private static final List<Iteration> iterations = new ArrayList<>();
static {
for (int f = -1; f < 2; f++) {
for (int s = -1; s < 2; s++) {
for (boolean sprinting : TRUE_FALSE) {
for (int fastMath = 0; fastMath <= 2; fastMath++) {
for (boolean attack : TRUE_FALSE) {
for (boolean using : TRUE_FALSE) {
for (boolean sneaking : TRUE_FALSE) {
for (boolean jumped : TRUE_FALSE) {
if(sprinting && f <= 0) continue;
if(jumped && !sprinting) continue;
iterations.add(new Iteration(f, s, fastMath, sprinting,
attack, using, sneaking, jumped));
}
}
}
}
}
}
}
}
}
private static final float[] SIN_TABLE_FAST = new float[4096], SIN_TABLE_FAST_NEW = new float[4096];
private static final float[] SIN_TABLE = new float[65536];
private static final float radToIndex = roundToFloat(651.8986469044033D);
@@ -2,20 +2,15 @@ package dev.brighten.ac.command;
import co.aikar.commands.*;
import co.aikar.commands.annotation.*;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.bukkit.contexts.OnlinePlayer;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.gui.Logs;
import dev.brighten.ac.handler.BBRevealHandler;
import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.Pastebin;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.msg.ChatBuilder;
import dev.brighten.ac.utils.reflections.Reflections;
@@ -39,13 +34,13 @@ import org.bukkit.plugin.PluginDescriptionFile;
import java.io.*;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.zip.CRC32;
@Init
@Init(priority = Priority.LOW)
@CommandAlias("kauri|anticheat|ac")
@CommandPermission("anticheat.command")
public class AnticheatCommand extends BaseCommand {
@@ -216,78 +211,6 @@ public class AnticheatCommand extends BaseCommand {
"You've been given a very special wand. Handle it responsibly.").color(ChatColor.GREEN).create());
}
@Subcommand("logs")
@Syntax("[player] [check]")
@CommandCompletion("@players @checkIds")
@CommandPermission("anticheat.command.logs")
@Description("Get player logs")
public void onLogs(CommandSender sender, @Single String playername,
@Single @Optional @Default("none") String check) {
UUID uuid = Bukkit.getOfflinePlayer(playername).getUniqueId();
sender.sendMessage(Color.Red + "Getting logs for " + playername + "...");
if(sender instanceof Player) {
if(check.equals("none")) {
Logs logs = new Logs(uuid);
logs.showMenu((Player) sender);
} else {
Logs logs = new Logs(uuid, check);
logs.showMenu((Player) sender);
}
} else {
List<String> logs = new ArrayList<>();
if(check.equals("none")) {
Anticheat.INSTANCE.getLogManager().getLogs(uuid, logsList -> {
logsList.forEach(log -> {
logs.add("[" + new Timestamp(log.getTime()).toLocalDateTime()
.format(DateTimeFormatter.ISO_DATE_TIME) + "] funkemunky failed "
+ Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId()) + "(VL: "
+ log.getVl() + ") {" + log.getData() + "}");
});
if(logs.size() == 0) {
sender.sendMessage(Color.Gray + "There are no logs for player \"" + playername + "\"");
} else {
String url = null;
try {
url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs",
Pastebin.Privacy.UNLISTED);
sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
});
} else {
Anticheat.INSTANCE.getLogManager().getLogs(uuid, check, logsList -> {
logsList.forEach(log -> {
logs.add("[" + new Timestamp(log.getTime()).toLocalDateTime()
.format(DateTimeFormatter.ISO_DATE_TIME) + "] funkemunky failed "
+ Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId())
+ "(VL: " + log.getVl() + ") {" + log.getData() + "}");
});
if(logs.size() == 0) {
sender.sendMessage(Color.Gray + " does not have any violations for check \"" + check + "\"");
} else {
String url = null;
try {
url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs",
Pastebin.Privacy.UNLISTED);
sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
});
}
}
}
@Subcommand("title")
@Private
public void onTitle(CommandSender sender, OnlinePlayer target, String title) {
@@ -0,0 +1,240 @@
package dev.brighten.ac.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.*;
import co.aikar.commands.annotation.Optional;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.check.CheckSettings;
import dev.brighten.ac.gui.Logs;
import dev.brighten.ac.logging.Log;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.Pastebin;
import dev.brighten.ac.utils.Priority;
import dev.brighten.ac.utils.annotation.Init;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Init(priority = Priority.LOW)
@CommandAlias("kauri|anticheat|ac")
@CommandPermission("anticheat.command")
public class LogsCommand extends BaseCommand {
@Subcommand("logs")
@Syntax("[player] [check]")
@CommandCompletion("@players @checkIds")
@CommandPermission("anticheat.command.logs")
@Description("Get player logs")
public void onLogs(CommandSender sender, @Single String playername,
@Single @Optional @Default("none") String check) {
UUID uuid = Bukkit.getOfflinePlayer(playername).getUniqueId();
sender.sendMessage(Color.Red + "Getting logs for " + playername + "...");
if(sender instanceof Player) {
if(check.equals("none")) {
Logs logs = new Logs(uuid);
logs.showMenu((Player) sender);
} else {
Logs logs = new Logs(uuid, check);
logs.showMenu((Player) sender);
}
} else {
List<String> logs = new ArrayList<>();
if(check.equals("none")) {
Anticheat.INSTANCE.getLogManager().getLogs(uuid, logsList -> {
logsList.forEach(log -> {
logs.add("[" + new Timestamp(log.getTime()).toLocalDateTime()
.format(DateTimeFormatter.ISO_DATE_TIME) + "] funkemunky failed "
+ Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId()) + "(VL: "
+ log.getVl() + ") {" + log.getData() + "}");
});
if(logs.size() == 0) {
sender.sendMessage(Color.Gray + "There are no logs for player \"" + playername + "\"");
} else {
String url = null;
try {
url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs",
Pastebin.Privacy.UNLISTED);
sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
});
} else {
Anticheat.INSTANCE.getLogManager().getLogs(uuid, check, logsList -> {
logsList.forEach(log -> {
logs.add("[" + new Timestamp(log.getTime()).toLocalDateTime()
.format(DateTimeFormatter.ISO_DATE_TIME) + "] funkemunky failed "
+ Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId())
+ "(VL: " + log.getVl() + ") {" + log.getData() + "}");
});
if(logs.size() == 0) {
sender.sendMessage(Color.Gray + " does not have any violations for check \"" + check + "\"");
} else {
String url = null;
try {
url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs",
Pastebin.Privacy.UNLISTED);
sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
});
}
}
}
@Subcommand("logs paste")
@CommandPermission("kauri.command.logs")
@Syntax("[player]")
@CommandCompletion("@players")
@Description("View logs via Pastebin")
public void onLogsPasteBin(CommandSender sender, String[] args) {
if(args.length == 0) {
sender.sendMessage(Color.Red + "Usage: /kauri logs web <player>");
return;
}
String playername = args[0];
UUID uuid = Bukkit.getOfflinePlayer(playername).getUniqueId();
sender.sendMessage(Color.Red + "Getting logs for " + playername + "...");
if(sender instanceof Player) {
Logs logs = new Logs(uuid);
logs.showMenu((Player) sender);
} else {
List<String> logs = new ArrayList<>();
Anticheat.INSTANCE.getLogManager().getLogs(uuid, logsList -> {
logsList.forEach(log -> {
logs.add("[" + new Timestamp(log.getTime()).toLocalDateTime()
.format(DateTimeFormatter.ISO_DATE_TIME) + "] funkemunky failed "
+ Anticheat.INSTANCE.getCheckManager().getIdToName().get(log.getCheckId()) + "(VL: "
+ log.getVl() + ") {" + log.getData() + "}");
});
if(logs.size() == 0) {
sender.sendMessage(Color.Gray + "There are no logs for player \"" + playername + "\"");
} else {
String url = null;
try {
url = Pastebin.makePaste(String.join("\n", logs), playername + "'s Logs",
Pastebin.Privacy.UNLISTED);
sender.sendMessage(Color.Green + "Logs for " + playername + ": " + Color.White + url);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
});
}
}
@Subcommand("logs web")
@CommandPermission("kauri.command.logs")
@Syntax("[player]")
@CommandCompletion("@players")
@Description("View the logs of a user")
public void onLogsWeb(CommandSender sender, String[] args) {
if(args.length == 0) {
if(sender instanceof Player) {
Player player = (Player) sender;
runWebLog(sender, player);
} else sender.sendMessage(Color.translate("You cannot view your own logs from console."));
} else {
OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]);
if(player == null) {
sender.sendMessage(Color.translate("&cSomehow, out of hundreds of millions of"
+ "Minecraft accounts, you found one that doesn't exist."));
return;
}
runWebLog(sender, player);
}
}
private void runWebLog(CommandSender sender, OfflinePlayer target) {
//val logs = Kauri.INSTANCE.loggerManager.getLogs(target.getUniqueId());
Anticheat.INSTANCE.getLogManager().getLogs(target.getUniqueId(), 100000, 0, logs -> {
Map<String, Integer> violations = new HashMap<>();
for (Log log : logs) {
violations.compute(log.getCheckId(), (name, count) -> {
if(count == null) {
return 1;
}
return count + 1;
});
}
StringBuilder url = new StringBuilder("https://funkemunky.cc/api/kauri?uuid=" + target.getUniqueId().toString().replaceAll("-", "") + (violations.keySet().size() > 0 ? "&violations=" : ""));
if (violations.keySet().size() > 0) {
for (String key : violations.keySet()) {
if (Anticheat.INSTANCE.getCheckManager().isCheck(key)) {
CheckSettings checkData = Anticheat.INSTANCE.getCheckManager().getCheckSettings(Anticheat.INSTANCE.getCheckManager().getCheckClasses()
.get(Anticheat.INSTANCE.getCheckManager().getIdToName().get(key)).getCheckClass().getParent());
int vl = violations.get(key), maxVL = checkData.getPunishVl();
boolean developer = false;
String toAppend = key + ":" + vl + ":" + maxVL + ":" + developer + ";";
toAppend = toAppend.replaceAll(" ", "%20");
url.append(toAppend);
}
}
if (violations.keySet().size() > 0) {
url.deleteCharAt(url.length() - 1);
}
String finalURL = "https://funkemunky.cc/api/kauri/cache/%id%";
try {
URL url2Run = new URL(url.toString());
//%3F
BufferedReader reader = new BufferedReader(new InputStreamReader(url2Run
.openConnection().getInputStream(), StandardCharsets.UTF_8));
finalURL = finalURL.replace("%id%", readAll(reader));
} catch (IOException e) {
e.printStackTrace();
}
sender.sendMessage(Color.translate("&aView the log here&7: &f" + finalURL));
} else {
sender.sendMessage(Color.translate("&cPlayer has no logs."));
}
});
}
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
}
@@ -13,12 +13,14 @@ import dev.brighten.ac.handler.MovementHandler;
import dev.brighten.ac.handler.PotionHandler;
import dev.brighten.ac.handler.VelocityHandler;
import dev.brighten.ac.handler.block.BlockUpdateHandler;
import dev.brighten.ac.handler.entity.FakeMob;
import dev.brighten.ac.handler.keepalive.KeepAlive;
import dev.brighten.ac.handler.protocolsupport.ProtocolAPI;
import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.wrapper.WPacket;
import dev.brighten.ac.packet.wrapper.objects.WrappedWatchableObject;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.RunUtils;
import dev.brighten.ac.utils.Tuple;
@@ -26,10 +28,14 @@ import dev.brighten.ac.utils.objects.evicting.EvictingList;
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
import dev.brighten.ac.utils.world.types.RayCollision;
import lombok.Getter;
import lombok.Setter;
import lombok.val;
import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction;
import org.bukkit.Achievement;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@@ -89,6 +95,8 @@ public class APlayer {
@Getter
private final List<Consumer<Vector>> onVelocityTasks = new ArrayList<>();
public final EvictingList<Tuple<KLocation, Double>> pastLocations = new EvictingList<>(20);
@Getter
private FakeMob mob;
@Setter
@Getter
@@ -124,18 +132,38 @@ public class APlayer {
});
});
// Removing inventory achievement
getBukkitPlayer().removeAchievement(Achievement.OPEN_INVENTORY);
// Enabling alerts for players on join if they have the permissions to
if(getBukkitPlayer().hasPermission("anticheat.command.alerts")
|| getBukkitPlayer().hasPermission("anticheat.alerts")) {
Check.alertsEnabled.add(getUuid());
getBukkitPlayer().spigot().sendMessage(Messages.ALERTS_ON);
}
generateEntities();
}
private void generateEntities() {
mob = new FakeMob(EntityType.MAGMA_CUBE);
KLocation origin = getMovement().getTo().getLoc().clone().add(0, 1.7, 0);
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
Location loc1 = coll.collisionPoint(2).toLocation(getBukkitPlayer().getWorld());
mob.spawn(true, loc1,
new ArrayList<>(Collections.singletonList(
new WrappedWatchableObject(0, 16, (byte) 1))), this);
}
protected void unload() {
this.info = null;
this.lagInfo = null;
this.movement = null;
mob.despawn();
}
@@ -10,7 +10,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
import lombok.SneakyThrows;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.Plugin;
@@ -26,7 +25,6 @@ import java.util.zip.CRC32;
public class PlayerRegistry {
public PlayerRegistry() {
Bukkit.getOnlinePlayers().forEach(this::generate);
checkIntegrity();
}
public final Int2ObjectMap<APlayer> aplayerMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
@@ -31,11 +31,13 @@ public class GeneralInformation {
lastRespawn = new TickTimer(), lastEntityCollision = new TickTimer(), lastWeb = new TickTimer(),
lastLiquid = new TickTimer(), lastBlockDig = new TickTimer(), lastBlockPlace = new TickTimer(),
lastBlockUpdate = new TickTimer(), lastMiscNear = new TickTimer(), lastHalfBlock = new TickTimer(),
lastFence = new TickTimer(), lastFakeBotHit = new TickTimer();
lastFence = new TickTimer(), lastFakeBotHit = new TickTimer(), lastInventoryOpen = new TickTimer(),
botAttack = new TickTimer();
public LivingEntity target;
public Optional<PotionEffect> groundJumpBoost;
public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative,
sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock;
sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock,
inventoryOpen;
public List<Entity> nearbyEntities = Collections.emptyList();
public PastLocation targetPastLocation = new PastLocation();
public KLocation lastKnownGoodPosition;
@@ -265,8 +265,10 @@ public class EntityLocationHandler {
for (double offset : offsets) {
FakeMob mob = new FakeMob(EntityType.MAGMA_CUBE);
// Setting Magma cube size to size 10
mob.spawn(true, location.clone().add(offset, offset, offset),
new ArrayList<>(Arrays.asList(new WrappedWatchableObject(0, 16, (byte)10))), data);
new ArrayList<>(Collections.singletonList(
new WrappedWatchableObject(0, 16, (byte) 10))), data);
fakeMobToEntityId.put(mob.getEntityId(), entityId);
@@ -300,6 +300,8 @@ public class MovementHandler {
lastFlying.reset();
processBotMove(packet);
/*
ata.playerInfo.generalCancel = data.getPlayer().getAllowFlight()
|| this.creativelastLastY
@@ -342,6 +344,22 @@ it
}
}
private void processBotMove(WPacketPlayInFlying packet) {
if(packet.isMoved() || packet.isLooked()) {
KLocation origin = to.getLoc().clone().add(0, 1.7, 0);
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
Location loc1 = coll.collisionPoint(2.2).toLocation(player.getBukkitPlayer().getWorld());
if(player.getInfo().botAttack.isNotPassed(7)) {
loc1.setY(Math.max(origin.y + 1.2, loc1.getY()));
} else loc1.setY(Math.max(origin.y + 0.3, loc1.getY()));
player.getMob().teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch());
}
}
private static float getDeltaX(float yawDelta, float gcd) {
return MathHelper.ceiling_float_int(yawDelta / gcd);
}
@@ -294,6 +294,9 @@ public class PacketHandler {
player.getEntityLocationHandler().removeFakeMob(targetId);
player.getInfo().lastFakeBotHit.reset();
});
if(player.getMob().getEntityId() == packet.getEntityId()) {
player.getInfo().botAttack.reset();
}
} else {
Entity target = packet.getEntity(player.getBukkitPlayer().getWorld());
@@ -338,6 +341,32 @@ public class PacketHandler {
player.getBlockUpdateHandler().onDig(packet);
break;
}
case CLIENT_COMMAND: {
WPacketPlayInClientCommand packet = (WPacketPlayInClientCommand) packetObject;
if(packet.getCommand() == WPacketPlayInClientCommand.WrappedEnumClientCommand
.OPEN_INVENTORY_ACHIEVEMENT) {
player.getInfo().setInventoryOpen(true);
player.getInfo().lastInventoryOpen.reset();
return true;
}
break;
}
case CLIENT_CLOSE_WINDOW: {
player.getInfo().setInventoryOpen(false);
break;
}
case SERVER_CLOSE_WINDOW: {
player.runKeepaliveAction(ka -> player.getInfo().setInventoryOpen(false));
break;
}
case SERVER_OPEN_WINDOW: {
player.runKeepaliveAction(ka -> {
player.getInfo().setInventoryOpen(true);
player.getInfo().lastInventoryOpen.reset();
});
break;
}
}
if(player.sniffing) {
@@ -2,7 +2,11 @@ package dev.brighten.ac.listener;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.objects.WrappedWatchableObject;
import dev.brighten.ac.utils.RunUtils;
import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.world.types.RayCollision;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -14,6 +18,9 @@ import org.bukkit.event.player.PlayerEditBookEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.ArrayList;
import java.util.Collections;
@Init
public class GeneralListener implements Listener {
@@ -50,7 +57,23 @@ public class GeneralListener implements Listener {
if(event.getFrom().getWorld().equals(event.getTo().getWorld())) return;
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId())
.ifPresent(player -> player.getBlockUpdateHandler().onWorldChange());
.ifPresent(player -> {
player.getBlockUpdateHandler().onWorldChange();
// Updating bot loc when changing worlds
Location origin = event.getTo().clone().add(0, 1.7, 0);
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
Location loc1 = coll.collisionPoint(1.2).toLocation(event.getTo().getWorld());
RunUtils.taskLater(() -> {
player.getMob().despawn();
player.getMob().spawn(true, loc1,
new ArrayList<>(Collections.singletonList(
new WrappedWatchableObject(0, 16, (byte) 1))), player);
}, 5);
});
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@@ -133,6 +133,7 @@ public class PacketProcessor {
public Object call(Player player, Object packet, PacketType type) {
if(packet == null) return false;
PacketInfo info = new PacketInfo(player, packet, type, System.currentTimeMillis()),
asyncInfo;
boolean cancelled = false;
@@ -90,4 +90,8 @@ public interface PacketConverter {
WPacketPlayOutMapChunk processMapChunk(Object object);
WPacketPlayOutMapChunkBulk processMapChunkBulk(Object packet);
WPacketPlayInClientCommand processInClientCommand(Object packet);
WPacketPlayInWindowClick processInWindowClick(Object packet);
}
@@ -25,7 +25,7 @@ public enum PacketType {
BLOCK_DIG("PacketPlayInBlockDig"),
BLOCK_PLACE("PacketPlayInBlockPlace"),
CHAT("PacketPlayInChat"),
CLIENT_COMMAND("PacketPlayInCommand"),
CLIENT_COMMAND("PacketPlayInClientCommand"),
CLIENT_CLOSE_WINDOW("PacketPlayInCloseWindow"),
ENTITY_ACTION("PacketPlayInEntityAction"),
ENTITY_EFFECT("PacketPlayOutEntityEffect"),
@@ -153,6 +153,10 @@ public enum PacketType {
return convert.processMapChunk(object);
case MAP_CHUNK_BULK:
return convert.processMapChunkBulk(object);
case CLIENT_COMMAND:
return convert.processInClientCommand(object);
case WINDOW_CLICK:
return convert.processInWindowClick(object);
default:
return object;
}
@@ -793,6 +793,26 @@ public class Processor_18 implements PacketConverter {
return new WPacketPlayOutMapChunkBulk(chunks);
}
@Override
public WPacketPlayInClientCommand processInClientCommand(Object packet) {
PacketPlayInClientCommand clientCommand = (PacketPlayInClientCommand) packet;
return new WPacketPlayInClientCommand(WPacketPlayInClientCommand
.WrappedEnumClientCommand.valueOf(clientCommand.a().name()));
}
@Override
public WPacketPlayInWindowClick processInWindowClick(Object packet) {
PacketPlayInWindowClick windowClick = (PacketPlayInWindowClick) packet;
return WPacketPlayInWindowClick.builder().windowId(windowClick.a())
.slot(windowClick.b()).button(windowClick.c())
.action(windowClick.d()).mode(windowClick.f())
.clickedItem(windowClick.e() == null ? null : CraftItemStack.asBukkitCopy(windowClick.e()))
.build();
}
private static void processChunk(byte[] locs, int size, int chunkX, int chunkZ, boolean groundUp,
Map<IntVector, WPacketPlayOutMapChunk.MinBlock> blocks) {
ChunkSection[] sections = new ChunkSection[16];
@@ -0,0 +1,26 @@
package dev.brighten.ac.packet.wrapper.in;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.WPacket;
import lombok.Builder;
import lombok.Getter;
import org.bukkit.inventory.ItemStack;
@Getter
@Builder
public class WPacketPlayInWindowClick extends WPacket {
private int windowId, slot, button, mode;
private short action;
private ItemStack clickedItem;
@Override
public PacketType getPacketType() {
return PacketType.WINDOW_CLICK;
}
@Override
public Object getPacket() {
return null;
}
}
@@ -0,0 +1,29 @@
package dev.brighten.ac.packet.wrapper.out;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.WPacket;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class WPacketPlayInClientCommand extends WPacket {
private WrappedEnumClientCommand command;
@Override
public PacketType getPacketType() {
return PacketType.CLIENT_COMMAND;
}
@Override
public Object getPacket() {
return null;
}
public enum WrappedEnumClientCommand {
PERFORM_RESPAWN,
REQUEST_STATS,
OPEN_INVENTORY_ACHIEVEMENT;
}
}
+323 -291
View File
@@ -22,347 +22,379 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @author DeprecatedLuke
* Taken from https://github.com/DeprecatedLuke/fireflyx/blob/master/src/main/java/com/ngxdev/anticheat/utils/Helper.java
*/
public class Helper {
public static int angularDistance(double alpha, double beta) {
while (alpha < 0) alpha += 360;
while (beta < 0) beta += 360;
double phi = Math.abs(beta - alpha) % 360;
return (int) (phi > 180 ? 360 - phi : phi);
}
public static Vector vector(double yaw, double pitch) {
Vector vector = new Vector();
vector.setY(-Math.sin(Math.toRadians(pitch)));
double xz = Math.cos(Math.toRadians(pitch));
vector.setX(-xz * Math.sin(Math.toRadians(yaw)));
vector.setZ(xz * Math.cos(Math.toRadians(yaw)));
return vector;
}
public static Vector vector(double yaw, double pitch) {
Vector vector = new Vector();
vector.setY(-Math.sin(Math.toRadians(pitch)));
double xz = Math.cos(Math.toRadians(pitch));
vector.setX(-xz * Math.sin(Math.toRadians(yaw)));
vector.setZ(xz * Math.cos(Math.toRadians(yaw)));
return vector;
}
public static void drawRay(RayCollision collision, double distance, EnumParticle particle, Collection<? extends Player> players) {
for (double i = 0; i < distance; 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));
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));
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x(fx)
.y(fy)
.z(fz)
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.longD(true)
.data(new int[0])
.build();
players.forEach(p -> HandlerAbstract.getHandler().sendPacketSilently(p, packet));
}
}
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x(fx)
.y(fy)
.z(fz)
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.longD(true)
.data(new int[0])
.build();
players.forEach(p -> HandlerAbstract.getHandler().sendPacketSilently(p, packet));
}
}
public static void drawCuboid(SimpleCollisionBox box, EnumParticle particle, Collection<? extends Player> players) {
Step.GenericStepper<Float> x = Step.step((float)box.minX, 0.241F, (float)box.maxX);
Step.GenericStepper<Float> y = Step.step((float)box.minY, 0.241F, (float)box.maxY);
Step.GenericStepper<Float> z = Step.step((float)box.minZ, 0.241F, (float)box.maxZ);
Iterator var6 = x.iterator();
public static void drawCuboid(SimpleCollisionBox box, EnumParticle particle, Collection<? extends Player> players) {
Step.GenericStepper<Float> x = Step.step((float) box.minX, 0.241F, (float) box.maxX);
Step.GenericStepper<Float> y = Step.step((float) box.minY, 0.241F, (float) box.maxY);
Step.GenericStepper<Float> z = Step.step((float) box.minZ, 0.241F, (float) box.maxZ);
Iterator var6 = x.iterator();
while(var6.hasNext()) {
float fx = (Float)var6.next();
Iterator var8 = y.iterator();
while (var6.hasNext()) {
float fx = (Float) var6.next();
Iterator var8 = y.iterator();
label61:
while(var8.hasNext()) {
float fy = (Float)var8.next();
Iterator var10 = z.iterator();
label61:
while (var8.hasNext()) {
float fy = (Float) var8.next();
Iterator var10 = z.iterator();
while(true) {
float fz;
int check;
do {
if (!var10.hasNext()) {
continue label61;
}
while (true) {
float fz;
int check;
do {
if (!var10.hasNext()) {
continue label61;
}
fz = (Float)var10.next();
check = 0;
if (x.first() || x.last()) {
++check;
}
fz = (Float) var10.next();
check = 0;
if (x.first() || x.last()) {
++check;
}
if (y.first() || y.last()) {
++check;
}
if (y.first() || y.last()) {
++check;
}
if (z.first() || z.last()) {
++check;
}
} while(check < 2);
if (z.first() || z.last()) {
++check;
}
} while (check < 2);
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x(fx)
.y(fy)
.z(fz)
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.data(new int[0])
.build();
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x(fx)
.y(fy)
.z(fz)
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.data(new int[0])
.build();
Iterator<? extends Player> var14 = players.iterator();
Iterator<? extends Player> var14 = players.iterator();
while(var14.hasNext()) {
Player p = var14.next();
HandlerAbstract.getHandler().sendPacketSilently(p, packet);
}
}
}
}
while (var14.hasNext()) {
Player p = var14.next();
HandlerAbstract.getHandler().sendPacketSilently(p, packet);
}
}
}
}
}
}
public static void drawPoint(Vector point, EnumParticle particle, Collection<? extends Player> players) {
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x((float)point.getX())
.y((float)point.getY())
.z((float)point.getZ())
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.data(new int[0])
.build();
Iterator<? extends Player> var4 = players.iterator();
public static void drawPoint(Vector point, EnumParticle particle, Collection<? extends Player> players) {
WPacketPlayOutWorldParticles packet = WPacketPlayOutWorldParticles.builder()
.particle(particle)
.x((float) point.getX())
.y((float) point.getY())
.z((float) point.getZ())
.offsetX(0)
.offsetY(0)
.offsetZ(0)
.speed(0)
.amount(1)
.data(new int[0])
.build();
Iterator<? extends Player> var4 = players.iterator();
while(var4.hasNext()) {
Player p = var4.next();
HandlerAbstract.getHandler().sendPacketSilently(p, packet);
}
while (var4.hasNext()) {
Player p = var4.next();
HandlerAbstract.getHandler().sendPacketSilently(p, packet);
}
}
}
public static Block getBlockAt(World world, int x, int y, int z) {
return world.isChunkLoaded(x >> 4, z >> 4)
? world.getChunkAt(x >> 4, z >> 4).getBlock(x & 15, y, z & 15)
: null;
}
public static Block getBlockAt(World world, int x, int y, int z) {
return world.isChunkLoaded(x >> 4, z >> 4)
? world.getChunkAt(x >> 4, z >> 4).getBlock(x & 15, y, z & 15)
: null;
}
public static SimpleCollisionBox wrap(SimpleCollisionBox a, SimpleCollisionBox b) {
double minX = Math.min(a.minX, b.minX);
double minY = Math.min(a.minY, b.minY);
double minZ = Math.min(a.minZ, b.minZ);
double maxX = Math.max(a.maxX, b.maxX);
double maxY = Math.max(a.maxY, b.maxY);
double maxZ = Math.max(a.maxZ, b.maxZ);
return new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public static SimpleCollisionBox wrap(SimpleCollisionBox a, SimpleCollisionBox b) {
double minX = Math.min(a.minX, b.minX);
double minY = Math.min(a.minY, b.minY);
double minZ = Math.min(a.minZ, b.minZ);
double maxX = Math.max(a.maxX, b.maxX);
double maxY = Math.max(a.maxY, b.maxY);
double maxZ = Math.max(a.maxZ, b.maxZ);
return new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public static SimpleCollisionBox wrap(List<SimpleCollisionBox> box) {
if (!box.isEmpty()) {
SimpleCollisionBox wrap = box.get(0).copy();
for (int i = 1; i < box.size(); i++) {
SimpleCollisionBox a = box.get(i);
if (wrap.minX > a.minX) wrap.minX = a.minX;
if (wrap.minY > a.minY) wrap.minY = a.minY;
if (wrap.minZ > a.minZ) wrap.minZ = a.minZ;
if (wrap.maxX < a.maxX) wrap.maxX = a.maxX;
if (wrap.maxY < a.maxY) wrap.maxY = a.maxY;
if (wrap.maxZ < a.maxZ) wrap.maxZ = a.maxZ;
}
return wrap;
}
return null;
}
public static SimpleCollisionBox wrap(List<SimpleCollisionBox> box) {
if (!box.isEmpty()) {
SimpleCollisionBox wrap = box.get(0).copy();
for (int i = 1; i < box.size(); i++) {
SimpleCollisionBox a = box.get(i);
if (wrap.minX > a.minX) wrap.minX = a.minX;
if (wrap.minY > a.minY) wrap.minY = a.minY;
if (wrap.minZ > a.minZ) wrap.minZ = a.minZ;
if (wrap.maxX < a.maxX) wrap.maxX = a.maxX;
if (wrap.maxY < a.maxY) wrap.maxY = a.maxY;
if (wrap.maxZ < a.maxZ) wrap.maxZ = a.maxZ;
}
return wrap;
}
return null;
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box) {
return blocks.stream()
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box) {
return blocks.stream()
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static boolean isCollided(SimpleCollisionBox toCheck, CollisionBox other) {
List<SimpleCollisionBox> downcasted = new ArrayList<>();
public static boolean isCollided(SimpleCollisionBox toCheck, CollisionBox other) {
List<SimpleCollisionBox> downcasted = new ArrayList<>();
other.downCast(downcasted);
other.downCast(downcasted);
return downcasted.stream().anyMatch(box -> box.maxX >= toCheck.minX && box.minX <= toCheck.maxX
&& box.maxY >= toCheck.minY && box.minY <= toCheck.maxY && box.maxZ >= toCheck.minZ
&& box.minZ <= toCheck.maxZ);
}
return downcasted.stream().anyMatch(box -> box.maxX >= toCheck.minX && box.minX <= toCheck.maxX
&& box.maxY >= toCheck.minY && box.minY <= toCheck.maxY && box.maxZ >= toCheck.minZ
&& box.minZ <= toCheck.maxZ);
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box, int material) {
return blocks.stream().filter(b -> Materials.checkFlag(b.getType(), material))
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box, int material) {
return blocks.stream().filter(b -> Materials.checkFlag(b.getType(), material))
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static <C extends CollisionBox> List<C> collisions(List<C> boxes, CollisionBox box) {
return boxes.stream().filter(b -> b.isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static <C extends CollisionBox> List<C> collisions(List<C> boxes, CollisionBox box) {
return boxes.stream().filter(b -> b.isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<SimpleCollisionBox> getCollisions(World world, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
Block block;
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z)
if ((block = getBlockAt(world, x, y, z)) != null
&& BlockUtils.getXMaterial(block.getType()) != XMaterial.AIR)
if (Materials.checkFlag(block.getType(),mask)) {
CollisionBox box = BlockData.getData(block.getType())
.getBox(block, ProtocolVersion.getGameVersion());
public static List<SimpleCollisionBox> getCollisions(World world, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
Block block;
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z)
if ((block = getBlockAt(world, x, y, z)) != null
&& BlockUtils.getXMaterial(block.getType()) != XMaterial.AIR)
if (Materials.checkFlag(block.getType(), mask)) {
CollisionBox box = BlockData.getData(block.getType())
.getBox(block, ProtocolVersion.getGameVersion());
if(box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
return collisionBoxes;
}
if (box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
return collisionBoxes;
}
public static List<SimpleCollisionBox> getCollisions(APlayer player, SimpleCollisionBox collisionBox) {
return getCollisions(player, collisionBox, Materials.COLLIDABLE);
}
public static List<SimpleCollisionBox> getCollisions(APlayer player, SimpleCollisionBox collisionBox) {
return getCollisions(player, collisionBox, Materials.COLLIDABLE);
}
public static SimpleCollisionBox getEntityCollision(Entity entity) {
return new SimpleCollisionBox((Object)MinecraftReflection.getEntityBoundingBox(entity));
}
public static SimpleCollisionBox getEntityCollision(Entity entity) {
return new SimpleCollisionBox((Object) MinecraftReflection.getEntityBoundingBox(entity));
}
public static List<SimpleCollisionBox> getCollisions(APlayer player, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z);
Material type = player.getBlockUpdateHandler().getBlock(vec).getType();
public static List<SimpleCollisionBox> getCollisions(APlayer player, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z);
Material type = player.getBlockUpdateHandler().getBlock(vec).getType();
if(type != Material.AIR && Materials.checkFlag(type, mask)) {
CollisionBox box = BlockData.getData(type)
.getBox(player, vec, ProtocolVersion.getGameVersion());
if (type != Material.AIR && Materials.checkFlag(type, mask)) {
CollisionBox box = BlockData.getData(type)
.getBox(player, vec, ProtocolVersion.getGameVersion());
if(box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
}
if (box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
}
for (Entity entity : player.getInfo().getNearbyEntities()) {
if(!BlockUtils.isEntityCollidable(entity)) continue;
for (Entity entity : player.getInfo().getNearbyEntities()) {
if (!BlockUtils.isEntityCollidable(entity)) continue;
SimpleCollisionBox entityCollisionBox = new SimpleCollisionBox(ReflectionsUtil.getBoundingBox(entity));
SimpleCollisionBox entityCollisionBox = new SimpleCollisionBox(ReflectionsUtil.getBoundingBox(entity));
if(entityCollisionBox.isIntersected(collisionBox))
entityCollisionBox.downCast(collisionBoxes);
}
if (entityCollisionBox.isIntersected(collisionBox))
entityCollisionBox.downCast(collisionBoxes);
}
return collisionBoxes;
}
return collisionBoxes;
}
public static List<SimpleCollisionBox> getCollisionsNoEntities(APlayer player,
SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z);
Material type = player.getBlockUpdateHandler().getBlock(vec).getType();
public static List<Tuple<SimpleCollisionBox, Material>>
getCollisionsWithTypeNoEntities(APlayer player, SimpleCollisionBox collisionBox) {
return getCollisionsWithTypeNoEntities(player, collisionBox, Materials.COLLIDABLE);
}
if(type != Material.AIR && Materials.checkFlag(type, mask)) {
CollisionBox box = BlockData.getData(type)
.getBox(player, vec, ProtocolVersion.getGameVersion());
public static List<Tuple<SimpleCollisionBox, Material>>
getCollisionsWithTypeNoEntities(APlayer player, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<Tuple<SimpleCollisionBox, Material>> collisionBoxes = new ArrayList<>();
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z);
Material type = player.getBlockUpdateHandler().getBlock(vec).getType();
if(box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
}
if (type != Material.AIR && Materials.checkFlag(type, mask)) {
CollisionBox box = BlockData.getData(type)
.getBox(player, vec, ProtocolVersion.getGameVersion());
return collisionBoxes;
}
if (box.isIntersected(collisionBox)) {
for (SimpleCollisionBox simpleCollisionBox : box.downCast()) {
collisionBoxes.add(new Tuple<>(simpleCollisionBox, type));
}
}
}
}
public static List<Block> getBlocksNearby2(World world, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.ceil(collisionBox.maxX);
int y2 = (int) Math.ceil(collisionBox.maxY);
int z2 = (int) Math.ceil(collisionBox.maxZ);
List<Block> blocks = new LinkedList<>();
Block block;
for (int x = x1; x <= x2; x++)
for (int y = y1; y <= y2; y++)
for (int z = z1; z <= z2; z++)
if ((block = getBlockAt(world, x, y, z)) != null
&& BlockUtils.getXMaterial(block.getType()) != XMaterial.AIR)
if (Materials.checkFlag(block.getType(),mask))
blocks.add(block);
return blocks;
}
return collisionBoxes;
}
private static final int[] decimalPlaces = {0, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
public static List<SimpleCollisionBox> getCollisionsNoEntities(APlayer player,
SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.floor(collisionBox.maxX + 1);
int y2 = (int) Math.floor(collisionBox.maxY + 1);
int z2 = (int) Math.floor(collisionBox.maxZ + 1);
List<SimpleCollisionBox> collisionBoxes = new ArrayList<>();
for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z);
Material type = player.getBlockUpdateHandler().getBlock(vec).getType();
public static double format(double d, int dec) {
return (long) (d * decimalPlaces[dec] + 0.5) / (double) decimalPlaces[dec];
}
if (type != Material.AIR && Materials.checkFlag(type, mask)) {
CollisionBox box = BlockData.getData(type)
.getBox(player, vec, ProtocolVersion.getGameVersion());
public static String drawUsage(long max, long time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String zeros = "00";
String nums = Integer.toString((int) ((time / (double) max) * 100));
return line + "§f] §c" + zeros.substring(0, 3 - nums.length()) + nums + "% §f❘";
}
if (box.isIntersected(collisionBox)) {
box.downCast(collisionBoxes);
}
}
}
public static String drawUsage(long max, double time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String nums = String.valueOf(format((time / (double) max) * 100, 3));
return line + "§f] §c" + nums + "%";
}
return collisionBoxes;
}
public static List<CollisionBox> toCollisions(List<Block> blocks) {
return blocks.stream().map(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<Block> getBlocksNearby2(World world, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.minX);
int y1 = (int) Math.floor(collisionBox.minY);
int z1 = (int) Math.floor(collisionBox.minZ);
int x2 = (int) Math.ceil(collisionBox.maxX);
int y2 = (int) Math.ceil(collisionBox.maxY);
int z2 = (int) Math.ceil(collisionBox.maxZ);
List<Block> blocks = new LinkedList<>();
Block block;
for (int x = x1; x <= x2; x++)
for (int y = y1; y <= y2; y++)
for (int z = z1; z <= z2; z++)
if ((block = getBlockAt(world, x, y, z)) != null
&& BlockUtils.getXMaterial(block.getType()) != XMaterial.AIR)
if (Materials.checkFlag(block.getType(), mask))
blocks.add(block);
return blocks;
}
public static List<SimpleCollisionBox> toCollisionsDowncasted(List<Block> blocks) {
List<SimpleCollisionBox> collisions = new LinkedList<>();
blocks.forEach(b -> BlockData.getData(b.getType())
.getBox(b, ProtocolVersion.getGameVersion()).downCast(collisions));
return collisions;
}
private static final int[] decimalPlaces = {0, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
public static CollisionBox toCollisions(Block b) {
return BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion());
}
public static double format(double d, int dec) {
return (long) (d * decimalPlaces[dec] + 0.5) / (double) decimalPlaces[dec];
}
public static String drawUsage(long max, long time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String zeros = "00";
String nums = Integer.toString((int) ((time / (double) max) * 100));
return line + "§f] §c" + zeros.substring(0, 3 - nums.length()) + nums + "% §f❘";
}
public static String drawUsage(long max, double time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String nums = String.valueOf(format((time / (double) max) * 100, 3));
return line + "§f] §c" + nums + "%";
}
public static List<CollisionBox> toCollisions(List<Block> blocks) {
return blocks.stream().map(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<SimpleCollisionBox> toCollisionsDowncasted(List<Block> blocks) {
List<SimpleCollisionBox> collisions = new LinkedList<>();
blocks.forEach(b -> BlockData.getData(b.getType())
.getBox(b, ProtocolVersion.getGameVersion()).downCast(collisions));
return collisions;
}
public static CollisionBox toCollisions(Block b) {
return BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion());
}
}
@@ -87,6 +87,10 @@ public class KLocation implements Cloneable {
return this;
}
public Vector getDirection() {
return MathUtils.getDirection(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -24,6 +24,12 @@ public class MathUtils {
return to.subtract(from).length();
}
public static int angularDistance(double alpha, double beta) {
while (alpha < 0) alpha += 360;
while (beta < 0) beta += 360;
double phi = Math.abs(beta - alpha) % 360;
return (int) (phi > 180 ? 360 - phi : phi);
}
public static boolean playerMoved(Location from, Location to) {
return playerMoved(from.toVector(), to.toVector());
}
@@ -15,5 +15,7 @@ public interface CollisionBox {
CollisionBox expand(double x, double y, double z);
void draw(EnumParticle particle, Player... players);
void downCast(List<SimpleCollisionBox> list);
List<SimpleCollisionBox> downCast();
boolean isNull();
}
@@ -70,6 +70,16 @@ public class ComplexCollisionBox implements CollisionBox {
box.downCast(list);
}
@Override
public List<SimpleCollisionBox> downCast() {
List<SimpleCollisionBox> list = new ArrayList<>();
for (CollisionBox box : boxes) {
box.downCast(list);
}
return list;
}
@Override
public boolean isNull() {
for(CollisionBox box : boxes)
@@ -8,6 +8,7 @@ import dev.brighten.ac.utils.world.CollisionBox;
import lombok.Setter;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
public class DynamicCollisionBox implements CollisionBox {
@@ -70,6 +71,15 @@ public class DynamicCollisionBox implements CollisionBox {
box.fetch(version, player, block).offset(x,y,z).downCast(list);
}
@Override
public List<SimpleCollisionBox> downCast() {
List<SimpleCollisionBox> boxes = new ArrayList<>();
box.fetch(version, player, block).offset(x,y,z).downCast(boxes);
return boxes;
}
@Override
public boolean isNull() {
return box.fetch(version, player, block).isNull();
@@ -4,6 +4,7 @@ import dev.brighten.ac.packet.wrapper.objects.EnumParticle;
import dev.brighten.ac.utils.world.CollisionBox;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
public class NoCollisionBox implements CollisionBox {
@@ -45,6 +46,11 @@ public class NoCollisionBox implements CollisionBox {
@Override
public void downCast(List<SimpleCollisionBox> list) { /**/ }
@Override
public List<SimpleCollisionBox> downCast() {
return Collections.emptyList();
}
@Override
public boolean isNull() {
return true;
@@ -20,6 +20,7 @@ import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class RayCollision implements CollisionBox {
@@ -211,6 +212,11 @@ public class RayCollision implements CollisionBox {
@Override
public void downCast(List<SimpleCollisionBox> list) {/*Do Nothing, Ray cannot be down-casted*/}
@Override
public List<SimpleCollisionBox> downCast() {
return Collections.emptyList();
}
@Override
public boolean isNull() {
return true;
@@ -11,6 +11,7 @@ import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -134,6 +135,11 @@ public class SimpleCollisionBox implements CollisionBox {
list.add(this);
}
@Override
public List<SimpleCollisionBox> downCast() {
return Collections.singletonList(this);
}
@Override
public boolean isNull() {
return false;